Skip to main content

dig_merkle/
lib.rs

1//! # dig-merkle — the DIG Network canonical CHIP-0035 DataLayer coin expert crate
2//!
3//! `dig-merkle` is a **pure, key-free, network-free** SpendBundle-builder for the Chia CHIP-0035
4//! DataLayer singleton that anchors a `.dig` file's merkle root on-chain. It constructs the exact
5//! [`CoinSpend`]s for every DataLayer-coin lifecycle operation and reports — via
6//! [`required_signatures`] — the exact signatures a caller must produce. It never holds a secret
7//! key, never signs, and never touches the network. The consumer signs the reported messages,
8//! assembles the `SpendBundle`, and broadcasts.
9//!
10//! ## The DataLayer coin
11//!
12//! A DataLayer coin is a CHIP-0035 singleton whose `launcher_id` IS the DIG `store_id`. Its
13//! [`DatastoreMetadata`] carries the capsule's `root_hash` (the anchored `.dig` merkle root) plus
14//! optional `label`/`description`/`size_proof`, the additive `program_hash` (`"p"`), and the store
15//! size as a power-of-2 `size_bucket` (`"sz"` — see [`SizeBucket`]) that REPLACES the SDK's exact
16//! `bytes`/`"b"` field, and its [`DelegatedPuzzle`] list grants
17//! admin/writer/oracle authority. Spending the coin recreates it with a new root, transferring
18//! ownership, delegating write access, or melting it. dig-merkle builds each such spend unsigned.
19//!
20//! ## Invariants
21//!
22//! These four invariants hold across the entire crate and are the contract every unit is built to
23//! (SPEC §1):
24//!
25//! - **INV-1 — No network.** dig-merkle performs NO network or chain I/O. Every function is a pure
26//!   transform of its inputs; the caller fetches coins and broadcasts bundles.
27//! - **INV-2 — No keys.** dig-merkle never accepts, holds, derives, or logs a secret key. It
28//!   computes what must be signed ([`required_signatures`]); the caller's signer produces the
29//!   signatures.
30//! - **INV-3 — Unsigned output.** Every operation returns an unsigned [`MerkleCoinSpend`] — coin
31//!   spends plus the recreated child Datastore. Signatures are always the caller's responsibility.
32//! - **INV-4 — SDK byte-source-of-truth.** Every puzzle, layer, and coin-spend byte is produced by
33//!   `chia-wallet-sdk` (pinned to the 0.30 / chia-protocol 0.26 family, `chip-0035` feature).
34//!   dig-merkle adds DataLayer-workflow ergonomics on top; it never re-implements a puzzle or
35//!   hand-rolls a spend bundle, and re-exports the SDK's Datastore types verbatim.
36//!
37//! ## Consumer pattern
38//!
39//! ```text
40//! build an unsigned MerkleCoinSpend  ->  required_signatures(&spend.coin_spends, &constants)
41//!   ->  caller signs each reported message  ->  assemble SpendBundle  ->  broadcast
42//! ```
43//!
44//! ## Operation surface
45//!
46//! On the foundation (the type surface [`MerkleCoinSpend`]/[`Owner`] + re-exported SDK Datastore
47//! types, the error taxonomy [`MerkleError`], the inner-spend helpers, and the signing boundary
48//! [`required_signatures`]) the crate ships the DataLayer-coin lifecycle:
49//! - [`mint_datastore`] / [`mint_datastore_with_kind`] — launch a new DataLayer coin anchoring a
50//!   root; the kind-aware entry selects the launcher-hint discriminator ([`StoreKind`], SPEC §9).
51//! - [`update_root`] — recreate the coin with new metadata (a new merkle root), preserving identity.
52//! - [`melt()`] — terminally spend the coin, leaving no successor.
53//! - [`did_ref_from_spend`] / [`resolve_owner_did`] — read owner-DID ownership without spending.
54//! - [`hydrate()`] — reconstruct a spendable [`Datastore`] from a parent coin spend (fail-closed).
55//! - [`child_lineage_proof`] — derive the [`LineageProof`] a child spend requires.
56//! - [`launcher_hint_for`] / [`from_launcher_hint`] — the launcher-hint kind contract (SPEC §9).
57//!
58//! `delegation`, `oracle`, and `fee` remain doc-only stubs, landing in their own units.
59
60// Internal helpers — not part of the public surface.
61mod context;
62
63// Public modules.
64pub mod error;
65pub mod sign;
66pub mod types;
67
68// The DataLayer operation modules. `delegation`/`oracle`/`fee` remain doc-only stubs (declared so
69// the crate layout is final); the rest are implemented.
70
71pub mod metadata;
72
73pub mod mint;
74
75pub mod size;
76
77pub mod update;
78
79/// Grant or revoke admin/writer/oracle [`crate::DelegatedPuzzle`] authority (future unit,
80/// SPEC §3.3).
81pub mod delegation {}
82
83/// Spend the oracle delegated puzzle to read the coin for a fee (future unit, SPEC §3.4).
84pub mod oracle {}
85
86pub mod melt;
87
88pub mod read;
89
90pub mod hydrate;
91
92pub mod lineage;
93
94pub mod hint;
95
96/// Attach a reserve fee condition to any DataLayer operation (future unit, SPEC §3).
97pub mod fee {}
98
99// The curated public surface — consumers depend on these paths, not the module layout.
100pub use error::{MerkleError, MerkleResult};
101pub use hint::{
102    digstore_owner_hint, from_launcher_hint, launcher_hint_for, StoreKind, DATASTORE_LAUNCHER_HINT,
103    DID_PROFILE_LAUNCHER_HINT, DIGSTORE_OWNER_HINT_DOMAIN,
104};
105pub use hydrate::hydrate;
106pub use lineage::child_lineage_proof;
107pub use melt::melt;
108pub use metadata::DigDataStoreMetadata;
109pub use mint::{
110    mint_datastore, mint_datastore_launch_with_kind, mint_datastore_with_kind, DatastoreLaunch,
111};
112pub use read::{did_ref_from_spend, resolve_owner_did, DidRef};
113pub use sign::required_signatures;
114pub use size::SizeBucket;
115pub use types::{
116    Bytes32, Coin, CoinSpend, Conditions, Datastore, DatastoreInfo, DatastoreMetadata,
117    DelegatedPuzzle, LineageProof, MerkleCoinSpend, Owner, Proof, SpendContext,
118};
119pub use update::update_root;
120
121// Re-export the signing types a consumer needs to CALL [`required_signatures`] and consume its
122// result, so a downstream crate need not add a direct chia-wallet-sdk dependency for them.
123pub use chia_wallet_sdk::signer::{AggSigConstants, RequiredSignature};
124
125// Re-export the two launcher builders a consumer needs to CALL
126// [`mint_datastore_launch_with_kind`], for the same reason: `Launcher::new(parent_coin_id, 1)` for an
127// ordinary parent, `IntermediateLauncher::new(parent_coin_id, 0, 1).create(ctx)?` for a singleton one.
128pub use chia_wallet_sdk::driver::{IntermediateLauncher, Launcher};