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::{fake_commitment, BlockError, Leaf2, ViewNumber},
14    traits::{
15        block_contents::BlockHeader,
16        node_implementation::NodeType,
17        states::{InstanceState, StateDelta, TestableState, ValidatedState},
18        BlockPayload,
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    type Time = ViewNumber;
101
102    async fn validate_and_apply_header(
103        &self,
104        instance: &Self::Instance,
105        _parent_leaf: &Leaf2<TYPES>,
106        _proposed_header: &TYPES::BlockHeader,
107        _payload_byte_len: u32,
108        _version: Version,
109        _view_number: u64,
110    ) -> Result<(Self, Self::Delta), Self::Error> {
111        Self::run_delay_settings_from_config(&instance.delay_config).await;
112        Ok((
113            TestValidatedState {
114                block_height: self.block_height + 1,
115                prev_state_commitment: self.commit(),
116            },
117            TestStateDelta {},
118        ))
119    }
120
121    fn from_header(block_header: &TYPES::BlockHeader) -> Self {
122        Self {
123            block_height: block_header.block_number(),
124            ..Default::default()
125        }
126    }
127
128    fn on_commit(&self) {}
129
130    fn genesis(_instance: &Self::Instance) -> (Self, Self::Delta) {
131        (Self::default(), TestStateDelta {})
132    }
133}
134
135impl<TYPES: NodeType<BlockPayload = TestBlockPayload>> TestableState<TYPES> for TestValidatedState {
136    fn create_random_transaction(
137        _state: Option<&Self>,
138        rng: &mut dyn rand::RngCore,
139        padding: u64,
140    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction {
141        /// clippy appeasement for `RANDOM_TX_BASE_SIZE`
142        const RANDOM_TX_BASE_SIZE: usize = 8;
143
144        // Generate a random transaction
145        let mut tx = rng.gen::<[u8; RANDOM_TX_BASE_SIZE]>().to_vec();
146
147        // Create and add padding to the transaction
148        let padding = vec![0; padding.try_into().expect("transaction padding too large")];
149        tx.extend(padding);
150
151        // Return the transaction
152        TestTransaction::new(tx)
153    }
154}