Skip to main content
The Keystone is the agentic-payment trust chain: identity, authority, policy, decision, execution, and a single verdict, each a content-addressed reference bound to the one before it. This page shows that chain carried all the way through a real payment: composed, signed, bound to an actual USDC transfer on a public blockchain, and then verified from scratch by an independent checker. We ran it on seven public testnets through the AlgoVoi payment rails. Each settlement is a real on-chain transfer; each Keystone chain is checked by recomputing every reference, verifying the decision signature, and re-scanning the transaction on-chain. On Algorand, Stellar and Solana the keystone decision is written into the transaction itself, so it is visible directly on the block explorer. The Keystone proven over real on-chain settlements

Why it flows through every part

Each reference is "sha256:" + SHA-256(JCS(...)) over the part before it. mandate_ref embeds passport_ref, policy_bound_ref embeds mandate_ref, decision_ref embeds policy_bound_ref, and execution_ref embeds both decision_ref and the settlement itself. A later reference cannot exist unless every earlier part is real and unchanged, so recomputing the chain is the proof that the settlement passed through each stage in order, with none skipped or altered.
1

passport_ref — who is acting

The agent’s identity. Root of the chain.
2

mandate_ref — what it may spend

Spend authority. Embeds passport_ref.
3

policy_bound_ref — under which policy

The rules in force. Embeds mandate_ref.
4

decision_ref — was it authorised (signed)

The Spend Guardrail verdict, ALLOW, Ed25519 signed and timestamped before the payment. Embeds policy_bound_ref.
5

settlement — the money moves

A real USDC transfer to the merchant on a public chain. The gateway’s own facilitator re-checks it on-chain and returns verified = true.
6

execution_ref — decision bound to the tx

Binds the signed decision to the exact settlement. Embeds decision_ref and the transaction.
7

trust_query_ref — one verdict over the chain

A single reference over all seven parts.

Seven live settlements

Every row is a real testnet transfer, settled and verified by the AlgoVoi rails. On Algorand, Stellar and Solana the decision reference is carried on-chain, in the note, memo and reference respectively.
ChainAssetTransactionDecision on-chain
Base SepoliaUSDC0x7ae7b275…ac6acbsigned decision
Arc testnetUSDC (native)0x9a75bc27…858e06signed decision
Tempo testnetPathUSD0x9156044b…5c7d29signed decision
Algorand testnetUSDCSEHZ2FUC…LE3Qin the tx note
Stellar testnetUSDCf11afe33…7bd7f17in the tx memo
Solana devnetUSDC7W5s2Rrz…NhvBSas the reference
Hedera testnetHBAR (native)0.0.7314364…988662signed decision
Tempo settles in PathUSD and Hedera in native HBAR; the other five settle in USDC.

Four protocols, one receipt

An agent can ask to pay in more than one way. x402, MPP, AP2 and A2A are four agent-payment protocols, each with its own authorisation form. The Keystone sits above all of them: whichever protocol carried the request, the settlement is recorded once, in one shared format, so the four converge on a single settlement reference. We composed and signed the four authorisation chains, then settled one real USDC transfer of 1 USDC through the AlgoVoi rails on Base Sepolia (0x21ce033f…f603e7b, block 43,628,975). Each decision was signed before the settlement block, and the rails re-checked the transfer on-chain and returned verified = true. All four chains share one agent passport_ref (sha256:b536bd6d83…b7193d) and bind to one settlement_ref (sha256:71ae1e76f6…d6279d). Above the settlement, each protocol keeps a distinct authorisation chain, so the mandate_ref and the final trust_query_ref differ per protocol.
ProtocolAuthorisation formmandate_reftrust_query_ref
x402PaymentRequirementssha256:36423bf4bd…2f303a5696b2e75a…b260e0
MPPpayment contextsha256:de7a3c1d5c…f1f6bbfdf5b51131…a9dc22
AP2IntentMandate to CartMandate to PaymentMandatesha256:e15d82171f…daab0df020643919…ddc884
A2Aagent card task with payment requestsha256:5a5b09c830…34ee6d4860542db0…e5465e
Every object behind those references, along with the settlement attestation, the transaction and its on-chain verification, is published in the proof pack. An independent verifier that imports nothing from AlgoVoi and uses only SHA-256, RFC 8785 and Ed25519 re-derives every reference and checks every signature: 46 of 46 checks pass in a clean environment.

Proof pack (JSON)

Download it: every object, reference, signature, the settlement attestation, the transaction and its on-chain verification. Then run the verifier below against it.
Save the verifier as verify_4proto.py, then run it against the pack:
pip install rfc8785 cryptography
python verify_4proto.py keystone_4proto_pack.json
#!/usr/bin/env python3
"""Independent offline verifier for the AlgoVoi four-protocol Keystone proof pack.

Depends only on SHA-256 and Ed25519 (stdlib) plus RFC 8785 JSON Canonicalisation
(pip install rfc8785 cryptography). It reads keystone_4proto_pack.json and, using
nothing from AlgoVoi, re-derives every content-addressed reference, verifies every
decision signature, and confirms the four protocol chains converge on one settlement.

  python verify_4proto.py keystone_4proto_pack.json

Exit code 0 iff every check passes. No network call is made; re-scan the transaction
on the public Base Sepolia explorer yourself to confirm the settlement is real.
"""
import sys, json, base64, hashlib

