hotshot_example_types/
state_types.rs

1// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
2// This file is part of the HotShot repository.
3
4// You should have received a copy of the MIT License
5// along with the HotShot repository. If not, see <https://mit-license.org/>.
6
7//! Implementations for examples and tests only
8use std::fmt::Debug;
9
10use async_trait::async_trait;
11use committable::{Commitment, Committable};
12use hotshot_types::{
13    data::{BlockError, Leaf2, fake_commitment},
14    traits::{
15        BlockPayload,
16        block_contents::BlockHeader,
17        node_implementation::NodeType,
18        states::{InstanceState, StateDelta, TestableState, ValidatedState},
19    },
20};
21use rand::Rng;
22use serde::{Deserialize, Serialize};
23use vbs::version::Version;
24
25pub use crate::node_types::{TestTwoStakeTablesTypes, TestTypes};
26use crate::{
27    block_types::{TestBlockPayload, TestTransaction},
28    testable_delay::{DelayConfig, SupportedTraitTypesForAsyncDelay, TestableDelay},
29};
30
31/// Instance-level state implementation for testing purposes.
32#[derive(Clone, Debug, Default)]
33pub struct TestInstanceState {
34    pub delay_config: DelayConfig,
35}
36
37impl InstanceState for TestInstanceState {}
38
39impl TestInstanceState {
40    pub fn new(delay_config: DelayConfig) -> Self {
41        TestInstanceState { delay_config }
42    }
43}
44
45/// Application-specific state delta implementation for testing purposes.
46#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
47pub struct TestStateDelta {}
48
49impl StateDelta for TestStateDelta {}
50
51/// Validated state implementation for testing purposes.
52#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)]
53pub struct TestValidatedState {
54    /// the block height
55    block_height: u64,
56    /// the previous state commitment
57    prev_state_commitment: Commitment<Self>,
58}
59
60impl Committable for TestValidatedState {
61    fn commit(&self) -> Commitment<Self> {
62        committable::RawCommitmentBuilder::new("Test State Commit")
63            .u64_field("block_height", self.block_height)
64            .field("prev_state_commitment", self.prev_state_commitment)
65            .finalize()
66    }
67
68    fn tag() -> String {
69        "TEST_STATE".to_string()
70    }
71}
72
73impl Default for TestValidatedState {
74    fn default() -> Self {
75        Self {
76            block_height: 0,
77            prev_state_commitment: fake_commitment(),
78        }
79    }
80}
81
82#[async_trait]
83impl TestableDelay for TestValidatedState {
84    async fn run_delay_settings_from_config(delay_config: &DelayConfig) {
85        if let Some(settings) =
86            delay_config.get_setting(&SupportedTraitTypesForAsyncDelay::ValidatedState)
87        {
88            Self::handle_async_delay(settings).await;
89        }
90    }
91}
92
93impl<TYPES: NodeType> ValidatedState<TYPES> for TestValidatedState {
94    type Error = BlockError;
95
96    type Instance = TestInstanceState;
97
98    type Delta = TestStateDelta;
99
100    async fn validate_and_apply_header(
101        &self,
102        instance: &Self::Instance,
103        _parent_leaf: &Leaf2<TYPES>,
104        _proposed_header: &TYPES::BlockHeader,
105        _payload_byte_len: u32,
106        _version: Version,
107        _view_number: u64,
108    ) -> Result<(Self, Self::Delta), Self::Error> {
109        Self::run_delay_settings_from_config(&instance.delay_config).await;
110        Ok((
111            TestValidatedState {
112                block_height: self.block_height + 1,
113                prev_state_commitment: self.commit(),
114            },
115            TestStateDelta {},
116        ))
117    }
118
119    fn from_header(block_header: &TYPES::BlockHeader) -> Self {
120        Self {
121            block_height: block_header.block_number(),
122            ..Default::default()
123        }
124    }
125
126    fn on_commit(&self) {}
127
128    fn genesis(_instance: &Self::Instance) -> (Self, Self::Delta) {
129        (Self::default(), TestStateDelta {})
130    }
131}
132
133impl<TYPES: NodeType<BlockPayload = TestBlockPayload>> TestableState<TYPES> for TestValidatedState {
134    fn create_random_transaction(
135        _state: Option<&Self>,
136        rng: &mut dyn rand::RngCore,
137        padding: u64,
138    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction {
139        /// clippy appeasement for `RANDOM_TX_BASE_SIZE`
140        const RANDOM_TX_BASE_SIZE: usize = 8;
141
142        // Generate a random transaction
143        let mut tx = rng.r#gen::<[u8; RANDOM_TX_BASE_SIZE]>().to_vec();
144
145        // Create and add padding to the transaction
146        let padding = vec![0; padding.try_into().expect("transaction padding too large")];
147        tx.extend(padding);
148
149        // Return the transaction
150        TestTransaction::new(tx)
151    }
152}