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::{collections::HashMap, fmt::Debug, hash::Hash, sync::Arc, time::Duration};
13
14use async_trait::async_trait;
15use serde::{Deserialize, Serialize};
16
17use super::{
18    ValidatedState,
19    block_contents::{BlockHeader, TestableBlock, Transaction},
20    network::{
21        AsyncGenerator, ConnectedNetwork, NetworkReliability, TestableNetworkingImplementation,
22    },
23    signature_key::{
24        BuilderSignatureKey, LCV1StateSignatureKey, LCV2StateSignatureKey, LCV3StateSignatureKey,
25        StateSignatureKey,
26    },
27    states::TestableState,
28    storage::Storage,
29};
30use crate::{
31    PeerConnectInfo,
32    constants::DEFAULT_UPGRADE_CONSTANTS,
33    data::{Leaf2, TestableLeaf},
34    traits::{
35        BlockPayload, election::Membership, signature_key::SignatureKey, states::InstanceState,
36    },
37    upgrade_config::UpgradeConstants,
38};
39
40/// Node implementation aggregate trait
41///
42/// This trait exists to collect multiple behavior implementations into one type, to allow
43/// `HotShot` to avoid annoying numbers of type arguments and type patching.
44///
45/// It is recommended you implement this trait on a zero sized type, as `HotShot`does not actually
46/// store or keep a reference to any value implementing this trait.
47pub trait NodeImplementation<TYPES: NodeType>:
48    Send + Sync + Clone + Eq + Hash + 'static + Serialize + for<'de> Deserialize<'de>
49{
50    /// The underlying network type
51    type Network: ConnectedNetwork<TYPES::SignatureKey>;
52
53    /// Storage for DA layer interactions
54    type Storage: Storage<TYPES>;
55}
56
57/// extra functions required on a node implementation to be usable by hotshot-testing
58#[allow(clippy::type_complexity)]
59#[async_trait]
60pub trait TestableNodeImplementation<TYPES: NodeType>: NodeImplementation<TYPES> {
61    /// Creates random transaction if possible
62    /// otherwise panics
63    /// `padding` is the bytes of padding to add to the transaction
64    fn state_create_random_transaction(
65        state: Option<&TYPES::ValidatedState>,
66        rng: &mut dyn rand::RngCore,
67        padding: u64,
68    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction;
69
70    /// Creates random transaction if possible
71    /// otherwise panics
72    /// `padding` is the bytes of padding to add to the transaction
73    fn leaf_create_random_transaction(
74        leaf: &Leaf2<TYPES>,
75        rng: &mut dyn rand::RngCore,
76        padding: u64,
77    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction;
78
79    /// generate a genesis block
80    fn block_genesis() -> TYPES::BlockPayload;
81
82    /// the number of transactions in a block
83    fn txn_count(block: &TYPES::BlockPayload) -> u64;
84
85    /// Generate the communication channels for testing
86    fn gen_networks(
87        expected_node_count: usize,
88        num_bootstrap: usize,
89        da_committee_size: usize,
90        reliability_config: Option<Box<dyn NetworkReliability>>,
91        secondary_network_delay: Duration,
92        connect_infos: &mut HashMap<TYPES::SignatureKey, PeerConnectInfo>,
93    ) -> AsyncGenerator<Arc<Self::Network>>;
94}
95
96#[async_trait]
97impl<TYPES: NodeType, I: NodeImplementation<TYPES>> TestableNodeImplementation<TYPES> for I
98where
99    TYPES::ValidatedState: TestableState<TYPES>,
100    TYPES::BlockPayload: TestableBlock<TYPES>,
101    I::Network: TestableNetworkingImplementation<TYPES>,
102{
103    fn state_create_random_transaction(
104        state: Option<&TYPES::ValidatedState>,
105        rng: &mut dyn rand::RngCore,
106        padding: u64,
107    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction {
108        <TYPES::ValidatedState as TestableState<TYPES>>::create_random_transaction(
109            state, rng, padding,
110        )
111    }
112
113    fn leaf_create_random_transaction(
114        leaf: &Leaf2<TYPES>,
115        rng: &mut dyn rand::RngCore,
116        padding: u64,
117    ) -> <TYPES::BlockPayload as BlockPayload<TYPES>>::Transaction {
118        Leaf2::create_random_transaction(leaf, rng, padding)
119    }
120
121    fn block_genesis() -> TYPES::BlockPayload {
122        <TYPES::BlockPayload as TestableBlock<TYPES>>::genesis()
123    }
124
125    fn txn_count(block: &TYPES::BlockPayload) -> u64 {
126        <TYPES::BlockPayload as TestableBlock<TYPES>>::txn_count(block)
127    }
128
129    fn gen_networks(
130        expected_node_count: usize,
131        num_bootstrap: usize,
132        da_committee_size: usize,
133        reliability_config: Option<Box<dyn NetworkReliability>>,
134        secondary_network_delay: Duration,
135        connect_infos: &mut HashMap<TYPES::SignatureKey, PeerConnectInfo>,
136    ) -> AsyncGenerator<Arc<Self::Network>> {
137        <I::Network as TestableNetworkingImplementation<TYPES>>::generator(
138            expected_node_count,
139            num_bootstrap,
140            0,
141            da_committee_size,
142            reliability_config.clone(),
143            secondary_network_delay,
144            connect_infos,
145        )
146    }
147}
148
149/// Trait with all the type definitions that are used in the current hotshot setup.
150pub trait NodeType:
151    Clone
152    + Copy
153    + Debug
154    + Hash
155    + PartialEq
156    + Eq
157    + Default
158    + serde::Serialize
159    + for<'de> Deserialize<'de>
160    + Send
161    + Sync
162    + 'static
163{
164    /// Constants used to construct upgrade proposals
165    const UPGRADE_CONSTANTS: UpgradeConstants = DEFAULT_UPGRADE_CONSTANTS;
166    /// The block header type that this hotshot setup is using.
167    type BlockHeader: BlockHeader<Self>;
168    /// The block type that this hotshot setup is using.
169    ///
170    /// This should be the same block that `ValidatedState::BlockPayload` is using.
171    type BlockPayload: BlockPayload<
172            Self,
173            Instance = Self::InstanceState,
174            Transaction = Self::Transaction,
175            ValidatedState = Self::ValidatedState,
176        >;
177    /// The signature key that this hotshot setup is using.
178    type SignatureKey: SignatureKey;
179    /// The transaction type that this hotshot setup is using.
180    ///
181    /// This should be equal to `BlockPayload::Transaction`
182    type Transaction: Transaction;
183
184    /// The instance-level state type that this hotshot setup is using.
185    type InstanceState: InstanceState;
186
187    /// The validated state type that this hotshot setup is using.
188    type ValidatedState: ValidatedState<Self, Instance = Self::InstanceState>;
189
190    /// Membership used for this implementation
191    type Membership: Membership<Self>;
192
193    /// The type builder uses to sign its messages
194    type BuilderSignatureKey: BuilderSignatureKey;
195
196    /// The type replica uses to sign the light client state
197    type StateSignatureKey: StateSignatureKey
198        + LCV1StateSignatureKey
199        + LCV2StateSignatureKey
200        + LCV3StateSignatureKey;
201}