Skip to main content

dig_block/validation/
state.rs

1//! Tier 3 **state validation** (STV-*): coin existence, puzzle hash cross-checks, lock evaluation,
2//! proposer signature, and state root verification.
3//!
4//! ## Requirements trace
5//!
6//! - **[STV-001](docs/requirements/domains/state_validation/specs/STV-001.md)** — `validate_state()` API + `validate_full()` composite.
7//! - **[STV-002](docs/requirements/domains/state_validation/specs/STV-002.md)** — coin existence checks: removals must exist and be unspent, or be ephemeral (created in same block). Also handles `ASSERT_EPHEMERAL` condition.
8//! - **[STV-003](docs/requirements/domains/state_validation/specs/STV-003.md)** — puzzle hash cross-check: `CoinState.coin.puzzle_hash == CoinSpend.coin.puzzle_hash`.
9//! - **[STV-004](docs/requirements/domains/state_validation/specs/STV-004.md)** — addition non-existence: created coins must not already exist in coin set (exception: ephemeral spent in same block).
10//! - **[STV-005](docs/requirements/domains/state_validation/specs/STV-005.md)** — height/time lock evaluation: 8 assertion types from `PendingAssertion` (EXE-009) evaluated against chain context from [`crate::CoinLookup`].
11//! - **[STV-006](docs/requirements/domains/state_validation/specs/STV-006.md)** — proposer signature: `chia-bls::verify(pubkey, header.hash(), block.proposer_signature)`.
12//! - **[STV-007](docs/requirements/domains/state_validation/specs/STV-007.md)** — state root verification: apply additions/removals, recompute Merkle root, compare to `header.state_root`.
13//! - **[NORMATIVE](docs/requirements/domains/state_validation/NORMATIVE.md)** — full state validation domain.
14//! - **[SPEC §7.5](docs/resources/SPEC.md)** — Tier 3 state validation pipeline.
15//!
16//! ## API signatures (STV-001)
17//!
18//! ```text
19//! L2Block::validate_state(&self, exec: &ExecutionResult, coins: &dyn CoinLookup, proposer_pubkey: &PublicKey)
20//!     -> Result<Bytes32, BlockError>
21//!     // Returns computed state_root on success
22//!
23//! L2Block::validate_full(&self, config: &ValidationConfig, genesis: &Bytes32, coins: &dyn CoinLookup, pubkey: &PublicKey)
24//!     -> Result<Bytes32, BlockError>
25//!     // Chains: validate_structure() → validate_execution() → validate_state()
26//!     // Returns first error or Ok(state_root)
27//! ```
28//!
29//! ## Height/time lock assertion types (STV-005)
30//!
31//! | Assertion | Evaluation |
32//! |-----------|-----------|
33//! | `ASSERT_HEIGHT_ABSOLUTE(h)` | `chain_height >= h` |
34//! | `ASSERT_HEIGHT_RELATIVE(h)` | `chain_height >= coin_confirmed_height + h` |
35//! | `ASSERT_SECONDS_ABSOLUTE(t)` | `chain_timestamp >= t` |
36//! | `ASSERT_SECONDS_RELATIVE(t)` | `chain_timestamp >= coin_timestamp + t` |
37//! | `BEFORE_HEIGHT_ABSOLUTE(h)` | `chain_height < h` |
38//! | `BEFORE_HEIGHT_RELATIVE(h)` | `chain_height < coin_confirmed_height + h` |
39//! | `BEFORE_SECONDS_ABSOLUTE(t)` | `chain_timestamp < t` |
40//! | `BEFORE_SECONDS_RELATIVE(t)` | `chain_timestamp < coin_timestamp + t` |
41//!
42//! Relative assertions require looking up the coin's `created_height` / timestamp from [`crate::CoinLookup`].
43//! For ephemeral coins (created in the same block), `created_height` is the current block height.
44//!
45//! ## Chia parity
46//!
47//! - Coin existence: [`block_body_validation.py` Check 15](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/block_body_validation.py) (`UNKNOWN_UNSPENT`, `DOUBLE_SPEND`).
48//! - Height/time locks: [`block_body_validation.py` Check 21](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/block_body_validation.py).
49//! - Proposer signature: Analogous to Chia's farmer signature verification in [`block_header_validation.py`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/block_header_validation.py).
50//!
51//! ## Status
52//!
53//! Stub — full implementation in STV-001 through STV-007.