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, ExecutionErrorTrait};
25 use sui_types::execution_params::ExecutionOrEarlyError;
26 use sui_types::execution_status::{ExecutionErrorKind, 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::ExecutionMetrics;
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<ExecutionMetrics>,
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 ExecutionStatus::new_failure(error.to_execution_failure())
113 } else {
114 ExecutionStatus::Success
115 };
116
117 #[skip_checked_arithmetic]
118 trace!(
119 tx_digest = ?transaction_digest,
120 computation_gas_cost = gas_cost_summary.computation_cost,
121 storage_gas_cost = gas_cost_summary.storage_cost,
122 storage_gas_rebate = gas_cost_summary.storage_rebate,
123 "Finished execution of transaction with status {:?}",
124 status
125 );
126
127 transaction_dependencies.remove(&TransactionDigest::genesis_marker());
129
130 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
131 temporary_store
132 .check_ownership_invariants(&transaction_signer, &mut gas_charger, is_epoch_change)
133 .unwrap()
134 } let (inner, effects) = temporary_store.to_effects(
137 shared_object_refs,
138 &transaction_digest,
139 transaction_dependencies.into_iter().collect(),
140 gas_cost_summary,
141 status,
142 &mut gas_charger,
143 *epoch_id,
144 );
145 (
146 inner,
147 gas_charger.into_gas_status(),
148 effects,
149 execution_result,
150 )
151 }
152
153 pub fn execute_genesis_state_update(
154 store: &dyn BackingStore,
155 protocol_config: &ProtocolConfig,
156 metrics: Arc<ExecutionMetrics>,
157 move_vm: &Arc<MoveVM>,
158 tx_context: &mut TxContext,
159 input_objects: CheckedInputObjects,
160 pt: ProgrammableTransaction,
161 ) -> Result<InnerTemporaryStore, ExecutionError> {
162 let input_objects = input_objects.into_inner();
163 let mut temporary_store =
164 TemporaryStore::new(store, input_objects, tx_context.digest(), protocol_config);
165 let mut gas_charger = GasCharger::new_unmetered(tx_context.digest());
166 programmable_transactions::execution::execute::<execution_mode::Genesis>(
167 protocol_config,
168 metrics,
169 move_vm,
170 &mut temporary_store,
171 tx_context,
172 &mut gas_charger,
173 pt,
174 )?;
175 temporary_store.update_object_version_and_prev_tx();
176 Ok(temporary_store.into_inner())
177 }
178
179 #[instrument(name = "tx_execute", level = "debug", skip_all)]
180 fn execute_transaction<Mode: ExecutionMode>(
181 temporary_store: &mut TemporaryStore<'_>,
182 transaction_kind: TransactionKind,
183 gas_charger: &mut GasCharger,
184 tx_ctx: &mut TxContext,
185 move_vm: &Arc<MoveVM>,
186 protocol_config: &ProtocolConfig,
187 metrics: Arc<ExecutionMetrics>,
188 enable_expensive_checks: bool,
189 execution_params: ExecutionOrEarlyError,
190 ) -> (
191 GasCostSummary,
192 Result<Mode::ExecutionResults, ExecutionError>,
193 ) {
194 gas_charger.smash_gas(temporary_store);
195
196 debug_assert!(
198 gas_charger.no_charges(),
199 "No gas charges must be applied yet"
200 );
201 let is_genesis_tx = matches!(transaction_kind, TransactionKind::Genesis(_));
202 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
203
204 let result = gas_charger.charge_input_objects(temporary_store);
207 let mut result = result.and_then(|()| {
208 let mut execution_result = match execution_params {
209 ExecutionOrEarlyError::Err(early_execution_error) => {
210 Err(ExecutionError::new(early_execution_error, None))
211 }
212 ExecutionOrEarlyError::Ok(()) => execution_loop::<Mode>(
213 temporary_store,
214 transaction_kind,
215 tx_ctx,
216 move_vm,
217 gas_charger,
218 protocol_config,
219 metrics.clone(),
220 ),
221 };
222
223 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
224
225 match check_limit_by_meter!(
229 !gas_charger.is_unmetered(),
230 effects_estimated_size,
231 protocol_config.max_serialized_tx_effects_size_bytes(),
232 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
233 metrics.limits_metrics.excessive_estimated_effects_size
234 ) {
235 LimitThresholdCrossed::None => (),
236 LimitThresholdCrossed::Soft(_, limit) => {
237 warn!(
238 effects_estimated_size = effects_estimated_size,
239 soft_limit = limit,
240 "Estimated transaction effects size crossed soft limit",
241 )
242 }
243 LimitThresholdCrossed::Hard(_, lim) => {
244 execution_result = Err(ExecutionError::new_with_source(
245 ExecutionErrorKind::EffectsTooLarge {
246 current_size: effects_estimated_size as u64,
247 max_size: lim as u64,
248 },
249 "Transaction effects are too large",
250 ))
251 }
252 };
253 if execution_result.is_ok() {
254 if let (Some(normal_lim), Some(system_lim)) = (
256 protocol_config.max_size_written_objects_as_option(),
257 protocol_config.max_size_written_objects_system_tx_as_option(),
258 ) {
259 let written_objects_size = temporary_store.written_objects_size();
260
261 match check_limit_by_meter!(
262 !gas_charger.is_unmetered(),
263 written_objects_size,
264 normal_lim,
265 system_lim,
266 metrics.limits_metrics.excessive_written_objects_size
267 ) {
268 LimitThresholdCrossed::None => (),
269 LimitThresholdCrossed::Soft(_, limit) => {
270 warn!(
271 written_objects_size = written_objects_size,
272 soft_limit = limit,
273 "Written objects size crossed soft limit",
274 )
275 }
276 LimitThresholdCrossed::Hard(_, lim) => {
277 execution_result = Err(ExecutionError::new_with_source(
278 ExecutionErrorKind::WrittenObjectsTooLarge {
279 current_size: written_objects_size as u64,
280 max_size: lim as u64,
281 },
282 "Written objects size crossed hard limit",
283 ))
284 }
285 };
286 }
287 }
288
289 execution_result
290 });
291
292 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
293 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
301
302 if !is_genesis_tx && !Mode::allow_arbitrary_values() {
304 let conservation_result = {
306 let mut layout_resolver =
307 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
308 temporary_store.check_sui_conserved(
309 &cost_summary,
310 advance_epoch_gas_summary,
311 &mut layout_resolver,
312 enable_expensive_checks,
313 )
314 };
315 if let Err(conservation_err) = conservation_result {
316 result = Err(conservation_err);
319 gas_charger.reset(temporary_store);
320 gas_charger.charge_gas(temporary_store, &mut result);
321 let mut layout_resolver =
323 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
324 if let Err(recovery_err) = temporary_store.check_sui_conserved(
325 &cost_summary,
326 advance_epoch_gas_summary,
327 &mut layout_resolver,
328 enable_expensive_checks,
329 ) {
330 panic!(
334 "SUI conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
335 tx_ctx.digest(),
336 recovery_err,
337 gas_charger.summary()
338 )
339 }
340 }
341 } (cost_summary, result)
345 }
346
347 fn execution_loop<Mode: ExecutionMode>(
348 temporary_store: &mut TemporaryStore<'_>,
349 transaction_kind: TransactionKind,
350 tx_ctx: &mut TxContext,
351 move_vm: &Arc<MoveVM>,
352 gas_charger: &mut GasCharger,
353 protocol_config: &ProtocolConfig,
354 metrics: Arc<ExecutionMetrics>,
355 ) -> Result<Mode::ExecutionResults, ExecutionError> {
356 match transaction_kind {
357 TransactionKind::ChangeEpoch(change_epoch) => {
358 advance_epoch(
359 change_epoch,
360 temporary_store,
361 tx_ctx,
362 move_vm,
363 gas_charger,
364 protocol_config,
365 metrics,
366 )?;
367 Ok(Mode::empty_results())
368 }
369 TransactionKind::Genesis(GenesisTransaction { objects }) => {
370 if tx_ctx.epoch() != 0 {
371 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
372 }
373
374 for genesis_object in objects {
375 match genesis_object {
376 sui_types::transaction::GenesisObject::RawObject { data, owner } => {
377 let object = ObjectInner {
378 data,
379 owner,
380 previous_transaction: tx_ctx.digest(),
381 storage_rebate: 0,
382 };
383 temporary_store.write_object(object.into(), WriteKind::Create);
384 }
385 }
386 }
387 Ok(Mode::empty_results())
388 }
389 TransactionKind::ConsensusCommitPrologue(prologue) => {
390 setup_consensus_commit(
391 prologue.commit_timestamp_ms,
392 temporary_store,
393 tx_ctx,
394 move_vm,
395 gas_charger,
396 protocol_config,
397 metrics,
398 )
399 .expect("ConsensusCommitPrologue cannot fail");
400 Ok(Mode::empty_results())
401 }
402 TransactionKind::ConsensusCommitPrologueV2(prologue) => {
403 setup_consensus_commit(
404 prologue.commit_timestamp_ms,
405 temporary_store,
406 tx_ctx,
407 move_vm,
408 gas_charger,
409 protocol_config,
410 metrics,
411 )
412 .expect("ConsensusCommitPrologue cannot fail");
413 Ok(Mode::empty_results())
414 }
415 TransactionKind::ConsensusCommitPrologueV3(prologue) => {
416 setup_consensus_commit(
417 prologue.commit_timestamp_ms,
418 temporary_store,
419 tx_ctx,
420 move_vm,
421 gas_charger,
422 protocol_config,
423 metrics,
424 )
425 .expect("ConsensusCommitPrologue cannot fail");
426 Ok(Mode::empty_results())
427 }
428 TransactionKind::ConsensusCommitPrologueV4(prologue) => {
429 setup_consensus_commit(
430 prologue.commit_timestamp_ms,
431 temporary_store,
432 tx_ctx,
433 move_vm,
434 gas_charger,
435 protocol_config,
436 metrics,
437 )
438 .expect("ConsensusCommitPrologue cannot fail");
439 Ok(Mode::empty_results())
440 }
441 TransactionKind::ProgrammableTransaction(pt) => {
442 programmable_transactions::execution::execute::<Mode>(
443 protocol_config,
444 metrics,
445 move_vm,
446 temporary_store,
447 tx_ctx,
448 gas_charger,
449 pt,
450 )
451 }
452 TransactionKind::AuthenticatorStateUpdate(_) => {
453 panic!("AuthenticatorStateUpdate should not exist in execution layer v0");
454 }
455 TransactionKind::RandomnessStateUpdate(_) => {
456 panic!("RandomnessStateUpdate should not exist in execution layer v0");
457 }
458 TransactionKind::EndOfEpochTransaction(_) => {
459 panic!("EndOfEpochTransaction should not exist in execution layer v0");
460 }
461 TransactionKind::ProgrammableSystemTransaction(_) => {
462 panic!("ProgrammableSystemTransaction should not exist in execution layer v0");
463 }
464 }
465 }
466
467 fn mint_epoch_rewards_in_pt(
468 builder: &mut ProgrammableTransactionBuilder,
469 params: &AdvanceEpochParams,
470 ) -> (Argument, Argument) {
471 let storage_charge_arg = builder
473 .input(CallArg::Pure(
474 bcs::to_bytes(¶ms.storage_charge).unwrap(),
475 ))
476 .unwrap();
477 let storage_rewards = builder.programmable_move_call(
478 SUI_FRAMEWORK_PACKAGE_ID,
479 BALANCE_MODULE_NAME.to_owned(),
480 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
481 vec![GAS::type_tag()],
482 vec![storage_charge_arg],
483 );
484
485 let computation_charge_arg = builder
487 .input(CallArg::Pure(
488 bcs::to_bytes(¶ms.computation_charge).unwrap(),
489 ))
490 .unwrap();
491 let computation_rewards = builder.programmable_move_call(
492 SUI_FRAMEWORK_PACKAGE_ID,
493 BALANCE_MODULE_NAME.to_owned(),
494 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
495 vec![GAS::type_tag()],
496 vec![computation_charge_arg],
497 );
498 (storage_rewards, computation_rewards)
499 }
500
501 pub fn construct_advance_epoch_pt(
502 params: &AdvanceEpochParams,
503 ) -> Result<ProgrammableTransaction, ExecutionError> {
504 let mut builder = ProgrammableTransactionBuilder::new();
505 let (storage_rewards, computation_rewards) = mint_epoch_rewards_in_pt(&mut builder, params);
507
508 let mut arguments = vec![storage_rewards, computation_rewards];
510 let call_arg_arguments = vec![
511 CallArg::SUI_SYSTEM_MUT,
512 CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()),
513 CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()),
514 CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()),
515 CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()),
516 CallArg::Pure(bcs::to_bytes(¶ms.storage_fund_reinvest_rate).unwrap()),
517 CallArg::Pure(bcs::to_bytes(¶ms.reward_slashing_rate).unwrap()),
518 CallArg::Pure(bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap()),
519 ]
520 .into_iter()
521 .map(|a| builder.input(a))
522 .collect::<Result<_, _>>();
523
524 assert_invariant!(
525 call_arg_arguments.is_ok(),
526 "Unable to generate args for advance_epoch transaction!"
527 );
528
529 arguments.append(&mut call_arg_arguments.unwrap());
530
531 info!("Call arguments to advance_epoch transaction: {:?}", params);
532
533 let storage_rebates = builder.programmable_move_call(
534 SUI_SYSTEM_PACKAGE_ID,
535 SUI_SYSTEM_MODULE_NAME.to_owned(),
536 ADVANCE_EPOCH_FUNCTION_NAME.to_owned(),
537 vec![],
538 arguments,
539 );
540
541 builder.programmable_move_call(
543 SUI_FRAMEWORK_PACKAGE_ID,
544 BALANCE_MODULE_NAME.to_owned(),
545 BALANCE_DESTROY_REBATES_FUNCTION_NAME.to_owned(),
546 vec![GAS::type_tag()],
547 vec![storage_rebates],
548 );
549 Ok(builder.finish())
550 }
551
552 pub fn construct_advance_epoch_safe_mode_pt(
553 params: &AdvanceEpochParams,
554 protocol_config: &ProtocolConfig,
555 ) -> Result<ProgrammableTransaction, ExecutionError> {
556 let mut builder = ProgrammableTransactionBuilder::new();
557 let (storage_rewards, computation_rewards) = mint_epoch_rewards_in_pt(&mut builder, params);
559
560 let mut arguments = vec![storage_rewards, computation_rewards];
562
563 let mut args = vec![
564 CallArg::SUI_SYSTEM_MUT,
565 CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()),
566 CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()),
567 CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()),
568 CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()),
569 ];
570
571 if protocol_config.get_advance_epoch_start_time_in_safe_mode() {
572 args.push(CallArg::Pure(
573 bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap(),
574 ));
575 }
576
577 let call_arg_arguments = args
578 .into_iter()
579 .map(|a| builder.input(a))
580 .collect::<Result<_, _>>();
581
582 assert_invariant!(
583 call_arg_arguments.is_ok(),
584 "Unable to generate args for advance_epoch transaction!"
585 );
586
587 arguments.append(&mut call_arg_arguments.unwrap());
588
589 info!("Call arguments to advance_epoch transaction: {:?}", params);
590
591 builder.programmable_move_call(
592 SUI_SYSTEM_PACKAGE_ID,
593 SUI_SYSTEM_MODULE_NAME.to_owned(),
594 ADVANCE_EPOCH_SAFE_MODE_FUNCTION_NAME.to_owned(),
595 vec![],
596 arguments,
597 );
598
599 Ok(builder.finish())
600 }
601
602 fn advance_epoch(
603 change_epoch: ChangeEpoch,
604 temporary_store: &mut TemporaryStore<'_>,
605 tx_ctx: &mut TxContext,
606 move_vm: &Arc<MoveVM>,
607 gas_charger: &mut GasCharger,
608 protocol_config: &ProtocolConfig,
609 metrics: Arc<ExecutionMetrics>,
610 ) -> Result<(), ExecutionError> {
611 let params = AdvanceEpochParams {
612 epoch: change_epoch.epoch,
613 next_protocol_version: change_epoch.protocol_version,
614 storage_charge: change_epoch.storage_charge,
615 computation_charge: change_epoch.computation_charge,
616 storage_rebate: change_epoch.storage_rebate,
617 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
618 storage_fund_reinvest_rate: protocol_config.storage_fund_reinvest_rate(),
619 reward_slashing_rate: protocol_config.reward_slashing_rate(),
620 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
621 };
622 let advance_epoch_pt = construct_advance_epoch_pt(¶ms)?;
623 let result = programmable_transactions::execution::execute::<execution_mode::System>(
624 protocol_config,
625 metrics.clone(),
626 move_vm,
627 temporary_store,
628 tx_ctx,
629 gas_charger,
630 advance_epoch_pt,
631 );
632
633 #[cfg(msim)]
634 let result = maybe_modify_result_legacy(result, change_epoch.epoch);
635
636 if result.is_err() {
637 tracing::error!(
638 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx data: {:?}",
639 result.as_ref().err(),
640 temporary_store.objects(),
641 change_epoch,
642 );
643 temporary_store.drop_writes();
644 gas_charger.reset_storage_cost_and_rebate();
646
647 if protocol_config.get_advance_epoch_start_time_in_safe_mode() {
648 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
649 } else {
650 let advance_epoch_safe_mode_pt =
651 construct_advance_epoch_safe_mode_pt(¶ms, protocol_config)?;
652 programmable_transactions::execution::execute::<execution_mode::System>(
653 protocol_config,
654 metrics.clone(),
655 move_vm,
656 temporary_store,
657 tx_ctx,
658 gas_charger,
659 advance_epoch_safe_mode_pt,
660 )
661 .expect("Advance epoch with safe mode must succeed");
662 }
663 }
664
665 let binary_config = protocol_config.binary_config(None);
666 for (version, modules, dependencies) in change_epoch.system_packages.into_iter() {
667 let deserialized_modules: Vec<_> = modules
668 .iter()
669 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
670 .collect();
671
672 if version == OBJECT_START_VERSION {
673 let package_id = deserialized_modules.first().unwrap().address();
674 info!("adding new system package {package_id}");
675
676 let publish_pt = {
677 let mut b = ProgrammableTransactionBuilder::new();
678 b.command(Command::Publish(modules, dependencies));
679 b.finish()
680 };
681
682 programmable_transactions::execution::execute::<execution_mode::System>(
683 protocol_config,
684 metrics.clone(),
685 move_vm,
686 temporary_store,
687 tx_ctx,
688 gas_charger,
689 publish_pt,
690 )
691 .expect("System Package Publish must succeed");
692 } else {
693 let mut new_package = Object::new_system_package(
694 &deserialized_modules,
695 version,
696 dependencies,
697 tx_ctx.digest(),
698 );
699
700 info!(
701 "upgraded system package {:?}",
702 new_package.compute_object_reference()
703 );
704
705 new_package
708 .data
709 .try_as_package_mut()
710 .unwrap()
711 .decrement_version();
712
713 temporary_store.write_object(new_package, WriteKind::Mutate);
715 }
716 }
717
718 Ok(())
719 }
720
721 fn setup_consensus_commit(
726 consensus_commit_timestamp_ms: CheckpointTimestamp,
727 temporary_store: &mut TemporaryStore<'_>,
728 tx_ctx: &mut TxContext,
729 move_vm: &Arc<MoveVM>,
730 gas_charger: &mut GasCharger,
731 protocol_config: &ProtocolConfig,
732 metrics: Arc<ExecutionMetrics>,
733 ) -> Result<(), ExecutionError> {
734 let pt = {
735 let mut builder = ProgrammableTransactionBuilder::new();
736 let res = builder.move_call(
737 SUI_FRAMEWORK_ADDRESS.into(),
738 CLOCK_MODULE_NAME.to_owned(),
739 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME.to_owned(),
740 vec![],
741 vec![
742 CallArg::CLOCK_MUT,
743 CallArg::Pure(bcs::to_bytes(&consensus_commit_timestamp_ms).unwrap()),
744 ],
745 );
746 assert_invariant!(
747 res.is_ok(),
748 "Unable to generate consensus_commit_prologue transaction!"
749 );
750 builder.finish()
751 };
752 programmable_transactions::execution::execute::<execution_mode::System>(
753 protocol_config,
754 metrics,
755 move_vm,
756 temporary_store,
757 tx_ctx,
758 gas_charger,
759 pt,
760 )
761 }
762}