hotshot_types/traits/
states.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//! Abstractions over the immutable instance-level state and the global state that blocks modify.
8//!
9//! This module provides the [`InstanceState`] and [`ValidatedState`] traits, which serve as
10//! compatibilities over the current network state, which is modified by the transactions contained
11//! within blocks.
12
13use std::{error::Error, fmt::Debug, future::Future};
14
15use serde::{de::DeserializeOwned, Deserialize, Serialize};
16use vbs::version::Version;
17
18use super::block_contents::TestableBlock;
19use crate::{
20    data::Leaf2,
21    traits::{
22        node_implementation::{ConsensusTime, NodeType},
23        BlockPayload,
24    },
25};
26
27/// Instance-level state, which allows us to fetch missing validated state.
28pub trait InstanceState: Debug + Clone + Send + Sync {}
29
30/// Application-specific state delta, which will be used to store a list of merkle tree entries.
31pub trait StateDelta:
32    Debug + PartialEq + Eq + Send + Sync + Serialize + for<'a> Deserialize<'a>
33{
34}
35
36/// Abstraction over the state that blocks modify
37///
38/// This trait represents the behaviors that the 'global' ledger state must have:
39///   * A defined error type ([`Error`](ValidatedState::Error))
40///   * The type of block that modifies this type of state ([`BlockPayload`](`ValidatedStates::
41/// BlockPayload`))
42///   * The ability to validate that a block header is actually a valid extension of this state and
43///     produce a new state, with the modifications from the block applied
44///
45/// ([`validate_and_apply_header`](`ValidatedState::validate_and_apply_header`))
46pub trait ValidatedState<TYPES: NodeType>:
47    Serialize + DeserializeOwned + Debug + Default + PartialEq + Eq + Send + Sync + Clone
48{
49    /// The error type for this particular type of ledger state
50    type Error: Error + Debug + Send + Sync;
51    /// The type of the instance-level state this state is associated with
52    type Instance: InstanceState;
53    /// The type of the state delta this state is associated with.
54    type Delta: StateDelta;
55    /// Time compatibility needed for reward collection
56    type Time: ConsensusTime;
57
58    /// Check if the proposed block header is valid and apply it to the state if so.
59    ///
60    /// Returns the new state and state delta.
61    ///
62    /// # Arguments
63    /// * `instance` - Immutable instance-level state.
64    ///
65    /// # Errors
66    ///
67    /// If the block header is invalid or appending it would lead to an invalid state.
68    fn validate_and_apply_header(
69        &self,
70        instance: &Self::Instance,
71        parent_leaf: &Leaf2<TYPES>,
72        proposed_header: &TYPES::BlockHeader,
73        payload_byte_len: u32,
74        version: Version,
75        view_number: u64,
76    ) -> impl Future<Output = Result<(Self, Self::Delta), Self::Error>> + Send;
77
78    /// Construct the state with the given block header.
79    ///
80    /// This can also be used to rebuild the state for catchup.
81    fn from_header(block_header: &TYPES::BlockHeader) -> Self;
82
83    /// Construct a genesis validated state.
84    #[must_use]
85    fn genesis(instance: &Self::Instance) -> (Self, Self::Delta);
86
87    /// Gets called to notify the persistence backend that this state has been committed
88    fn on_commit(&self);
89}
90
91/// extra functions required on state to be usable by hotshot-testing
92pub trait TestableState<TYPES>: ValidatedState<TYPES>
93where
94    TYPES: NodeType,
95    TYPES::BlockPayload: TestableBlock<TYPES>,
96{
97    /// Creates random transaction if possible
98    /// otherwise panics
99    /// `padding` is the bytes of padding to add to the transaction
100    fn create_random_transaction(
101        state: Option<&Self>,
102        rng: &mut dyn rand::RngCore,
103        padding: u64,
104    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction;
105}