-
Notifications
You must be signed in to change notification settings - Fork 1
zkp
title: Zero-Knowledge Proving Pipeline acronyms: [ZKP] created: 2026-07-07 updated: 2026-07-15 type: concept tags: [cryptography] confidence: high source_files:
- integrity-zkp/src/main.nr
- integrity-zkp/README.md
- integrity-zkp/Makefile
- integrity-zkp/generated/UltraPlonkVerifier.sol
- contracts/src/oracle/UltraPlonkVerifier.sol
- contracts/src/oracle/IZkVerifier.sol
- contracts/src/oracle/VerifierRegistry.sol
- contracts/src/oracle/ReputationRegistry.sol
- contracts/script/Deploy.s.sol
- integrity_sdk/prover.py
- integrity-sdk/circuits/poc_commitment/src/main.nr
- integrity-oracle/backend/src/handlers.rs
- integrity-oracle/backend/src/chain.rs
- integrity-oracle/backend/src/db.rs
- docs/INTERFACE_CONTRACT.md
Correction to the previous version of this page: it claimed the pipeline
was "real at every layer." That overclaimed. Every individual stage below
is real (no assert(true), no hardcoded-true verifier) — but the stages
are not yet wired to each other end to end. Three concrete gaps, detailed in
§4-§6: the deployed on-chain verifier is a fail-closed placeholder, not the
real generated verifier; integrity-sdk's prover targets a different,
stand-in circuit, not the one in integrity-zkp; and nothing in this repo
currently calls ReputationRegistry.submitZkAttestation. This is a large
improvement over the old prototype (which failed open — a mock verifier
that accepted any non-empty proof) but "real, not yet connected" is the
accurate description, not "real end to end."
Noir is a Rust-like DSL for writing zero-knowledge
circuits: you write a fn main(...) whose asserts become the circuit's
constraints, nargo compiles it to ACIR (an intermediate arithmetic-circuit
representation), and a separate proving backend turns a satisfying
assignment ("witness") into a succinct proof that the constraints hold,
without revealing the private inputs. This repo uses
Barretenberg (bb) as that
backend, on the UltraHonk proving system (see §3 for why the generated
contract is still named "UltraPlonk"). Pinned versions: nargo
1.0.0-beta.22, bb 5.0.0-nightly.20260522 (docs/INTERFACE_CONTRACT.md).
The one real circuit is integrity-zkp/src/main.nr — a key/intent binding
proof, not a proof about AIS computation or any behavioral-metric
arithmetic. Full formula and domain-tag detail lives on
integrity-zkp; summarized here only for
pipeline context: given a private secret_key (KDF'd off-circuit from the
agent's real Ed25519 seed) and a private intent_payload_hash (the BCC
object's SHA-256 intended_state_hash, reduced to a Field), the circuit
asserts two Pedersen-hash equalities against public inputs
(agent_id_commitment, nonce, intent_commitment):
-
pedersen_hash([DOMAIN_IDENTITY, secret_key]) == agent_id_commitment— the prover holds the exact secret behind the agent's published identity, not just anyone who observed the public commitment. -
pedersen_hash([DOMAIN_INTENT, secret_key, intent_payload_hash, nonce]) == intent_commitment— the prover actually knows the payload locked in for this nonce/action, binding the proof to one specific action and blocking replay as a different action.
Both are real constraints on real Pedersen gates, exercised by 4 nargo test cases (1 valid, 3 should_fail negative controls: wrong secret,
substituted payload, zero nonce — all 4 pass). Explicit scope limit:
this is proof-of-possession of a KDF-derived secret, not a full in-circuit
Ed25519 signature check (that would need a non-native Curve25519
bignum/foreign-field gadget library — a separate undertaking, documented
rather than silently skipped).
Exact commands, all actually run (full transcripts in
integrity-zkp/README.md):
nargo test # 4/4 constraint unit tests pass
nargo compile # -> target/integrity_zkp.json (ACIR)
nargo execute witness # -> target/witness.gz, using Prover.toml
bb write_vk -b target/integrity_zkp.json -o target/vk -t evm
bb prove -b target/integrity_zkp.json -w target/witness.gz -k target/vk/vk -o target/proof -t evm
bb verify -k target/vk/vk -p target/proof/proof -i target/proof/public_inputs -t evm # exit 0
bb write_solidity_verifier -k target/vk/vk -o generated/UltraPlonkVerifier.sol -t evm # 2465 lines
bb verify was confirmed to actually check the proof (not hardcode
success): flipping one byte of public_inputs and re-running produces
UltraVerifier: verification failed at reduction step, exit 1.
Two naming/shape traps for anyone consuming the output:
-
bb's printed scheme isultra_honk(Barretenberg 5.0.0-nightly's current default), not classic UltraPlonk. The generated contract is a real Honk verifier;UltraPlonkVerifier.solis only the filenamecontracts/expects, not a claim about the proving system. - The generated contract declares
NUMBER_OF_PUBLIC_INPUTS = 11, not the circuit's logical 3 (agent_id_commitment,nonce,intent_commitment) — Honk appends internal accumulator/pairing-point public inputs. Callers must passbb'spublic_inputsoutput through verbatim, not assume a 3-element array.
Makefile targets (integrity-zkp/Makefile): make test (nargo only, fast,
CI-safe), make compile, make execute, make vk, make prove, make verify, make solidity-verifier, make build (= test + verify +
solidity-verifier, the full sequence above), make clean.
On-chain contract shape (all real code, per contracts/src/oracle/):
IZkVerifier defines verify(bytes calldata proof, bytes32[] calldata publicInputs) external view returns (bool) — the exact signature bb write_solidity_verifier emits. ReputationRegistry.submitZkAttestation
(only callable by agent == msg.sender, blocking cross-agent replay) checks
the leaf against a StateAnchor-anchored Merkle root, then calls
zkVerifier.verify(proof, publicInputs); on success it sets a 7-day
zkBoostExpiry, and effectiveScore() applies the 1.15x (ZK_BOOST_BPS = 11_500/10_000) multiplier while that window is live. The verifier call is
indirected through VerifierRegistry (a per-agent clone mapping circuit
version → verifier address) so a global circuit upgrade doesn't force
every agent onto a new verifier simultaneously.
What's not yet connected:
-
Nothing calls
submitZkAttestation.grep -rln "submitZkAttestation"across the repo matches only Solidity contracts and Solidity tests — no Python (integrity-sdk,integrity-cli) or Rust (integrity-oracle) caller submits a proof on-chain anywhere in this repo today.[PLANNED]. -
integrity-sdk's prover targets a different circuit.integrity_sdk/prover.py'sNoirProver.generate_proof()really shells out tonargo executeandbb prove(subprocess.run(...), not a mock) — but againstintegrity-sdk/circuits/poc_commitment/src/main.nr, a smaller stand-in circuit (fn main(secret: Field, intent_hash: pub Field) -> pub Field) built to exercise the SDK's proving code path beforeintegrity-zkp's real circuit existed. Its own docstring says so explicitly. It also derives its field element with SHA-256 +int.from_bytes(...) % FR_MODULUS, not theblake2s-basedderive_circuit_secret()conventionintegrity-zkp/README.mdspecifies for the real circuit'ssecret_key. Repointingprover.pyatintegrity-zkp/src/main.nrand reconciling the KDF is[PLANNED], not done. -
The oracle does not run
bb verify.integrity-oracle's AIS response has two related-but-distinct fields (integrity-oracle/backend/src/handlers.rs):zk_proof_verifiedis set straight from an off-chain telemetry aggregate (aggregate.zk_verified_this_period, itselfCOALESCE(BOOL_OR(zk_verified), false)over ingested telemetry rows,backend/src/db.rs) — i.e. a self-reported flag, not a recomputed proof check.onchain_zk_boost_consistent: Option<bool>is a genuine on-chain cross-check, callingReputationRegistry.isZkBoosted(agent)viaalloy(backend/src/chain.rs::is_zk_boosted) and comparing it against the telemetry flag — but it only detects disagreement between the two; it never verifies a Barretenberg proof itself, and given §4/§6 below, on-chainisZkBoostedcan currently never betrueat all (nothing setszkBoostExpiry, and even if something calledsubmitZkAttestation, the deployed verifier reverts unconditionally — see §5).
It is the fail-closed placeholder, confirmed. contracts/src/ contains
exactly one UltraPlonkVerifier contract in source:
contracts/src/oracle/UltraPlonkVerifier.sol, 52 lines. Its own NatSpec
states this plainly:
PLACEHOLDER — THIS FILE WILL BE REPLACED WHOLESALE, NOT EDITED. ... This placeholder instead fails CLOSED: every call to
verifyreverts, unconditionally.
function verify(bytes calldata, bytes32[] calldata) external pure override returns (bool) {
revert PlaceholderVerifierNotYetGenerated();
}contracts/script/Deploy.s.sol instantiates exactly this contract
(verifier = new UltraPlonkVerifier();, line 108) and registers its address
under singletons.UltraPlonkVerifier in the deployments file. Cross-checked
against deployments.baseSepolia.json: the live Base Sepolia address is
0xD6eE9031320382831c8C96627D02aEE573089226 under singletons — that is
the placeholder, deployed. Any call to its verify() reverts
unconditionally; it is not a mock that returns true/false, it simply
cannot be exercised on-chain at all right now, by design (contrast with the
old /INTEGRITY/ prototype, whose equivalent contract returned true for
any non-empty proof — a fail-open silent mock). Tests that need to
exercise the rest of submitZkAttestation (Merkle-anchor check, boost
bookkeeping) do so against a vm.mockCall-controlled IZkVerifier stand-in
in contracts/test/ReputationRegistry.t.sol, not against this contract.
The real, 2465-line generated verifier exists only at
integrity-zkp/generated/UltraPlonkVerifier.sol and has never been copied
into contracts/src/oracle/UltraPlonkVerifier.sol. Diffing the two files
confirms they are unrelated beyond sharing a filename and the IZkVerifier
signature — the placeholder doesn't even import Honk verification-key
constants.
integrity-zkp/README.md documents the circuit-side regeneration step,
and it's real and runnable today: make solidity-verifier (or make build) in integrity-zkp/ re-runs bb write_vk + bb write_solidity_verifier and rewrites integrity-zkp/generated/UltraPlonkVerifier.sol.
The hand-off step — copying that generated file into
contracts/src/oracle/UltraPlonkVerifier.sol and redeploying — is where the
gap is. The placeholder's own NatSpec and docs/wiki's root CLAUDE.md
both reference a make generate-verifier target and a
contracts/script/GenerateVerifier.sh script as the intended way to do
this. Neither exists. Checked: no Makefile anywhere in the repo (root
or contracts/) defines a generate-verifier target — contracts/ has no
Makefile at all — and contracts/script/GenerateVerifier.sh is not
present on disk. grep -rln "generate-verifier" across the repo matches
only prose references (CLAUDE.md, the placeholder's NatSpec, two test
files' comments), never a target definition. This is a genuine, documented
tooling gap, not something to paper over: today, replacing the placeholder
is a manual copy (cp integrity-zkp/generated/UltraPlonkVerifier.sol contracts/src/oracle/UltraPlonkVerifier.sol) followed by a manual
forge script script/Deploy.s.sol redeploy — no single command does both
steps. [PLANNED].
flowchart LR
subgraph Real["Real, working today"]
Circuit["Circuit constraints<br/>(main.nr, 4/4 nargo test)"]
Prove["nargo compile → witness →<br/>bb prove / bb verify"]
Verifier["bb write_solidity_verifier<br/>(2465-line Honk verifier)"]
OracleChain["oracle: onchain_zk_boost_consistent<br/>(real isZkBoosted read)"]
end
subgraph Gaps["Documented gaps — [PLANNED]"]
Handoff["Manual copy into contracts/,<br/>no generate-verifier tooling"]
Deployed["Deployed verifier is the<br/>fail-closed PLACEHOLDER"]
SDKProver["SDK prover.py targets<br/>poc_commitment, not this circuit"]
Submit["Nothing calls<br/>submitZkAttestation"]
OracleFlag["oracle: zk_proof_verified is a<br/>self-reported telemetry flag"]
end
Circuit --> Prove --> Verifier --> Handoff --> Deployed
SDKProver -.-> Prove
Submit -.-> Deployed
OracleFlag -.-> OracleChain
OracleChain -.->|can only detect disagreement| Deployed
| Stage | Status |
|---|---|
Circuit constraints (integrity-zkp/src/main.nr) |
Real, tested (4/4 nargo test) |
nargo compile → witness → bb prove/bb verify
|
Real, real transcripts, real negative control |
bb write_solidity_verifier output |
Real, 2465-line generated Honk verifier |
| Deployed on-chain verifier (Base Sepolia) |
Placeholder — fails closed, reverts unconditionally |
| Circuit → contracts hand-off tooling |
Missing — make generate-verifier / GenerateVerifier.sh referenced, not built |
integrity-sdk proof generation |
Real toolchain calls, but against poc_commitment, not integrity-zkp's circuit |
Proof submission to ReputationRegistry.submitZkAttestation
|
Nothing calls it anywhere in this repo |
Oracle zk_proof_verified field |
Self-reported telemetry flag, not a recomputed proof check |
Oracle onchain_zk_boost_consistent field |
Real on-chain read (isZkBoosted via alloy), but only ever detects disagreement — can't currently observe true given the gaps above |
See Interface Contract §5 for the pipeline's original spec, and integrity-zkp for the concrete hash-function/domain-separation decisions every consumer must replicate exactly.
Generated from INTEGRITY-LATEST/docs/wiki. Edit the canonical repository files, not this mirror.
- A2A Negotiation Protocol [PLANNED]
- AIS API — Versioned Wire Spec
- Agent Integrity Score (AIS)
- Agent Primitives (Self-Sovereign Identity)
- Behavioral Commitment Chain (BCC)
- ComplianceGate & Integrity Health
- Cross-Chain Reputation Sync [PLANNED]
- Decentralized Identifier (DID)
- Identity Ceiling & Verification Ladder [BUILT]
- Integrity Market (Prediction Markets, Binary Options, A2A Capital Allocation)
- Integrity Protocol Specification
- Local Metrology (Client-Side AIS Signal Derivation)
- Merkle Batching & Anchoring Convention
- Observability & PHI Safety Pipeline
- On-Chain Governance
- Persistent Memory Bridge
- Persistent Memory, Genesis Root & Lineage [PARTIALLY BUILT]
- Smart BAA (On-Chain Business Associate Agreement Escrow)
- Telemetry Ingestion Pipeline
- Testing Strategy
- The Four Foundational Primitives
- Xibalba Agent Operating Model
- ZK-ML Model-Inference Verification [PLANNED]
- Zero-Knowledge Proving Pipeline