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