1pub use checked::*;
5
6#[sui_macros::with_checked_arithmetic]
7mod checked {
8 use crate::execution_mode::{self, ExecutionMode};
9 use crate::gas_charger::GasCharger;
10 use crate::programmable_transactions;
11 use crate::temporary_store::TemporaryStore;
12 use crate::type_layout_resolver::TypeLayoutResolver;
13 use move_binary_format::CompiledModule;
14 use move_vm_runtime::move_vm::MoveVM;
15 use std::sync::Arc;
16 use sui_protocol_config::{check_limit_by_meter, LimitThresholdCrossed, ProtocolConfig};
17 use sui_types::balance::{
18 BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME,
19 BALANCE_MODULE_NAME,
20 };
21 use sui_types::clock::{CLOCK_MODULE_NAME, CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME};
22 use sui_types::committee::EpochId;
23 use sui_types::effects::TransactionEffects;
24 use sui_types::error::{ExecutionError, ExecutionErrorKind};
25 use sui_types::execution_params::ExecutionOrEarlyError;
26 use sui_types::execution_status::ExecutionStatus;
27 use sui_types::gas::GasCostSummary;
28 use sui_types::gas::SuiGasStatus;
29 use sui_types::gas_coin::GAS;
30 use sui_types::inner_temporary_store::InnerTemporaryStore;
31 use sui_types::messages_checkpoint::CheckpointTimestamp;
32 use sui_types::metrics::LimitsMetrics;
33 use sui_types::object::OBJECT_START_VERSION;
34 use sui_types::programmable_transaction_builder::ProgrammableTransactionBuilder;
35 use sui_types::storage::BackingStore;
36 use sui_types::storage::WriteKind;
37 #[cfg(msim)]
38 use sui_types::sui_system_state::advance_epoch_result_injection::maybe_modify_result_legacy;
39 use sui_types::sui_system_state::{AdvanceEpochParams, ADVANCE_EPOCH_SAFE_MODE_FUNCTION_NAME};
40 use sui_types::transaction::CheckedInputObjects;
41 use sui_types::transaction::{
42 Argument, CallArg, ChangeEpoch, Command, GenesisTransaction, ProgrammableTransaction,
43 TransactionKind,
44 };
45 use sui_types::{
46 base_types::{ObjectRef, SuiAddress, TransactionDigest, TxContext},
47 object::{Object, ObjectInner},
48 sui_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, SUI_SYSTEM_MODULE_NAME},
49 SUI_FRAMEWORK_ADDRESS,
50 };
51 use sui_types::{SUI_FRAMEWORK_PACKAGE_ID, SUI_SYSTEM_PACKAGE_ID};
52 use tracing::{info, instrument, trace, warn};
53
54 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
55 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
56 store: &dyn BackingStore,
57 input_objects: CheckedInputObjects,
58 gas_coins: Vec<ObjectRef>,
59 gas_status: SuiGasStatus,
60 transaction_kind: TransactionKind,
61 transaction_signer: SuiAddress,
62 transaction_digest: TransactionDigest,
63 move_vm: &Arc<MoveVM>,
64 epoch_id: &EpochId,
65 epoch_timestamp_ms: u64,
66 protocol_config: &ProtocolConfig,
67 metrics: Arc<LimitsMetrics>,
68 enable_expensive_checks: bool,
69 execution_params: ExecutionOrEarlyError,
70 ) -> (
71 InnerTemporaryStore,
72 SuiGasStatus,
73 TransactionEffects,
74 Result<Mode::ExecutionResults, ExecutionError>,
75 ) {
76 let input_objects = input_objects.into_inner();
77 let shared_object_refs = input_objects.filter_shared_objects();
78 let mut transaction_dependencies = input_objects.transaction_dependencies();
79 let mut temporary_store =
80 TemporaryStore::new(store, input_objects, transaction_digest, protocol_config);
81 let mut gas_charger =
82 GasCharger::new(transaction_digest, gas_coins, gas_status, protocol_config);
83
84 let mut tx_ctx = TxContext::new_from_components(
85 &transaction_signer,
86 &transaction_digest,
87 epoch_id,
88 epoch_timestamp_ms,
89 1,
91 1,
92 1_000_000,
93 None,
94 protocol_config,
95 );
96
97 let is_epoch_change = matches!(transaction_kind, TransactionKind::ChangeEpoch(_));
98
99 let (gas_cost_summary, execution_result) = execute_transaction::<Mode>(
100 &mut temporary_store,
101 transaction_kind,
102 &mut gas_charger,
103 &mut tx_ctx,
104 move_vm,
105 protocol_config,
106 metrics,
107 enable_expensive_checks,
108 execution_params,
109 );
110
111 let status = if let Err(error) = &execution_result {
112 use ExecutionErrorKind as K;
114 match error.kind() {
115 K::InvariantViolation | K::VMInvariantViolation => {
116 #[skip_checked_arithmetic]
117 tracing::error!(
118 kind = ?error.kind(),
119 tx_digest = ?transaction_digest,
120 "INVARIANT VIOLATION! Source: {:?}",
121 error.source(),
122 );
123 }
124
125 K::SuiMoveVerificationError | K::VMVerificationOrDeserializationError => {
126 #[skip_checked_arithmetic]
127 tracing::debug!(
128 kind = ?error.kind(),
129 tx_digest = ?transaction_digest,
130 "Verification Error. Source: {:?}",
131 error.source(),
132 );
133 }
134
135 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
136 #[skip_checked_arithmetic]
137 tracing::debug!(
138 kind = ?error.kind(),
139 tx_digest = ?transaction_digest,
140 "Publish/Upgrade Error. Source: {:?}",
141 error.source(),
142 )
143 }
144
145 _ => (),
146 };
147
148 let (status, command) = error.to_execution_status();
149 ExecutionStatus::new_failure(status, command)
150 } else {
151 ExecutionStatus::Success
152 };
153
154 #[skip_checked_arithmetic]
155 trace!(
156 tx_digest = ?transaction_digest,
157 computation_gas_cost = gas_cost_summary.computation_cost,
158 storage_gas_cost = gas_cost_summary.storage_cost,
159 storage_gas_rebate = gas_cost_summary.storage_rebate,
160 "Finished execution of transaction with status {:?}",
161 status
162 );
163
164 transaction_dependencies.remove(&TransactionDigest::genesis_marker());
166
167 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
168 temporary_store
169 .check_ownership_invariants(&transaction_signer, &mut gas_charger, is_epoch_change)
170 .unwrap()
171 } let (inner, effects) = temporary_store.to_effects(
174 shared_object_refs,
175 &transaction_digest,
176 transaction_dependencies.into_iter().collect(),
177 gas_cost_summary,
178 status,
179 &mut gas_charger,
180 *epoch_id,
181 );
182 (
183 inner,
184 gas_charger.into_gas_status(),
185 effects,
186 execution_result,
187 )
188 }
189
190 pub fn execute_genesis_state_update(
191 store: &dyn BackingStore,
192 protocol_config: &ProtocolConfig,
193 metrics: Arc<LimitsMetrics>,
194 move_vm: &Arc<MoveVM>,
195 tx_context: &mut TxContext,
196 input_objects: CheckedInputObjects,
197 pt: ProgrammableTransaction,
198 ) -> Result<InnerTemporaryStore, ExecutionError> {
199 let input_objects = input_objects.into_inner();
200 let mut temporary_store =
201 TemporaryStore::new(store, input_objects, tx_context.digest(), protocol_config);
202 let mut gas_charger = GasCharger::new_unmetered(tx_context.digest());
203 programmable_transactions::execution::execute::<execution_mode::Genesis>(
204 protocol_config,
205 metrics,
206 move_vm,
207 &mut temporary_store,
208 tx_context,
209 &mut gas_charger,
210 pt,
211 )?;
212 temporary_store.update_object_version_and_prev_tx();
213 Ok(temporary_store.into_inner())
214 }
215
216 #[instrument(name = "tx_execute", level = "debug", skip_all)]
217 fn execute_transaction<Mode: ExecutionMode>(
218 temporary_store: &mut TemporaryStore<'_>,
219 transaction_kind: TransactionKind,
220 gas_charger: &mut GasCharger,
221 tx_ctx: &mut TxContext,
222 move_vm: &Arc<MoveVM>,
223 protocol_config: &ProtocolConfig,
224 metrics: Arc<LimitsMetrics>,
225 enable_expensive_checks: bool,
226 execution_params: ExecutionOrEarlyError,
227 ) -> (
228 GasCostSummary,
229 Result<Mode::ExecutionResults, ExecutionError>,
230 ) {
231 gas_charger.smash_gas(temporary_store);
232
233 debug_assert!(
235 gas_charger.no_charges(),
236 "No gas charges must be applied yet"
237 );
238 let is_genesis_tx = matches!(transaction_kind, TransactionKind::Genesis(_));
239 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
240
241 let result = gas_charger.charge_input_objects(temporary_store);
244 let mut result = result.and_then(|()| {
245 let mut execution_result = match execution_params {
246 ExecutionOrEarlyError::Err(early_execution_error) => {
247 Err(ExecutionError::new(early_execution_error, None))
248 }
249 ExecutionOrEarlyError::Ok(()) => execution_loop::<Mode>(
250 temporary_store,
251 transaction_kind,
252 tx_ctx,
253 move_vm,
254 gas_charger,
255 protocol_config,
256 metrics.clone(),
257 ),
258 };
259
260 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
261
262 match check_limit_by_meter!(
266 !gas_charger.is_unmetered(),
267 effects_estimated_size,
268 protocol_config.max_serialized_tx_effects_size_bytes(),
269 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
270 metrics.excessive_estimated_effects_size
271 ) {
272 LimitThresholdCrossed::None => (),
273 LimitThresholdCrossed::Soft(_, limit) => {
274 warn!(
275 effects_estimated_size = effects_estimated_size,
276 soft_limit = limit,
277 "Estimated transaction effects size crossed soft limit",
278 )
279 }
280 LimitThresholdCrossed::Hard(_, lim) => {
281 execution_result = Err(ExecutionError::new_with_source(
282 ExecutionErrorKind::EffectsTooLarge {
283 current_size: effects_estimated_size as u64,
284 max_size: lim as u64,
285 },
286 "Transaction effects are too large",
287 ))
288 }
289 };
290 if execution_result.is_ok() {
291 if let (Some(normal_lim), Some(system_lim)) = (
293 protocol_config.max_size_written_objects_as_option(),
294 protocol_config.max_size_written_objects_system_tx_as_option(),
295 ) {
296 let written_objects_size = temporary_store.written_objects_size();
297
298 match check_limit_by_meter!(
299 !gas_charger.is_unmetered(),
300 written_objects_size,
301 normal_lim,
302 system_lim,
303 metrics.excessive_written_objects_size
304 ) {
305 LimitThresholdCrossed::None => (),
306 LimitThresholdCrossed::Soft(_, limit) => {
307 warn!(
308 written_objects_size = written_objects_size,
309 soft_limit = limit,
310 "Written objects size crossed soft limit",
311 )
312 }
313 LimitThresholdCrossed::Hard(_, lim) => {
314 execution_result = Err(ExecutionError::new_with_source(
315 ExecutionErrorKind::WrittenObjectsTooLarge {
316 current_size: written_objects_size as u64,
317 max_size: lim as u64,
318 },
319 "Written objects size crossed hard limit",
320 ))
321 }
322 };
323 }
324 }
325
326 execution_result
327 });
328
329 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
330 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
338
339 if !is_genesis_tx && !Mode::allow_arbitrary_values() {
341 let conservation_result = {
343 let mut layout_resolver =
344 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
345 temporary_store.check_sui_conserved(
346 &cost_summary,
347 advance_epoch_gas_summary,
348 &mut layout_resolver,
349 enable_expensive_checks,
350 )
351 };
352 if let Err(conservation_err) = conservation_result {
353 result = Err(conservation_err);
356 gas_charger.reset(temporary_store);
357 gas_charger.charge_gas(temporary_store, &mut result);
358 let mut layout_resolver =
360 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
361 if let Err(recovery_err) = temporary_store.check_sui_conserved(
362 &cost_summary,
363 advance_epoch_gas_summary,
364 &mut layout_resolver,
365 enable_expensive_checks,
366 ) {
367 panic!(
371 "SUI conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
372 tx_ctx.digest(),
373 recovery_err,
374 gas_charger.summary()
375 )
376 }
377 }
378 } (cost_summary, result)
382 }
383
384 fn execution_loop<Mode: ExecutionMode>(
385 temporary_store: &mut TemporaryStore<'_>,
386 transaction_kind: TransactionKind,
387 tx_ctx: &mut TxContext,
388 move_vm: &Arc<MoveVM>,
389 gas_charger: &mut GasCharger,
390 protocol_config: &ProtocolConfig,
391 metrics: Arc<LimitsMetrics>,
392 ) -> Result<Mode::ExecutionResults, ExecutionError> {
393 match transaction_kind {
394 TransactionKind::ChangeEpoch(change_epoch) => {
395 advance_epoch(
396 change_epoch,
397 temporary_store,
398 tx_ctx,
399 move_vm,
400 gas_charger,
401 protocol_config,
402 metrics,
403 )?;
404 Ok(Mode::empty_results())
405 }
406 TransactionKind::Genesis(GenesisTransaction { objects }) => {
407 if tx_ctx.epoch() != 0 {
408 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
409 }
410
411 for genesis_object in objects {
412 match genesis_object {
413 sui_types::transaction::GenesisObject::RawObject { data, owner } => {
414 let object = ObjectInner {
415 data,
416 owner,
417 previous_transaction: tx_ctx.digest(),
418 storage_rebate: 0,
419 };
420 temporary_store.write_object(object.into(), WriteKind::Create);
421 }
422 }
423 }
424 Ok(Mode::empty_results())
425 }
426 TransactionKind::ConsensusCommitPrologue(prologue) => {
427 setup_consensus_commit(
428 prologue.commit_timestamp_ms,
429 temporary_store,
430 tx_ctx,
431 move_vm,
432 gas_charger,
433 protocol_config,
434 metrics,
435 )
436 .expect("ConsensusCommitPrologue cannot fail");
437 Ok(Mode::empty_results())
438 }
439 TransactionKind::ConsensusCommitPrologueV2(prologue) => {
440 setup_consensus_commit(
441 prologue.commit_timestamp_ms,
442 temporary_store,
443 tx_ctx,
444 move_vm,
445 gas_charger,
446 protocol_config,
447 metrics,
448 )
449 .expect("ConsensusCommitPrologue cannot fail");
450 Ok(Mode::empty_results())
451 }
452 TransactionKind::ConsensusCommitPrologueV3(prologue) => {
453 setup_consensus_commit(
454 prologue.commit_timestamp_ms,
455 temporary_store,
456 tx_ctx,
457 move_vm,
458 gas_charger,
459 protocol_config,
460 metrics,
461 )
462 .expect("ConsensusCommitPrologue cannot fail");
463 Ok(Mode::empty_results())
464 }
465 TransactionKind::ConsensusCommitPrologueV4(prologue) => {
466 setup_consensus_commit(
467 prologue.commit_timestamp_ms,
468 temporary_store,
469 tx_ctx,
470 move_vm,
471 gas_charger,
472 protocol_config,
473 metrics,
474 )
475 .expect("ConsensusCommitPrologue cannot fail");
476 Ok(Mode::empty_results())
477 }
478 TransactionKind::ProgrammableTransaction(pt) => {
479 programmable_transactions::execution::execute::<Mode>(
480 protocol_config,
481 metrics,
482 move_vm,
483 temporary_store,
484 tx_ctx,
485 gas_charger,
486 pt,
487 )
488 }
489 TransactionKind::AuthenticatorStateUpdate(_) => {
490 panic!("AuthenticatorStateUpdate should not exist in execution layer v0");
491 }
492 TransactionKind::RandomnessStateUpdate(_) => {
493 panic!("RandomnessStateUpdate should not exist in execution layer v0");
494 }
495 TransactionKind::EndOfEpochTransaction(_) => {
496 panic!("EndOfEpochTransaction should not exist in execution layer v0");
497 }
498 TransactionKind::ProgrammableSystemTransaction(_) => {
499 panic!("ProgrammableSystemTransaction should not exist in execution layer v0");
500 }
501 }
502 }
503
504 fn mint_epoch_rewards_in_pt(
505 builder: &mut ProgrammableTransactionBuilder,
506 params: &AdvanceEpochParams,
507 ) -> (Argument, Argument) {
508 let storage_charge_arg = builder
510 .input(CallArg::Pure(
511 bcs::to_bytes(¶ms.storage_charge).unwrap(),
512 ))
513 .unwrap();
514 let storage_rewards = builder.programmable_move_call(
515 SUI_FRAMEWORK_PACKAGE_ID,
516 BALANCE_MODULE_NAME.to_owned(),
517 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
518 vec![GAS::type_tag()],
519 vec![storage_charge_arg],
520 );
521
522 let computation_charge_arg = builder
524 .input(CallArg::Pure(
525 bcs::to_bytes(¶ms.computation_charge).unwrap(),
526 ))
527 .unwrap();
528 let computation_rewards = builder.programmable_move_call(
529 SUI_FRAMEWORK_PACKAGE_ID,
530 BALANCE_MODULE_NAME.to_owned(),
531 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
532 vec![GAS::type_tag()],
533 vec![computation_charge_arg],
534 );
535 (storage_rewards, computation_rewards)
536 }
537
538 pub fn construct_advance_epoch_pt(
539 params: &AdvanceEpochParams,
540 ) -> Result<ProgrammableTransaction, ExecutionError> {
541 let mut builder = ProgrammableTransactionBuilder::new();
542 let (storage_rewards, computation_rewards) = mint_epoch_rewards_in_pt(&mut builder, params);
544
545 let mut arguments = vec![storage_rewards, computation_rewards];
547 let call_arg_arguments = vec![
548 CallArg::SUI_SYSTEM_MUT,
549 CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()),
550 CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()),
551 CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()),
552 CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()),
553 CallArg::Pure(bcs::to_bytes(¶ms.storage_fund_reinvest_rate).unwrap()),
554 CallArg::Pure(bcs::to_bytes(¶ms.reward_slashing_rate).unwrap()),
555 CallArg::Pure(bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap()),
556 ]
557 .into_iter()
558 .map(|a| builder.input(a))
559 .collect::<Result<_, _>>();
560
561 assert_invariant!(
562 call_arg_arguments.is_ok(),
563 "Unable to generate args for advance_epoch transaction!"
564 );
565
566 arguments.append(&mut call_arg_arguments.unwrap());
567
568 info!("Call arguments to advance_epoch transaction: {:?}", params);
569
570 let storage_rebates = builder.programmable_move_call(
571 SUI_SYSTEM_PACKAGE_ID,
572 SUI_SYSTEM_MODULE_NAME.to_owned(),
573 ADVANCE_EPOCH_FUNCTION_NAME.to_owned(),
574 vec![],
575 arguments,
576 );
577
578 builder.programmable_move_call(
580 SUI_FRAMEWORK_PACKAGE_ID,
581 BALANCE_MODULE_NAME.to_owned(),
582 BALANCE_DESTROY_REBATES_FUNCTION_NAME.to_owned(),
583 vec![GAS::type_tag()],
584 vec![storage_rebates],
585 );
586 Ok(builder.finish())
587 }
588
589 pub fn construct_advance_epoch_safe_mode_pt(
590 params: &AdvanceEpochParams,
591 protocol_config: &ProtocolConfig,
592 ) -> Result<ProgrammableTransaction, ExecutionError> {
593 let mut builder = ProgrammableTransactionBuilder::new();
594 let (storage_rewards, computation_rewards) = mint_epoch_rewards_in_pt(&mut builder, params);
596
597 let mut arguments = vec![storage_rewards, computation_rewards];
599
600 let mut args = vec![
601 CallArg::SUI_SYSTEM_MUT,
602 CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()),
603 CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()),
604 CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()),
605 CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()),
606 ];
607
608 if protocol_config.get_advance_epoch_start_time_in_safe_mode() {
609 args.push(CallArg::Pure(
610 bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap(),
611 ));
612 }
613
614 let call_arg_arguments = args
615 .into_iter()
616 .map(|a| builder.input(a))
617 .collect::<Result<_, _>>();
618
619 assert_invariant!(
620 call_arg_arguments.is_ok(),
621 "Unable to generate args for advance_epoch transaction!"
622 );
623
624 arguments.append(&mut call_arg_arguments.unwrap());
625
626 info!("Call arguments to advance_epoch transaction: {:?}", params);
627
628 builder.programmable_move_call(
629 SUI_SYSTEM_PACKAGE_ID,
630 SUI_SYSTEM_MODULE_NAME.to_owned(),
631 ADVANCE_EPOCH_SAFE_MODE_FUNCTION_NAME.to_owned(),
632 vec![],
633 arguments,
634 );
635
636 Ok(builder.finish())
637 }
638
639 fn advance_epoch(
640 change_epoch: ChangeEpoch,
641 temporary_store: &mut TemporaryStore<'_>,
642 tx_ctx: &mut TxContext,
643 move_vm: &Arc<MoveVM>,
644 gas_charger: &mut GasCharger,
645 protocol_config: &ProtocolConfig,
646 metrics: Arc<LimitsMetrics>,
647 ) -> Result<(), ExecutionError> {
648 let params = AdvanceEpochParams {
649 epoch: change_epoch.epoch,
650 next_protocol_version: change_epoch.protocol_version,
651 storage_charge: change_epoch.storage_charge,
652 computation_charge: change_epoch.computation_charge,
653 storage_rebate: change_epoch.storage_rebate,
654 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
655 storage_fund_reinvest_rate: protocol_config.storage_fund_reinvest_rate(),
656 reward_slashing_rate: protocol_config.reward_slashing_rate(),
657 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
658 };
659 let advance_epoch_pt = construct_advance_epoch_pt(¶ms)?;
660 let result = programmable_transactions::execution::execute::<execution_mode::System>(
661 protocol_config,
662 metrics.clone(),
663 move_vm,
664 temporary_store,
665 tx_ctx,
666 gas_charger,
667 advance_epoch_pt,
668 );
669
670 #[cfg(msim)]
671 let result = maybe_modify_result_legacy(result, change_epoch.epoch);
672
673 if result.is_err() {
674 tracing::error!(
675 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx data: {:?}",
676 result.as_ref().err(),
677 temporary_store.objects(),
678 change_epoch,
679 );
680 temporary_store.drop_writes();
681 gas_charger.reset_storage_cost_and_rebate();
683
684 if protocol_config.get_advance_epoch_start_time_in_safe_mode() {
685 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
686 } else {
687 let advance_epoch_safe_mode_pt =
688 construct_advance_epoch_safe_mode_pt(¶ms, protocol_config)?;
689 programmable_transactions::execution::execute::<execution_mode::System>(
690 protocol_config,
691 metrics.clone(),
692 move_vm,
693 temporary_store,
694 tx_ctx,
695 gas_charger,
696 advance_epoch_safe_mode_pt,
697 )
698 .expect("Advance epoch with safe mode must succeed");
699 }
700 }
701
702 let binary_config = protocol_config.binary_config(None);
703 for (version, modules, dependencies) in change_epoch.system_packages.into_iter() {
704 let deserialized_modules: Vec<_> = modules
705 .iter()
706 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
707 .collect();
708
709 if version == OBJECT_START_VERSION {
710 let package_id = deserialized_modules.first().unwrap().address();
711 info!("adding new system package {package_id}");
712
713 let publish_pt = {
714 let mut b = ProgrammableTransactionBuilder::new();
715 b.command(Command::Publish(modules, dependencies));
716 b.finish()
717 };
718
719 programmable_transactions::execution::execute::<execution_mode::System>(
720 protocol_config,
721 metrics.clone(),
722 move_vm,
723 temporary_store,
724 tx_ctx,
725 gas_charger,
726 publish_pt,
727 )
728 .expect("System Package Publish must succeed");
729 } else {
730 let mut new_package = Object::new_system_package(
731 &deserialized_modules,
732 version,
733 dependencies,
734 tx_ctx.digest(),
735 );
736
737 info!(
738 "upgraded system package {:?}",
739 new_package.compute_object_reference()
740 );
741
742 new_package
745 .data
746 .try_as_package_mut()
747 .unwrap()
748 .decrement_version();
749
750 temporary_store.write_object(new_package, WriteKind::Mutate);
752 }
753 }
754
755 Ok(())
756 }
757
758 fn setup_consensus_commit(
763 consensus_commit_timestamp_ms: CheckpointTimestamp,
764 temporary_store: &mut TemporaryStore<'_>,
765 tx_ctx: &mut TxContext,
766 move_vm: &Arc<MoveVM>,
767 gas_charger: &mut GasCharger,
768 protocol_config: &ProtocolConfig,
769 metrics: Arc<LimitsMetrics>,
770 ) -> Result<(), ExecutionError> {
771 let pt = {
772 let mut builder = ProgrammableTransactionBuilder::new();
773 let res = builder.move_call(
774 SUI_FRAMEWORK_ADDRESS.into(),
775 CLOCK_MODULE_NAME.to_owned(),
776 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME.to_owned(),
777 vec![],
778 vec![
779 CallArg::CLOCK_MUT,
780 CallArg::Pure(bcs::to_bytes(&consensus_commit_timestamp_ms).unwrap()),
781 ],
782 );
783 assert_invariant!(
784 res.is_ok(),
785 "Unable to generate consensus_commit_prologue transaction!"
786 );
787 builder.finish()
788 };
789 programmable_transactions::execution::execute::<execution_mode::System>(
790 protocol_config,
791 metrics,
792 move_vm,
793 temporary_store,
794 tx_ctx,
795 gas_charger,
796 pt,
797 )
798 }
799}