Skip to main content

dig_epoch/types/
verification.rs

1//! # `types::verification` — verification-related data types
2//!
3//! **Introduced by:** `STR-002` — Module hierarchy (SPEC §13).
4//!
5//! **Future owner:**
6//! [`TYP-006`](../../../docs/requirements/domains/epoch_types/specs/TYP-006.md)
7//! — verification-related data structures:
8//!
9//! - `EpochCheckpointData` with `hash()` and `test_coin_id()`
10//! - `EpochBlockLink`
11//!
12//! **Spec reference:** [`SPEC.md` §7](../../../docs/resources/SPEC.md) —
13//! verification.
14//!
15//! ## Relationship to `src/verification.rs`
16//!
17//! This module owns the **type surface** of verification. The **free
18//! functions** that compute verification artefacts (epoch block Merkle
19//! root, inclusion proofs, withdrawals Merkle-set root, checkpoint signing
20//! material) live in [`crate::verification`] per STR-002's Implementation
21//! Notes. Both modules must exist simultaneously with distinct
22//! responsibilities.
23//!
24//! ## Status at STR-002
25//!
26//! Empty aside from the [`STR_002_MODULE_PRESENT`] sentinel.
27
28/// Sentinel marker proving the module exists and is reachable at
29/// `dig_epoch::types::verification::STR_002_MODULE_PRESENT`.
30///
31/// Exercised by the STR-002 integration test — see
32/// [`tests/crate_structure/str_002_test.rs`](../../../tests/crate_structure/str_002_test.rs).
33#[doc(hidden)]
34pub const STR_002_MODULE_PRESENT: () = ();
35
36use chia_protocol::Bytes32;
37use chia_sha2::Sha256;
38use serde::{Deserialize, Serialize};
39
40use crate::error::EpochError;
41
42// -----------------------------------------------------------------------------
43// TYP-006 — EpochBlockLink
44// -----------------------------------------------------------------------------
45
46/// Parent-to-child relationship between consecutive blocks within an epoch.
47///
48/// Spec ref: SPEC §3.13 / TYP-006.
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct EpochBlockLink {
51    /// Hash of the parent block.
52    pub parent_hash: Bytes32,
53    /// Hash of the current block.
54    pub block_hash: Bytes32,
55}
56
57// -----------------------------------------------------------------------------
58// VER-004 — EpochCheckpointData
59// -----------------------------------------------------------------------------
60
61/// Minimum data needed to identify and verify an epoch checkpoint.
62///
63/// Binds `network_id` to the other fields to prevent cross-network replay.
64///
65/// Spec ref: SPEC §7.4 / VER-004.
66#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
67pub struct EpochCheckpointData {
68    /// Network identifier (prevents cross-network replay).
69    pub network_id: Bytes32,
70    /// Epoch number this checkpoint summarizes.
71    pub epoch: u64,
72    /// Ordered Merkle root over epoch block hashes (VER-001).
73    pub block_root: Bytes32,
74    /// Post-epoch L2 state root.
75    pub state_root: Bytes32,
76    /// Order-independent Merkle set root over epoch withdrawals (VER-003).
77    pub withdrawals_root: Bytes32,
78    /// Hash of the underlying [`dig_block::Checkpoint`] struct.
79    pub checkpoint_hash: Bytes32,
80}
81
82impl EpochCheckpointData {
83    /// SHA-256 over `network_id || epoch_le || block_root || state_root ||
84    /// withdrawals_root || checkpoint_hash`.
85    pub fn signing_digest(&self) -> Bytes32 {
86        let mut h = Sha256::new();
87        h.update(self.network_id.as_ref());
88        h.update(self.epoch.to_le_bytes());
89        h.update(self.block_root.as_ref());
90        h.update(self.state_root.as_ref());
91        h.update(self.withdrawals_root.as_ref());
92        h.update(self.checkpoint_hash.as_ref());
93        Bytes32::new(h.finalize())
94    }
95
96    /// Serializes with bincode. Infallible for well-formed structs.
97    pub fn to_bytes(&self) -> Vec<u8> {
98        bincode::serialize(self).expect("EpochCheckpointData serialization should never fail")
99    }
100
101    /// Deserializes from bincode bytes, returning `EpochError::InvalidData` on failure.
102    pub fn from_bytes(bytes: &[u8]) -> Result<Self, EpochError> {
103        bincode::deserialize(bytes).map_err(|e| EpochError::InvalidData(e.to_string()))
104    }
105}
106
107/// Validator-facing signing material: [`EpochCheckpointData`] plus the
108/// competition score and the exact bytes to sign.
109///
110/// Spec ref: SPEC §7.5 / VER-004.
111#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
112pub struct EpochCheckpointSignMaterial {
113    /// Core checkpoint data (network-bound).
114    pub checkpoint: EpochCheckpointData,
115    /// Competition score = `stake_percentage * block_count` (CKP-004).
116    pub score: u64,
117    /// BLS signing digest (hash of `checkpoint`).
118    pub signing_digest: Bytes32,
119}