dig-rpc-protocol 0.14.0

Canonical DIG-node JSON-RPC protocol: request/response types, the method enum + tier classification, the error-code taxonomy, and an OpenRPC 1.2.6 document generator. The single source of truth both DIG node implementations depend on. Pure types — no I/O, no async, no server logic. (Formerly dig-rpc-types.)
Documentation

dig-rpc-protocol

The canonical DIG-node JSON-RPC protocol (formerly dig-rpc-types) — the single source of truth both DIG node implementations (the digstore dig-node crate and the standalone dig-node binary) depend on instead of hand-rolling json!({…}) shapes and ad-hoc error codes.

Pure types: no I/O, no async, no server logic, no crypto. The dig-rpc server crate and the node implementations build on these types.

What's here

Module Contents
envelope JSON-RPC 2.0 request/response, RequestId, Version
error the canonical ErrorCode taxonomy, the RpcError envelope ({code, message, data:{code, origin}}), and the one constructor helper
method the Method enum — stable wire names, per-method Tier, the mTLS peer allowlist
tier the three access tiers (PublicRead / Peer / Control)
types every method's params + results, field-for-field with the canonical node
frames the shape-dispatched DHT + PEX peer wires
openrpc the OpenRPC 1.2.6 document generator (the single discovery source)

The full contract is in SPEC.md.

Full Protocol Interface (at-a-glance LLM reference)

All Methods (34 total)

Method Name Wire Name Tier Peer-Reachable Summary
GetContent dig.getContent PublicRead ✓ Read a verified window of a resource's ciphertext
GetCapsule dig.getCapsule PublicRead ✗ Fetch the whole .dig module for (store, root)
GetModule dig.getModule PublicRead ✗ Alias of dig.getCapsule
GetManifest dig.getManifest PublicRead ✗ Fetch the public discovery manifest resource
GetMetadata dig.getMetadata PublicRead ✗ Fetch the plaintext metadata manifest
ListCapsules dig.listCapsules PublicRead ✗ List a store's confirmed capsules
GetProof dig.getProof PublicRead ✗ Get the real inclusion proof + execution-proof status
GetProofStatus dig.getProofStatus PublicRead ✗ Poll a real execution-proof job by id
GetAnchoredRoot dig.getAnchoredRoot PublicRead ✓ Resolve a store's chain-anchored tip root
GetCollection dig.getCollection PublicRead ✓ Get collection-level facts for NFT launcher ids
ListCollectionItems dig.listCollectionItems PublicRead ✓ List resolved NFT collection items (paginated)
Health dig.health PublicRead ✗ Liveness and capability summary
Methods dig.methods PublicRead ✗ List the method names this node implements
GetNetworkInfo dig.getNetworkInfo Peer ✓ This node's peer-network posture
GetPeers dig.getPeers Peer ✓ The peers this node currently knows
Announce dig.announce Peer ✓ Accept a peer announcement (peer_id + addresses)
GetAvailability dig.getAvailability Peer ✓ Batch-check whether this node holds items
ListInventory dig.listInventory Peer ✓ Enumerate the stores / roots this node serves
FetchRange dig.fetchRange Peer ✓ Fetch a single verified range frame of a resource
GetModuleInfo dig.getModuleInfo Peer ✓ Get the whole-.dig-module transfer descriptor (size + hashes)
FetchModuleRange dig.fetchModuleRange Peer ✓ Fetch a single range frame of the whole .dig module blob
Stage dig.stage Control ✗ Compile a local folder into a capsule .dig in-process
CacheGetConfig cache.getConfig Control ✗ Get the local-cache configuration
CacheSetCapBytes cache.setCapBytes Control ✗ Set the local-cache size cap
CacheClear cache.clear Control ✗ Clear the local cache
CacheListCached cache.listCached Control ✗ List the durable cached modules
CacheRemoveCached cache.removeCached Control ✗ Remove one cached capsule
CacheFetchAndCache cache.fetchAndCache Control ✗ Fetch and cache one capsule
CacheStats cache.stats Control ✗ Cache telemetry: cap + usage, entry count + bytes, eviction + hit/miss
ControlPeerStatus control.peerStatus Control ✗ Snapshot the node's peer network
ControlSubscribe control.subscribe Control ✗ Subscribe the node to a store (persisted watch + gap-fill)
ControlUnsubscribe control.unsubscribe Control ✗ Unsubscribe the node from a store
ControlListSubscriptions control.listSubscriptions Control ✗ List the node's persisted store subscriptions
ControlPeersConnect control.peers.connect Control ✗ Dial a peer into the connected pool
ControlPeersDisconnect control.peers.disconnect Control ✗ Drop a pooled peer by peer_id
RpcDiscover rpc.discover Control ✗ Return the OpenRPC self-describe document

Access Tiers: PublicRead = anonymous content reads (HTTPS / mTLS). Peer = mTLS peer surface (node↔node). Control = loopback / in-process only.

Peer-Reachable Methods (12 total): dig.getContent, dig.getNetworkInfo, dig.getPeers, dig.announce, dig.getAvailability, dig.listInventory, dig.fetchRange, dig.getModuleInfo, dig.fetchModuleRange, dig.getAnchoredRoot, dig.getCollection, dig.listCollectionItems. All Control and non-peer PublicRead methods are never peer-reachable.

