ROOTVIELROOTVIEL
← Academy

Module 5 · Research case studies

ZK in agents: credentials, chains and the delegation circuit

The unit of delegation is a signed hop with six fields; a chain of hops passes five validation checks plus two authorization conditions. A zero-knowledge circuit then proves that such a chain exists for a given root and action, keeping the chain private. This lesson walks the credential schema, the chain checks, the circuit’s public and private signals, the separable engine, and the registry of proof-system adapters — and is explicit that two of the five adapters prove only a FRAGMENT of the check.

Learning objective

Learn how a delegation is represented as a signed hop, how a chain of hops is validated and attenuated, how a zero-knowledge circuit proves that a valid chain exists without revealing it, and how a separable cryptographic engine and a proving-system abstraction keep the design honest about what each proof backend actually proves.

Track
Research
Module
5 · Research case studies
Prerequisites
ZK in agents: the delegated-authorization problem · Digital signatures · Scope attenuation

What a credential contains

The unit of delegation is a single signed hop. One hop says: this issuer grants this subject this scope, linked to a specific parent, valid until some instant, and here is the issuer’s signature over all of it. A hop carries six fields.

issuer key
Who delegates.
subject key
Who receives.
scope
The set of permitted action types.
parent link
The digest of the parent hop, or a genesis marker for the first hop.
expiry
The instant after which the hop is invalid, or none.
signature
The issuer’s signature over the canonical encoding of the hop.

The digest is a hash over the canonical encoding of everything but the signature, and it is what the next hop links to via its parent link. A chain is an ordered sequence of hops: its root is the issuer of the first hop, its leaf is the subject of the last, and its depth is the number of hops. Canonical encoding is part of the mechanism, not an implementation detail: once signatures exist, two serializers differing in field order or integer representation produce different digests and do not interoperate at all.

Chain validation: five checks plus the contract

Validation walks the chain from root to leaf and stops at the first failure, returning the reason. At every hop it checks five things:

  1. 1V1 Continuity of identity — the issuer equals the subject of the previous hop.
  2. 2V2 Continuity of linkage — the parent link equals the digest of the previous hop.
  3. 3V3 Authenticity — the issuer’s signature verifies.
  4. 4V4 Freshness — the hop has not expired at the given instant.
  5. 5V5 Attenuation — the scope is contained in the parent’s scope.

Over a complete chain, the authorization check adds two conditions on top of V1–V5: that the chain’s root is the expected authority, and that the required action lies within the leaf’s scope. Those two conditions, together with the five per-hop checks, are the contract of the system. Everything else in the architecture either enforces this contract, proves it, or measures the cost of proving it.

Note

V5 is where structural attenuation (requirement R2) lives: scope containment is checked at every hop, so a child can only ever narrow what its parent granted. Because this is enforced per hop rather than trusted to the delegator, it holds even when the delegating component is stochastic or manipulated.

The delegation circuit

The circuit proves, in zero knowledge, that a valid chain exists for a given root and action — without revealing the chain. The split between public and private signals is the whole point: the verifier learns the statement, not the witness.

Public signals (the statement)
The root authority’s key, expressed as coordinates on a circuit-friendly curve, and a bitmask encoding the required action(s). Roughly: “there exists a chain of some depth, rooted here, whose leaf scope covers this action.”
Private signals (the witness)
For each hop: the issuer and subject coordinates, the scope bitmask, and the signature components. The chain itself never leaves the prover.

The circuit imposes five constraints — four at every hop and a fifth at the leaf:

the five circuit constraints (schematic)
attenuation (per hop): bits(scope_i) AND NOT bits(scope_{i-1}) == 0 // scope_i ⊆ scope_{i-1} linkage (per hop): circuit_friendly_hash(hop_{i-1}) == parent_link_i continuity (per hop): subject_{i-1} == issuer_i // signal equality signature (per hop): in-circuit verify(issuer_i, hop_i, sig_i) // dominates cost leaf (at leaf): required_action_mask ⊆ scope_{leaf}

The attenuation constraint is a bitwise containment: for each bit set in a child scope, the same bit must be set in the parent scope, which arithmetically forces child-scope ⊆ parent-scope. Cost is dominated by in-circuit signature verification. The prototype reports approximately 9.15×10³ constraints per hop — a measured figure for this circuit, not a universal property of ZK systems.

Curve translation and what it costs

There is an honest wrinkle. The circuit operates over a curve chosen because in-circuit signature verification is affordable on it, whereas the signature scheme the agents actually use is prohibitively expensive to verify inside a circuit. A translation maps one to the other, preserving the depth, the attenuation pattern, and the authorized action — but NOT credential identity.

Note

