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