Skip to content

System Architecture

How cardano-keri lets an on-chain Cardano validator gate an action on a real-world credential (a vLEI ACDC) that lives off-chain in the KERI network — verified natively in Blake2b, served by a network of watchers, and anchored by a coordinator.

Emerging design

This page presents the current architecture. Several choices are still open; the working design record with the open decisions lives in specs/68-keystate-shape/system-architecture.md. Identity update (2026-07-09): per specs/68-keystate-shape/identity-model.md (PR #87), the identity key-state (R-KEL) is an on-chain cryptographic checkpoint advanced by witness-receipted anchoring seals from the controller's own KEL — not a watcher-attested mirror. The watcher-mirror framing on this page applies to the credential plane (R-TEL · R-MAP) only.

The planes

Four things cooperate: the off-chain KERI world (where identities and credentials actually live), a watcher network run by stake-pool operators (which mirrors the credential-plane state we care about — R-TEL · R-MAP), the coordinator (Cardano Foundation, which anchors the credential mirror on-chain), and the on-chain validators and state. Identity key-state takes a different path: the controller's witnessed anchoring seal drives an on-chain checkpoint directly — no watcher in that loop.

flowchart TB
    subgraph OFF["Off-chain KERI world"]
        direction LR
        GLEIF["GLEIF root"] --> QVI["QVIs"] --> WIT["Witnesses<br/>KELs · TELs · ACDCs"]
    end
    subgraph NET["Watcher network — SPOs"]
        W["Proof builders<br/>watch the closure<br/>build mirror trees<br/>serve proofs"]
    end
    subgraph COORD["Coordinator — Cardano Foundation"]
        C["anchor agreed roots<br/>source the issuer pool"]
    end
    subgraph CHAIN["On-chain — Cardano"]
        direction LR
        MIRROR["Anchored credential mirror roots<br/>R-TEL · R-MAP"]
        IDCK["Identity checkpoint<br/>R-KEL — advanced by<br/>witness-receipted seals"]
        NATIVE["Native app state<br/>R-ID · R-VAL · R-FRZ"]
        VAL["Validators<br/>proof vs root + authorization"]
    end
    U["AID holders / dApps"]

    WIT -->|observe| W
    U -->|register AID| NATIVE
    U -->|"advance tx:<br/>anchoring seal + witness receipts"| IDCK
    NATIVE -->|closure computable| W
    W -->|signed roots| C
    C -->|anchor R_N| MIRROR
    U -->|request proof| W
    W -->|proof vs R_N| U
    U -->|gated action + proof| VAL
    VAL --> MIRROR
    VAL --> IDCK
    VAL --> NATIVE

The trust layering

The key idea is that correctness is on-chain and watcher-agnostic, while service is an off-chain market. A proof is valid or not against the anchored root regardless of who produced it — so the chain never needs to trust a watcher to establish correctness. The watcher network exists to serve proofs and maintain the mirror; that's a market and a bonded-consensus concern, not a validity concern.

flowchart TB
    subgraph L4["Market — off-chain, competitive"]
        M["serving · micropayments · reward distribution"]
    end
    subgraph L3["Credential mirror — anchored, SPO-consensus, falsifiable"]
        S["R-TEL · R-MAP, over the closure"]
    end
    subgraph L2["Closure — computed, pinned to a settled R-ID checkpoint"]
        CL["the deterministic watch set"]
    end
    subgraph L1["Native + checkpoint state — on-chain"]
        N["R-ID · R-VAL · R-FRZ + validators<br/>R-KEL identity checkpoint (witnessed seals)"]
    end
    L4 --> L3 --> L2 --> L1
Layer Roots Trust
Native app state R-ID · R-VAL · R-FRZ (· R-POOL · R-REG) trustless on-chain
Identity checkpoint R-KEL cryptographic from a registration-attested genesis — advances only through witness-receipted anchoring seals (identity-model §5–7a)
Closure computed, pinned to R-ID@N deterministic — everyone recomputes the same
Credential mirror R-TEL · R-MAP falsifiable, SPO-consensus + slash-for-wrong-root
Market off-chain, competitive

The closure — what gets watched

The watchers don't mirror all of KERI — only the closure of the registered identities: the minimal set of AIDs and credentials needed to verify whoever opted in, following each credential chain up to GLEIF. It's a pure function of who registered, so no one curates it.

flowchart BT
    Alice["Alice AID<br/>registered — a seed"] --> OOR["OOR credential"]
    OOR --> OAUTH["OOR-AUTH"]
    OAUTH --> LE["Legal Entity<br/>AID + credential"]
    LE --> QVI["QVI<br/>AID + credential"]
    QVI --> GLEIF["GLEIF — terminal"]

When Alice registers, her whole chain is pulled into the watch set; another holder under a different QVI pulls that QVI in; shared issuers dedup; GLEIF is always the root.

This is the historical credential closure, not a command to create a live checkpoint for every issuer. Alice's current Cardano action reads Alice's checkpoint. The LE/QVI/GLEIF KELs are followed as historical issuance/delegation evidence; those issuers need their own current checkpoints only if they separately authorize a new Cardano action.

Registration and the proof flow (credential plane)

This flow covers registration and credential proofs — the watcher-mirrored plane. Identity key-state advances are a separate, watcher-free flow (next section).

sequenceDiagram
    participant H as Holder
    participant CH as On-chain (R-ID)
    participant W as SPO watcher
    participant CO as Coordinator
    participant V as Validator
    H->>CH: register AID (+ credential-chain path)
    Note over CH,W: closure(R-ID@N) is computable by every watcher
    W->>W: watch the closure, build mirror trees
    W->>CO: sign root R_N
    CO->>CH: anchor R_N
    H->>W: request inclusion proof
    W-->>H: proof against R_N
    H->>V: gated action + proof
    V->>CH: verify proof vs anchored R_N + authorization
    V-->>H: action allowed

The proof the holder presents is watcher-agnostic — a plain inclusion proof against the anchored root. The validator neither knows nor cares which watcher computed it.

Identity checkpoint advance (no watcher in the loop)

Identity key-state never rides the mirror. The controller emits a witnessed anchoring seal into her own KEL — a plain native event whose payload carries blake2b commitments to the new key-state — and the on-chain checkpoint advances only through it (specs/68-keystate-shape/identity-model.md §§3–6a):

sequenceDiagram
    participant CT as Controller (wallet)
    participant KW as Her KERI witnesses
    participant V as Validator
    participant CK as Checkpoint (R-KEL leaf)
    CT->>KW: anchoring seal (blake2b payload commitments)
    KW-->>CT: threshold witness receipts (over raw seal bytes)
    CT->>V: advance tx — seal + receipts
    V->>CK: read stored keys · next_keys · next_threshold · witnesses · toad
    V->>V: revealed digests ∈ next_keys + dual thresholds,<br/>Ed25519 receipts vs incoming (new) witness set at new toad
    V->>CK: seq+1 — new keys, new next_keys/next_threshold
    Note over CT,CK: witness-set change: validated against the incoming (new) set<br/>at the new toad — no outgoing endorsement (§6a)

When the advance's incoming new_toad > 0, receipts below new_toad over the incoming (new) set make the advance invalid; controller signatures and elapsed time never replace them in V1 (for a pure key rotation the incoming set equals the stored one). This prevents a controller from activating one witnessed key state on Cardano, using it, and only later publishing a different KERI rotation. A rotation to new_toad = 0 validates against the empty incoming set (zero receipts); the resulting checkpoint visibly carries toad = 0, an explicit weaker mode consumers may reject.

Genesis (the first leaf) remains registration-attested and publicly falsifiable pending a full-context single-transaction measurement (identity-model §7a). Lane-packed spike #88 now fits the BLAKE3 core across the whole single-chunk domain — 17.1% cpu / 22.4% mem at 300 bytes, 54.3% cpu / 71.7% mem at the full 1024-byte chunk.

Two Blake worlds, one system

Plutus has blake2b_256 but no blake3, and the vLEI ecosystem is Blake3. This does not fork the architecture — the watch→build→anchor layer exists regardless. It only changes whether the R-MAP (Blake3↔Blake2b) mirror is present:

  • CF-as-QVI issuing Blake2b credentials — no R-MAP; validators recompute SAIDs directly.
  • Real Blake3 vLEI credentials — R-MAP carries the mapping the chain can't compute.

Either way, a future Plutus blake3 builtin simply deletes R-MAP and lets validators recompute it themselves — a pure upgrade, no redesign.

The one place possession-checking belongs on-chain is gating who draws the reward pool — and the paid set is SPOs, because they are already bonded (stake), highly available, identified on-chain (the pool registry), and VRF-native. Reward is an extra SPO revenue stream, and root-consensus rides on the SPO set, so the mirror inherits Cardano's decentralization.

flowchart LR
    ISS["Issuer"] -->|subscription — fixed cost| POOL["Issuer pool"]
    POOL -->|by stake / performance| SPO["SPO watchers"]
    HOLD["Holder"] -->|micropayment — marginal cost| SPO
    SPO -->|watch + serve| SVC["availability + proofs"]

Reward-eligibility is proven by a batched VRF challenge, decoupled from user actions:

sequenceDiagram
    participant B as Beacon (on-chain randomness)
    participant CO as Coordinator
    participant S as SPO watcher
    participant V as Validator
    CO->>B: read an un-grindable seed
    CO->>S: one challenge tx (the seed)
    S->>S: derive its own key = VRF(seed, stake)
    S->>V: response tx — proof for that key vs R_N
    V-->>CO: on-chain pass/fail witness
    CO->>S: pay from the pool (on pass)

Because the challenge key comes from each SPO's own VRF over a seed the coordinator can't grind, neither the coordinator nor the SPO chooses it — the coordinator stays mechanical, and collusion collapses to "did it use the honest beacon," which is publicly checkable.

Cost structure in one line

Two costs, two payers: watching is a fixed cost (scales with the closure) → the issuer pays, which also gates whether its credentials are usable on Cardano at all; serving proofs is a marginal cost (scales with usage) → holders micropay, via prepaid accounts or channels. Competition floors the proof price at marginal cost, which is fine because the fixed cost is already issuer-covered.