1use std::{num::NonZeroUsize, time::Duration};
2
3use hotshot_types::{
4 HotShotConfig, PeerConfig, ValidatorConfig, VersionedDaCommittee,
5 addr::NetAddr,
6 network::{
7 BuilderType, CombinedNetworkConfig, Libp2pConfig, NetworkConfig, RandomBuilderConfig,
8 },
9 x25519,
10};
11use serde::{Deserialize, Serialize};
12use tide_disco::Url;
13use vec1::Vec1;
14
15use crate::{PubKey, SeqTypes};
16
17#[derive(Clone, Debug, Deserialize, Serialize)]
20pub struct PublicValidatorConfig {
21 public_key: PubKey,
22 stake_value: u64,
23 is_da: bool,
24 private_key: String,
25 state_public_key: String,
26 state_key_pair: String,
27 x25519_key: Option<x25519::PublicKey>,
28 p2p_addr: Option<NetAddr>,
29}
30
31impl From<ValidatorConfig<SeqTypes>> for PublicValidatorConfig {
32 fn from(v: ValidatorConfig<SeqTypes>) -> Self {
33 let ValidatorConfig::<SeqTypes> {
34 public_key,
35 private_key: _,
36 stake_value,
37 state_public_key,
38 state_private_key: _,
39 is_da,
40 p2p_addr,
41 x25519_keypair,
42 } = v;
43
44 Self {
45 public_key,
46 stake_value: stake_value.to::<u64>(),
47 is_da,
48 state_public_key: state_public_key.to_string(),
49 private_key: "*****".into(),
50 state_key_pair: "*****".into(),
51 x25519_key: x25519_keypair.map(|x| x.public_key()),
52 p2p_addr,
53 }
54 }
55}
56
57#[derive(Clone, Debug, Deserialize, Serialize)]
61pub struct PublicHotShotConfig {
62 start_threshold: (u64, u64),
63 num_nodes_with_stake: NonZeroUsize,
64 known_nodes_with_stake: Vec<PeerConfig<SeqTypes>>,
65 known_da_nodes: Vec<PeerConfig<SeqTypes>>,
66 #[serde(default)]
67 da_committees: Vec<VersionedDaCommittee<SeqTypes>>,
68 da_staked_committee_size: usize,
69 fixed_leader_for_gpuvid: usize,
70 next_view_timeout: u64,
71 view_sync_timeout: Duration,
72 num_bootstrap: usize,
73 builder_timeout: Duration,
74 data_request_delay: Duration,
75 builder_urls: Vec1<Url>,
76 start_proposing_view: u64,
77 stop_proposing_view: u64,
78 start_voting_view: u64,
79 stop_voting_view: u64,
80 start_proposing_time: u64,
81 stop_proposing_time: u64,
82 start_voting_time: u64,
83 stop_voting_time: u64,
84 epoch_height: u64,
85 epoch_start_block: u64,
86 #[serde(default = "default_stake_table_capacity")]
87 stake_table_capacity: usize,
88 #[serde(default = "default_drb_difficulty")]
89 drb_difficulty: u64,
90 #[serde(default = "default_drb_upgrade_difficulty")]
91 drb_upgrade_difficulty: u64,
92}
93
94fn default_stake_table_capacity() -> usize {
95 hotshot_types::light_client::DEFAULT_STAKE_TABLE_CAPACITY
96}
97
98fn default_drb_difficulty() -> u64 {
100 0
101}
102
103fn default_drb_upgrade_difficulty() -> u64 {
105 0
106}
107
108impl From<HotShotConfig<SeqTypes>> for PublicHotShotConfig {
109 fn from(v: HotShotConfig<SeqTypes>) -> Self {
110 let HotShotConfig::<SeqTypes> {
114 start_threshold,
115 num_nodes_with_stake,
116 known_nodes_with_stake,
117 known_da_nodes,
118 da_committees,
119 da_staked_committee_size,
120 fixed_leader_for_gpuvid,
121 next_view_timeout,
122 view_sync_timeout,
123 num_bootstrap,
124 builder_timeout,
125 data_request_delay,
126 builder_urls,
127 start_proposing_view,
128 stop_proposing_view,
129 start_voting_view,
130 stop_voting_view,
131 start_proposing_time,
132 stop_proposing_time,
133 start_voting_time,
134 stop_voting_time,
135 epoch_height,
136 epoch_start_block,
137 stake_table_capacity,
138 drb_difficulty,
139 drb_upgrade_difficulty,
140 } = v;
141
142 Self {
143 start_threshold,
144 num_nodes_with_stake,
145 known_nodes_with_stake,
146 known_da_nodes,
147 da_committees,
148 da_staked_committee_size,
149 fixed_leader_for_gpuvid,
150 next_view_timeout,
151 view_sync_timeout,
152 num_bootstrap,
153 builder_timeout,
154 data_request_delay,
155 builder_urls,
156 start_proposing_view,
157 stop_proposing_view,
158 start_voting_view,
159 stop_voting_view,
160 start_proposing_time,
161 stop_proposing_time,
162 start_voting_time,
163 stop_voting_time,
164 epoch_height,
165 epoch_start_block,
166 stake_table_capacity,
167 drb_difficulty,
168 drb_upgrade_difficulty,
169 }
170 }
171}
172
173impl PublicHotShotConfig {
174 pub fn into_hotshot_config(self) -> HotShotConfig<SeqTypes> {
175 HotShotConfig {
176 start_threshold: self.start_threshold,
177 num_nodes_with_stake: self.num_nodes_with_stake,
178 known_nodes_with_stake: self.known_nodes_with_stake,
179 known_da_nodes: self.known_da_nodes,
180 da_committees: self.da_committees,
181 da_staked_committee_size: self.da_staked_committee_size,
182 fixed_leader_for_gpuvid: self.fixed_leader_for_gpuvid,
183 next_view_timeout: self.next_view_timeout,
184 view_sync_timeout: self.view_sync_timeout,
185 num_bootstrap: self.num_bootstrap,
186 builder_timeout: self.builder_timeout,
187 data_request_delay: self.data_request_delay,
188 builder_urls: self.builder_urls,
189 start_proposing_view: self.start_proposing_view,
190 stop_proposing_view: self.stop_proposing_view,
191 start_voting_view: self.start_voting_view,
192 stop_voting_view: self.stop_voting_view,
193 start_proposing_time: self.start_proposing_time,
194 stop_proposing_time: self.stop_proposing_time,
195 start_voting_time: self.start_voting_time,
196 stop_voting_time: self.stop_voting_time,
197 epoch_height: self.epoch_height,
198 epoch_start_block: self.epoch_start_block,
199 stake_table_capacity: self.stake_table_capacity,
200 drb_difficulty: self.drb_difficulty,
201 drb_upgrade_difficulty: self.drb_upgrade_difficulty,
202 }
203 }
204
205 pub fn known_nodes_with_stake(&self) -> Vec<PeerConfig<SeqTypes>> {
206 self.known_nodes_with_stake.clone()
207 }
208
209 pub fn known_da_nodes(&self) -> Vec<PeerConfig<SeqTypes>> {
210 self.known_da_nodes.clone()
211 }
212
213 pub fn blocks_per_epoch(&self) -> u64 {
214 self.epoch_height
215 }
216
217 pub fn epoch_start_block(&self) -> u64 {
218 self.epoch_start_block
219 }
220}
221
222#[derive(Clone, Debug, Deserialize, Serialize)]
223pub struct PublicNetworkConfig {
224 rounds: usize,
225 indexed_da: bool,
226 transactions_per_round: usize,
227 manual_start_password: Option<String>,
228 num_bootrap: usize,
229 next_view_timeout: u64,
230 view_sync_timeout: Duration,
231 builder_timeout: Duration,
232 data_request_delay: Duration,
233 node_index: u64,
234 seed: [u8; 32],
235 transaction_size: usize,
236 key_type_name: String,
237 libp2p_config: Option<Libp2pConfig>,
238 config: PublicHotShotConfig,
239 cdn_marshal_address: Option<String>,
240 combined_network_config: Option<CombinedNetworkConfig>,
241 commit_sha: String,
242 builder: BuilderType,
243 random_builder: Option<RandomBuilderConfig>,
244}
245
246impl From<NetworkConfig<SeqTypes>> for PublicNetworkConfig {
247 fn from(cfg: NetworkConfig<SeqTypes>) -> Self {
248 Self {
249 rounds: cfg.rounds,
250 indexed_da: cfg.indexed_da,
251 transactions_per_round: cfg.transactions_per_round,
252 manual_start_password: Some("*****".into()),
253 num_bootrap: cfg.num_bootrap,
254 next_view_timeout: cfg.next_view_timeout,
255 view_sync_timeout: cfg.view_sync_timeout,
256 builder_timeout: cfg.builder_timeout,
257 data_request_delay: cfg.data_request_delay,
258 node_index: cfg.node_index,
259 seed: cfg.seed,
260 transaction_size: cfg.transaction_size,
261 key_type_name: cfg.key_type_name,
262 libp2p_config: cfg.libp2p_config,
263 config: cfg.config.into(),
264 cdn_marshal_address: cfg.cdn_marshal_address,
265 combined_network_config: cfg.combined_network_config,
266 commit_sha: cfg.commit_sha,
267 builder: cfg.builder,
268 random_builder: cfg.random_builder,
269 }
270 }
271}
272
273impl PublicNetworkConfig {
274 pub fn into_network_config(
275 self,
276 my_own_validator_config: ValidatorConfig<SeqTypes>,
277 ) -> anyhow::Result<NetworkConfig<SeqTypes>> {
278 let node_index = self
279 .config
280 .known_nodes_with_stake
281 .iter()
282 .position(|peer| peer.stake_table_entry.stake_key == my_own_validator_config.public_key)
283 .unwrap_or(0) as u64;
284
285 Ok(NetworkConfig {
286 rounds: self.rounds,
287 indexed_da: self.indexed_da,
288 transactions_per_round: self.transactions_per_round,
289 manual_start_password: self.manual_start_password,
290 num_bootrap: self.num_bootrap,
291 next_view_timeout: self.next_view_timeout,
292 view_sync_timeout: self.view_sync_timeout,
293 builder_timeout: self.builder_timeout,
294 data_request_delay: self.data_request_delay,
295 node_index,
296 seed: self.seed,
297 transaction_size: self.transaction_size,
298 key_type_name: self.key_type_name,
299 libp2p_config: self.libp2p_config,
300 config: self.config.into_hotshot_config(),
301 cdn_marshal_address: self.cdn_marshal_address,
302 combined_network_config: self.combined_network_config,
303 commit_sha: self.commit_sha,
304 builder: self.builder,
305 random_builder: self.random_builder,
306 public_keys: Vec::new(),
307 })
308 }
309
310 pub fn hotshot_config(&self) -> PublicHotShotConfig {
311 self.config.clone()
312 }
313}
314
315#[cfg(test)]
316mod tests {
317 use super::PublicNetworkConfig;
318
319 #[test]
320 fn test_deserialize_from_old_config() {
321 let json_str = r#"
323 {
324 "rounds": 100,
325 "indexed_da": false,
326 "transactions_per_round": 10,
327 "manual_start_password": "*****",
328 "num_bootrap": 5,
329 "next_view_timeout": 10,
330 "view_sync_timeout": {
331 "secs": 2,
332 "nanos": 0
333 },
334 "builder_timeout": {
335 "secs": 10,
336 "nanos": 0
337 },
338 "data_request_delay": {
339 "secs": 2,
340 "nanos": 500000000
341 },
342 "node_index": 1,
343 "seed": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
344 "transaction_size": 100,
345 "key_type_name": "jf_signature::bls_over_bn254::VerKey",
346 "libp2p_config": {
347 "bootstrap_nodes": []
348 },
349 "config": {
350 "start_threshold": [100, 100],
351 "num_nodes_with_stake": 100,
352 "known_nodes_with_stake": [],
353 "known_da_nodes": [],
354 "da_staked_committee_size": 100,
355 "fixed_leader_for_gpuvid": 1,
356 "next_view_timeout": 12000,
357 "view_sync_timeout": {
358 "secs": 1,
359 "nanos": 0
360 },
361 "num_bootstrap": 5,
362 "builder_timeout": {
363 "secs": 8,
364 "nanos": 0
365 },
366 "data_request_delay": {
367 "secs": 5,
368 "nanos": 0
369 },
370 "builder_urls": [
371 "https://builder.decaf.testnet.espresso.network/"
372 ],
373 "start_proposing_view": 0,
374 "stop_proposing_view": 0,
375 "start_voting_view": 0,
376 "stop_voting_view": 0,
377 "start_proposing_time": 0,
378 "stop_proposing_time": 0,
379 "start_voting_time": 0,
380 "stop_voting_time": 0,
381 "epoch_height": 3000,
382 "epoch_start_block": 3160636
383 },
384 "cdn_marshal_address": null,
385 "combined_network_config": null,
386 "commit_sha": "",
387 "builder": "Simple",
388 "random_builder": null
389}
390 "#;
391 let _public_config: PublicNetworkConfig = serde_json::from_str(json_str).unwrap();
392 }
393}