Legacy: zero-knowledge step (retired 2026-10-16)
AdPriva no longer generates a zero-knowledge proof for new view batches. This page explains the step that was retired, why it was retired, and how to read the records it left behind.
What changed
New view batches are anchored directly on Horizen. The anchor worker builds a Poseidon Merkle tree over the batch, recomputes the root from the batch’s proof ids and sends the root to AdPriva’s Anchor.sol contract. No Groth16 proof is generated and nothing is sent to zkVerify. View batches created since 2026-09-28 are anchored this way.
What a reader can check is the proof’s Merkle inclusion receipt against the root in the Horizen transaction. See Proof Systems & Verification and Anchor Worker.
What the retired step did
For view batches anchored before 2026-09-28:
- The anchor worker grouped new view proofs into a batch and built a Merkle tree over them with the Poseidon hash. The tree has 20 levels, and each leaf is the hash of one proof’s internal number.
- For the batch, it generated a Groth16 proof with the circuit
merkleroot.circom(circuit versionv2.0.0). The statement was: I know a leaf and a Merkle path that hash up to this root. The root was the only public input. The leaf and the path were private inputs. - The proof was submitted to zkVerify, which checked it on its own chain.
- After zkVerify accepted it, the batch root was anchored on Horizen through
Anchor.sol.
Why it was retired
- It covered one leaf per batch. The proven leaf was always the batch’s first leaf (
zk_proven_leaf_index: 0). Every other proof in the batch relied on its Merkle path and the anchored root. - It added no guarantee beyond the anchored root. AdPriva built both the Merkle tree and the proof.
- It was never part of the Horizen anchor. The
Anchoredevent carries only the batch root. The zkVerify attestation was a separate record on another chain. - It was one more outside dependency in the path of every view batch.
The step never said anything about whether a visit was human. The validity score and verdict come from scoring. See Proofs of Engagement.
Reading legacy records
The public API still returns the zkVerify fields on every record. Their values tell you which kind of batch you are looking at:
| Batch | zkverify_status | zkverify_url | zk_proven_leaf_index |
|---|---|---|---|
| View batch anchored before 2026-09-28 (legacy) | FINALIZED | A zkVerify transaction link | 0 |
| View batch created since 2026-09-28 | NOT_APPLICABLE | null | Absent |
Consent batches have always shown NOT_APPLICABLE. They use a SHA-256 Merkle tree and never had a zero-knowledge step.
Legacy batches stay valid. This is a real legacy record, with the Merkle path fields left out:
{
"proof_id": "666959fe0c24984a6aec482e4d2835b847341577cb303b34183aa0c6290d6897",
"type": "view",
"batch_id_hash": "00000000000007f7",
"merkle_root": "0x0365496d53b1437195520f69d21296efd113ed17f2c334484b83faed856f5805",
"leaf": "2895",
"leaf_index": 0,
"hash_version": "poseidon",
"zk_proven_leaf_index": 0,
"zkverify_status": "FINALIZED",
"zkverify_url": "https://zkverify.subscan.io/extrinsic/0xe3ceb6532877cf9cf324dfad74bf79f8c3c941751db647b3e68936564e5ab13b",
"horizen_status": "CONFIRMED",
"horizen_tx": "0x7fa649ce95ed242b75c5457265c826ab687421ca14a4f12ec3d617df55a08e1a"
}
zkverify_urlopens the zkVerify transaction that checked the batch’s proof.horizen_txis the anchor transaction. ItsAnchoredevent carries the same root.leaf,merkle_pathandmerkle_path_indiceslet you recompute the root offline, for any proof in the batch, legacy or not. The API Reference has the algorithm.