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