Verification and securityVerify a decision
Verify a decision
Check a decision against Exchain's signed journal and the Cardano mainnet anchor, and read a wallet's signed worst case.
Check any decision yourself, three ways from quickest to strongest, and read the wallet's signed worst case.
What each method proves
| Method | Needs | Proves | Does not prove |
|---|---|---|---|
| Journal page in the browser | Nothing | Merkle path to the wallet root, the wallet root's Ed25519 signature, the path to the run root; shows the anchor | Does not recompute the leaf; does not check the anchor on chain |
exchain-verify | The decision JSON (token-gated), the wallet root, publisher.json | Recomputes the leaf, matches it to the request, checks inclusion and the signed root | Does not check the run-root path, the anchor transaction or auditHead |
| Manual anchor check | A Cardano mainnet explorer | The run root is in a Cardano mainnet transaction under metadata label 1958 | — |
The journal's layers and files: Journal. x402 sellers check a payment's guard receipt: Guard receipt.
In the browser
Search a decision id, wallet id or transaction hash on journal.exchain.network. The status shows how far the decision is committed:
| Status | Meaning |
|---|---|
pending | No root includes the decision yet |
signed | In a signed wallet root; no anchor has landed for its run yet |
anchored | Its own run is anchored on Cardano mainnet |
covered | A later run's anchor is the first to land after this decision's run |
With exchain-verify
Ask Exchain for the exchain-verify binary.
Get the inputs
| Input | Where |
|---|---|
| Decision | GET /v1/decisions/{decisionId} with a node or read token, or proofs/<decisionId>.json from the evidence bundle |
| Root | https://journal.exchain.network/<walletId>/<epoch>.json (the decision's proof.epoch), or latest.json |
| Key | https://journal.exchain.network/publisher.json |
Run it
exchain-verify \
--decision decision.json \
--root wal_01J9XK3M4N5P6Q7R8S9T0V1W2Z/42.json \
--publisher publisher.json \
--offline--offline refuses any http(s):// source.
Read the output
decision dec_01J9XK3M4N5P6Q7R8S9T0V1W2X wallet wal_01J9XK3M4N5P6Q7R8S9T0V1W2Z outcome ALLOWED
leaf recomputed == proof.leaf
request 1 intent(s) == bound members (purchase, output, amount, asset, counterparty, job, agent)
inclusion index 3 of 8 path 3 root 9c1f… OK
root epoch 42 published 2026-11-05T10:00:00Z signature OK (publisher <key hash>)
anchor tx <anchor tx hash> slot <slot> (verify on any explorer)
VERIFIED no access to Masumi or Exchain was required| Exit code | Meaning |
|---|---|
0 | Verified |
2 | Mismatch. The failing line ends in FAIL and the tool prints NOT VERIFIED |
1 | Usage, read or parse error, or the decision has no proof yet |
The anchor line is informational: check it on chain with the next section.
Check the anchor on Cardano
Find the run root
Take proof.globalRoot from the journal's decision file d/<decisionId>.json, or the root of the matching entry in anchors.json.
Read the anchor metadata
The anchor is a Cardano mainnet transaction with metadata label 1958. Open it on any explorer and read { v: 1, root, walletCount, epochRange }: root must equal the run root.
Climb to the run root
Hash proof.walletRoot up proof.globalPath with SHA-256(left ‖ right), pairing a lone node with itself, and compare the result with the run root.
Bound statement
GET /v1/wallets/{walletId}/bound (node or read token) returns the wallet's worst case at one block, signed as a JWS by the journal key.
| Field | Meaning |
|---|---|
v, walletId, issuedAt | Statement version, the wallet, when it was signed |
rail, network, asset | cardano or x402; cardano:preprod, cardano:mainnet or eip155:<chainId>; the wallet's first governed asset |
slot or block | The Cardano slot or EVM block the statement was read at |
honest, worstCase, worstCaseParts | The honest-case amount, the worst-case amount, and the parts of the worst case |
assets[] | On Cardano, the same three amounts for each governed asset |
statement | The JWS over the statement |
On Cardano, worstCase is the lesser of what the wallet holds and what remains of the on-chain period limit (walletValue, periodRemaining). On an EVM Safe, it is the Safe's balance of the asset plus its Permit2 approval, plus the treasury's allowance per period when treasurySafe is set (safeBalance, permit2Approval, treasuryAllowancePerPeriod). Chain errors return 502 rpc_failed or 503 chain_unavailable.
Evidence bundle
GET /v1/wallets/{walletId}/evidence.zip?from=&to= with a node or read token returns a wallet's history for offline checks.
| File | Content |
|---|---|
README.txt, VERIFY.md | Instructions |
mandate.json | The mandate |
decisions.jsonl | Every decision in the range |
roots.jsonl | Every signed wallet root |
publisher.json | The publisher key |
proofs/<decisionId>.json | One proof per decision |
The default range is the last 30 days. Bundles over 50 MB return 413; narrow from and to.