On-chain vs Off-chain

AdPriva keeps its records off-chain and puts only one hash per batch on-chain. This page lists what lives where.

Off-chain: AdPriva’s database

  • Every proof and consent certificate, with its seal, score and verdict.
  • The data captured with each proof: aggregate interaction counts, page path, referrer, IP address and user agent. The raw IP address and user agent are emptied after 30 days (current production setting).
  • The batches, their Merkle roots and each proof’s place in its batch.

This is where sealing and scoring happen, in real time, when an event arrives. The public API and the Explorer read from here, and show no publisher, site, page or visitor data.

zkVerify: retired

New batches are not sent to zkVerify. For view batches anchored before 2026-09-28, the anchor worker sent zkVerify a Groth16 zero-knowledge proof with the batch’s Merkle root as its only public input. Those attestations stay on zkVerify’s chain as legacy records. See Legacy: zero-knowledge step.

Consent batches never had this step.

On-chain: Horizen

  • Each batch’s Merkle root is sent to AdPriva’s Anchor.sol contract on Horizen, which emits an Anchored(merkleRoot) event.
  • The contract stores nothing else. The event is the permanent public record.
  • One transaction per batch, whatever the batch size. Batches are made every 5 minutes, or sooner when 100 proofs are waiting.

Comparison

Off-chain (AdPriva database)On-chain (Horizen)
What is thereFull records: proofs, verdicts, consent certificatesOne Merkle root per batch
WhenAs each event arrivesWhen each batch is anchored
Personal dataYes, with the retention described in Data Flows for your DPIANone: only hashes
Who can read itPublic lookup by proof id (no publisher, site or visitor data); full records only for the owning organization in the consoleAnyone
Can it changeAdPriva runs the databaseNo: the transaction is permanent

Checking one against the other

A proof’s Merkle inclusion receipt, from GET https://api.adpriva.com/public/proofs/{proof_id}, lets you recompute its batch root offline and compare it with the Anchored event. That shows the proof was in the batch when the batch was anchored. It does not fix the proof’s score or verdict, which live only off-chain. See Proof Systems & Verification.

{% @mermaid/diagram content="flowchart TD
A\[View event]
B\[Ingest server: seal and score]
C\[AdPriva database: full records]
D\[Anchor worker: Merkle batch]
E\[Horizen: Anchored event]
F\[Public API and Explorer]

A --> B
B --> C
C --> D
D --> E
C --> F" %}