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