Skip to main content

Layer 6 · The dig RPC — the machine interface

Canonical reference: hub services/retrieval/src/bin/bootstrap.rs (the canonical rpc.dig.net server); 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.

Machine-readable specs (regenerated from the implementation)

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.
  • params is always by-name; id is 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).

2 · Method catalogue (network profile)

The canonical server implements (bootstrap.rs:453-461):

MethodReturns
dig.getContenta chunk object of one resource's ciphertext
dig.getProofthe REAL sync inclusion proof + execution-proof status
dig.getProofStatusa REAL execution-proof job by id
dig.getCapsule (alias dig.getModule)the whole .dig for (store, root)
dig.getManifestthe public discovery manifest resource
dig.getMetadatathe plaintext metadata manifest (no proof, never encrypted)
dig.listCapsulesthe confirmed capsule list (discovery metadata)
dig.health, dig.methodsservice / capability discovery (authoritative for agent self-describe)

Unknown method → -32601.

Identifiers

All lower-case hex on the wire.

IdentifierFormMeaning
store_id64 hexthe CHIP-0035 singleton launcher id
retrieval_key64 hexSHA-256(urn) — the only URN-derived value sent to a node; the AES key is derived client-side and never transmitted
root64 hex | "latest" | absenta 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):

FieldTypeMeaning
ciphertextb64 stringthis window's bytes
total_lengthuintfull resource ciphertext length (pre-windowing)
offsetuintwindow start
lengthuintthis window's byte length
completebooloffset + len >= total_length
next_offsetuint | nullnext offset, or null when complete
inclusion_proofb64 | nullmerkle proof of the whole resource, relayed verbatim. Present every window on getContent/getManifest; empty/null on getCapsule
chunk_lensuint[]per-chunk ciphertext lengths of the full resource. First window only (offset == 0); empty ⇒ single chunk
program_hash64 hexSHA-256(.dig bytes) — the on-chain program identity
root64 hexthe resolved generation root
There is NO decoy field on the wire

A 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

  1. Loop dig.getContent with offset, length = 3 MiB until complete || next_offset == null; reassemble by total_length.
  2. Keep the first inclusion_proof and the first chunk_lens.
  3. verifyInclusion(ciphertext, proof, root) against the CALLER-supplied chain-anchored root — the host is never the trust anchor (see Verification).
  4. Split the reassembled ciphertext by chunk_lens and AES-256-GCM-SIV-open each chunk.

Range / window math

length is clamped to 3 MiB (RPC_MAX_CHUNK), then the requested range is 64-KiB up-aligned (align_range): start rounded down to 64 KiB, end up to the next 64-KiB boundary − 1; rejected if the aligned span > 16 MiB. So a window may be up to 3 MiB + ~64 KiB — document the effective size, not the imprecise "3 MiB" cap (range.rs:38-61). Alignment bounds the cache-key range cardinality (anti-amplification). Full-200 slice semantics (no HTTP 206).

5 · Error model

Standard JSON-RPC -32700 / -32600 / -32601 / -32602 / -32603, plus the protocol-specific:

CodeMeaning
-32004Resource not available at the requested root — a genuine infra miss (no host seed, module absent in both buckets, bad magic, oversize, a wasmtime trap, an undecodable envelope). Returned by getContent/getProof/getCapsule/getManifest/getMetadata. Distinct from a content miss, which is an indistinguishable decoy and never an error.

See the full error catalog.

6 · Proof surface

dig.getProof always returns the REAL synchronous inclusion_proof + program_hash + root. The execution_proof (risc0) is read-only / job-based: null with execution_proof_status = "request_via_control_plane" unless a proof_id (requested via the gated hub /v1 control plane) resolves a job. dig.getProofStatus polls the real job. Never a mock receipt on the wire. See inclusion vs execution proofs.

7 · Node profile

The local dig-node / dig-companion that the DIG Browser runs in-process (FFI) is rpc.dig.net-compatible but implements a different, smaller subset (dig-node/src/lib.rs:1121-1297):

  • Of the byte methods, only dig.getContent (local-first: cached .dig → §21.9 whole-store sync → proxy upstream). Everything else proxies or returns -32601.
  • Plus node-only methods the security model depends on:
    • dig.getAnchoredRoot — resolves the CHIP-0035 on-chain head via coinset.org (lib.rs:721-743); the trusted root for mandatory root-pinning.
    • dig.stage — compiles a local folder into a capsule .dig in-process (lib.rs:768-904).
    • cache.*getConfig/setCapBytes/clear/listCached/removeCached/fetchAndCache (lib.rs:1143-1231).

An agent gates on dig.methods rather than assuming one uniform surface — hence two OpenRPC documents (network + node).