Skip to main content

Store Structure

A store has an identity, a history of generations, and a compiled module. This page covers each.

Store identity

A store is identified by a 64-hex store id:

store_id = SHA-256(store's BLS public key)

This makes the id self-certifying: anyone who learns a store id can later check that a module claiming that id embeds a public key whose hash equals it. The id is curried into every URN that references the store and is the only mandatory addressing component. The matching private key is what signs the store's published roots.

Generations and root hashes

Every commit seals the current content into a new generation, identified by a root hash — the Merkle root over the generation's per-resource leaves.

TermMeaning
GenerationA store state identified by a root hash, with a monotonic ordinal id
Root hashMerkle root over the generation's per-resource leaves
Root historyAppend-only list of every root hash the store has produced

Each commit produces exactly one new generation, one new module file, and one new root hash. History grows monotonically — like Git. Any past root hash can be quoted in a URN to address the store at that generation; omit it to address the current one.

digstore log            # list generations (each root hash is a commit)
digstore diff <a> <b> # what changed between two roots

The content root

Unlike Git, a store doesn't track a source tree — it captures a content root: a build-output directory.

  • Default content root is the current directory.
  • Set it at creation with digstore init --dir <path>, or later with digstore dir <path>.
  • Override it for a single command with -C/--cwd <path>.

Resource keys are always relative to the content root, so a URN is stable no matter which subdirectory you run a command from.

On-disk layout

A project lives in a .dig/ directory, the way a Git repo lives in .git/. It holds the store configuration, the append-only root history, the per-generation chunk pools and manifests, and the compiled module(s). Commands discover the .dig/ workspace by walking up from wherever you run them.

A single .dig/ workspace can hold many stores ("capsules"), each with its own content, keys, and history. See Project Workflow.

The compiled module

When you commit, the content and a small serving program compile into a single .wasm. It embeds:

  • Encrypted content — every resource's chunks, sealed with AES-256-GCM-SIV (see URNs & Encryption).
  • A key table — maps each resource's retrieval key to the ordered chunk indices that reassemble it.
  • The Merkle tree — one leaf per resource, rooting at the generation's root hash (see Proofs & Security).
  • The serving program — answers "give me the bytes for this URN" via a fixed host/module ABI, and nothing else.
  • Trusted host keys — the module refuses to serve content to a host that can't attest to one of these keys; an un-attested host receives only decoys.

The whole module is padded to a uniform size so its byte length reveals nothing about how much content it actually holds. Each store is capped at 128 MB of staged content, enforced at add (and defensively at commit).

Next: URNs & Encryption →