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,
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    /// Number of staking DA nodes
49    pub staked_da_nodes: usize,
50    /// Number of fixed leaders for GPU VID
51    pub fixed_leader_for_gpuvid: usize,
52    /// Base duration for next-view timeout, in milliseconds
53    pub next_view_timeout: u64,
54    /// Duration for view sync round timeout
55    pub view_sync_timeout: Duration,
56    /// Number of network bootstrap nodes
57    pub num_bootstrap: usize,
58    /// The maximum amount of time a leader can wait to get a block from a builder
59    pub builder_timeout: Duration,
60    /// Time to wait until we request data associated with a proposal
61    pub data_request_delay: Option<Duration>,
62    /// Builder API base URL
63    #[serde(default = "default_builder_urls")]
64    pub builder_urls: Vec1<Url>,
65    /// Upgrade config
66    pub upgrade: UpgradeConfig,
67    /// Number of blocks in an epoch, zero means there are no epochs
68    pub epoch_height: u64,
69    /// Epoch start block
70    pub epoch_start_block: u64,
71    /// Stake table capacity for light client use
72    #[serde(default = "default_stake_table_capacity")]
73    pub stake_table_capacity: usize,
74    #[serde(default = "default_drb_difficulty")]
75    /// number of iterations for DRB calculation
76    pub drb_difficulty: u64,
77    #[serde(default = "default_drb_upgrade_difficulty")]
78    /// number of iterations for DRB calculation
79    pub drb_upgrade_difficulty: u64,
80}
81
82fn default_stake_table_capacity() -> usize {
83    crate::light_client::DEFAULT_STAKE_TABLE_CAPACITY
84}
85
86impl<TYPES: NodeType> From<HotShotConfigFile<TYPES>> for HotShotConfig<TYPES> {
87    fn from(val: HotShotConfigFile<TYPES>) -> Self {
88        HotShotConfig {
89            start_threshold: val.start_threshold,
90            num_nodes_with_stake: val.num_nodes_with_stake,
91            known_da_nodes: val.known_da_nodes,
92            known_nodes_with_stake: val.known_nodes_with_stake,
93            da_staked_committee_size: val.staked_da_nodes,
94            fixed_leader_for_gpuvid: val.fixed_leader_for_gpuvid,
95            next_view_timeout: val.next_view_timeout,
96            view_sync_timeout: val.view_sync_timeout,
97            num_bootstrap: val.num_bootstrap,
98            builder_timeout: val.builder_timeout,
99            data_request_delay: val
100                .data_request_delay
101                .unwrap_or(Duration::from_millis(REQUEST_DATA_DELAY)),
102            builder_urls: val.builder_urls,
103            start_proposing_view: val.upgrade.start_proposing_view,
104            stop_proposing_view: val.upgrade.stop_proposing_view,
105            start_voting_view: val.upgrade.start_voting_view,
106            stop_voting_view: val.upgrade.stop_voting_view,
107            start_proposing_time: val.upgrade.start_proposing_time,
108            stop_proposing_time: val.upgrade.stop_proposing_time,
109            start_voting_time: val.upgrade.start_voting_time,
110            stop_voting_time: val.upgrade.stop_voting_time,
111            epoch_height: val.epoch_height,
112            epoch_start_block: val.epoch_start_block,
113            stake_table_capacity: val.stake_table_capacity,
114            drb_difficulty: val.drb_difficulty,
115            drb_upgrade_difficulty: val.drb_upgrade_difficulty,
116        }
117    }
118}
119
120impl<TYPES: NodeType> HotShotConfigFile<TYPES> {
121    /// Creates a new `HotShotConfigFile` with 5 nodes and 10 DA nodes.
122    ///
123    /// # Panics
124    ///
125    /// Cannot panic, but will if `NonZeroUsize` is somehow an error.
126    #[must_use]
127    pub fn hotshot_config_5_nodes_10_da() -> Self {
128        let staked_da_nodes: usize = 5;
129
130        let mut known_da_nodes = Vec::new();
131
132        let gen_known_nodes_with_stake = (0..10)
133            .map(|node_id| {
134                let mut cur_validator_config: ValidatorConfig<TYPES> =
135                    ValidatorConfig::generated_from_seed_indexed(
136                        [0u8; 32],
137                        node_id,
138                        U256::from(1),
139                        false,
140                    );
141
142                if node_id < staked_da_nodes as u64 {
143                    known_da_nodes.push(cur_validator_config.public_config());
144                    cur_validator_config.is_da = true;
145                }
146
147                cur_validator_config.public_config()
148            })
149            .collect();
150
151        Self {
152            num_nodes_with_stake: NonZeroUsize::new(10).unwrap(),
153            start_threshold: (1, 1),
154            known_nodes_with_stake: gen_known_nodes_with_stake,
155            staked_da_nodes,
156            known_da_nodes,
157            fixed_leader_for_gpuvid: 1,
158            next_view_timeout: 10000,
159            view_sync_timeout: Duration::from_millis(1000),
160            num_bootstrap: 5,
161            builder_timeout: Duration::from_secs(10),
162            data_request_delay: Some(Duration::from_millis(REQUEST_DATA_DELAY)),
163            builder_urls: default_builder_urls(),
164            upgrade: UpgradeConfig::default(),
165            epoch_height: 0,
166            epoch_start_block: 0,
167            stake_table_capacity: crate::light_client::DEFAULT_STAKE_TABLE_CAPACITY,
168            drb_difficulty: 10,
169            drb_upgrade_difficulty: 20,
170        }
171    }
172}