Layer 6 · The dig RPC — the machine interface
Canonical reference: hub
services/retrieval/src/bin/bootstrap.rs(the canonicalrpc.dig.netserver);dig-node/src/lib.rs(the node profile). The §21 REST routes are its transport sibling.
The dig RPC is the single, agent-consumable network surface of the protocol — the only way content is read. JSON-RPC 2.0 over HTTPS POST to a single endpoint. There is no CDN.
- Network profile:
openrpc.json - Node profile:
openrpc-node.json - Cross-surface error catalog:
error-codes.json
Both OpenRPC documents are generated from one source of truth and are intended to be CI-diffed against live server responses, so an agent can drive the protocol without scraping prose. The verified browser client dig-client-wasm is pinned by an SRI digest.
1 · Transport envelope
POST https://rpc.dig.net
Content-Type: application/json
{ "jsonrpc": "2.0", "id": <id>, "method": "<name>", "params": { … } }
- A single request object OR a non-empty batch array (each element dispatched independently, re-collected into a response array) —
bootstrap.rs:515-525. paramsis always by-name;idis echoed.- Any well-formed JSON body → HTTP 200; success/error rides in the JSON-RPC envelope.
- CORS
*, no credentials (content is public ciphertext);OPTIONS→ 204 (bootstrap.rs:468).
rpc.dig.net and this network profile ARE the anonymous, browser-reachable public read tier of the dual-transport model: no client certificate, CORS-*, read-only, decoy-on-miss, and integrity self-verified client-side against the chain-anchored root. The peer / write / config / control surface (peer exchange, DHT, PEX, availability-for-sync, PUSH/WRITE, node control) lives on the separate mTLS peer/control tier and is never reachable here — see the tier map.
2 · Method catalogue (network profile)
The canonical server implements (bootstrap.rs:453-461):
| Method | Returns |
|---|---|
dig.getContent | a chunk object of one resource's ciphertext |
dig.getProof | the REAL sync inclusion proof + execution-proof status |
dig.getProofStatus | a REAL execution-proof job by id |
dig.getCapsule (alias dig.getModule) | the whole .dig for (store, root) |
dig.getManifest | the public discovery manifest resource |
dig.getMetadata | the plaintext metadata manifest (no proof, never encrypted) |
dig.listCapsules | the confirmed capsule list (discovery metadata) |
dig.listCollectionItems | an NFT collection's items resolved to their current on-chain owner + royalty + CHIP-0007 metadata (paginated) |
dig.getCollection | collection-level facts (creator DID, item count, uniform royalty) for a set of NFT launcher ids |
dig.health, dig.methods | service / capability discovery (authoritative for agent self-describe) |
Unknown method → -32601.
Identifiers
All lower-case hex on the wire.
| Identifier | Form | Meaning |
|---|---|---|
store_id | 64 hex | the CHIP-0035 singleton launcher id |
retrieval_key | 64 hex | SHA-256(urn) — the only URN-derived value sent to a node; the AES key is derived client-side and never transmitted |
root | 64 hex | "latest" | absent | a generation root; "latest"/absent → newest confirmed generation. root_is_pinned gates caching — only an explicit concrete root is immutable/cacheable |
| capsule identity | <store_id>:<root> | one immutable generation |
3 · The chunk wire object
Every byte method returns this object (rpc_chunk_result, bootstrap.rs:650-675):
| Field | Type | Meaning |
|---|---|---|
ciphertext | b64 string | this window's bytes |
total_length | uint | full resource ciphertext length (pre-windowing) |
offset | uint | window start |
length | uint | this window's byte length |
complete | bool | offset + len >= total_length |
next_offset | uint | null | next offset, or null when complete |
inclusion_proof | b64 | null | merkle proof of the whole resource, relayed verbatim. Present every window on getContent/getManifest; empty/null on getCapsule |
chunk_lens | uint[] | per-chunk ciphertext lengths of the full resource. First window only (offset == 0); empty ⇒ single chunk |
program_hash | 64 hex | SHA-256(.dig bytes) — the on-chain program identity |
root | 64 hex | the resolved generation root |
decoy field on the wireA non-present resource yields the .dig's own indistinguishable, non-verifying response (the decoy, same shape) — the client discovers non-presence only by inclusion-proof failure and/or decryption failure. The absence of a decoy field is regression-locked (bootstrap.rs:2830); the in-process node additively tags source ("local"/"remote") but never a decoy.
4 · Streaming + client contract
- Loop
dig.getContentwithoffset,length = 3 MiBuntilcomplete || next_offset == null; reassemble bytotal_length. - Keep the first
inclusion_proofand the firstchunk_lens. verifyInclusion(ciphertext, proof, root)against the CALLER-supplied chain-anchored root — the host is never the trust anchor (see Verification).- Split the reassembled ciphertext by
chunk_lensand AES-256-GCM-SIV-open each chunk.