Error Codes (22 total)

Code Machine Code Origin Meaning
-32700 PARSE_ERROR Node Invalid JSON received
-32600 INVALID_REQUEST Node JSON is not a valid Request object
-32601 METHOD_NOT_FOUND Node Method does not exist / is not available
-32602 INVALID_PARAMS Node Invalid or missing method parameters
-32603 INTERNAL_ERROR Node Node failed to satisfy a well-formed call
-32000 SERVER_ERROR Node Generic server error (config/IO/chain failure)
-32004 RESOURCE_UNAVAILABLE Node Resource not available at requested root (genuine miss)
-32005 ROOT_NOT_ANCHORED Node Requested/served root is not chain-anchored (fail-closed)
-32006 PEER_UNREACHABLE Peer No NAT-traversal strategy reached the peer
-32007 RANGE_NOT_SATISFIABLE Node Byte range lies outside the resource
-32008 CONTENT_REDIRECT Node Content held elsewhere — data.redirect names holders
-32010 UPSTREAM_ERROR Upstream Upstream/proxy fetch failed
-32011 STAGE_INVALID_INPUT Node dig.stage: dir unreadable / walk budget exceeded
-32012 STAGE_NO_FILES Node dig.stage: no files to compile
-32013 STAGE_OVER_CAP Node dig.stage: input exceeds store cap
-32014 STAGE_COMPILE_FAILED Node dig.stage: compile / IO failure
-32015 METADATA_TOO_LARGE Node dig.getMetadata: metadata section over the bounded response ceiling
-32016 PUSH_PENDING_LIMITED Node cache.pushCapsule: pending-reassembly budget exhausted (retriable)
-32017 CONTENT_MISS_INCONCLUSIVE Peer Absence NOT established — a hop could not be consulted
-32020 ONION_CIRCUIT_UNAVAILABLE Onion Private read circuit could not be built/kept
-32021 PRIVACY_REQUIRES_LOCAL_NODE Onion Privacy mode requires local originator
-32022 ONION_HOPS_OUT_OF_RANGE Onion Hop count outside [2, 5]
-32030 UNAUTHORIZED Control Control-plane call not authorized (loopback gate failed)
-32031 NOT_SUPPORTED Control Control-plane method recognized but not supported
-32032 CONTROL_ERROR Control Control-plane runtime error
-32050 NO_IDENTITY Node No persistent identity key — cannot seal as sender
-32051 NO_PEER_NETWORK Peer No gossip pool — a directed send has no transport
-32052 SEND_FAILED Peer Seal or send failed

Error Origins: Node = node's own read/serve path. Peer = peer-network layer. Upstream = upstream fetch (proxy/whole-store sync). Onion = private-retrieval layer. Control = loopback control plane.

Request/Response Envelope

JSON-RPC 2.0 strict:

Request: {"jsonrpc":"2.0","id":<num|str>,"method":"<wire_name>","params":<object|null>}
Response: {"jsonrpc":"2.0","id":<num|str>,"result":<any>} | {"jsonrpc":"2.0","id":<num|str>,"error":{"code":<int>,"message":"<str>","data":{"code":"<UPPER_SNAKE>","origin":"<str>",...}}}

Error Envelope Structure:

{
  code: i32,                    // numeric wire code (e.g., -32004)
  message: String,              // human-readable summary
  data: {
    code: String,              // stable machine code (e.g., "RESOURCE_UNAVAILABLE")
    origin: String,            // subsystem (node/peer/upstream/onion/control)
    redirect?: RedirectInfo,   // present only on CONTENT_REDIRECT
    <extra fields>             // method-specific fields flattened
  }
}

Interface Version

INTERFACE_VERSION is not yet versioned in the wire (future work). The protocol evolves via additive Method variants and ErrorCode assignments; both are #[non_exhaustive] so a client match-arm default (_ => …) handles future extensions.

Error taxonomy at a glance

Standard JSON-RPC codes plus the DIG protocol codes. The onion codes -32020/-32021/-32022 are the published normative contract and keep their numbers; the control-plane codes are -32030/-32031/-32032.

use dig_rpc_protocol::{RpcError, ErrorCode, ErrorOrigin};

let e = RpcError::of(ErrorCode::ResourceUnavailable, "not at this root");
assert_eq!(e.code, ErrorCode::ResourceUnavailable);       // -32004
assert_eq!(e.data.code, "RESOURCE_UNAVAILABLE");          // stable branch key
assert_eq!(e.data.origin, ErrorOrigin::Node);

Method catalogue + discovery

use dig_rpc_protocol::{Method, Tier, openrpc_document};

assert_eq!(Method::GetContent.name(), "dig.getContent");
assert_eq!(Method::GetContent.tier(), Tier::PublicRead);
assert!(Method::GetContent.is_peer_reachable());
assert!(!Method::CacheClear.is_peer_reachable());          // control tier

let doc = openrpc_document(env!("CARGO_PKG_VERSION"));      // OpenRPC 1.2.6

Features

Flag Default Effect
schema-export off derive schemars::JsonSchema on every wire type (Go/TS codegen)

Testing

cargo test --all-features        # unit + conformance vectors
cargo llvm-cov --all-features    # coverage (CI-gated ≥80%)

Licensed under Apache-2.0 OR MIT.