1pub use checked::*;
5
6#[sui_macros::with_checked_arithmetic]
7mod checked {
8
9 use crate::execution_mode::{self, ExecutionMode};
10 use crate::execution_value::SuiResolver;
11 use crate::gas_charger::PaymentMethod;
12 use move_binary_format::CompiledModule;
13 use move_trace_format::format::MoveTraceBuilder;
14 use move_vm_runtime::move_vm::MoveVM;
15 use mysten_common::debug_fatal;
16 use std::collections::BTreeMap;
17 use std::{cell::RefCell, collections::HashSet, rc::Rc, sync::Arc};
18 use sui_types::accumulator_root::{ACCUMULATOR_ROOT_CREATE_FUNC, ACCUMULATOR_ROOT_MODULE};
19 use sui_types::balance::{
20 BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME,
21 BALANCE_MODULE_NAME,
22 };
23 use sui_types::execution_params::ExecutionOrEarlyError;
24 use sui_types::gas_coin::GAS;
25 use sui_types::messages_checkpoint::CheckpointTimestamp;
26 use sui_types::metrics::LimitsMetrics;
27 use sui_types::object::OBJECT_START_VERSION;
28 use sui_types::programmable_transaction_builder::ProgrammableTransactionBuilder;
29 use sui_types::randomness_state::{
30 RANDOMNESS_MODULE_NAME, RANDOMNESS_STATE_CREATE_FUNCTION_NAME,
31 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
32 };
33 use sui_types::{BRIDGE_ADDRESS, SUI_BRIDGE_OBJECT_ID, SUI_RANDOMNESS_STATE_OBJECT_ID};
34 use tracing::{info, instrument, trace, warn};
35
36 use crate::adapter::new_move_vm;
37 use crate::programmable_transactions;
38 use crate::sui_types::gas::SuiGasStatusAPI;
39 use crate::type_layout_resolver::TypeLayoutResolver;
40 use crate::{gas_charger::GasCharger, temporary_store::TemporaryStore};
41 use move_core_types::ident_str;
42 use sui_move_natives::all_natives;
43 use sui_protocol_config::{
44 LimitThresholdCrossed, PerObjectCongestionControlMode, ProtocolConfig, check_limit_by_meter,
45 };
46 use sui_types::authenticator_state::{
47 AUTHENTICATOR_STATE_CREATE_FUNCTION_NAME, AUTHENTICATOR_STATE_EXPIRE_JWKS_FUNCTION_NAME,
48 AUTHENTICATOR_STATE_MODULE_NAME, AUTHENTICATOR_STATE_UPDATE_FUNCTION_NAME,
49 };
50 use sui_types::base_types::SequenceNumber;
51 use sui_types::bridge::BRIDGE_COMMITTEE_MINIMAL_VOTING_POWER;
52 use sui_types::bridge::{
53 BRIDGE_CREATE_FUNCTION_NAME, BRIDGE_INIT_COMMITTEE_FUNCTION_NAME, BRIDGE_MODULE_NAME,
54 BridgeChainId,
55 };
56 use sui_types::clock::{CLOCK_MODULE_NAME, CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME};
57 use sui_types::committee::EpochId;
58 use sui_types::deny_list_v1::{DENY_LIST_CREATE_FUNC, DENY_LIST_MODULE};
59 use sui_types::digests::{
60 ChainIdentifier, get_mainnet_chain_identifier, get_testnet_chain_identifier,
61 };
62 use sui_types::effects::TransactionEffects;
63 use sui_types::error::{ExecutionError, ExecutionErrorKind};
64 use sui_types::execution::{ExecutionTiming, ResultWithTimings};
65 use sui_types::execution_status::ExecutionStatus;
66 use sui_types::gas::GasCostSummary;
67 use sui_types::gas::SuiGasStatus;
68 use sui_types::id::UID;
69 use sui_types::inner_temporary_store::InnerTemporaryStore;
70 use sui_types::storage::BackingStore;
71 #[cfg(msim)]
72 use sui_types::sui_system_state::advance_epoch_result_injection::maybe_modify_result;
73 use sui_types::sui_system_state::{ADVANCE_EPOCH_SAFE_MODE_FUNCTION_NAME, AdvanceEpochParams};
74 use sui_types::transaction::{
75 Argument, AuthenticatorStateExpire, AuthenticatorStateUpdate, CallArg, ChangeEpoch,
76 Command, EndOfEpochTransactionKind, GasData, GenesisTransaction, ObjectArg,
77 ProgrammableTransaction, StoredExecutionTimeObservations, TransactionKind,
78 WriteAccumulatorStorageCost, is_gas_paid_from_address_balance,
79 };
80 use sui_types::transaction::{CheckedInputObjects, RandomnessStateUpdate};
81 use sui_types::{
82 SUI_AUTHENTICATOR_STATE_OBJECT_ID, SUI_FRAMEWORK_ADDRESS, SUI_FRAMEWORK_PACKAGE_ID,
83 SUI_SYSTEM_PACKAGE_ID,
84 base_types::{SuiAddress, TransactionDigest, TxContext},
85 object::{Object, ObjectInner},
86 sui_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, SUI_SYSTEM_MODULE_NAME},
87 };
88
89 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
90 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
91 store: &dyn BackingStore,
92 input_objects: CheckedInputObjects,
93 gas_data: GasData,
94 gas_status: SuiGasStatus,
95 transaction_kind: TransactionKind,
96 transaction_signer: SuiAddress,
97 transaction_digest: TransactionDigest,
98 move_vm: &Arc<MoveVM>,
99 epoch_id: &EpochId,
100 epoch_timestamp_ms: u64,
101 protocol_config: &ProtocolConfig,
102 metrics: Arc<LimitsMetrics>,
103 enable_expensive_checks: bool,
104 execution_params: ExecutionOrEarlyError,
105 trace_builder_opt: &mut Option<MoveTraceBuilder>,
106 ) -> (
107 InnerTemporaryStore,
108 SuiGasStatus,
109 TransactionEffects,
110 Vec<ExecutionTiming>,
111 Result<Mode::ExecutionResults, ExecutionError>,
112 ) {
113 let input_objects = input_objects.into_inner();
114 let mutable_inputs = if enable_expensive_checks {
115 input_objects.all_mutable_inputs().keys().copied().collect()
116 } else {
117 HashSet::new()
118 };
119 let shared_object_refs = input_objects.filter_shared_objects();
120 let receiving_objects = transaction_kind.receiving_objects();
121 let mut transaction_dependencies = input_objects.transaction_dependencies();
122
123 let mut temporary_store = TemporaryStore::new(
124 store,
125 input_objects,
126 receiving_objects,
127 transaction_digest,
128 protocol_config,
129 *epoch_id,
130 );
131
132 let sponsor = {
133 let gas_owner = gas_data.owner;
134 if gas_owner == transaction_signer {
135 None
136 } else {
137 Some(gas_owner)
138 }
139 };
140 let gas_price = gas_status.gas_price();
141 let rgp = gas_status.reference_gas_price();
142
143 let payment_method = if gas_data.is_unmetered() || transaction_kind.is_system_tx() {
144 PaymentMethod::Unmetered
145 } else if is_gas_paid_from_address_balance(&gas_data, &transaction_kind) {
146 PaymentMethod::AddressBalance(gas_data.owner)
147 } else {
148 PaymentMethod::Coins(gas_data.payment)
149 };
150
151 let mut gas_charger = GasCharger::new(
152 transaction_digest,
153 payment_method,
154 gas_status,
155 protocol_config,
156 );
157
158 let tx_ctx = TxContext::new_from_components(
159 &transaction_signer,
160 &transaction_digest,
161 epoch_id,
162 epoch_timestamp_ms,
163 rgp,
164 gas_price,
165 gas_data.budget,
166 sponsor,
167 protocol_config,
168 );
169 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
170
171 let is_epoch_change = transaction_kind.is_end_of_epoch_tx();
172
173 let (gas_cost_summary, execution_result, timings) = execute_transaction::<Mode>(
174 store,
175 &mut temporary_store,
176 transaction_kind,
177 &mut gas_charger,
178 tx_ctx,
179 move_vm,
180 protocol_config,
181 metrics,
182 enable_expensive_checks,
183 execution_params,
184 trace_builder_opt,
185 );
186
187 let status = if let Err(error) = &execution_result {
188 use ExecutionErrorKind as K;
190 match error.kind() {
191 K::InvariantViolation | K::VMInvariantViolation => {
192 if protocol_config.debug_fatal_on_move_invariant_violation() {
193 debug_fatal!(
194 "INVARIANT VIOLATION! Txn Digest: {}, Source: {:?}",
195 transaction_digest,
196 error.source(),
197 );
198 } else {
199 #[skip_checked_arithmetic]
200 tracing::error!(
201 kind = ?error.kind(),
202 tx_digest = ?transaction_digest,
203 "INVARIANT VIOLATION! Source: {:?}",
204 error.source(),
205 );
206 }
207 }
208
209 K::SuiMoveVerificationError | K::VMVerificationOrDeserializationError => {
210 #[skip_checked_arithmetic]
211 tracing::debug!(
212 kind = ?error.kind(),
213 tx_digest = ?transaction_digest,
214 "Verification Error. Source: {:?}",
215 error.source(),
216 );
217 }
218
219 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
220 #[skip_checked_arithmetic]
221 tracing::debug!(
222 kind = ?error.kind(),
223 tx_digest = ?transaction_digest,
224 "Publish/Upgrade Error. Source: {:?}",
225 error.source(),
226 )
227 }
228
229 _ => (),
230 };
231
232 let (status, command) = error.to_execution_status();
233 ExecutionStatus::new_failure(status, command)
234 } else {
235 ExecutionStatus::Success
236 };
237
238 #[skip_checked_arithmetic]
239 trace!(
240 tx_digest = ?transaction_digest,
241 computation_gas_cost = gas_cost_summary.computation_cost,
242 storage_gas_cost = gas_cost_summary.storage_cost,
243 storage_gas_rebate = gas_cost_summary.storage_rebate,
244 "Finished execution of transaction with status {:?}",
245 status
246 );
247
248 transaction_dependencies.remove(&TransactionDigest::genesis_marker());
252
253 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
254 temporary_store
255 .check_ownership_invariants(
256 &transaction_signer,
257 &sponsor,
258 &mut gas_charger,
259 &mutable_inputs,
260 is_epoch_change,
261 )
262 .unwrap()
263 } let (inner, effects) = temporary_store.into_effects(
266 shared_object_refs,
267 &transaction_digest,
268 transaction_dependencies,
269 gas_cost_summary,
270 status,
271 &mut gas_charger,
272 *epoch_id,
273 );
274
275 (
276 inner,
277 gas_charger.into_gas_status(),
278 effects,
279 timings,
280 execution_result,
281 )
282 }
283
284 pub fn execute_genesis_state_update(
285 store: &dyn BackingStore,
286 protocol_config: &ProtocolConfig,
287 metrics: Arc<LimitsMetrics>,
288 move_vm: &Arc<MoveVM>,
289 tx_context: Rc<RefCell<TxContext>>,
290 input_objects: CheckedInputObjects,
291 pt: ProgrammableTransaction,
292 ) -> Result<InnerTemporaryStore, ExecutionError> {
293 let input_objects = input_objects.into_inner();
294 let mut temporary_store = TemporaryStore::new(
295 store,
296 input_objects,
297 vec![],
298 tx_context.borrow().digest(),
299 protocol_config,
300 0,
301 );
302 let mut gas_charger = GasCharger::new_unmetered(tx_context.borrow().digest());
303 programmable_transactions::execution::execute::<execution_mode::Genesis>(
304 protocol_config,
305 metrics,
306 move_vm,
307 &mut temporary_store,
308 store.as_backing_package_store(),
309 tx_context,
310 &mut gas_charger,
311 None,
312 pt,
313 &mut None,
314 )
315 .map_err(|(e, _)| e)?;
316 temporary_store.update_object_version_and_prev_tx();
317 Ok(temporary_store.into_inner(BTreeMap::new()))
318 }
319
320 #[instrument(name = "tx_execute", level = "debug", skip_all)]
321 fn execute_transaction<Mode: ExecutionMode>(
322 store: &dyn BackingStore,
323 temporary_store: &mut TemporaryStore<'_>,
324 transaction_kind: TransactionKind,
325 gas_charger: &mut GasCharger,
326 tx_ctx: Rc<RefCell<TxContext>>,
327 move_vm: &Arc<MoveVM>,
328 protocol_config: &ProtocolConfig,
329 metrics: Arc<LimitsMetrics>,
330 enable_expensive_checks: bool,
331 execution_params: ExecutionOrEarlyError,
332 trace_builder_opt: &mut Option<MoveTraceBuilder>,
333 ) -> (
334 GasCostSummary,
335 Result<Mode::ExecutionResults, ExecutionError>,
336 Vec<ExecutionTiming>,
337 ) {
338 gas_charger.smash_gas(temporary_store);
339
340 debug_assert!(
342 gas_charger.no_charges(),
343 "No gas charges must be applied yet"
344 );
345
346 let is_genesis_tx = matches!(transaction_kind, TransactionKind::Genesis(_));
347 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
348 let digest = tx_ctx.borrow().digest();
349
350 let result = gas_charger.charge_input_objects(temporary_store);
353
354 let result: ResultWithTimings<Mode::ExecutionResults, ExecutionError> =
355 result.map_err(|e| (e, vec![])).and_then(
356 |()| -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
357 let mut execution_result: ResultWithTimings<
358 Mode::ExecutionResults,
359 ExecutionError,
360 > = match execution_params {
361 ExecutionOrEarlyError::Err(early_execution_error) => {
362 Err((ExecutionError::new(early_execution_error, None), vec![]))
363 }
364 ExecutionOrEarlyError::Ok(()) => execution_loop::<Mode>(
365 store,
366 temporary_store,
367 transaction_kind,
368 tx_ctx,
369 move_vm,
370 gas_charger,
371 protocol_config,
372 metrics.clone(),
373 trace_builder_opt,
374 ),
375 };
376
377 let meter_check = check_meter_limit(
378 temporary_store,
379 gas_charger,
380 protocol_config,
381 metrics.clone(),
382 );
383 if let Err(e) = meter_check {
384 execution_result = Err((e, vec![]));
385 }
386
387 if execution_result.is_ok() {
388 let gas_check = check_written_objects_limit(
389 temporary_store,
390 gas_charger,
391 protocol_config,
392 metrics,
393 );
394 if let Err(e) = gas_check {
395 execution_result = Err((e, vec![]));
396 }
397 }
398
399 execution_result
400 },
401 );
402
403 let (mut result, timings) = match result {
404 Ok((r, t)) => (Ok(r), t),
405 Err((e, t)) => (Err(e), t),
406 };
407
408 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
409 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
417
418 if let Err(e) = run_conservation_checks::<Mode>(
419 temporary_store,
420 gas_charger,
421 digest,
422 move_vm,
423 protocol_config.simple_conservation_checks(),
424 enable_expensive_checks,
425 &cost_summary,
426 is_genesis_tx,
427 advance_epoch_gas_summary,
428 ) {
429 result = Err(e);
431 }
432
433 (cost_summary, result, timings)
434 }
435
436 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
437 fn run_conservation_checks<Mode: ExecutionMode>(
438 temporary_store: &mut TemporaryStore<'_>,
439 gas_charger: &mut GasCharger,
440 tx_digest: TransactionDigest,
441 move_vm: &Arc<MoveVM>,
442 simple_conservation_checks: bool,
443 enable_expensive_checks: bool,
444 cost_summary: &GasCostSummary,
445 is_genesis_tx: bool,
446 advance_epoch_gas_summary: Option<(u64, u64)>,
447 ) -> Result<(), ExecutionError> {
448 let mut result: std::result::Result<(), sui_types::error::ExecutionError> = Ok(());
449 if !is_genesis_tx && !Mode::skip_conservation_checks() {
450 let conservation_result = {
452 temporary_store
453 .check_sui_conserved(simple_conservation_checks, cost_summary)
454 .and_then(|()| {
455 if enable_expensive_checks {
456 let mut layout_resolver =
458 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
459 temporary_store.check_sui_conserved_expensive(
460 cost_summary,
461 advance_epoch_gas_summary,
462 &mut layout_resolver,
463 )
464 } else {
465 Ok(())
466 }
467 })
468 };
469 if let Err(conservation_err) = conservation_result {
470 result = Err(conservation_err);
473 gas_charger.reset(temporary_store);
474 gas_charger.charge_gas(temporary_store, &mut result);
475 if let Err(recovery_err) = {
477 temporary_store
478 .check_sui_conserved(simple_conservation_checks, cost_summary)
479 .and_then(|()| {
480 if enable_expensive_checks {
481 let mut layout_resolver =
483 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
484 temporary_store.check_sui_conserved_expensive(
485 cost_summary,
486 advance_epoch_gas_summary,
487 &mut layout_resolver,
488 )
489 } else {
490 Ok(())
491 }
492 })
493 } {
494 panic!(
498 "SUI conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
499 tx_digest,
500 recovery_err,
501 gas_charger.summary()
502 )
503 }
504 }
505 } result
508 }
509
510 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
511 fn check_meter_limit(
512 temporary_store: &mut TemporaryStore<'_>,
513 gas_charger: &mut GasCharger,
514 protocol_config: &ProtocolConfig,
515 metrics: Arc<LimitsMetrics>,
516 ) -> Result<(), ExecutionError> {
517 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
518
519 match check_limit_by_meter!(
523 !gas_charger.is_unmetered(),
524 effects_estimated_size,
525 protocol_config.max_serialized_tx_effects_size_bytes(),
526 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
527 metrics.excessive_estimated_effects_size
528 ) {
529 LimitThresholdCrossed::None => Ok(()),
530 LimitThresholdCrossed::Soft(_, limit) => {
531 warn!(
532 effects_estimated_size = effects_estimated_size,
533 soft_limit = limit,
534 "Estimated transaction effects size crossed soft limit",
535 );
536 Ok(())
537 }
538 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
539 ExecutionErrorKind::EffectsTooLarge {
540 current_size: effects_estimated_size as u64,
541 max_size: lim as u64,
542 },
543 "Transaction effects are too large",
544 )),
545 }
546 }
547
548 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
549 fn check_written_objects_limit(
550 temporary_store: &mut TemporaryStore<'_>,
551 gas_charger: &mut GasCharger,
552 protocol_config: &ProtocolConfig,
553 metrics: Arc<LimitsMetrics>,
554 ) -> Result<(), ExecutionError> {
555 if let (Some(normal_lim), Some(system_lim)) = (
556 protocol_config.max_size_written_objects_as_option(),
557 protocol_config.max_size_written_objects_system_tx_as_option(),
558 ) {
559 let written_objects_size = temporary_store.written_objects_size();
560
561 match check_limit_by_meter!(
562 !gas_charger.is_unmetered(),
563 written_objects_size,
564 normal_lim,
565 system_lim,
566 metrics.excessive_written_objects_size
567 ) {
568 LimitThresholdCrossed::None => (),
569 LimitThresholdCrossed::Soft(_, limit) => {
570 warn!(
571 written_objects_size = written_objects_size,
572 soft_limit = limit,
573 "Written objects size crossed soft limit",
574 )
575 }
576 LimitThresholdCrossed::Hard(_, lim) => {
577 return Err(ExecutionError::new_with_source(
578 ExecutionErrorKind::WrittenObjectsTooLarge {
579 current_size: written_objects_size as u64,
580 max_size: lim as u64,
581 },
582 "Written objects size crossed hard limit",
583 ));
584 }
585 };
586 }
587
588 Ok(())
589 }
590
591 #[instrument(level = "debug", skip_all)]
592 fn execution_loop<Mode: ExecutionMode>(
593 store: &dyn BackingStore,
594 temporary_store: &mut TemporaryStore<'_>,
595 transaction_kind: TransactionKind,
596 tx_ctx: Rc<RefCell<TxContext>>,
597 move_vm: &Arc<MoveVM>,
598 gas_charger: &mut GasCharger,
599 protocol_config: &ProtocolConfig,
600 metrics: Arc<LimitsMetrics>,
601 trace_builder_opt: &mut Option<MoveTraceBuilder>,
602 ) -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
603 let result = match transaction_kind {
604 TransactionKind::ChangeEpoch(change_epoch) => {
605 let builder = ProgrammableTransactionBuilder::new();
606 advance_epoch(
607 builder,
608 change_epoch,
609 temporary_store,
610 store,
611 tx_ctx,
612 move_vm,
613 gas_charger,
614 protocol_config,
615 metrics,
616 trace_builder_opt,
617 )
618 .map_err(|e| (e, vec![]))?;
619 Ok((Mode::empty_results(), vec![]))
620 }
621 TransactionKind::Genesis(GenesisTransaction { objects }) => {
622 if tx_ctx.borrow().epoch() != 0 {
623 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
624 }
625
626 for genesis_object in objects {
627 match genesis_object {
628 sui_types::transaction::GenesisObject::RawObject { data, owner } => {
629 let object = ObjectInner {
630 data,
631 owner,
632 previous_transaction: tx_ctx.borrow().digest(),
633 storage_rebate: 0,
634 };
635 temporary_store.create_object(object.into());
636 }
637 }
638 }
639 Ok((Mode::empty_results(), vec![]))
640 }
641 TransactionKind::ConsensusCommitPrologue(prologue) => {
642 setup_consensus_commit(
643 prologue.commit_timestamp_ms,
644 temporary_store,
645 store,
646 tx_ctx,
647 move_vm,
648 gas_charger,
649 protocol_config,
650 metrics,
651 trace_builder_opt,
652 )
653 .expect("ConsensusCommitPrologue cannot fail");
654 Ok((Mode::empty_results(), vec![]))
655 }
656 TransactionKind::ConsensusCommitPrologueV2(prologue) => {
657 setup_consensus_commit(
658 prologue.commit_timestamp_ms,
659 temporary_store,
660 store,
661 tx_ctx,
662 move_vm,
663 gas_charger,
664 protocol_config,
665 metrics,
666 trace_builder_opt,
667 )
668 .expect("ConsensusCommitPrologueV2 cannot fail");
669 Ok((Mode::empty_results(), vec![]))
670 }
671 TransactionKind::ConsensusCommitPrologueV3(prologue) => {
672 setup_consensus_commit(
673 prologue.commit_timestamp_ms,
674 temporary_store,
675 store,
676 tx_ctx,
677 move_vm,
678 gas_charger,
679 protocol_config,
680 metrics,
681 trace_builder_opt,
682 )
683 .expect("ConsensusCommitPrologueV3 cannot fail");
684 Ok((Mode::empty_results(), vec![]))
685 }
686 TransactionKind::ConsensusCommitPrologueV4(prologue) => {
687 setup_consensus_commit(
688 prologue.commit_timestamp_ms,
689 temporary_store,
690 store,
691 tx_ctx,
692 move_vm,
693 gas_charger,
694 protocol_config,
695 metrics,
696 trace_builder_opt,
697 )
698 .expect("ConsensusCommitPrologue cannot fail");
699 Ok((Mode::empty_results(), vec![]))
700 }
701 TransactionKind::ProgrammableTransaction(pt) => {
702 programmable_transactions::execution::execute::<Mode>(
703 protocol_config,
704 metrics,
705 move_vm,
706 temporary_store,
707 store.as_backing_package_store(),
708 tx_ctx,
709 gas_charger,
710 None,
711 pt,
712 trace_builder_opt,
713 )
714 }
715 TransactionKind::ProgrammableSystemTransaction(pt) => {
716 programmable_transactions::execution::execute::<execution_mode::System>(
717 protocol_config,
718 metrics,
719 move_vm,
720 temporary_store,
721 store.as_backing_package_store(),
722 tx_ctx,
723 gas_charger,
724 None,
725 pt,
726 trace_builder_opt,
727 )?;
728 Ok((Mode::empty_results(), vec![]))
729 }
730 TransactionKind::EndOfEpochTransaction(txns) => {
731 let mut builder = ProgrammableTransactionBuilder::new();
732 let len = txns.len();
733 for (i, tx) in txns.into_iter().enumerate() {
734 match tx {
735 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
736 assert_eq!(i, len - 1);
737 advance_epoch(
738 builder,
739 change_epoch,
740 temporary_store,
741 store,
742 tx_ctx,
743 move_vm,
744 gas_charger,
745 protocol_config,
746 metrics,
747 trace_builder_opt,
748 )
749 .map_err(|e| (e, vec![]))?;
750 return Ok((Mode::empty_results(), vec![]));
751 }
752 EndOfEpochTransactionKind::AuthenticatorStateCreate => {
753 assert!(protocol_config.enable_jwk_consensus_updates());
754 builder = setup_authenticator_state_create(builder);
755 }
756 EndOfEpochTransactionKind::AuthenticatorStateExpire(expire) => {
757 assert!(protocol_config.enable_jwk_consensus_updates());
758
759 builder = setup_authenticator_state_expire(builder, expire);
762 }
763 EndOfEpochTransactionKind::RandomnessStateCreate => {
764 assert!(protocol_config.random_beacon());
765 builder = setup_randomness_state_create(builder);
766 }
767 EndOfEpochTransactionKind::DenyListStateCreate => {
768 assert!(protocol_config.enable_coin_deny_list_v1());
769 builder = setup_coin_deny_list_state_create(builder);
770 }
771 EndOfEpochTransactionKind::BridgeStateCreate(chain_id) => {
772 assert!(protocol_config.enable_bridge());
773 builder = setup_bridge_create(builder, chain_id)
774 }
775 EndOfEpochTransactionKind::BridgeCommitteeInit(bridge_shared_version) => {
776 assert!(protocol_config.enable_bridge());
777 assert!(protocol_config.should_try_to_finalize_bridge_committee());
778 builder = setup_bridge_committee_update(builder, bridge_shared_version)
779 }
780 EndOfEpochTransactionKind::StoreExecutionTimeObservations(estimates) => {
781 if let PerObjectCongestionControlMode::ExecutionTimeEstimate(params) =
782 protocol_config.per_object_congestion_control_mode()
783 {
784 if let Some(chunk_size) = params.observations_chunk_size {
785 builder = setup_store_execution_time_estimates_v2(
786 builder,
787 estimates,
788 chunk_size as usize,
789 );
790 } else {
791 builder =
792 setup_store_execution_time_estimates(builder, estimates);
793 }
794 }
795 }
796 EndOfEpochTransactionKind::AccumulatorRootCreate => {
797 assert!(protocol_config.create_root_accumulator_object());
798 builder = setup_accumulator_root_create(builder);
799 }
800 EndOfEpochTransactionKind::WriteAccumulatorStorageCost(
801 write_storage_cost,
802 ) => {
803 assert!(protocol_config.enable_accumulators());
804 builder =
805 setup_write_accumulator_storage_cost(builder, &write_storage_cost);
806 }
807 EndOfEpochTransactionKind::CoinRegistryCreate => {
808 assert!(protocol_config.enable_coin_registry());
809 builder = setup_coin_registry_create(builder);
810 }
811 EndOfEpochTransactionKind::DisplayRegistryCreate => {
812 assert!(protocol_config.enable_display_registry());
813 builder = setup_display_registry_create(builder);
814 }
815 EndOfEpochTransactionKind::AddressAliasStateCreate => {
816 assert!(protocol_config.address_aliases());
817 builder = setup_address_alias_state_create(builder);
818 }
819 }
820 }
821 unreachable!(
822 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
823 )
824 }
825 TransactionKind::AuthenticatorStateUpdate(auth_state_update) => {
826 setup_authenticator_state_update(
827 auth_state_update,
828 temporary_store,
829 store,
830 tx_ctx,
831 move_vm,
832 gas_charger,
833 protocol_config,
834 metrics,
835 trace_builder_opt,
836 )
837 .map_err(|e| (e, vec![]))?;
838 Ok((Mode::empty_results(), vec![]))
839 }
840 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
841 setup_randomness_state_update(
842 randomness_state_update,
843 temporary_store,
844 store,
845 tx_ctx,
846 move_vm,
847 gas_charger,
848 protocol_config,
849 metrics,
850 trace_builder_opt,
851 )
852 .map_err(|e| (e, vec![]))?;
853 Ok((Mode::empty_results(), vec![]))
854 }
855 }?;
856 temporary_store
857 .check_execution_results_consistency()
858 .map_err(|e| (e, vec![]))?;
859 Ok(result)
860 }
861
862 fn mint_epoch_rewards_in_pt(
863 builder: &mut ProgrammableTransactionBuilder,
864 params: &AdvanceEpochParams,
865 ) -> (Argument, Argument) {
866 let storage_charge_arg = builder
868 .input(CallArg::Pure(
869 bcs::to_bytes(¶ms.storage_charge).unwrap(),
870 ))
871 .unwrap();
872 let storage_rewards = builder.programmable_move_call(
873 SUI_FRAMEWORK_PACKAGE_ID,
874 BALANCE_MODULE_NAME.to_owned(),
875 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
876 vec![GAS::type_tag()],
877 vec![storage_charge_arg],
878 );
879
880 let computation_charge_arg = builder
882 .input(CallArg::Pure(
883 bcs::to_bytes(¶ms.computation_charge).unwrap(),
884 ))
885 .unwrap();
886 let computation_rewards = builder.programmable_move_call(
887 SUI_FRAMEWORK_PACKAGE_ID,
888 BALANCE_MODULE_NAME.to_owned(),
889 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
890 vec![GAS::type_tag()],
891 vec![computation_charge_arg],
892 );
893 (storage_rewards, computation_rewards)
894 }
895
896 pub fn construct_advance_epoch_pt(
897 mut builder: ProgrammableTransactionBuilder,
898 params: &AdvanceEpochParams,
899 ) -> Result<ProgrammableTransaction, ExecutionError> {
900 let (storage_rewards, computation_rewards) = mint_epoch_rewards_in_pt(&mut builder, params);
902
903 let mut arguments = vec![storage_rewards, computation_rewards];
905 let call_arg_arguments = vec![
906 CallArg::SUI_SYSTEM_MUT,
907 CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()),
908 CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()),
909 CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()),
910 CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()),
911 CallArg::Pure(bcs::to_bytes(¶ms.storage_fund_reinvest_rate).unwrap()),
912 CallArg::Pure(bcs::to_bytes(¶ms.reward_slashing_rate).unwrap()),
913 CallArg::Pure(bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap()),
914 ]
915 .into_iter()
916 .map(|a| builder.input(a))
917 .collect::<Result<_, _>>();
918
919 assert_invariant!(
920 call_arg_arguments.is_ok(),
921 "Unable to generate args for advance_epoch transaction!"
922 );
923
924 arguments.append(&mut call_arg_arguments.unwrap());
925
926 info!("Call arguments to advance_epoch transaction: {:?}", params);
927
928 let storage_rebates = builder.programmable_move_call(
929 SUI_SYSTEM_PACKAGE_ID,
930 SUI_SYSTEM_MODULE_NAME.to_owned(),
931 ADVANCE_EPOCH_FUNCTION_NAME.to_owned(),
932 vec![],
933 arguments,
934 );
935
936 builder.programmable_move_call(
938 SUI_FRAMEWORK_PACKAGE_ID,
939 BALANCE_MODULE_NAME.to_owned(),
940 BALANCE_DESTROY_REBATES_FUNCTION_NAME.to_owned(),
941 vec![GAS::type_tag()],
942 vec![storage_rebates],
943 );
944 Ok(builder.finish())
945 }
946
947 pub fn construct_advance_epoch_safe_mode_pt(
948 params: &AdvanceEpochParams,
949 protocol_config: &ProtocolConfig,
950 ) -> Result<ProgrammableTransaction, ExecutionError> {
951 let mut builder = ProgrammableTransactionBuilder::new();
952 let (storage_rewards, computation_rewards) = mint_epoch_rewards_in_pt(&mut builder, params);
954
955 let mut arguments = vec![storage_rewards, computation_rewards];
957
958 let mut args = vec![
959 CallArg::SUI_SYSTEM_MUT,
960 CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()),
961 CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()),
962 CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()),
963 CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()),
964 ];
965
966 if protocol_config.get_advance_epoch_start_time_in_safe_mode() {
967 args.push(CallArg::Pure(
968 bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap(),
969 ));
970 }
971
972 let call_arg_arguments = args
973 .into_iter()
974 .map(|a| builder.input(a))
975 .collect::<Result<_, _>>();
976
977 assert_invariant!(
978 call_arg_arguments.is_ok(),
979 "Unable to generate args for advance_epoch transaction!"
980 );
981
982 arguments.append(&mut call_arg_arguments.unwrap());
983
984 info!("Call arguments to advance_epoch transaction: {:?}", params);
985
986 builder.programmable_move_call(
987 SUI_SYSTEM_PACKAGE_ID,
988 SUI_SYSTEM_MODULE_NAME.to_owned(),
989 ADVANCE_EPOCH_SAFE_MODE_FUNCTION_NAME.to_owned(),
990 vec![],
991 arguments,
992 );
993
994 Ok(builder.finish())
995 }
996
997 fn advance_epoch(
998 builder: ProgrammableTransactionBuilder,
999 change_epoch: ChangeEpoch,
1000 temporary_store: &mut TemporaryStore<'_>,
1001 store: &dyn BackingStore,
1002 tx_ctx: Rc<RefCell<TxContext>>,
1003 move_vm: &Arc<MoveVM>,
1004 gas_charger: &mut GasCharger,
1005 protocol_config: &ProtocolConfig,
1006 metrics: Arc<LimitsMetrics>,
1007 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1008 ) -> Result<(), ExecutionError> {
1009 let params = AdvanceEpochParams {
1010 epoch: change_epoch.epoch,
1011 next_protocol_version: change_epoch.protocol_version,
1012 storage_charge: change_epoch.storage_charge,
1013 computation_charge: change_epoch.computation_charge,
1014 storage_rebate: change_epoch.storage_rebate,
1015 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1016 storage_fund_reinvest_rate: protocol_config.storage_fund_reinvest_rate(),
1017 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1018 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1019 };
1020 let advance_epoch_pt = construct_advance_epoch_pt(builder, ¶ms)?;
1021 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1022 protocol_config,
1023 metrics.clone(),
1024 move_vm,
1025 temporary_store,
1026 store.as_backing_package_store(),
1027 tx_ctx.clone(),
1028 gas_charger,
1029 None,
1030 advance_epoch_pt,
1031 trace_builder_opt,
1032 );
1033
1034 #[cfg(msim)]
1035 let result = maybe_modify_result(result, change_epoch.epoch);
1036
1037 if let Err(err) = &result {
1038 tracing::error!(
1039 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx data: {:?}",
1040 err.0,
1041 temporary_store.objects(),
1042 change_epoch,
1043 );
1044 temporary_store.drop_writes();
1045 gas_charger.reset_storage_cost_and_rebate();
1047
1048 if protocol_config.get_advance_epoch_start_time_in_safe_mode() {
1049 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1050 } else {
1051 let advance_epoch_safe_mode_pt =
1052 construct_advance_epoch_safe_mode_pt(¶ms, protocol_config)?;
1053 programmable_transactions::execution::execute::<execution_mode::System>(
1054 protocol_config,
1055 metrics.clone(),
1056 move_vm,
1057 temporary_store,
1058 store.as_backing_package_store(),
1059 tx_ctx.clone(),
1060 gas_charger,
1061 None,
1062 advance_epoch_safe_mode_pt,
1063 trace_builder_opt,
1064 )
1065 .map_err(|(e, _)| e)
1066 .expect("Advance epoch with safe mode must succeed");
1067 }
1068 }
1069
1070 if protocol_config.fresh_vm_on_framework_upgrade() {
1071 let new_vm = new_move_vm(
1072 all_natives(true, protocol_config),
1073 protocol_config,
1074 )
1075 .expect("Failed to create new MoveVM");
1076 process_system_packages(
1077 change_epoch,
1078 temporary_store,
1079 store,
1080 tx_ctx,
1081 &new_vm,
1082 gas_charger,
1083 protocol_config,
1084 metrics,
1085 trace_builder_opt,
1086 );
1087 } else {
1088 process_system_packages(
1089 change_epoch,
1090 temporary_store,
1091 store,
1092 tx_ctx,
1093 move_vm,
1094 gas_charger,
1095 protocol_config,
1096 metrics,
1097 trace_builder_opt,
1098 );
1099 }
1100 Ok(())
1101 }
1102
1103 fn process_system_packages(
1104 change_epoch: ChangeEpoch,
1105 temporary_store: &mut TemporaryStore<'_>,
1106 store: &dyn BackingStore,
1107 tx_ctx: Rc<RefCell<TxContext>>,
1108 move_vm: &MoveVM,
1109 gas_charger: &mut GasCharger,
1110 protocol_config: &ProtocolConfig,
1111 metrics: Arc<LimitsMetrics>,
1112 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1113 ) {
1114 let digest = tx_ctx.borrow().digest();
1115 let binary_config = protocol_config.binary_config(None);
1116 for (version, modules, dependencies) in change_epoch.system_packages.into_iter() {
1117 let deserialized_modules: Vec<_> = modules
1118 .iter()
1119 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1120 .collect();
1121
1122 if version == OBJECT_START_VERSION {
1123 let package_id = deserialized_modules.first().unwrap().address();
1124 info!("adding new system package {package_id}");
1125
1126 let publish_pt = {
1127 let mut b = ProgrammableTransactionBuilder::new();
1128 b.command(Command::Publish(modules, dependencies));
1129 b.finish()
1130 };
1131
1132 programmable_transactions::execution::execute::<execution_mode::System>(
1133 protocol_config,
1134 metrics.clone(),
1135 move_vm,
1136 temporary_store,
1137 store.as_backing_package_store(),
1138 tx_ctx.clone(),
1139 gas_charger,
1140 None,
1141 publish_pt,
1142 trace_builder_opt,
1143 )
1144 .map_err(|(e, _)| e)
1145 .expect("System Package Publish must succeed");
1146 } else {
1147 let mut new_package = Object::new_system_package(
1148 &deserialized_modules,
1149 version,
1150 dependencies,
1151 digest,
1152 );
1153
1154 info!(
1155 "upgraded system package {:?}",
1156 new_package.compute_object_reference()
1157 );
1158
1159 new_package
1162 .data
1163 .try_as_package_mut()
1164 .unwrap()
1165 .decrement_version();
1166
1167 temporary_store.upgrade_system_package(new_package);
1169 }
1170 }
1171 }
1172
1173 fn setup_consensus_commit(
1178 consensus_commit_timestamp_ms: CheckpointTimestamp,
1179 temporary_store: &mut TemporaryStore<'_>,
1180 store: &dyn BackingStore,
1181 tx_ctx: Rc<RefCell<TxContext>>,
1182 move_vm: &Arc<MoveVM>,
1183 gas_charger: &mut GasCharger,
1184 protocol_config: &ProtocolConfig,
1185 metrics: Arc<LimitsMetrics>,
1186 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1187 ) -> Result<(), ExecutionError> {
1188 let pt = {
1189 let mut builder = ProgrammableTransactionBuilder::new();
1190 let res = builder.move_call(
1191 SUI_FRAMEWORK_ADDRESS.into(),
1192 CLOCK_MODULE_NAME.to_owned(),
1193 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME.to_owned(),
1194 vec![],
1195 vec![
1196 CallArg::CLOCK_MUT,
1197 CallArg::Pure(bcs::to_bytes(&consensus_commit_timestamp_ms).unwrap()),
1198 ],
1199 );
1200 assert_invariant!(
1201 res.is_ok(),
1202 "Unable to generate consensus_commit_prologue transaction!"
1203 );
1204 builder.finish()
1205 };
1206 programmable_transactions::execution::execute::<execution_mode::System>(
1207 protocol_config,
1208 metrics,
1209 move_vm,
1210 temporary_store,
1211 store.as_backing_package_store(),
1212 tx_ctx,
1213 gas_charger,
1214 None,
1215 pt,
1216 trace_builder_opt,
1217 )
1218 .map_err(|(e, _)| e)?;
1219 Ok(())
1220 }
1221
1222 fn setup_authenticator_state_create(
1223 mut builder: ProgrammableTransactionBuilder,
1224 ) -> ProgrammableTransactionBuilder {
1225 builder
1226 .move_call(
1227 SUI_FRAMEWORK_ADDRESS.into(),
1228 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1229 AUTHENTICATOR_STATE_CREATE_FUNCTION_NAME.to_owned(),
1230 vec![],
1231 vec![],
1232 )
1233 .expect("Unable to generate authenticator_state_create transaction!");
1234 builder
1235 }
1236
1237 fn setup_randomness_state_create(
1238 mut builder: ProgrammableTransactionBuilder,
1239 ) -> ProgrammableTransactionBuilder {
1240 builder
1241 .move_call(
1242 SUI_FRAMEWORK_ADDRESS.into(),
1243 RANDOMNESS_MODULE_NAME.to_owned(),
1244 RANDOMNESS_STATE_CREATE_FUNCTION_NAME.to_owned(),
1245 vec![],
1246 vec![],
1247 )
1248 .expect("Unable to generate randomness_state_create transaction!");
1249 builder
1250 }
1251
1252 fn setup_bridge_create(
1253 mut builder: ProgrammableTransactionBuilder,
1254 chain_id: ChainIdentifier,
1255 ) -> ProgrammableTransactionBuilder {
1256 let bridge_uid = builder
1257 .input(CallArg::Pure(UID::new(SUI_BRIDGE_OBJECT_ID).to_bcs_bytes()))
1258 .expect("Unable to create Bridge object UID!");
1259
1260 let bridge_chain_id = if chain_id == get_mainnet_chain_identifier() {
1261 BridgeChainId::SuiMainnet as u8
1262 } else if chain_id == get_testnet_chain_identifier() {
1263 BridgeChainId::SuiTestnet as u8
1264 } else {
1265 BridgeChainId::SuiCustom as u8
1267 };
1268
1269 let bridge_chain_id = builder.pure(bridge_chain_id).unwrap();
1270 builder.programmable_move_call(
1271 BRIDGE_ADDRESS.into(),
1272 BRIDGE_MODULE_NAME.to_owned(),
1273 BRIDGE_CREATE_FUNCTION_NAME.to_owned(),
1274 vec![],
1275 vec![bridge_uid, bridge_chain_id],
1276 );
1277 builder
1278 }
1279
1280 fn setup_bridge_committee_update(
1281 mut builder: ProgrammableTransactionBuilder,
1282 bridge_shared_version: SequenceNumber,
1283 ) -> ProgrammableTransactionBuilder {
1284 let bridge = builder
1285 .obj(ObjectArg::SharedObject {
1286 id: SUI_BRIDGE_OBJECT_ID,
1287 initial_shared_version: bridge_shared_version,
1288 mutability: sui_types::transaction::SharedObjectMutability::Mutable,
1289 })
1290 .expect("Unable to create Bridge object arg!");
1291 let system_state = builder
1292 .obj(ObjectArg::SUI_SYSTEM_MUT)
1293 .expect("Unable to create System State object arg!");
1294
1295 let voting_power = builder.programmable_move_call(
1296 SUI_SYSTEM_PACKAGE_ID,
1297 SUI_SYSTEM_MODULE_NAME.to_owned(),
1298 ident_str!("validator_voting_powers").to_owned(),
1299 vec![],
1300 vec![system_state],
1301 );
1302
1303 let min_stake_participation_percentage = builder
1306 .input(CallArg::Pure(
1307 bcs::to_bytes(&BRIDGE_COMMITTEE_MINIMAL_VOTING_POWER).unwrap(),
1308 ))
1309 .unwrap();
1310
1311 builder.programmable_move_call(
1312 BRIDGE_ADDRESS.into(),
1313 BRIDGE_MODULE_NAME.to_owned(),
1314 BRIDGE_INIT_COMMITTEE_FUNCTION_NAME.to_owned(),
1315 vec![],
1316 vec![bridge, voting_power, min_stake_participation_percentage],
1317 );
1318 builder
1319 }
1320
1321 fn setup_authenticator_state_update(
1322 update: AuthenticatorStateUpdate,
1323 temporary_store: &mut TemporaryStore<'_>,
1324 store: &dyn BackingStore,
1325 tx_ctx: Rc<RefCell<TxContext>>,
1326 move_vm: &Arc<MoveVM>,
1327 gas_charger: &mut GasCharger,
1328 protocol_config: &ProtocolConfig,
1329 metrics: Arc<LimitsMetrics>,
1330 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1331 ) -> Result<(), ExecutionError> {
1332 let pt = {
1333 let mut builder = ProgrammableTransactionBuilder::new();
1334 let res = builder.move_call(
1335 SUI_FRAMEWORK_ADDRESS.into(),
1336 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1337 AUTHENTICATOR_STATE_UPDATE_FUNCTION_NAME.to_owned(),
1338 vec![],
1339 vec![
1340 CallArg::Object(ObjectArg::SharedObject {
1341 id: SUI_AUTHENTICATOR_STATE_OBJECT_ID,
1342 initial_shared_version: update.authenticator_obj_initial_shared_version,
1343 mutability: sui_types::transaction::SharedObjectMutability::Mutable,
1344 }),
1345 CallArg::Pure(bcs::to_bytes(&update.new_active_jwks).unwrap()),
1346 ],
1347 );
1348 assert_invariant!(
1349 res.is_ok(),
1350 "Unable to generate authenticator_state_update transaction!"
1351 );
1352 builder.finish()
1353 };
1354 programmable_transactions::execution::execute::<execution_mode::System>(
1355 protocol_config,
1356 metrics,
1357 move_vm,
1358 temporary_store,
1359 store.as_backing_package_store(),
1360 tx_ctx,
1361 gas_charger,
1362 None,
1363 pt,
1364 trace_builder_opt,
1365 )
1366 .map_err(|(e, _)| e)?;
1367 Ok(())
1368 }
1369
1370 fn setup_authenticator_state_expire(
1371 mut builder: ProgrammableTransactionBuilder,
1372 expire: AuthenticatorStateExpire,
1373 ) -> ProgrammableTransactionBuilder {
1374 builder
1375 .move_call(
1376 SUI_FRAMEWORK_ADDRESS.into(),
1377 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1378 AUTHENTICATOR_STATE_EXPIRE_JWKS_FUNCTION_NAME.to_owned(),
1379 vec![],
1380 vec![
1381 CallArg::Object(ObjectArg::SharedObject {
1382 id: SUI_AUTHENTICATOR_STATE_OBJECT_ID,
1383 initial_shared_version: expire.authenticator_obj_initial_shared_version,
1384 mutability: sui_types::transaction::SharedObjectMutability::Mutable,
1385 }),
1386 CallArg::Pure(bcs::to_bytes(&expire.min_epoch).unwrap()),
1387 ],
1388 )
1389 .expect("Unable to generate authenticator_state_expire transaction!");
1390 builder
1391 }
1392
1393 fn setup_randomness_state_update(
1394 update: RandomnessStateUpdate,
1395 temporary_store: &mut TemporaryStore<'_>,
1396 store: &dyn BackingStore,
1397 tx_ctx: Rc<RefCell<TxContext>>,
1398 move_vm: &Arc<MoveVM>,
1399 gas_charger: &mut GasCharger,
1400 protocol_config: &ProtocolConfig,
1401 metrics: Arc<LimitsMetrics>,
1402 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1403 ) -> Result<(), ExecutionError> {
1404 let pt = {
1405 let mut builder = ProgrammableTransactionBuilder::new();
1406 let res = builder.move_call(
1407 SUI_FRAMEWORK_ADDRESS.into(),
1408 RANDOMNESS_MODULE_NAME.to_owned(),
1409 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME.to_owned(),
1410 vec![],
1411 vec![
1412 CallArg::Object(ObjectArg::SharedObject {
1413 id: SUI_RANDOMNESS_STATE_OBJECT_ID,
1414 initial_shared_version: update.randomness_obj_initial_shared_version,
1415 mutability: sui_types::transaction::SharedObjectMutability::Mutable,
1416 }),
1417 CallArg::Pure(bcs::to_bytes(&update.randomness_round).unwrap()),
1418 CallArg::Pure(bcs::to_bytes(&update.random_bytes).unwrap()),
1419 ],
1420 );
1421 assert_invariant!(
1422 res.is_ok(),
1423 "Unable to generate randomness_state_update transaction!"
1424 );
1425 builder.finish()
1426 };
1427 programmable_transactions::execution::execute::<execution_mode::System>(
1428 protocol_config,
1429 metrics,
1430 move_vm,
1431 temporary_store,
1432 store.as_backing_package_store(),
1433 tx_ctx,
1434 gas_charger,
1435 None,
1436 pt,
1437 trace_builder_opt,
1438 )
1439 .map_err(|(e, _)| e)?;
1440 Ok(())
1441 }
1442
1443 fn setup_coin_deny_list_state_create(
1444 mut builder: ProgrammableTransactionBuilder,
1445 ) -> ProgrammableTransactionBuilder {
1446 builder
1447 .move_call(
1448 SUI_FRAMEWORK_ADDRESS.into(),
1449 DENY_LIST_MODULE.to_owned(),
1450 DENY_LIST_CREATE_FUNC.to_owned(),
1451 vec![],
1452 vec![],
1453 )
1454 .expect("Unable to generate coin_deny_list_create transaction!");
1455 builder
1456 }
1457
1458 fn setup_store_execution_time_estimates(
1459 mut builder: ProgrammableTransactionBuilder,
1460 estimates: StoredExecutionTimeObservations,
1461 ) -> ProgrammableTransactionBuilder {
1462 let system_state = builder.obj(ObjectArg::SUI_SYSTEM_MUT).unwrap();
1463 let estimates_bytes = bcs::to_bytes(&estimates).unwrap();
1466 let estimates_arg = builder.pure(estimates_bytes).unwrap();
1467 builder.programmable_move_call(
1468 SUI_SYSTEM_PACKAGE_ID,
1469 SUI_SYSTEM_MODULE_NAME.to_owned(),
1470 ident_str!("store_execution_time_estimates").to_owned(),
1471 vec![],
1472 vec![system_state, estimates_arg],
1473 );
1474 builder
1475 }
1476
1477 fn setup_store_execution_time_estimates_v2(
1478 mut builder: ProgrammableTransactionBuilder,
1479 estimates: StoredExecutionTimeObservations,
1480 chunk_size: usize,
1481 ) -> ProgrammableTransactionBuilder {
1482 let system_state = builder.obj(ObjectArg::SUI_SYSTEM_MUT).unwrap();
1483
1484 let estimate_chunks = estimates.chunk_observations(chunk_size);
1485
1486 let chunk_bytes: Vec<Vec<u8>> = estimate_chunks
1487 .into_iter()
1488 .map(|chunk| bcs::to_bytes(&chunk).unwrap())
1489 .collect();
1490
1491 let chunks_arg = builder.pure(chunk_bytes).unwrap();
1492
1493 builder.programmable_move_call(
1494 SUI_SYSTEM_PACKAGE_ID,
1495 SUI_SYSTEM_MODULE_NAME.to_owned(),
1496 ident_str!("store_execution_time_estimates_v2").to_owned(),
1497 vec![],
1498 vec![system_state, chunks_arg],
1499 );
1500 builder
1501 }
1502
1503 fn setup_accumulator_root_create(
1504 mut builder: ProgrammableTransactionBuilder,
1505 ) -> ProgrammableTransactionBuilder {
1506 builder
1507 .move_call(
1508 SUI_FRAMEWORK_ADDRESS.into(),
1509 ACCUMULATOR_ROOT_MODULE.to_owned(),
1510 ACCUMULATOR_ROOT_CREATE_FUNC.to_owned(),
1511 vec![],
1512 vec![],
1513 )
1514 .expect("Unable to generate accumulator_root_create transaction!");
1515 builder
1516 }
1517
1518 fn setup_write_accumulator_storage_cost(
1519 mut builder: ProgrammableTransactionBuilder,
1520 write_storage_cost: &WriteAccumulatorStorageCost,
1521 ) -> ProgrammableTransactionBuilder {
1522 let system_state = builder.obj(ObjectArg::SUI_SYSTEM_MUT).unwrap();
1523 let storage_cost_arg = builder.pure(write_storage_cost.storage_cost).unwrap();
1524 builder.programmable_move_call(
1525 SUI_SYSTEM_PACKAGE_ID,
1526 SUI_SYSTEM_MODULE_NAME.to_owned(),
1527 ident_str!("write_accumulator_storage_cost").to_owned(),
1528 vec![],
1529 vec![system_state, storage_cost_arg],
1530 );
1531 builder
1532 }
1533
1534 fn setup_coin_registry_create(
1535 mut builder: ProgrammableTransactionBuilder,
1536 ) -> ProgrammableTransactionBuilder {
1537 builder
1538 .move_call(
1539 SUI_FRAMEWORK_ADDRESS.into(),
1540 ident_str!("coin_registry").to_owned(),
1541 ident_str!("create").to_owned(),
1542 vec![],
1543 vec![],
1544 )
1545 .expect("Unable to generate coin_registry_create transaction!");
1546 builder
1547 }
1548
1549 fn setup_display_registry_create(
1550 mut builder: ProgrammableTransactionBuilder,
1551 ) -> ProgrammableTransactionBuilder {
1552 builder
1553 .move_call(
1554 SUI_FRAMEWORK_ADDRESS.into(),
1555 ident_str!("display_registry").to_owned(),
1556 ident_str!("create").to_owned(),
1557 vec![],
1558 vec![],
1559 )
1560 .expect("Unable to generate display_registry_create transaction!");
1561 builder
1562 }
1563
1564 fn setup_address_alias_state_create(
1565 mut builder: ProgrammableTransactionBuilder,
1566 ) -> ProgrammableTransactionBuilder {
1567 builder
1568 .move_call(
1569 SUI_FRAMEWORK_ADDRESS.into(),
1570 ident_str!("address_alias").to_owned(),
1571 ident_str!("create").to_owned(),
1572 vec![],
1573 vec![],
1574 )
1575 .expect("Unable to generate address_alias_state_create transaction!");
1576 builder
1577 }
1578}