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