import rfc8785
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey

PROTOCOLS = ["x402", "mpp", "ap2", "a2a"]

def ref(obj):
    return "sha256:" + hashlib.sha256(rfc8785.dumps(obj)).hexdigest()

def b64u_dec(s):
    return base64.urlsafe_b64decode(s + "=" * ((-len(s)) % 4))

def verify_decision_signature(sig, decision_obj):
    """Verify the compact EdDSA JWS and confirm it covers the exact decision object."""
    pk = Ed25519PublicKey.from_public_bytes(base64.b64decode(sig["authority_pubkey_b64"]))
    h, p, s = sig["jws"].split(".")
    pk.verify(b64u_dec(s), f"{h}.{p}".encode())          # raises on a bad signature
    payload = json.loads(b64u_dec(p))
    return payload == decision_obj

def main(path):
    pack = json.load(open(path, encoding="utf-8"))
    checks = []
    def ck(name, ok): checks.append((name, bool(ok))); print(f"  [{'PASS' if ok else 'FAIL'}] {name}")

    tx = pack["tx"]
    settlement_ref = pack["settlement"]["settlement_ref"]
    ck("settlement_ref == sha256:JCS(settlement_attestation)",
       ref(pack["settlement"]["attestation"]) == settlement_ref)
    ck("passport_ref recomputes",
       ref(pack["passport_object"]) == pack["protocols"]["x402"]["passport_ref"])
    ck("compose timestamp precedes settlement block",
       pack["compose_ts_ms"] / 1000.0 < pack["settlement_block"]["timestamp_s"])

    seen_settlement, mandate_refs, tq_refs = set(), set(), set()
    for proto in PROTOCOLS:
        c = pack["protocols"][proto]
        ck(f"[{proto}] mandate_ref recomputes", ref(c["mandate_object"]) == c["mandate_ref"])
        ck(f"[{proto}] policy_bound_ref recomputes", ref(c["policy_object"]) == c["policy_bound_ref"])
        ck(f"[{proto}] decision_ref recomputes", ref(c["decision_object"]) == c["decision_ref"])
        ck(f"[{proto}] execution_ref recomputes", ref(c["execution_object"]) == c["execution_ref"])
        ck(f"[{proto}] mandate embeds passport_ref",
           c["mandate_object"].get("passport_ref") == c["passport_ref"])
        ck(f"[{proto}] policy embeds mandate_ref",
           c["policy_object"].get("mandate_ref") == c["mandate_ref"])
        ck(f"[{proto}] decision embeds policy_bound_ref",
           c["decision_object"].get("policy_bound_ref") == c["policy_bound_ref"])
        ck(f"[{proto}] execution embeds decision_ref",
           c["execution_object"].get("decision_ref") == c["decision_ref"])
        ck(f"[{proto}] execution binds shared settlement_ref + this tx",
           c["execution_object"].get("settlement_ref") == settlement_ref
           and c["execution_object"]["settlement"]["tx_id"] == tx)
        ck(f"[{proto}] decision signature valid + covers decision object",
           verify_decision_signature(c["decision_signature"], c["decision_object"]))
        seen_settlement.add(c["settlement_ref"]); mandate_refs.add(c["mandate_ref"]); tq_refs.add(c["trust_query_ref"])

    ck("all four protocols converge on ONE settlement_ref", seen_settlement == {settlement_ref})
    ck("four protocol-distinct mandate_refs", len(mandate_refs) == 4)
    ck("four protocol-distinct trust_query_refs", len(tq_refs) == 4)

    passed = sum(1 for _, ok in checks if ok)
    print(f"\n{passed}/{len(checks)} checks pass  (tx {tx})")
    print(f"settlement_ref {settlement_ref}")
    return 0 if passed == len(checks) else 1

if __name__ == "__main__":
    sys.exit(main(sys.argv[1] if len(sys.argv) > 1 else "keystone_4proto_pack.json"))

Two-way binding: why it cannot be faked

A transaction on an explorer proves money moved. It does not, by itself, prove the payment went through the Keystone. The binding runs both directions:
  • Keystone to transaction. execution_ref is a hash over the signed decision plus the settlement, so the chain commits to that exact transaction. Recompute it and it matches.
  • Transaction to Keystone. The decision is Ed25519 signed and its timestamp precedes the settlement block, and the on-chain amount, asset, and recipient match the signed decision. So the transaction cannot be re-bound to any other decision, and the decision provably existed before the money moved.

Verify it yourself

Every check is offline and deterministic. It needs only SHA-256, JSON Canonicalisation (RFC 8785), and the public chain.
  1. Recompute each reference: ref == "sha256:" + SHA-256(JCS(object)).
  2. Verify the decision signature against the published authority key, and confirm it covers the exact decision object.
  3. Recompute execution_ref and confirm it contains the transaction id.
  4. Re-scan the transaction on the public chain and confirm the USDC transfer to the merchant for the decided amount.
  5. Confirm the decision timestamp precedes the settlement block.
No trust in AlgoVoi is required. The chain is open and the two standards it rests on, SHA-256 and RFC 8785, are all you need.