1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! External integration traits: [`CoinLookup`] and [`BlockSigner`].
//!
//! ## Requirements trace
//!
//! - **[STR-004](docs/requirements/domains/crate_structure/specs/STR-004.md)** — trait definitions, method signatures, object safety.
//! - **[NORMATIVE § STR-004](docs/requirements/domains/crate_structure/NORMATIVE.md)** — `CoinLookup` uses `chia-protocol::CoinState` directly;
//! `BlockSigner` returns `chia-bls::Signature`.
//! - **[SPEC §7.2](docs/resources/SPEC.md)** — validation context traits.
//!
//! ## Design decisions
//!
//! - **[`CoinLookup`] returns `Option<CoinState>`, not `Result`:** A missing coin is a normal validation
//! condition (Tier 3 checks for ephemeral coins — STV-002), not an I/O error. Implementors that wrap a
//! database should map DB errors to `None` or propagate them through a higher-level API.
//!
//! - **[`CoinState`] from `chia-protocol`:** Reuses the same type Chia's peer protocol returns for
//! `register_for_coin_updates` responses ([`chia_protocol::CoinState`]). This means `dig-coinstore` can
//! implement [`CoinLookup`] without type conversion.
//! Reference: [`chia-blockchain/chia/protocols/wallet_protocol.py`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/protocols/wallet_protocol.py).
//!
//! - **[`BlockSigner`] is object-safe:** Both traits can be used as `dyn CoinLookup` / `dyn BlockSigner`
//! so validation and builder code can be generic over the signing backend (HSM, in-memory key, remote signer).
//!
//! - **[`SignerError`]:** Kept minimal (one variant) because the signing failure reason is opaque to
//! block validation — it only matters for logging. [`crate::BlockBuilder::build`](crate::BlockBuilder::build) maps
//! failures to [`BuilderError::SigningFailed`](crate::BuilderError::SigningFailed) using [`SignerError::to_string`]
//! (BLD-006 / [ERR-004](docs/requirements/domains/error_types/specs/ERR-004.md) — the `BuilderError` variant carries a
//! `String`, not a nested `SignerError`, so integration tests assert diagnostic text rather than type equality).
//!
//! ## Downstream implementors
//!
//! ```text
//! dig-coinstore ──► implements CoinLookup (returns chia-protocol::CoinState)
//! proposer ──► implements BlockSigner (returns chia-bls::Signature)
//! tests/common ──► MockCoinLookup, MockBlockSigner (STR-005)
//! ```
use Signature;
use ;
/// Coin state lookup for Tier 3 (state) validation ([SPEC §7.2](docs/resources/SPEC.md), [STV-001](docs/requirements/domains/state_validation/specs/STV-001.md)).
///
/// Implementors provide access to the persistent coin set. The three methods supply the chain context
/// needed for:
/// - **Coin existence checks** (STV-002): `get_coin_state` returns the coin's lifecycle.
/// - **Height/time lock evaluation** (STV-005): `get_chain_height` / `get_chain_timestamp` provide
/// the reference clock for `ASSERT_HEIGHT_*` / `ASSERT_SECONDS_*` conditions.
///
/// ## Object safety
///
/// All methods take `&self` and return owned/copyable types — no `Self` in return position, no
/// generic parameters. `Box<dyn CoinLookup>` and `&dyn CoinLookup` are valid.
///
/// ## Chia parity
///
/// Method signatures mirror [`chia-blockchain/chia/consensus/block_body_validation.py`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/block_body_validation.py)
/// where `CoinStore.get_coin_record(coin_id)` returns `Optional[CoinRecord]` (Check 15).
/// Signing failure from a [`BlockSigner`] implementation.
///
/// Kept intentionally simple — the failure reason is an opaque string because signing backends
/// vary (HSM timeout, key-not-found, permission denied). The [`crate::BuilderError::SigningFailed`]
/// variant (ERR-004) wraps this for builder callers.
/// Block header signing hook for [`crate::builder::BlockBuilder::build`] ([SPEC §7.2](docs/resources/SPEC.md), BLD-006).
///
/// The proposer calls `sign_block(&header_hash)` at the end of the build pipeline to produce
/// the BLS signature stored in [`crate::L2Block::proposer_signature`].
///
/// ## Object safety
///
/// Same constraints as [`CoinLookup`] — `&self`, no generics, returns concrete types.
/// `Box<dyn BlockSigner>` is valid for dependency injection.
///
/// ## Chia parity
///
/// Signing uses `chia-bls::sign(secret_key, message)` internally. The message is the
/// header hash bytes (`Bytes32::as_ref()` → `&[u8; 32]`), matching the pattern in
/// [`chia-blockchain/chia/consensus/block_creation.py`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/block_creation.py)
/// where the farmer signs the header hash.