Expand description
The chain-reading seam and the singleton lineage-authentication core (SPEC §5 & §10).
dig-did performs NO network or chain I/O (INV-1). Yet authenticating that a coin is a genuine
singleton — and rooting it in a DID’s identity — requires reading chain state (a coin’s creating
spend, a DID singleton’s lineage). ChainSource is the seam that squares that circle: the caller
supplies an honest READER of chain state (a full node / coinset client / chia-query), and dig-did
supplies ALL the trust logic on top. Reads are not broadcasts — this keeps the crate no-network and
wasm-buildable while still proving lineage.
§Why the walk, and why puzzle-hash equality is NOT enough (the soundness crux)
A Chia coin’s puzzle_hash is attacker-chosen: anyone can pay-to a coin whose puzzle hash equals a
singleton’s outer puzzle hash for a victim launcher. Such a coin is NOT a singleton — it has no
genuine recreation history. To authenticate a coin as a real singleton this module WALKS the
parent-spend chain: for each step it parses the parent’s puzzle with the SDK’s SingletonLayer
(proving the parent is itself a singleton and reading its curried launcher_id), RUNS the parent’s
inner puzzle to derive the exact singleton successor it creates, and requires that successor to be
the child under authentication (binding amount parity + the singleton curry). The walk terminates at
the singleton LAUNCHER coin, yielding an AUTHENTICATED launcher_id. A coin whose parent chain does
not resolve this way is DidError::NotASingleton — never trusted on a bare puzzle hash or a bare
parent_coin_info.
§Trust model
The ChainSource MUST be the caller’s OWN honest view of the chain, not an attacker-controlled
channel. dig-did assumes the source reports real chain state; it cannot defend against a source that
fabricates the chain itself. Its job is to ensure that, given honest chain data, no coin can launder
itself into a DID’s authority (see the adversarial tests). Every read failure or gap fails CLOSED —
an error, never an “assume owned” default.
Structs§
- DidTip
- The current unspent tip of a DID singleton, reconstructed from chain reads: the tip coin, its
DidInfo, and the lineageProofneeded to spend it. - Singleton
Lineage - The lineage of a Chia singleton: every coin id from the launcher spend forward to the current unspent tip.
Constants§
- MAX_
LINEAGE_ DEPTH - The maximum number of parent-spend hops the singleton walk will follow before failing closed with
DidError::LineageTooDeep.
Traits§
- Chain
Source - A reads-only view of Chia chain state — the single canonical contract every provider implements and every consumer depends on.
Functions§
- resolve_
xch_ address - Resolves a DID’s CURRENT owner XCH payment address from chain — the DID→address primitive (SPEC §3, U10).
- resolve_
xch_ address_ from_ did_ string - Resolves a DID’s current owner XCH payment address from its
did:chia:1…string form — a convenience wrapper overresolve_xch_address(SPEC §3, U10). - walk_
did_ lineage_ to_ tip - Walks a DID singleton forward to its current unspent tip, reconstructing it as a
DidTip.