dig_chainsource_interface/lib.rs
1//! # dig-chainsource-interface — the DIG Network canonical `ChainSource` provider interface
2//!
3//! This crate defines the ONE [`ChainSource`] trait (and its query/result/error types) that every
4//! Chia chain-source provider implements and every DIG consumer depends on. There is a single
5//! canonical contract for reading Chia chain state across the ecosystem — never a per-crate copy
6//! that could byte-drift.
7//!
8//! It is a pure **leaf**: a trait, its typed query inputs and results, a typed error, an optional
9//! in-memory mock, and known-answer tests. It performs NO I/O, holds NO keys, opens NO network,
10//! and ships NO concrete provider. Providers (coinset.org, a local wallet/full node, DIG peers)
11//! live in their own crates; `chia-query` is the registry + aggregating canonical source that
12//! composes them. Consumers depend on THIS trait, not on any provider.
13//!
14//! ## Reads only — no broadcast, ever (custody stance)
15//!
16//! Nothing in this crate can broadcast, push, or submit to the chain: there is no such method, by
17//! design. It is a pure reader. Write/spend/broadcast paths — which touch keys and funds — live
18//! entirely outside this crate, so depending on it can never move value.
19//!
20//! ## Fail-closed: `Ok(None)` vs `Err` (the soundness contract)
21//!
22//! Every read distinguishes two outcomes consumers MUST treat differently:
23//! - `Ok(None)` / an empty `Vec` — the source reliably answered and the thing genuinely does not
24//! exist. Safe to act on.
25//! - `Err(_)` — the source could NOT reliably answer (transport/timeout/malformed/unsupported).
26//! The answer is unknown; the consumer MUST fail closed, never treating it as an absence.
27//!
28//! Absence is NEVER an error variant; an error is NEVER degraded to a value.
29//!
30//! ## Money-critical parent-walk enablement
31//!
32//! A Chia coin's `puzzle_hash` is attacker-chosen, so a `launcher_id ==` equality check is
33//! spoofable. Authenticating a coin as a genuine singleton requires walking
34//! [`ChainSource::parent_spend`] back toward the real launcher, proving each hop from the parent's
35//! actual reveal+solution — a spoofed curried-puzzle coin has no genuine recreation parent-spend,
36//! so the walk fails closed. This crate supplies that primitive (and [`SingletonLineage`], whose
37//! authority is MEMBERSHIP, not tip-equality); consumers supply the trust logic on top.
38
39mod error;
40mod lineage;
41mod provider;
42mod record;
43mod source;
44
45#[cfg(feature = "testing")]
46mod testing;
47
48pub use error::ChainSourceError;
49pub use lineage::SingletonLineage;
50pub use provider::{ProviderId, ProviderInfo, ProviderKind};
51pub use record::CoinRecord;
52pub use source::{ChainSource, ChainSourceProvider};
53
54#[cfg(feature = "testing")]
55pub use testing::MockChainSource;
56
57/// The crate version, sourced from `Cargo.toml` at build time.
58pub const VERSION: &str = env!("CARGO_PKG_VERSION");
59
60#[cfg(test)]
61mod tests {
62 use super::VERSION;
63
64 #[test]
65 fn version_is_reported() {
66 assert!(!VERSION.is_empty());
67 }
68}