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