hotshot_types/
hotshot_config_file.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
7use std::{num::NonZeroUsize, time::Duration};
8
9use alloy::primitives::U256;
10use url::Url;
11use vec1::Vec1;
12
13use crate::{
14    constants::REQUEST_DATA_DELAY, upgrade_config::UpgradeConfig, HotShotConfig, NodeType,
15    PeerConfig, ValidatorConfig, VersionedDaCommittee,
16};
17
18/// Default builder URL, used as placeholder
19fn default_builder_urls() -> Vec1<Url> {
20    vec1::vec1![Url::parse("http://0.0.0.0:3311").unwrap()]
21}
22
23/// Default DRB difficulty, set to 0 (intended to be overwritten)
24fn default_drb_difficulty() -> u64 {
25    0
26}
27
28/// Default DRB upgrade difficulty, set to 0 (intended to be overwritten)
29fn default_drb_upgrade_difficulty() -> u64 {
30    0
31}
32
33/// Holds configuration for a `HotShot`
34#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
35#[serde(bound(deserialize = ""))]
36pub struct HotShotConfigFile<TYPES: NodeType> {
37    /// The proportion of nodes required before the orchestrator issues the ready signal,
38    /// expressed as (numerator, denominator)
39    pub start_threshold: (u64, u64),
40    /// Total number of staked nodes in the network
41    pub num_nodes_with_stake: NonZeroUsize,
42    #[serde(skip)]
43    /// The known nodes' public key and stake value
44    pub known_nodes_with_stake: Vec<PeerConfig<TYPES>>,
45    #[serde(skip)]
46    /// The known DA nodes' public key and stake values
47    pub known_da_nodes: Vec<PeerConfig<TYPES>>,
48    #[serde(skip)]
49    /// The known DA nodes' public keys and stake values, by start epoch
50    pub da_committees: Vec<VersionedDaCommittee<TYPES>>,
51    /// Number of staking DA nodes
52    pub staked_da_nodes: usize,
53    /// Number of fixed leaders for GPU VID
54    pub fixed_leader_for_gpuvid: usize,
55    /// Base duration for next-view timeout, in milliseconds
56    pub next_view_timeout: u64,
57    /// Duration for view sync round timeout
58    pub view_sync_timeout: Duration,
59    /// Number of network bootstrap nodes
60    pub num_bootstrap: usize,
61    /// The maximum amount of time a leader can wait to get a block from a builder
62    pub builder_timeout: Duration,
63    /// Time to wait until we request data associated with a proposal
64    pub data_request_delay: Option<Duration>,
65    /// Builder API base URL
66    #[serde(default = "default_builder_urls")]
67    pub builder_urls: Vec1<Url>,
68    /// Upgrade config
69    pub upgrade: UpgradeConfig,
70    /// Number of blocks in an epoch, zero means there are no epochs
71    pub epoch_height: u64,
72    /// Epoch start block
73    pub epoch_start_block: u64,
74    /// Stake table capacity for light client use
75    #[serde(default = "default_stake_table_capacity")]
76    pub stake_table_capacity: usize,
77    #[serde(default = "default_drb_difficulty")]
78    /// number of iterations for DRB calculation
79    pub drb_difficulty: u64,
80    #[serde(default = "default_drb_upgrade_difficulty")]
81    /// number of iterations for DRB calculation
82    pub drb_upgrade_difficulty: u64,
83}
84
85fn default_stake_table_capacity() -> usize {
86    crate::light_client::DEFAULT_STAKE_TABLE_CAPACITY
87}
88
89impl<TYPES: NodeType> From<HotShotConfigFile<TYPES>> for HotShotConfig<TYPES> {
90    fn from(val: HotShotConfigFile<TYPES>) -> Self {
91        HotShotConfig {
92            start_threshold: val.start_threshold,
93            num_nodes_with_stake: val.num_nodes_with_stake,
94            known_da_nodes: val.known_da_nodes,
95            da_committees: val.da_committees,
96            known_nodes_with_stake: val.known_nodes_with_stake,
97            da_staked_committee_size: val.staked_da_nodes,
98            fixed_leader_for_gpuvid: val.fixed_leader_for_gpuvid,
99            next_view_timeout: val.next_view_timeout,
100            view_sync_timeout: val.view_sync_timeout,
101            num_bootstrap: val.num_bootstrap,
102            builder_timeout: val.builder_timeout,
103            data_request_delay: val
104                .data_request_delay
105                .unwrap_or(Duration::from_millis(REQUEST_DATA_DELAY)),
106            builder_urls: val.builder_urls,
107            start_proposing_view: val.upgrade.start_proposing_view,
108            stop_proposing_view: val.upgrade.stop_proposing_view,
109            start_voting_view: val.upgrade.start_voting_view,
110            stop_voting_view: val.upgrade.stop_voting_view,
111            start_proposing_time: val.upgrade.start_proposing_time,
112            stop_proposing_time: val.upgrade.stop_proposing_time,
113            start_voting_time: val.upgrade.start_voting_time,
114            stop_voting_time: val.upgrade.stop_voting_time,
115            epoch_height: val.epoch_height,
116            epoch_start_block: val.epoch_start_block,
117            stake_table_capacity: val.stake_table_capacity,
118            drb_difficulty: val.drb_difficulty,
119            drb_upgrade_difficulty: val.drb_upgrade_difficulty,
120        }
121    }
122}
123
124impl<TYPES: NodeType> HotShotConfigFile<TYPES> {
125    /// Creates a new `HotShotConfigFile` with 5 nodes and 10 DA nodes.
126    ///
127    /// # Panics
128    ///
129    /// Cannot panic, but will if `NonZeroUsize` is somehow an error.
130    #[must_use]
131    pub fn hotshot_config_5_nodes_10_da() -> Self {
132        let staked_da_nodes: usize = 5;
133
134        let mut known_da_nodes = Vec::new();
135
136        let gen_known_nodes_with_stake = (0..10)
137            .map(|node_id| {
138                let mut cur_validator_config: ValidatorConfig<TYPES> =
139                    ValidatorConfig::generated_from_seed_indexed(
140                        [0u8; 32],
141                        node_id,
142                        U256::from(1),
143                        false,
144                    );
145
146                if node_id < staked_da_nodes as u64 {
147                    known_da_nodes.push(cur_validator_config.public_config());
148                    cur_validator_config.is_da = true;
149                }
150
151                cur_validator_config.public_config()
152            })
153            .collect();
154
155        Self {
156            num_nodes_with_stake: NonZeroUsize::new(10).unwrap(),
157            start_threshold: (1, 1),
158            known_nodes_with_stake: gen_known_nodes_with_stake,
159            staked_da_nodes,
160            known_da_nodes,
161            da_committees: Default::default(),
162            fixed_leader_for_gpuvid: 1,
163            next_view_timeout: 10000,
164            view_sync_timeout: Duration::from_millis(1000),
165            num_bootstrap: 5,
166            builder_timeout: Duration::from_secs(10),
167            data_request_delay: Some(Duration::from_millis(REQUEST_DATA_DELAY)),
168            builder_urls: default_builder_urls(),
169            upgrade: UpgradeConfig::default(),
170            epoch_height: 0,
171            epoch_start_block: 0,
172            stake_table_capacity: crate::light_client::DEFAULT_STAKE_TABLE_CAPACITY,
173            drb_difficulty: 10,
174            drb_upgrade_difficulty: 20,
175        }
176    }
177}