hotshot_types/traits/
node_implementation.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//! Composite trait for node behavior
8//!
9//! This module defines the [`NodeImplementation`] trait, which is a composite trait used for
10//! describing the overall behavior of a node, as a composition of implementations of the node trait.
11
12use std::{
13    fmt::{Debug, Display},
14    hash::Hash,
15    ops::{self, Deref, Sub},
16    sync::Arc,
17    time::Duration,
18};
19
20use async_trait::async_trait;
21use committable::Committable;
22use serde::{Deserialize, Serialize};
23use vbs::version::StaticVersionType;
24
25use super::{
26    block_contents::{BlockHeader, TestableBlock, Transaction},
27    network::{
28        AsyncGenerator, ConnectedNetwork, NetworkReliability, TestableNetworkingImplementation,
29    },
30    signature_key::{
31        BuilderSignatureKey, LCV1StateSignatureKey, LCV2StateSignatureKey, LCV3StateSignatureKey,
32        StateSignatureKey,
33    },
34    states::TestableState,
35    storage::Storage,
36    ValidatedState,
37};
38use crate::{
39    constants::DEFAULT_UPGRADE_CONSTANTS,
40    data::{Leaf2, TestableLeaf},
41    traits::{
42        election::Membership, signature_key::SignatureKey, states::InstanceState, BlockPayload,
43    },
44    upgrade_config::UpgradeConstants,
45};
46
47/// Node implementation aggregate trait
48///
49/// This trait exists to collect multiple behavior implementations into one type, to allow
50/// `HotShot` to avoid annoying numbers of type arguments and type patching.
51///
52/// It is recommended you implement this trait on a zero sized type, as `HotShot`does not actually
53/// store or keep a reference to any value implementing this trait.
54pub trait NodeImplementation<TYPES: NodeType>:
55    Send + Sync + Clone + Eq + Hash + 'static + Serialize + for<'de> Deserialize<'de>
56{
57    /// The underlying network type
58    type Network: ConnectedNetwork<TYPES::SignatureKey>;
59
60    /// Storage for DA layer interactions
61    type Storage: Storage<TYPES>;
62}
63
64/// extra functions required on a node implementation to be usable by hotshot-testing
65#[allow(clippy::type_complexity)]
66#[async_trait]
67pub trait TestableNodeImplementation<TYPES: NodeType>: NodeImplementation<TYPES> {
68    /// Creates random transaction if possible
69    /// otherwise panics
70    /// `padding` is the bytes of padding to add to the transaction
71    fn state_create_random_transaction(
72        state: Option<&TYPES::ValidatedState>,
73        rng: &mut dyn rand::RngCore,
74        padding: u64,
75    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction;
76
77    /// Creates random transaction if possible
78    /// otherwise panics
79    /// `padding` is the bytes of padding to add to the transaction
80    fn leaf_create_random_transaction(
81        leaf: &Leaf2<TYPES>,
82        rng: &mut dyn rand::RngCore,
83        padding: u64,
84    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction;
85
86    /// generate a genesis block
87    fn block_genesis() -> TYPES::BlockPayload;
88
89    /// the number of transactions in a block
90    fn txn_count(block: &TYPES::BlockPayload) -> u64;
91
92    /// Generate the communication channels for testing
93    fn gen_networks(
94        expected_node_count: usize,
95        num_bootstrap: usize,
96        da_committee_size: usize,
97        reliability_config: Option<Box<dyn NetworkReliability>>,
98        secondary_network_delay: Duration,
99    ) -> AsyncGenerator<Arc<Self::Network>>;
100}
101
102#[async_trait]
103impl<TYPES: NodeType, I: NodeImplementation<TYPES>> TestableNodeImplementation<TYPES> for I
104where
105    TYPES::ValidatedState: TestableState<TYPES>,
106    TYPES::BlockPayload: TestableBlock<TYPES>,
107    I::Network: TestableNetworkingImplementation<TYPES>,
108{
109    fn state_create_random_transaction(
110        state: Option<&TYPES::ValidatedState>,
111        rng: &mut dyn rand::RngCore,
112        padding: u64,
113    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction {
114        <TYPES::ValidatedState as TestableState<TYPES>>::create_random_transaction(
115            state, rng, padding,
116        )
117    }
118
119    fn leaf_create_random_transaction(
120        leaf: &Leaf2<TYPES>,
121        rng: &mut dyn rand::RngCore,
122        padding: u64,
123    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction {
124        Leaf2::create_random_transaction(leaf, rng, padding)
125    }
126
127    fn block_genesis() -> TYPES::BlockPayload {
128        <TYPES::BlockPayload as TestableBlock<TYPES>>::genesis()
129    }
130
131    fn txn_count(block: &TYPES::BlockPayload) -> u64 {
132        <TYPES::BlockPayload as TestableBlock<TYPES>>::txn_count(block)
133    }
134
135    fn gen_networks(
136        expected_node_count: usize,
137        num_bootstrap: usize,
138        da_committee_size: usize,
139        reliability_config: Option<Box<dyn NetworkReliability>>,
140        secondary_network_delay: Duration,
141    ) -> AsyncGenerator<Arc<Self::Network>> {
142        <I::Network as TestableNetworkingImplementation<TYPES>>::generator(
143            expected_node_count,
144            num_bootstrap,
145            0,
146            da_committee_size,
147            reliability_config.clone(),
148            secondary_network_delay,
149        )
150    }
151}
152
153/// Trait for time compatibility needed for reward collection
154pub trait ConsensusTime:
155    PartialOrd
156    + Ord
157    + Send
158    + Sync
159    + Debug
160    + Clone
161    + Copy
162    + Hash
163    + Deref<Target = u64>
164    + serde::Serialize
165    + for<'de> serde::Deserialize<'de>
166    + ops::AddAssign<u64>
167    + ops::Add<u64, Output = Self>
168    + Sub<u64, Output = Self>
169    + 'static
170    + Committable
171{
172    /// Create a new instance of this time unit at time number 0
173    #[must_use]
174    fn genesis() -> Self {
175        Self::new(0)
176    }
177
178    /// Create a new instance of this time unit
179    fn new(val: u64) -> Self;
180
181    /// Get the u64 format of time
182    fn u64(&self) -> u64;
183}
184
185/// Trait with all the type definitions that are used in the current hotshot setup.
186pub trait NodeType:
187    Clone
188    + Copy
189    + Debug
190    + Hash
191    + PartialEq
192    + Eq
193    + PartialOrd
194    + Ord
195    + Default
196    + serde::Serialize
197    + for<'de> Deserialize<'de>
198    + Send
199    + Sync
200    + 'static
201{
202    /// Constants used to construct upgrade proposals
203    const UPGRADE_CONSTANTS: UpgradeConstants = DEFAULT_UPGRADE_CONSTANTS;
204    /// The time type that this hotshot setup is using.
205    ///
206    /// This should be the same `Time` that `ValidatedState::Time` is using.
207    type View: ConsensusTime + Display;
208    /// Same as above but for epoch.
209    type Epoch: ConsensusTime + Display;
210    /// The block header type that this hotshot setup is using.
211    type BlockHeader: BlockHeader<Self>;
212    /// The block type that this hotshot setup is using.
213    ///
214    /// This should be the same block that `ValidatedState::BlockPayload` is using.
215    type BlockPayload: BlockPayload<
216        Self,
217        Instance = Self::InstanceState,
218        Transaction = Self::Transaction,
219        ValidatedState = Self::ValidatedState,
220    >;
221    /// The signature key that this hotshot setup is using.
222    type SignatureKey: SignatureKey;
223    /// The transaction type that this hotshot setup is using.
224    ///
225    /// This should be equal to `BlockPayload::Transaction`
226    type Transaction: Transaction;
227
228    /// The instance-level state type that this hotshot setup is using.
229    type InstanceState: InstanceState;
230
231    /// The validated state type that this hotshot setup is using.
232    type ValidatedState: ValidatedState<Self, Instance = Self::InstanceState, Time = Self::View>;
233
234    /// Membership used for this implementation
235    type Membership: Membership<Self>;
236
237    /// The type builder uses to sign its messages
238    type BuilderSignatureKey: BuilderSignatureKey;
239
240    /// The type replica uses to sign the light client state
241    type StateSignatureKey: StateSignatureKey
242        + LCV1StateSignatureKey
243        + LCV2StateSignatureKey
244        + LCV3StateSignatureKey;
245}
246
247/// Version information for HotShot
248pub trait Versions: Clone + Copy + Debug + Send + Sync + 'static {
249    /// The base version of HotShot this node is instantiated with.
250    type Base: StaticVersionType;
251
252    /// The version of HotShot this node may be upgraded to. Set equal to `Base` to disable upgrades.
253    type Upgrade: StaticVersionType;
254
255    /// The hash for the upgrade.
256    const UPGRADE_HASH: [u8; 32];
257
258    /// The version at which to switch over to epochs logic
259    type Epochs: StaticVersionType;
260
261    /// The version at which to use the upgraded DRB difficulty
262    type DrbAndHeaderUpgrade: StaticVersionType;
263}