Consequence stated as property P7: a proof does NOT bind the specific stored credentials. The circuit works over a translated representation, so nothing in it commits to the digests of the real hops. A proof attests that an authorization of that SHAPE existed, not that it is these exact credentials. This is a by-construction limitation, acknowledged, not a bug — and later lessons return to it.

The separable cryptographic engine

The cryptographic engine does not import the runtime; the runtime dependency is an optional extra. This separability is what makes the artefact independently publishable and independently measurable, and the paper checks it as an invariant rather than leaving it to discipline. In the prototype the engine is a standalone package with the runtime declared as an optional dependency.

  • ▸No domain assumptions — a capability consumed by unrelated deployments cannot encode any one deployment’s vocabulary, so the delegation model is expressed over an abstract action universe rather than a specific application’s operations.
  • ▸Optional coupling — the engine never reaches into the runtime; the dependency only goes the other way, which is what lets the engine be measured on its own.
  • ▸Shared trace identity — a per-operation identifier is propagated end to end rather than regenerated, so an operation crossing from a consuming system and back can be reconstructed for audit.

The proving-system abstraction

Requirement R6 says no commitment to a single proof system. The paper satisfies it with an adapter interface: an adapter implements three operations — set up, prove, verify — over a statement (root authority, leaf subject, required actions, instant) and a witness (the chain). Crucially, an adapter also DECLARES five properties of itself: whether it is zero-knowledge, whether it is succinct, whether it needs a trusted ceremony, whether it resists quantum computation, and whether it supports recursion. No module resolves a proof system by type; resolution is by name through a registry, so swapping systems is a code change, not a type change.

The prototype ships five adapters occupying different corners of the design space. The honesty rule matters here: the declared-property vector is load-bearing, and two adapters prove only a FRAGMENT of the full check.

the five adapters (prototype-reported characteristics)
transparent : reveals the witness; no ZK, no ceremony; the baseline, not a competitor groth16 : constant-size proof; per-circuit trusted ceremony; ZK; proves the FULL check (with signatures) plonk : small constant proof; universal ceremony; ZK; proves the FULL check (with signatures) stark : larger proof; no ceremony; quantum-resistant; proves a FRAGMENT (attenuation + linkage, no signatures) nova (folding): constant-size via folding; proves a FRAGMENT (attenuation + linkage, no signatures)
Note

Be precise when repeating this: only the transparent and pairing-based (groth16/plonk) lanes prove the authorization check WITH in-circuit signatures. The hash-based (stark) and folding (nova) adapters leave signature verification outside their algebraic representation, so they prove attenuation and linkage only. Do not describe them as proving the full delegation check — the paper explicitly does not.

Exercise

Note

A teammate says: “We generated a Groth16 proof and a Nova proof for the same delegation — they both verify, so they prove the same thing.” Correct this precisely, and separately explain why a verifying proof still does not guarantee you are looking at the exact credentials that were stored.

Expected direction: They do not prove the same thing: the Groth16 (pairing-based) adapter proves the full check including in-circuit signatures, while the Nova (folding) adapter proves only a fragment — attenuation and linkage — leaving signature verification out of its representation. Separately, because the circuit works over a translated curve representation that preserves depth, attenuation pattern and authorized action but not credential identity (property P7), a verifying proof attests that an authorization of that shape existed, not that these exact stored credentials are the ones behind it.

Check your understanding

What are the six fields of a delegation hop, and what links one hop to the next?
issuer key, subject key, scope, parent link, expiry, and signature. The parent link holds the digest (hash of the canonical encoding minus the signature) of the previous hop, chaining them.
Which chain check enforces structural attenuation, and why does enforcing it per hop matter?
V5 — the scope is contained in the parent’s scope — checked at every hop. Per-hop enforcement means a child can only narrow authority by construction, so it holds even if the delegating component is stochastic or manipulated.
What does the circuit’s public statement reveal, and what stays in the witness?
Public: the root authority key and the required-action bitmask (there exists a valid chain of some depth rooted here whose leaf covers this action). Private: every hop’s issuer/subject coordinates, scope bitmask, and signature components — the chain itself.
Why can the stark and nova adapters not be described as proving the full authorization check?
They prove only a fragment — attenuation and linkage — leaving in-circuit signature verification outside their algebraic representation; only the transparent and pairing-based (groth16/plonk) lanes prove the check with signatures.

References

  1. [1]The reference paper this case study is based on — its credential schema, five-check validation, delegation circuit, separable engine and adapter registry (authors and venue intentionally omitted here).
  2. [2]Groth — On the size of pairing-based non-interactive arguments (EUROCRYPT 2016)
  3. [3]Kothapalli, Setty & Tzialla — Nova: recursive zero-knowledge arguments from folding schemes (CRYPTO 2022)

References point to public, well-known technical sources for further study.

Related articles