DAYPASS App
EU Battery Regulation 2023/1542 Digital Battery Passport on Cardano. One CIP-25 NFT per passport, plus an anchor metadata label with the payload hash, a Merkle content root and the public Point-1 fields. Sensitive data stays AES-encrypted off-chain. Three disclosure tiers render lawful views of one backend. Threshold statements like “carbon footprint below X” are proven in zero knowledge, with the Groth16 verification executed by the Cardano ledger itself. DAYPASS is the transparent twin of NIGHTPASS on Midnight.
Highlights
- CIP-25 NFT anchor: Mint under a policy bound to the producer key + anchor label 1155 with
payloadHash,contentRoot, Point-1 cleartext - Three disclosure tiers (Annex XIII): consumer / recycler / authority — enforced in the API layer; the chain carries the evidence, not the access control
- Selective disclosure: Reveal ONE field value with a Merkle inclusion proof against the anchored content root — any Cardano API can re-verify it
- On-chain ZK predicates:
provePassportPredicatemints a predicate token whose mint redeemer IS the Groth16 proof; the Plutus V3 validator runs the full pairing check - Re-attest chain: Metadata txs with new payload versions, chained via
prev; burn nets supply to zero on revocation - Catena-X export: CX-0143 BatteryPass aspect JSON + W3C-VC Predicate Attestation Credential (PAC) verifiable portably against Cardano
Stack
| Layer | Tech |
|---|---|
| Network | Cardano preview |
| Chain gateway | @odatano/core (CAP plugin) |
| ZK toolkit | @odatano/dayzero (Groth16 over BLS12-381, Poseidon) |
| On-chain verifier | Aiken (Plutus V3) |
| Backend | SAP CAP, Node.js, TypeScript |
| Signing | CIP-30 browser wallet (server key optional) |
| Dataspace | Catena-X / Tractus-X (CX-0143, PAC) |
Metadata Labels
Label 721 (CIP-25) display: name "DPP <passportId>", model, QR image
Label 1155 (anchor) evidence: op (mint|reattest|grant|revoke),
payloadHash, contentRoot, poseidonRoot,
version + prev tx hash, Point-1 cleartext
The mint tx carries both labels; re-attest and audit anchors are plain metadata txs with only the 1155 label. Grant/revoke anchors are pseudonymous: the grantee is sha256(did), never PII.
Zero-Knowledge Predicates
1. Anchor commits a Poseidon Merkle root over the 9 provable fields
2. Prover sidecar (@odatano/dayzero) builds the Groth16 proof
3. provePassportPredicate mints a token: redeemer = proof
4. Validator verifies the pairing on-chain; asset name commits
to the public inputs (blake2b-224 over the serialised datum)
Live on Preview: mint + anchor tx ae0d4c2d…05af8f, zk predicate tx 5a5c0a64…57d52c proving carbonFootprint lessOrEqual threshold.
Quick Start
git clone https://github.com/ODATANO/DAYPASS && cd DAYPASS
npm install
cp .env.example .env # fill in BLOCKFROST_API_KEY (preview)
npm run deploy # creates db/daypass.db + demo seeds
docker compose up -d daypass-prover # ZK prover sidecar on :8799
npm start # http://localhost:4004
- Producer cockpit:
/producer/webapp/index.html(producer/producer) - Consumer viewer:
/passport/webapp/index.html(recycler/recycler, authority/authority) - QR landing
/p/<passportId>, public verification JSON/verify/<passportId>