dig_store/lib.rs
1//! # dig-store — the DIG Network DataLayer store manager
2//!
3//! A **store** is the composition of two planes:
4//!
5//! - an **on-chain anchor** — a CHIP-0035 DataLayer singleton (owned by
6//! [`dig-merkle`](https://github.com/DIG-Network/dig-merkle)) whose metadata carries the `.dig`
7//! merkle root plus its label / description / size bucket / program hash; and
8//! - an **off-chain data plane** — the `.dig` capsule format (owned by
9//! [`dig-capsule`](https://github.com/DIG-Network/dig-capsule)).
10//!
11//! `dig-store` composes the two into ONE curated abstraction, with three concerns:
12//!
13//! 1. **Lifecycle** — a store is a coin that gets SPENT: [`create_store`], [`modify_store`],
14//! [`melt_store`]. Each returns an UNSIGNED [`MerkleCoinSpend`]; the wallet-backend / node signs +
15//! broadcasts. `dig-store` never holds a key, never signs, never dials the network.
16//! 2. **Size proof** — a store anchors its `.dig` SIZE on chain as a power-of-2 [`SizeBucket`]
17//! (1 MB..1 GB, NC-8 minimal encoding). Before keeping a downloaded `.dig`, a client runs
18//! [`SizeProof::verify`]: a real size that does not match the anchored bucket is
19//! [`SizeVerdict::Discard`]ed — a dig-node MUST NOT store or serve a size-mismatched capsule.
20//! 3. **Getters** — a comprehensive read surface over both planes:
21//! - **on-chain** (chain-proven, NC-9): [`get_store_did_owner`], [`get_store_singleton_tip`],
22//! [`get_root_history`], [`get_latest_root`], [`get_latest_root_urn`], [`get_store_urn`], the
23//! label / description / size / program-hash getters, and [`get_store_status`] — the aggregate
24//! status snapshot from ONE consistent lineage walk;
25//! - **off-chain** (from a compiled `.dig` module's bytes, wasmtime-free): [`get_capsule_identity`]
26//! recovers a capsule's declared `(store_id, root_hash)`, and [`open_capsule`] additionally
27//! cross-checks the declared `store_id` against a trusted anchor (fail-closed).
28//!
29//! The coin/identity types ([`Bytes32`], [`Coin`], [`CoinSpend`], [`Datastore`], [`DidRef`],
30//! [`DigDataStoreMetadata`], [`MerkleCoinSpend`]) are re-exported VERBATIM from `dig-merkle`, and
31//! [`ChainSource`] from `dig-chainsource-interface`, so a consumer depends on ONE canonical shape
32//! across the whole DataLayer surface. The owner type [`StoreOwner`] is the deliberate exception —
33//! `dig-store` owns it so that `dig_merkle::Owner::Custom`, which `dig-merkle` refuses on every
34//! lifecycle operation, is unexpressible here rather than a documented runtime error.
35//!
36//! ## Invariants
37//!
38//! - **INV-1 — No network.** `dig-store` performs no chain I/O itself; on-chain getters take a
39//! [`ChainSource`] the caller supplies (the user's verified node or a trusted provider set, NC-9),
40//! and lifecycle operations are pure transforms of their inputs.
41//! - **INV-2 — No keys, unsigned output.** Lifecycle operations return unsigned spends; signing is
42//! always the caller's responsibility (inherited from `dig-merkle`).
43//! - **INV-3 — Minimal on-chain encoding (NC-8).** The store's on-chain footprint is delegated
44//! wholesale to `dig-merkle`, which owns the minimal byte layout; the size is a single-byte bucket.
45//! - **INV-4 — On-chain proof always (NC-9).** Every getter that returns chain-anchored data proves
46//! it against the chain; trust never comes from a self-declared field or an unverified peer.
47//! - **INV-5 — `.dig` back-compat (§5.1).** The capsule surface reads every older `.dig` format
48//! identically (inherited from `dig-capsule`'s reader, which dispatches on the DIGS blob version); the
49//! public API is extended additively, never broken.
50//!
51//! ## The `store_id` trust boundary (off-chain capsule getters)
52//!
53//! [`get_capsule_identity`] recovers a capsule's DECLARED `store_id` from module bytes. That id is the
54//! store's on-chain launcher id and is NOT self-verifiable from the bytes alone — treat it as a CLAIM
55//! until cross-checked against a trusted anchor. [`open_capsule`] does that cross-check against a
56//! caller-supplied anchor and fails closed on mismatch. The `root_hash` is always proven internally
57//! consistent by the reader (it recomputes the merkle root and rejects a forged one).
58
59// Public modules.
60pub mod capsule;
61pub mod chain;
62pub mod error;
63pub mod lifecycle;
64pub mod size;
65pub mod store;
66pub mod types;
67pub mod urn;
68
69// The curated public surface — consumers depend on these paths, not the module layout.
70pub use capsule::{get_capsule_identity, open_capsule};
71pub use chain::ChainSource;
72pub use error::{DigStoreError, DigStoreResult};
73pub use lifecycle::{create_store, melt_store, modify_store, CreateStoreParams, StoreOwner};
74pub use size::{SizeBucket, SizeProof, SizeVerdict};
75pub use store::{
76 get_latest_root, get_latest_root_urn, get_root_history, get_store_description,
77 get_store_did_owner, get_store_label, get_store_program_hash, get_store_singleton_tip,
78 get_store_size_bucket, get_store_status, get_store_urn, DEFAULT_CONFIRMATION_TARGET,
79};
80pub use types::{
81 Bytes32, CapsuleIdentity, Coin, CoinSpend, Confirmations, Datastore, DelegatedPuzzle, DidRef,
82 DigDataStoreMetadata, LineageProof, MerkleCoinSpend, Proof, RootHistory, StoreStatus,
83 StoreStatusKind,
84};
85
86/// Derives the [`LineageProof`] a child singleton spend must carry to be recreated from a hydrated
87/// store (the lineage-getter surface). Re-exported verbatim from `dig-merkle` (the byte-source-of-
88/// truth, INV-4) so a consumer builds the next spend against a store the walk returned without a
89/// separate `dig-merkle` dependency. `dig-merkle` derives its `parent_inner_puzzle_hash` via
90/// the DataLayer updater path, so the resulting child spend is consensus-valid (no
91/// `AssertMyParentIdFailed`, #1332).
92pub use dig_merkle::child_lineage_proof;
93pub use urn::{capsule_urn, retrieval_key, store_urn, URN_PREFIX};