Skip to main content

Layer 2 · Capsule format — the DIGS data section

Canonical reference: digstore-core::datasection (BINDING contract D1, the single source of truth). The module that carries this blob is described in The self-defending module.

The DIGS blob byte layout

All multi-byte integers are BIG-ENDIAN (datasection.rs:9-18):

magic    "DIGS"              (4 bytes)
version u8 = 1 (1 byte)
count u32 BE (4 bytes)
rows count × 10 bytes: id:u16 BE | offset:u32 BE | len:u32 BE (offset/len relative to byte 0)
bodies concatenated section bodies

total_len = max(offset+len)self-describing, no terminator. HEADER_LEN = 9, ROW_LEN = 10. DataView::parse validates the magic, version == 1, and that every row lies within raw (datasection.rs:127-181).

Big-endian framing

All multi-byte integers are big-endian, matching Chia's streamable framing so the capsule shares one codec with the rest of the Chia-side wire formats.

SectionIds

SectionId is a u16 (datasection.rs:60-75). The compiler emits sections in ascending id order, and pushes ChainState (12) before Filler (11) so Filler stays the trailing / highest-offset body (data_section.rs:92-124).

idSectionBody
1StoreId32 raw bytes
2CurrentRoot32 raw bytes (the per-resource merkle root, D5)
3RootHistoryVec<Bytes32> = u32 BE count + raw 32B each
4PublicKey48 raw bytes (BLS G1)
5TrustedKeysu32 BE count, per entry [u8;48] pubkey + String label (u32 BE len + utf8)
6MetadataMetadataManifest (plaintext)
7AuthInfoAuthenticationInfo { requires_session, requires_jwt, jwks_url, accepted_algorithms }
8KeyTable (D3)see below
9ChunkPool (D4)see below
10MerkleNodes (D5)u32 BE count + count×32 raw — the per-resource leaves, ascending by static_key
11Fillerunreferenced ChaCha20 padding (self-defending module)
12ChainStateon-chain anchor pointer (see below)

KeyTable (8, D3)

u32 BE count, per entry:
static_key(32) | generation(32) | chunk_indices(Vec<u32>: u32 BE count + u32 BE each) | total_size(u64 BE)

lookup_key linear-scans for static_key == retrieval_key (keytable.rs:9-34, datasection.rs:200-227).

ChunkPool (9, D4)

u32 BE count, per chunk:  len:u32 BE | ciphertext

Chunks are in global index order (the order chunk_indices address into). Filler is NOT interleaved, so indexing stays exact (datasection.rs:229-282).

ChainState (12) — the on-chain anchor pointer

version:u8 | network(u32 len+utf8) | launcher_id(32) | coin_id(32)
| confirmed_height:u32 BE | tx_id(u32 len+utf8) | coinset_url(u32 len+utf8)

coinset_url is a hint only (callers override). VERSION = 1 (datasection.rs:323-422). This pointer lets a client resolve the on-chain head for anchored-root pinning.

Body codec note

The compiler carries a local codec for TrustedKeys because the core TrustedHostKey has no Encode/Decode (data_section.rs:58-73; guest decode content.rs:108-133). Metadata is the plaintext MetadataManifest; AuthInfo gates the serving guest.