R+3 is the export layer that turns thousands or millions of R+2 receipts into a single, signed, Merkle-rooted audit bundle — regulator-ready, optionally on-chain-anchored, and cryptographically verifiable end-to-end. Where R+2 makes every agent action signable, R+3 makes every audit period provable.
R+2 receipts are individually signed. They prove that a specific action occurred, was authorised, and has not been tampered with. They are emitted cheaply, automatically, and at high frequency — one per agent action.
But auditors do not consume single events. They consume periods. A compliance officer asks: "Show me everything Agent X did in Q1 2026, with proof that the record is complete and intact." A regulator asks: "Prove that no records were silently deleted between January and March." A Series-A investor asks: "Show me a verifiable settlement ledger across the last 90 days."
Answering those questions from raw R+2 receipts is feasible but expensive. The auditor would have to fetch every receipt, verify every signature, walk the hash chain, and trust that no receipts are missing. That is not how regulators work — and it does not scale beyond a few hundred receipts.
R+3 solves this by producing aggregate bundles. An R+3 export contains:
R+3 is strictly an aggregation and export layer on top of R+2. It introduces no new signing scheme for individual actions, no new cryptographic primitives, and no new identity model. R+2 receipts are the source data; R+3 exports are the bundled, signed, regulator-ready output.
┌──────────────────────────────────────────────────────────┐ │ R+3 · Audit Bundle │ │ Merkle root + signature + optional on-chain anchor │ Time-range aggregate over many R+2 receipts ├──────────────────────────────────────────────────────────┤ │ R+2 · Signed Action Receipt │ │ ed25519 + RFC 8785 canonical JSON + hash chain │ One receipt per agent action └──────────────────────────────────────────────────────────┘
An R+3 export does not modify R+2 receipts. It commits to them via Merkle root. R+2 receipts remain individually verifiable using the R+2 verification procedure (see /standard §6).
The key words MUST, MUST NOT, REQUIRED, SHALL, SHOULD, and MAY are interpreted as in BCP 14 [RFC 2119] and [RFC 8174].
| Term | Definition | Notes |
|---|---|---|
| Audit Bundle | A single R+3 export object covering a defined time range, optionally a defined principal or scope filter. | |
| Merkle Root | The 32-byte SHA-256 root of a binary Merkle tree whose leaves are the canonical hashes of the included R+2 receipts. | See §5 |
| Anchor | An on-chain transaction whose calldata contains the Merkle root of an R+3 bundle. | Optional but RECOMMENDED for sensitive audits |
| Issuer | The principal that signs the bundle. Typically the operator running the R+2-emitting agents. | |
| Bundle Sequence | A monotonically increasing integer identifying this bundle within an issuer's series. | Per-issuer counter |
| Predecessor Hash | The canonical hash of the immediately preceding R+3 bundle by the same issuer. | Forms an inter-bundle hash chain |
| Scope Filter | An optional clause restricting which R+2 receipts are included (by agent_id, action_type, or metadata predicate). | See §4.3 |
An R+3 bundle is a single canonical JSON document (per RFC 8785) with the following structure.
| Field | Type | Description | Required |
|---|---|---|---|
| version | string | Spec version. MUST be "r+3/0.1.0" for this version. | Yes |
| export_id | UUID | Globally unique identifier for this bundle. MUST be a UUIDv4. | Yes |
| issuer | DID | Decentralised identifier of the issuing principal. Format did:dcs:base:<identifier> or did:web:<host>. | Yes |
| sequence | uint64 | Bundle sequence number for this issuer, starting at 1 and incrementing by 1 for each subsequent bundle. | Yes |
| predecessor_hash | string | SHA-256 hash of the previous bundle by this issuer, formatted "sha256:<hex>". The genesis bundle MUST use "sha256:0000…0000". | Yes |
| time_range | object | UTC start and end timestamps that define the inclusion window. See §4.2. | Yes |
| scope | object | OPTIONAL filter restricting which R+2 receipts are included. See §4.3. | No |
| receipts_count | uint64 | Number of R+2 receipts committed to by merkle_root. | Yes |
| merkle_root | string | SHA-256 root of the receipt Merkle tree, formatted "sha256:<hex>". | Yes |
| merkle_construction | string | MUST be "binary-sha256-rfc8785" for this version. | Yes |
| anchor | object | OPTIONAL on-chain anchor. See §7. | No |
| bundle_uri | string | URI where the full receipt list and Merkle path table can be fetched. SHOULD be IPFS for permanence. | Yes |
| signature | object | Ed25519 signature over the canonicalised bundle, excluding the signature field itself. | Yes |
The time_range object SHALL contain:
from — RFC 3339 UTC timestamp of the inclusive start of the audit windowto — RFC 3339 UTC timestamp of the exclusive endThe bundle MUST include every R+2 receipt where from ≤ receipt.timestamp < to, subject to scope. The bundle MUST NOT include receipts outside this window.
An optional scope object MAY filter the included receipts. Defined filter types:
agent_id — list of DIDs to includeaction_type — list of dotted action-type prefixes (e.g. "treasury.", "memory.write")regulatory_scope — list of scope tags (e.g. "gdpr", "hipaa", "dpdp")If scope is absent, all receipts in the time window MUST be included. If scope is present, the filter rules apply with OR semantics within a field and AND across fields.
(issuer, sequence) tuple. Auditors MAY treat any conflicting bundle as evidence of tampering.
R+3 v0.1 uses a deterministic binary SHA-256 Merkle tree with RFC 8785-canonicalised leaves.
For each R+2 receipt to be included:
signature field, which is already part of the canonical content of the signed receipt — verifiers MUST canonicalise the receipt including its signature for the leaf hash)leaf_hash = SHA-256(canonical_bytes)For internal nodes, concatenate the left and right child hashes as raw bytes and hash:
pair_hash = SHA-256(left_hash || right_hash)
If a level has an odd number of nodes, the final node MUST be duplicated. (Equivalent to Bitcoin Merkle tree construction.)
Leaves MUST be ordered by:
receipt.timestampreceipt.action_id (UUIDv4 lexicographic)This ordering is deterministic and reproducible by any verifier with access to the receipt set.
An R+3 bundle with receipts_count = 0 is permitted (e.g. for "no activity in this period" audits). The merkle_root for an empty bundle SHALL be "sha256:0000000000000000000000000000000000000000000000000000000000000000".
R+3 bundles are signed using Ed25519 (RFC 8032). The signature commits to the canonical JSON of the entire bundle object except the signature field.
signature field if presentsignature to the structure below"signature": { "alg": "ed25519", "key_id": "did:dcs:base:issuer-prod#auditor-key-2026-05", "sig": "<base64url-encoded 64-byte signature>" }
The key_id MUST resolve to a public key via DID Document resolution. R+3 verifiers SHOULD cache the resolved public key for the duration of the bundle's signature validity.
An R+3 bundle MAY include an anchor object recording an on-chain transaction whose calldata contains the bundle's merkle_root. This makes the bundle's commitment publicly verifiable forever, independent of the issuer.
"anchor": { "chain": "base-mainnet", "tx_hash": "0x61f6d9019dd3503eafdc5ffc0f0335f05abce8bf19ac50d4e78369226a7211a1", "block_number": 12345678, "contract": "0xbDd1f5fC349D9a8EfCEb07Edbd491233b2540f5F", "method": "anchorMerkleRoot(bytes32,bytes32)", "params": { "root": "0xabc...123", "export_id": "0xdef...456" } }
A verifier with on-chain access SHOULD:
tx_hashcontract with method methodparams.root matches the bundle's merkle_root (modulo the sha256: prefix)The reference anchor contract on Base mainnet accepts (bytes32 root, bytes32 export_id) tuples and emits an AnchorAdded event. The contract is intentionally minimal: it stores nothing and verifies nothing. The on-chain record exists only to make the calldata indelibly visible.
To verify an R+3 bundle:
signature.key_id to a public key via DID Document resolutionsignature, canonicalise the bundle, and verify the Ed25519 signaturepredecessor_hash matches the canonical hash of the previous bundle in the issuer's series (or is the genesis zero hash)anchor is present, perform anchor verification per §7.2To prove that a specific R+2 receipt is included in an R+3 bundle:
bundle_urimerkle_rootA successful verification proves: (a) the bundle was signed by the claimed issuer, (b) the receipt was committed to in this bundle, (c) the receipt itself is signed and untampered. If an on-chain anchor is present and verified, the bundle is independently verifiable without trusting the issuer.
A reference implementation is published as @trdnetwork/r2-verify on npm. The R+3 verification commands include:
npx r2-verify r3-bundle <bundle.json> # full bundle verification npx r2-verify r3-inclusion <bundle.json> <receipt.json> # proof of inclusion npx r2-verify r3-anchor <bundle.json> # on-chain anchor verification
If an issuer's Ed25519 private key is compromised, an attacker can sign forged R+3 bundles. R+3 mitigates this with:
predecessor_hash chain — any forged bundle disrupts the chain and is detectable by any verifier holding earlier bundlesAn issuer might attempt to silently omit R+2 receipts from a bundle (selective non-disclosure). R+3 v0.1 does not prevent this — it only proves that the included receipts are committed to. Future revisions of R+3 will define completeness assertions via anchored receipt counts and gap-detection challenges.
All hashing and signing MUST use RFC 8785 canonicalisation. Implementations that deviate (e.g. by sorting keys differently or using non-UTF-8 encodings) will produce verification failures.
An R+3 bundle is uniquely identified by (issuer, sequence). Replayed bundles fail uniqueness checks at the verifier. Bundle predecessor-hash chaining additionally prevents reordering attacks.
R+3 bundles contain commitments (hashes) to R+2 receipts, not the receipts themselves. The receipt content is referenced through bundle_uri and MAY be access-controlled.
An issuer MAY publish the Merkle root and signature publicly (or anchor on-chain) while keeping the receipt contents behind authentication. A regulator with credentials retrieves the receipts; the public sees only the commitment.
For receipts referencing PHI, PII, or other regulated data, the underlying R+2 receipt MAY use the payload_hash_only mode (R+2 §7) where the receipt commits to a hash of the payload rather than the payload itself. R+3 bundles built from such receipts are publishable without revealing the underlying data.
When a data subject requests erasure under GDPR Article 17, the issuer SHALL:
erased via a follow-up R+2 receipt referencing the original by action_idThis satisfies erasure (the payload is gone) while preserving the auditability of the erasure act itself (regulators can prove that erasure was performed).
R+3 bundles are designed to satisfy specific audit-export requirements in major regulatory regimes.
| Regulation | Requirement | R+3 mechanism | Profile |
|---|---|---|---|
| EU AI Act Art. 12 | Logging of high-risk AI system events; retention > 6 months; tamper-evident | R+3 bundles emitted at least daily, anchored on-chain, retained > 6 months | r2-gov-v1 |
| NIST AI RMF GOVERN-1.4 | Reproducible audit trail of AI system decisions | Merkle-root commitment + Ed25519 signature + on-chain anchor | r2-gov-v1 |
| India DPDP §8(4), §8(5) | Accuracy + safeguard duties demonstrable on request | R+3 bundle plus scope-filtered receipt retrieval | r2-gov-v1 |
| HIPAA Security Rule | Audit controls (45 CFR 164.312(b)) — record and examine activity | R+3 bundles with payload-hash-only receipts; PHI never appears in commitments | r2-health-v1 |
| SOX §404 (US) | Internal controls over financial reporting; auditor-attestable | R+3 bundles scoped to finance.* action types, anchored monthly |
r2-finance-v1 |
| RBI Master Direction on IT Outsourcing | Operational risk audit logs available to regulator on demand | R+3 export endpoint, scope-filtered by regulatory_scope tag | r2-finance-v1 |
| UAE Data Office (forthcoming AI guidance) | Demonstrable accountability for autonomous system actions | R+3 bundles + on-chain anchor; recipient-government can audit independently | r2-gov-v1 |
| ISO/IEC 42001:2023 (AI Management Systems) | Documented evidence of AI system operation | Periodic R+3 bundles per AI management procedure | — |
A complete, signed, anchored R+3 bundle covering one day of treasury activity:
{
"version": "r+3/0.1.0",
"export_id": "7d8e3a1c-2f4b-4d9e-8a5c-1234567890ab",
"issuer": "did:dcs:base:treasury-prod",
"sequence": 42,
"predecessor_hash": "sha256:9f8e7d6c5b4a3a2918073625140312fffeeddccbba99887766554433221100",
"time_range": {
"from": "2026-05-20T00:00:00Z",
"to": "2026-05-21T00:00:00Z"
},
"scope": {
"action_type": ["treasury.settle"],
"regulatory_scope": ["dpdp", "sox"]
},
"receipts_count": 1,
"merkle_root": "sha256:c4f7b9a2e3d1f5c8a7b6e4d9c2f1e0a3b8c5d4e7f2a1b0c3d6e9f8a7b4c5d2e1",
"merkle_construction": "binary-sha256-rfc8785",
"anchor": {
"chain": "base-mainnet",
"tx_hash": "0x61f6d9019dd3503eafdc5ffc0f0335f05abce8bf19ac50d4e78369226a7211a1",
"block_number": 12345678,
"contract": "0xbDd1f5fC349D9a8EfCEb07Edbd491233b2540f5F",
"method": "anchorMerkleRoot(bytes32,bytes32)"
},
"bundle_uri": "ipfs://bafybeih...",
"signature": {
"alg": "ed25519",
"key_id": "did:dcs:base:treasury-prod#auditor-key-2026-05",
"sig": "BASE64URL_ENCODED_SIGNATURE_BYTES_HERE"
}
}
0x61f6d9…211a1) and any subsequent settlements through end of May. Anchor planned on Base mainnet at end of period.
anchor.chain field accepts any chain identifier per CAIP-2. Reference contracts are deployed on Base mainnet. We will accept contributions for Ethereum mainnet, Optimism, Arbitrum, and Polygon reference contracts on the GitHub repo.bundle_uri can be any URI. IPFS is RECOMMENDED for permanence, but operators MAY use HTTPS, Filecoin (via IPFS gateways), Arweave, or self-hosted endpoints. The cryptographic guarantees depend on the bundle content, not on where it is stored.@trdnetwork/r2-verify reference implementation includes a r3-build helper command that performs all three steps given a directory of R+2 receipts.trd-cn-backend are the first reference server implementation of R+3. They accept a time range, retrieve the relevant R+2 receipts, build the Merkle tree, sign the bundle with the operator key, and return the JSON. Anchor submission is a separate operator action.