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