6. Decentralized Evidence Storage
Summary: on-chain we keep hashes and IDs; off-chain we keep the actual evidence files. The chain stores evidenceHash and links; storage systems hold the canonical JSON and any raw artifacts under access control with integrity checks. This makes PoV auditable without leaking private data.
What goes where
On-chain: only proofs and pointers — evidenceHash, claimId, attestation UIDs, and a small set of link fields (for example evidence_uri, source_file_hash).
Off-chain: the canonical JSON (the exact bytes that hashed to evidenceHash) and optional raw exports (CSV/Parquet, photos, lab PDFs), stored in a system that can prove immutability and availability.
Storage options
Use what fits the evidence type and confidentiality, but keep a single rule: the bytes you fetch must reproduce the on-chain evidenceHash.
• S3/Cloud object store (with versioning & WORM): best for private or regulated artifacts; serves short-lived signed URLs.
• IPFS (CID v1, optional pinning providers): good for public or semi-public artifacts; use CAR files for large attachments.
• Arweave (permanent): for public proofs that must never disappear; expect higher cost, strong immutability.
You can mix them: for example, canonical JSON on IPFS; raw grid export in S3; an Arweave receipt for the JSON CID.
Evidence package
Each window or claim has exactly one canonical JSON. If there are extra files, describe them via a tiny manifest so auditors know what to fetch.
Canonical JSON (single source of truth): minified, sorted, UTF-8, includes batch_id, device_id, start_ts, end_ts, quantity_wh, nonce.
Manifest (optional, JSON):
{
"canonical_uri": "ipfs://bafy.../window.json",
"canonical_sha256": "0xdca11c7b4c9347db3134f5cced0610541b863c22cc26325d9c28e7e41870c34d",
"attachments": [
{"name":"grid_export.csv","sha256":"0x...","uri":"s3://edma-evidence/.../grid_export.csv"},
{"name":"meter_photo.jpg","sha256":"0x...","uri":"ipfs://bafy.../meter_photo.jpg"}
]
}On-chain you reference evidenceHash (the SHA-256 of the canonical JSON bytes) and, if used, a manifest_uri and manifest_sha256.
Addressing and links
Use stable, typed link fields in attestations or proofs:
• evidence_uri: where to fetch the canonical JSON (for example ipfs://…, s3://…, ar://…)
• evidence_sha256: identical to on-chain evidenceHash
• manifest_uri and manifest_sha256 (optional)
• source_file_hash: SHA-256 of the raw export (CSV/Parquet) if present
Explorers should render links but never assume public access; if a link requires a signed URL, show a “request access” button.
Access control and privacy
Keep PII off-chain. Gate private artifacts with short-lived signed URLs; log access. Do not embed secrets in URIs.
Example (Node, S3 presign):
For IPFS, pin the CID with at least two providers; for Arweave, record the transaction id and optional gateway URL.
Integrity checks
Fetch canonical_json via evidence_uri (or via the manifest).
Compute local SHA-256; compare to on-chain evidenceHash.
Recompute claimId from device_id, start_ts, end_ts, quantity_wh, and the evidenceHash.
Ensure the on-chain proof and One-Claim finalization used that same tuple.
TypeScript (verify):
Retention, versioning, and legal holds
Enable object versioning and a WORM (write-once, read-many) or legal-hold mode where policy requires. Never overwrite canonical_json; if there is a correction, it should appear as a new window with a new batch_id and its own evidenceHash. For regulated programs, document retention periods and keep region-appropriate replicas.
Failure modes and how to handle them
If a link breaks, you still have the on-chain evidenceHash. Operators should republish the exact same bytes (same hash) under a new URI and update the off-chain registry that your Explorer reads. If an artifact becomes confidential after the fact, move it behind signed URLs; the hash remains public and unchanged.
Conformance
Store canonical JSON off-chain; publish only its evidenceHash and a stable evidence_uri. Keep optional files referenced in a manifest with their own hashes. Use short-lived signed URLs for private data. Always verify the fetched bytes reproduce the on-chain evidenceHash, then re-derive claimId to confirm One-Claim aligns.
Bottom line: hashes on-chain, bytes off-chain. That split gives you privacy where needed and auditability where required—without ever weakening the guarantees of Proof of Verification.
Last updated
