1use std::path::PathBuf;
5use std::time::Duration;
6use std::{num::NonZeroUsize, path::Path, sync::Arc};
7
8use mysten_common::ZipDebugEqIteratorExt;
9use mysten_common::in_test_configuration;
10use rand::rngs::OsRng;
11use sui_config::ExecutionCacheConfig;
12use sui_config::genesis::{TokenAllocation, TokenDistributionScheduleBuilder};
13#[cfg(msim)]
14use sui_config::node::ExecutionTimeObserverConfig;
15use sui_config::node::FundsWithdrawSchedulerType;
16use sui_config::node::{AuthorityOverloadConfig, ConsensusTransactionPoolConfig};
17use sui_config::transaction_deny_config::PeerDenySyncConfig;
18use sui_protocol_config::Chain;
19use sui_types::base_types::{AuthorityName, SuiAddress};
20use sui_types::committee::{Committee, ProtocolVersion};
21use sui_types::crypto::{
22 AccountKeyPair, AuthorityKeyPair, KeypairTraits, PublicKey, get_key_pair_from_rng,
23};
24use sui_types::object::Object;
25use sui_types::supported_protocol_versions::SupportedProtocolVersions;
26use sui_types::traffic_control::{PolicyConfig, RemoteFirewallConfig};
27
28use consensus_config::ObserverParameters;
29
30use crate::genesis_config::{AccountConfig, DEFAULT_GAS_AMOUNT, ValidatorGenesisConfigBuilder};
31use crate::genesis_config::{GenesisConfig, ValidatorGenesisConfig};
32use crate::network_config::NetworkConfig;
33use crate::node_config_builder::ValidatorConfigBuilder;
34
35pub type ValidatorObserverConfigCallback =
36 Arc<dyn Fn(usize) -> Option<ObserverParameters> + Send + Sync + 'static>;
37
38pub struct KeyPairWrapper {
39 pub account_key_pair: AccountKeyPair,
40 pub protocol_key_pair: Option<AuthorityKeyPair>,
41}
42
43impl Clone for KeyPairWrapper {
44 fn clone(&self) -> Self {
45 Self {
46 account_key_pair: self.account_key_pair.copy(),
47 protocol_key_pair: self.protocol_key_pair.as_ref().map(|k| k.copy()),
48 }
49 }
50}
51
52pub enum CommitteeConfig {
53 Size(NonZeroUsize),
54 Validators(Vec<ValidatorGenesisConfig>),
55 AccountKeys(Vec<AccountKeyPair>),
56 Deterministic((NonZeroUsize, Option<Vec<KeyPairWrapper>>)),
59}
60
61pub type SupportedProtocolVersionsCallback = Arc<
62 dyn Fn(
63 usize, Option<AuthorityName>, ) -> SupportedProtocolVersions
66 + Send
67 + Sync
68 + 'static,
69>;
70
71#[derive(Clone)]
72pub enum ProtocolVersionsConfig {
73 Default,
75 Global(SupportedProtocolVersions),
77 PerValidator(SupportedProtocolVersionsCallback),
80}
81
82pub type GlobalStateHashV2EnabledCallback = Arc<dyn Fn(usize) -> bool + Send + Sync + 'static>;
83
84#[derive(Clone)]
85pub enum GlobalStateHashV2EnabledConfig {
86 Global(bool),
87 PerValidator(GlobalStateHashV2EnabledCallback),
88}
89
90pub type FundsWithdrawSchedulerTypeCallback =
91 Arc<dyn Fn(usize) -> FundsWithdrawSchedulerType + Send + Sync + 'static>;
92
93#[derive(Clone)]
94pub enum FundsWithdrawSchedulerTypeConfig {
95 Global(FundsWithdrawSchedulerType),
96 PerValidator(FundsWithdrawSchedulerTypeCallback),
97}
98
99pub type PeerDenySyncConfigCallback =
104 Arc<dyn Fn(AuthorityName, &[AuthorityName]) -> PeerDenySyncConfig + Send + Sync + 'static>;
105
106pub struct ConfigBuilder<R = OsRng> {
107 rng: Option<R>,
108 config_directory: PathBuf,
109 supported_protocol_versions_config: Option<ProtocolVersionsConfig>,
110 chain_override: Option<Chain>,
111 committee: CommitteeConfig,
112 genesis_config: Option<GenesisConfig>,
113 reference_gas_price: Option<u64>,
114 additional_objects: Vec<Object>,
115 jwk_fetch_interval: Option<Duration>,
116 num_unpruned_validators: Option<usize>,
117 authority_overload_config: Option<AuthorityOverloadConfig>,
118 consensus_transaction_pool_config: Option<ConsensusTransactionPoolConfig>,
119 execution_cache_config: Option<ExecutionCacheConfig>,
120 data_ingestion_dir: Option<PathBuf>,
121 policy_config: Option<PolicyConfig>,
122 firewall_config: Option<RemoteFirewallConfig>,
123 global_state_hash_v2_enabled_config: Option<GlobalStateHashV2EnabledConfig>,
124 funds_withdraw_scheduler_type_config: Option<FundsWithdrawSchedulerTypeConfig>,
125 state_sync_config: Option<sui_config::p2p::StateSyncConfig>,
126 peer_deny_sync_config: Option<PeerDenySyncConfigCallback>,
127 #[cfg(msim)]
128 execution_time_observer_config: Option<ExecutionTimeObserverConfig>,
129 validator_observer_config: Option<ValidatorObserverConfigCallback>,
130}
131
132impl ConfigBuilder {
133 pub fn new<P: AsRef<Path>>(config_directory: P) -> Self {
134 let funds_withdraw_scheduler_type_config = if in_test_configuration() {
138 Some(FundsWithdrawSchedulerTypeConfig::PerValidator(Arc::new(
139 |idx| {
140 if idx % 2 == 0 {
141 FundsWithdrawSchedulerType::Eager
142 } else {
143 FundsWithdrawSchedulerType::Naive
144 }
145 },
146 )))
147 } else {
148 None
149 };
150
151 Self {
152 rng: Some(OsRng),
153 config_directory: config_directory.as_ref().into(),
154 supported_protocol_versions_config: None,
155 chain_override: None,
156 committee: CommitteeConfig::Size(NonZeroUsize::new(1).unwrap()),
159 genesis_config: None,
160 reference_gas_price: None,
161 additional_objects: vec![],
162 jwk_fetch_interval: None,
163 num_unpruned_validators: None,
164 authority_overload_config: None,
165 consensus_transaction_pool_config: None,
166 execution_cache_config: None,
167 data_ingestion_dir: None,
168 policy_config: None,
169 firewall_config: None,
170 global_state_hash_v2_enabled_config: None,
171 funds_withdraw_scheduler_type_config,
172 state_sync_config: None,
173 peer_deny_sync_config: None,
174 #[cfg(msim)]
175 execution_time_observer_config: None,
176 validator_observer_config: None,
177 }
178 }
179
180 pub fn new_with_temp_dir() -> Self {
181 Self::new(mysten_common::tempdir().unwrap().keep())
182 }
183}
184
185impl<R> ConfigBuilder<R> {
186 pub fn committee(mut self, committee: CommitteeConfig) -> Self {
187 self.committee = committee;
188 self
189 }
190
191 pub fn committee_size(mut self, committee_size: NonZeroUsize) -> Self {
192 self.committee = CommitteeConfig::Size(committee_size);
193 self
194 }
195
196 pub fn deterministic_committee_size(mut self, committee_size: NonZeroUsize) -> Self {
197 self.committee = CommitteeConfig::Deterministic((committee_size, None));
198 self
199 }
200
201 pub fn deterministic_committee_validators(mut self, keys: Vec<KeyPairWrapper>) -> Self {
202 self.committee = CommitteeConfig::Deterministic((
203 NonZeroUsize::new(keys.len()).expect("Validator keys should be non empty"),
204 Some(keys),
205 ));
206 self
207 }
208
209 pub fn with_validator_account_keys(mut self, keys: Vec<AccountKeyPair>) -> Self {
210 self.committee = CommitteeConfig::AccountKeys(keys);
211 self
212 }
213
214 pub fn with_validators(mut self, validators: Vec<ValidatorGenesisConfig>) -> Self {
215 self.committee = CommitteeConfig::Validators(validators);
216 self
217 }
218
219 pub fn with_genesis_config(mut self, genesis_config: GenesisConfig) -> Self {
220 assert!(self.genesis_config.is_none(), "Genesis config already set");
221 self.genesis_config = Some(genesis_config);
222 self
223 }
224
225 pub fn with_chain_override(mut self, chain: Chain) -> Self {
226 assert!(self.chain_override.is_none(), "Chain override already set");
227 self.chain_override = Some(chain);
228 self
229 }
230
231 pub fn with_num_unpruned_validators(mut self, n: usize) -> Self {
232 self.num_unpruned_validators = Some(n);
233 self
234 }
235
236 pub fn with_jwk_fetch_interval(mut self, i: Duration) -> Self {
237 self.jwk_fetch_interval = Some(i);
238 self
239 }
240
241 pub fn with_data_ingestion_dir(mut self, path: PathBuf) -> Self {
242 self.data_ingestion_dir = Some(path);
243 self
244 }
245
246 pub fn with_reference_gas_price(mut self, reference_gas_price: u64) -> Self {
247 self.reference_gas_price = Some(reference_gas_price);
248 self
249 }
250
251 pub fn with_accounts(mut self, accounts: Vec<AccountConfig>) -> Self {
252 self.get_or_init_genesis_config().accounts = accounts;
253 self
254 }
255
256 pub fn with_chain_start_timestamp_ms(mut self, chain_start_timestamp_ms: u64) -> Self {
257 self.get_or_init_genesis_config()
258 .parameters
259 .chain_start_timestamp_ms = chain_start_timestamp_ms;
260 self
261 }
262
263 pub fn with_objects<I: IntoIterator<Item = Object>>(mut self, objects: I) -> Self {
264 self.additional_objects.extend(objects);
265 self
266 }
267
268 pub fn with_epoch_duration(mut self, epoch_duration_ms: u64) -> Self {
269 self.get_or_init_genesis_config()
270 .parameters
271 .epoch_duration_ms = epoch_duration_ms;
272 self
273 }
274
275 pub fn with_protocol_version(mut self, protocol_version: ProtocolVersion) -> Self {
276 self.get_or_init_genesis_config()
277 .parameters
278 .protocol_version = protocol_version;
279 self
280 }
281
282 pub fn with_supported_protocol_versions(mut self, c: SupportedProtocolVersions) -> Self {
283 self.supported_protocol_versions_config = Some(ProtocolVersionsConfig::Global(c));
284 self
285 }
286
287 pub fn with_supported_protocol_version_callback(
288 mut self,
289 func: SupportedProtocolVersionsCallback,
290 ) -> Self {
291 self.supported_protocol_versions_config = Some(ProtocolVersionsConfig::PerValidator(func));
292 self
293 }
294
295 pub fn with_supported_protocol_versions_config(mut self, c: ProtocolVersionsConfig) -> Self {
296 self.supported_protocol_versions_config = Some(c);
297 self
298 }
299
300 pub fn with_global_state_hash_v2_enabled(mut self, enabled: bool) -> Self {
301 self.global_state_hash_v2_enabled_config =
302 Some(GlobalStateHashV2EnabledConfig::Global(enabled));
303 self
304 }
305
306 pub fn with_global_state_hash_v2_enabled_callback(
307 mut self,
308 func: GlobalStateHashV2EnabledCallback,
309 ) -> Self {
310 self.global_state_hash_v2_enabled_config =
311 Some(GlobalStateHashV2EnabledConfig::PerValidator(func));
312 self
313 }
314
315 pub fn with_global_state_hash_v2_enabled_config(
316 mut self,
317 c: GlobalStateHashV2EnabledConfig,
318 ) -> Self {
319 self.global_state_hash_v2_enabled_config = Some(c);
320 self
321 }
322
323 pub fn with_funds_withdraw_scheduler_type(
324 mut self,
325 scheduler_type: FundsWithdrawSchedulerType,
326 ) -> Self {
327 self.funds_withdraw_scheduler_type_config =
328 Some(FundsWithdrawSchedulerTypeConfig::Global(scheduler_type));
329 self
330 }
331
332 pub fn with_funds_withdraw_scheduler_type_callback(
333 mut self,
334 func: FundsWithdrawSchedulerTypeCallback,
335 ) -> Self {
336 self.funds_withdraw_scheduler_type_config =
337 Some(FundsWithdrawSchedulerTypeConfig::PerValidator(func));
338 self
339 }
340
341 pub fn with_funds_withdraw_scheduler_type_config(
342 mut self,
343 c: FundsWithdrawSchedulerTypeConfig,
344 ) -> Self {
345 self.funds_withdraw_scheduler_type_config = Some(c);
346 self
347 }
348
349 #[cfg(msim)]
350 pub fn with_execution_time_observer_config(mut self, c: ExecutionTimeObserverConfig) -> Self {
351 self.execution_time_observer_config = Some(c);
352 self
353 }
354
355 pub fn with_validator_observer_config(mut self, c: ValidatorObserverConfigCallback) -> Self {
356 self.validator_observer_config = Some(c);
357 self
358 }
359
360 pub fn with_authority_overload_config(mut self, c: AuthorityOverloadConfig) -> Self {
361 self.authority_overload_config = Some(c);
362 self
363 }
364
365 pub fn with_consensus_transaction_pool_config(
366 mut self,
367 config: ConsensusTransactionPoolConfig,
368 ) -> Self {
369 self.consensus_transaction_pool_config = Some(config);
370 self
371 }
372
373 pub fn with_execution_cache_config(mut self, c: ExecutionCacheConfig) -> Self {
374 self.execution_cache_config = Some(c);
375 self
376 }
377
378 pub fn with_policy_config(mut self, config: Option<PolicyConfig>) -> Self {
379 self.policy_config = config;
380 self
381 }
382
383 pub fn with_firewall_config(mut self, config: Option<RemoteFirewallConfig>) -> Self {
384 self.firewall_config = config;
385 self
386 }
387
388 pub fn rng<N: rand::RngCore + rand::CryptoRng>(self, rng: N) -> ConfigBuilder<N> {
389 ConfigBuilder {
390 rng: Some(rng),
391 config_directory: self.config_directory,
392 supported_protocol_versions_config: self.supported_protocol_versions_config,
393 committee: self.committee,
394 genesis_config: self.genesis_config,
395 chain_override: self.chain_override,
396 reference_gas_price: self.reference_gas_price,
397 additional_objects: self.additional_objects,
398 num_unpruned_validators: self.num_unpruned_validators,
399 jwk_fetch_interval: self.jwk_fetch_interval,
400 authority_overload_config: self.authority_overload_config,
401 consensus_transaction_pool_config: self.consensus_transaction_pool_config,
402 execution_cache_config: self.execution_cache_config,
403 data_ingestion_dir: self.data_ingestion_dir,
404 policy_config: self.policy_config,
405 firewall_config: self.firewall_config,
406 global_state_hash_v2_enabled_config: self.global_state_hash_v2_enabled_config,
407 funds_withdraw_scheduler_type_config: self.funds_withdraw_scheduler_type_config,
408 state_sync_config: self.state_sync_config,
409 peer_deny_sync_config: self.peer_deny_sync_config,
410 #[cfg(msim)]
411 execution_time_observer_config: self.execution_time_observer_config,
412 validator_observer_config: self.validator_observer_config,
413 }
414 }
415
416 pub fn with_state_sync_config(mut self, config: sui_config::p2p::StateSyncConfig) -> Self {
417 self.state_sync_config = Some(config);
418 self
419 }
420
421 pub fn with_peer_deny_sync_config_per_validator(
426 mut self,
427 f: PeerDenySyncConfigCallback,
428 ) -> Self {
429 self.peer_deny_sync_config = Some(f);
430 self
431 }
432
433 fn get_or_init_genesis_config(&mut self) -> &mut GenesisConfig {
434 if self.genesis_config.is_none() {
435 self.genesis_config = Some(GenesisConfig::for_local_testing());
436 }
437 self.genesis_config.as_mut().unwrap()
438 }
439}
440
441impl<R: rand::RngCore + rand::CryptoRng> ConfigBuilder<R> {
442 pub fn build(self) -> NetworkConfig {
444 let committee = self.committee;
445
446 let mut rng = self.rng.unwrap();
447 let validators = match committee {
448 CommitteeConfig::Size(size) => {
449 let (_, keys) = Committee::new_simple_test_committee_of_size(size.into());
454
455 keys.into_iter()
456 .map(|authority_key| {
457 let mut builder = ValidatorGenesisConfigBuilder::new()
458 .with_protocol_key_pair(authority_key);
459 if let Some(rgp) = self.reference_gas_price {
460 builder = builder.with_gas_price(rgp);
461 }
462 builder.build(&mut rng)
463 })
464 .collect::<Vec<_>>()
465 }
466
467 CommitteeConfig::Validators(v) => v,
468
469 CommitteeConfig::AccountKeys(keys) => {
470 let (_, protocol_keys) = Committee::new_simple_test_committee_of_size(keys.len());
472 keys.into_iter()
473 .zip_debug_eq(protocol_keys)
474 .map(|(account_key, protocol_key)| {
475 let mut builder = ValidatorGenesisConfigBuilder::new()
476 .with_protocol_key_pair(protocol_key)
477 .with_account_key_pair(account_key);
478 if let Some(rgp) = self.reference_gas_price {
479 builder = builder.with_gas_price(rgp);
480 }
481 builder.build(&mut rng)
482 })
483 .collect::<Vec<_>>()
484 }
485 CommitteeConfig::Deterministic((size, key_pair_wrappers)) => {
486 let keys = key_pair_wrappers.unwrap_or_else(|| {
488 (0..size.get())
489 .map(|_| KeyPairWrapper {
490 account_key_pair: get_key_pair_from_rng(&mut rng).1,
491 protocol_key_pair: None,
492 })
493 .collect()
494 });
495
496 let mut configs = vec![];
497 for (i, key) in keys.into_iter().enumerate() {
498 let port_offset = 8000 + i * 10;
499 let mut builder = ValidatorGenesisConfigBuilder::new()
500 .with_ip("127.0.0.1".to_owned())
501 .with_account_key_pair(key.account_key_pair)
502 .with_deterministic_ports(port_offset as u16);
503 if let Some(protocol_key_pair) = key.protocol_key_pair {
504 builder = builder.with_protocol_key_pair(protocol_key_pair);
505 }
506 if let Some(rgp) = self.reference_gas_price {
507 builder = builder.with_gas_price(rgp);
508 }
509 configs.push(builder.build(&mut rng));
510 }
511 configs
512 }
513 };
514
515 if validators.len() == 1 {
518 const MSG: &str = "is per-validator but the committee has a single validator";
519 assert!(
520 !matches!(
521 self.supported_protocol_versions_config,
522 Some(ProtocolVersionsConfig::PerValidator(_))
523 ),
524 "supported protocol versions {MSG}"
525 );
526 assert!(
527 !matches!(
528 self.global_state_hash_v2_enabled_config,
529 Some(GlobalStateHashV2EnabledConfig::PerValidator(_))
530 ),
531 "global state hash v2 {MSG}"
532 );
533 assert!(
534 self.peer_deny_sync_config.is_none(),
535 "peer deny sync config {MSG}"
536 );
537 }
538
539 let genesis_config = self
540 .genesis_config
541 .unwrap_or_else(GenesisConfig::for_local_testing);
542
543 let (account_keys, allocations) = genesis_config.generate_accounts(&mut rng).unwrap();
544
545 let token_distribution_schedule = {
546 let mut builder = TokenDistributionScheduleBuilder::new();
547 for allocation in allocations {
548 builder.add_allocation(allocation);
549 }
550 for validator in &validators {
552 let account_key: PublicKey = validator.account_key_pair.public();
553 let address = SuiAddress::from(&account_key);
554 let gas_coin = TokenAllocation {
556 recipient_address: address,
557 amount_mist: DEFAULT_GAS_AMOUNT,
558 staked_with_validator: None,
559 };
560 let stake = TokenAllocation {
561 recipient_address: address,
562 amount_mist: validator.stake,
563 staked_with_validator: Some(address),
564 };
565 builder.add_allocation(gas_coin);
566 builder.add_allocation(stake);
567 }
568 builder.build()
569 };
570
571 let genesis = {
572 let mut builder = sui_genesis_builder::Builder::new()
573 .with_parameters(genesis_config.parameters)
574 .add_objects(self.additional_objects);
575
576 for (i, validator) in validators.iter().enumerate() {
577 let name = validator
578 .name
579 .clone()
580 .unwrap_or(format!("validator-{i}").to_string());
581 let validator_info = validator.to_validator_info(name);
582 builder =
583 builder.add_validator(validator_info.info, validator_info.proof_of_possession);
584 }
585
586 builder = builder.with_token_distribution_schedule(token_distribution_schedule);
587
588 for validator in &validators {
589 builder = builder.add_validator_signature(&validator.key_pair);
590 }
591
592 builder.build()
593 };
594
595 let all_authority_names: Vec<AuthorityName> = validators
596 .iter()
597 .map(|v| v.key_pair.public().into())
598 .collect();
599 let validator_configs = validators
600 .into_iter()
601 .enumerate()
602 .map(|(idx, validator)| {
603 let mut builder = ValidatorConfigBuilder::new()
604 .with_config_directory(self.config_directory.clone())
605 .with_policy_config(self.policy_config.clone())
606 .with_firewall_config(self.firewall_config.clone());
607
608 if let Some(chain) = self.chain_override {
609 builder = builder.with_chain_override(chain);
610 }
611
612 if let Some(jwk_fetch_interval) = self.jwk_fetch_interval {
613 builder = builder.with_jwk_fetch_interval(jwk_fetch_interval);
614 }
615
616 if let Some(authority_overload_config) = &self.authority_overload_config {
617 builder =
618 builder.with_authority_overload_config(authority_overload_config.clone());
619 }
620
621 if let Some(config) = &self.consensus_transaction_pool_config {
622 builder = builder.with_consensus_transaction_pool_config(config.clone());
623 }
624
625 if let Some(execution_cache_config) = &self.execution_cache_config {
626 builder = builder.with_execution_cache_config(execution_cache_config.clone());
627 }
628
629 if let Some(path) = &self.data_ingestion_dir {
630 builder = builder.with_data_ingestion_dir(path.clone());
631 }
632
633 if let Some(state_sync_config) = &self.state_sync_config {
634 builder = builder.with_state_sync_config(state_sync_config.clone());
635 }
636
637 #[cfg(msim)]
638 if let Some(execution_time_observer_config) = &self.execution_time_observer_config {
639 builder = builder.with_execution_time_observer_config(
640 execution_time_observer_config.clone(),
641 );
642 }
643
644 if let Some(spvc) = &self.supported_protocol_versions_config {
645 let supported_versions = match spvc {
646 ProtocolVersionsConfig::Default => {
647 SupportedProtocolVersions::SYSTEM_DEFAULT
648 }
649 ProtocolVersionsConfig::Global(v) => *v,
650 ProtocolVersionsConfig::PerValidator(func) => {
651 func(idx, Some(validator.key_pair.public().into()))
652 }
653 };
654 builder = builder.with_supported_protocol_versions(supported_versions);
655 }
656 if let Some(acc_v2_config) = &self.global_state_hash_v2_enabled_config {
657 let global_state_hash_v2_enabled: bool = match acc_v2_config {
658 GlobalStateHashV2EnabledConfig::Global(enabled) => *enabled,
659 GlobalStateHashV2EnabledConfig::PerValidator(func) => func(idx),
660 };
661 builder =
662 builder.with_global_state_hash_v2_enabled(global_state_hash_v2_enabled);
663 }
664 if let Some(scheduler_type_config) = &self.funds_withdraw_scheduler_type_config {
665 let scheduler_type = match scheduler_type_config {
666 FundsWithdrawSchedulerTypeConfig::Global(t) => *t,
667 FundsWithdrawSchedulerTypeConfig::PerValidator(func) => func(idx),
668 };
669 builder = builder.with_funds_withdraw_scheduler_type(scheduler_type);
670 }
671 if let Some(observer_config_fn) = &self.validator_observer_config
672 && let Some(observer_config) = observer_config_fn(idx)
673 {
674 builder = builder.with_observer_config(observer_config);
675 }
676 if let Some(num_unpruned_validators) = self.num_unpruned_validators
677 && idx < num_unpruned_validators
678 {
679 builder = builder.with_unpruned_checkpoints();
680 }
681 if let Some(peer_deny_sync_cb) = &self.peer_deny_sync_config {
682 let this_authority: AuthorityName = validator.key_pair.public().into();
683 builder = builder.with_peer_deny_sync_config(peer_deny_sync_cb(
684 this_authority,
685 &all_authority_names,
686 ));
687 }
688 builder.build(validator, genesis.clone())
689 })
690 .collect();
691 NetworkConfig {
692 validator_configs,
693 genesis,
694 account_keys,
695 }
696 }
697}
698
699#[cfg(test)]
700mod tests {
701 use sui_config::node::Genesis;
702
703 #[test]
704 fn serialize_genesis_config_in_place() {
705 let dir = tempfile::TempDir::new().unwrap();
706 let network_config = crate::network_config_builder::ConfigBuilder::new(&dir).build();
707 let genesis = network_config.genesis;
708
709 let g = Genesis::new(genesis);
710
711 let mut s = serde_yaml::to_string(&g).unwrap();
712 let loaded_genesis: Genesis = serde_yaml::from_str(&s).unwrap();
713 loaded_genesis
714 .genesis()
715 .unwrap()
716 .checkpoint_contents()
717 .digest(); assert_eq!(g, loaded_genesis);
719
720 s.push_str("\ngenesis-file-location: path/to/file");
722 let loaded_genesis: Genesis = serde_yaml::from_str(&s).unwrap();
723 loaded_genesis
724 .genesis()
725 .unwrap()
726 .checkpoint_contents()
727 .digest(); assert_eq!(g, loaded_genesis);
729 }
730
731 #[test]
732 fn load_genesis_config_from_file() {
733 let file = tempfile::NamedTempFile::new().unwrap();
734 let genesis_config = Genesis::new_from_file(file.path());
735
736 let dir = tempfile::TempDir::new().unwrap();
737 let network_config = crate::network_config_builder::ConfigBuilder::new(&dir).build();
738 let genesis = network_config.genesis;
739 genesis.save(file.path()).unwrap();
740
741 let loaded_genesis = genesis_config.genesis().unwrap();
742 loaded_genesis.checkpoint_contents().digest(); assert_eq!(&genesis, loaded_genesis);
744 }
745}
746
747#[cfg(test)]
748mod test {
749 use std::sync::Arc;
750 use sui_config::genesis::Genesis;
751 use sui_protocol_config::{Chain, ProtocolConfig, ProtocolVersion};
752 use sui_types::epoch_data::EpochData;
753 use sui_types::execution_params::ExecutionOrEarlyError;
754 use sui_types::in_memory_storage::InMemoryStorage;
755 use sui_types::metrics::ExecutionMetrics;
756 use sui_types::sui_system_state::SuiSystemStateTrait;
757 use sui_types::transaction::CheckedInputObjects;
758
759 #[test]
760 fn roundtrip() {
761 let dir = tempfile::TempDir::new().unwrap();
762 let network_config = crate::network_config_builder::ConfigBuilder::new(&dir).build();
763 let genesis = network_config.genesis;
764
765 let s = serde_yaml::to_string(&genesis).unwrap();
766 let from_s: Genesis = serde_yaml::from_str(&s).unwrap();
767 from_s.checkpoint_contents().digest();
769 assert_eq!(genesis, from_s);
770 }
771
772 #[test]
773 fn genesis_transaction() {
774 let builder = crate::network_config_builder::ConfigBuilder::new_with_temp_dir();
775 let network_config = builder.build();
776 let genesis = network_config.genesis;
777 let protocol_version = ProtocolVersion::new(genesis.sui_system_object().protocol_version());
778 let protocol_config = ProtocolConfig::get_for_version(protocol_version, Chain::Unknown);
779
780 let genesis_transaction = genesis.transaction().clone();
781
782 let genesis_digest = *genesis_transaction.digest();
783
784 let silent = true;
785 let executor = sui_execution::executor(&protocol_config, silent)
786 .expect("Creating an executor should not fail here");
787
788 let registry = prometheus::Registry::new();
790 let metrics = Arc::new(ExecutionMetrics::new(®istry));
791 let expensive_checks = false;
792 let epoch = EpochData::new_test();
793 let transaction_data = &genesis_transaction.data().intent_message().value;
794 let (kind, signer, mut gas_data) = transaction_data.execution_parts();
795 gas_data.payment = vec![];
796 let input_objects = CheckedInputObjects::new_for_genesis(vec![]);
797
798 let (_inner_temp_store, _, effects, _timings, _execution_error) = executor
799 .execute_transaction_to_effects(
800 &InMemoryStorage::new(Vec::new()),
801 &protocol_config,
802 metrics,
803 expensive_checks,
804 ExecutionOrEarlyError::ok(None),
805 &epoch.epoch_id(),
806 epoch.epoch_start_timestamp(),
807 input_objects,
808 sui_types::base_types::SystemObjectVersions::empty(),
809 &sui_types::accumulator_root::EmptyUnsettledObjectFunds,
812 gas_data,
813 0, kind,
815 None, signer,
817 genesis_digest,
818 &mut None,
819 );
820
821 assert_eq!(&effects, genesis.effects());
822 }
823}