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 EndOfEpochTransactionKind::AddressAliasStateCreate => {
802 assert!(protocol_config.address_aliases());
803 builder = setup_address_alias_state_create(builder);
804 }
805 }
806 }
807 unreachable!(
808 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
809 )
810 }
811 TransactionKind::AuthenticatorStateUpdate(auth_state_update) => {
812 setup_authenticator_state_update(
813 auth_state_update,
814 temporary_store,
815 store,
816 tx_ctx,
817 move_vm,
818 gas_charger,
819 protocol_config,
820 metrics,
821 trace_builder_opt,
822 )
823 .map_err(|e| (e, vec![]))?;
824 Ok((Mode::empty_results(), vec![]))
825 }
826 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
827 setup_randomness_state_update(
828 randomness_state_update,
829 temporary_store,
830 store,
831 tx_ctx,
832 move_vm,
833 gas_charger,
834 protocol_config,
835 metrics,
836 trace_builder_opt,
837 )
838 .map_err(|e| (e, vec![]))?;
839 Ok((Mode::empty_results(), vec![]))
840 }
841 }?;
842 temporary_store
843 .check_execution_results_consistency()
844 .map_err(|e| (e, vec![]))?;
845 Ok(result)
846 }
847
848 fn mint_epoch_rewards_in_pt(
849 builder: &mut ProgrammableTransactionBuilder,
850 params: &AdvanceEpochParams,
851 ) -> (Argument, Argument) {
852 let storage_charge_arg = builder
854 .input(CallArg::Pure(
855 bcs::to_bytes(¶ms.storage_charge).unwrap(),
856 ))
857 .unwrap();
858 let storage_rewards = builder.programmable_move_call(
859 SUI_FRAMEWORK_PACKAGE_ID,
860 BALANCE_MODULE_NAME.to_owned(),
861 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
862 vec![GAS::type_tag()],
863 vec![storage_charge_arg],
864 );
865
866 let computation_charge_arg = builder
868 .input(CallArg::Pure(
869 bcs::to_bytes(¶ms.computation_charge).unwrap(),
870 ))
871 .unwrap();
872 let computation_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![computation_charge_arg],
878 );
879 (storage_rewards, computation_rewards)
880 }
881
882 pub fn construct_advance_epoch_pt(
883 mut builder: ProgrammableTransactionBuilder,
884 params: &AdvanceEpochParams,
885 ) -> Result<ProgrammableTransaction, ExecutionError> {
886 let (storage_rewards, computation_rewards) = mint_epoch_rewards_in_pt(&mut builder, params);
888
889 let mut arguments = vec![storage_rewards, computation_rewards];
891 let call_arg_arguments = vec![
892 CallArg::SUI_SYSTEM_MUT,
893 CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()),
894 CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()),
895 CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()),
896 CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()),
897 CallArg::Pure(bcs::to_bytes(¶ms.storage_fund_reinvest_rate).unwrap()),
898 CallArg::Pure(bcs::to_bytes(¶ms.reward_slashing_rate).unwrap()),
899 CallArg::Pure(bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap()),
900 ]
901 .into_iter()
902 .map(|a| builder.input(a))
903 .collect::<Result<_, _>>();
904
905 assert_invariant!(
906 call_arg_arguments.is_ok(),
907 "Unable to generate args for advance_epoch transaction!"
908 );
909
910 arguments.append(&mut call_arg_arguments.unwrap());
911
912 info!("Call arguments to advance_epoch transaction: {:?}", params);
913
914 let storage_rebates = builder.programmable_move_call(
915 SUI_SYSTEM_PACKAGE_ID,
916 SUI_SYSTEM_MODULE_NAME.to_owned(),
917 ADVANCE_EPOCH_FUNCTION_NAME.to_owned(),
918 vec![],
919 arguments,
920 );
921
922 builder.programmable_move_call(
924 SUI_FRAMEWORK_PACKAGE_ID,
925 BALANCE_MODULE_NAME.to_owned(),
926 BALANCE_DESTROY_REBATES_FUNCTION_NAME.to_owned(),
927 vec![GAS::type_tag()],
928 vec![storage_rebates],
929 );
930 Ok(builder.finish())
931 }
932
933 pub fn construct_advance_epoch_safe_mode_pt(
934 params: &AdvanceEpochParams,
935 protocol_config: &ProtocolConfig,
936 ) -> Result<ProgrammableTransaction, ExecutionError> {
937 let mut builder = ProgrammableTransactionBuilder::new();
938 let (storage_rewards, computation_rewards) = mint_epoch_rewards_in_pt(&mut builder, params);
940
941 let mut arguments = vec![storage_rewards, computation_rewards];
943
944 let mut args = vec![
945 CallArg::SUI_SYSTEM_MUT,
946 CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()),
947 CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()),
948 CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()),
949 CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()),
950 ];
951
952 if protocol_config.get_advance_epoch_start_time_in_safe_mode() {
953 args.push(CallArg::Pure(
954 bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap(),
955 ));
956 }
957
958 let call_arg_arguments = args
959 .into_iter()
960 .map(|a| builder.input(a))
961 .collect::<Result<_, _>>();
962
963 assert_invariant!(
964 call_arg_arguments.is_ok(),
965 "Unable to generate args for advance_epoch transaction!"
966 );
967
968 arguments.append(&mut call_arg_arguments.unwrap());
969
970 info!("Call arguments to advance_epoch transaction: {:?}", params);
971
972 builder.programmable_move_call(
973 SUI_SYSTEM_PACKAGE_ID,
974 SUI_SYSTEM_MODULE_NAME.to_owned(),
975 ADVANCE_EPOCH_SAFE_MODE_FUNCTION_NAME.to_owned(),
976 vec![],
977 arguments,
978 );
979
980 Ok(builder.finish())
981 }
982
983 fn advance_epoch(
984 builder: ProgrammableTransactionBuilder,
985 change_epoch: ChangeEpoch,
986 temporary_store: &mut TemporaryStore<'_>,
987 store: &dyn BackingStore,
988 tx_ctx: Rc<RefCell<TxContext>>,
989 move_vm: &Arc<MoveVM>,
990 gas_charger: &mut GasCharger,
991 protocol_config: &ProtocolConfig,
992 metrics: Arc<LimitsMetrics>,
993 trace_builder_opt: &mut Option<MoveTraceBuilder>,
994 ) -> Result<(), ExecutionError> {
995 let params = AdvanceEpochParams {
996 epoch: change_epoch.epoch,
997 next_protocol_version: change_epoch.protocol_version,
998 storage_charge: change_epoch.storage_charge,
999 computation_charge: change_epoch.computation_charge,
1000 storage_rebate: change_epoch.storage_rebate,
1001 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1002 storage_fund_reinvest_rate: protocol_config.storage_fund_reinvest_rate(),
1003 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1004 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1005 };
1006 let advance_epoch_pt = construct_advance_epoch_pt(builder, ¶ms)?;
1007 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1008 protocol_config,
1009 metrics.clone(),
1010 move_vm,
1011 temporary_store,
1012 store.as_backing_package_store(),
1013 tx_ctx.clone(),
1014 gas_charger,
1015 advance_epoch_pt,
1016 trace_builder_opt,
1017 );
1018
1019 #[cfg(msim)]
1020 let result = maybe_modify_result(result, change_epoch.epoch);
1021
1022 if let Err(err) = &result {
1023 tracing::error!(
1024 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx data: {:?}",
1025 err.0,
1026 temporary_store.objects(),
1027 change_epoch,
1028 );
1029 temporary_store.drop_writes();
1030 gas_charger.reset_storage_cost_and_rebate();
1032
1033 if protocol_config.get_advance_epoch_start_time_in_safe_mode() {
1034 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1035 } else {
1036 let advance_epoch_safe_mode_pt =
1037 construct_advance_epoch_safe_mode_pt(¶ms, protocol_config)?;
1038 programmable_transactions::execution::execute::<execution_mode::System>(
1039 protocol_config,
1040 metrics.clone(),
1041 move_vm,
1042 temporary_store,
1043 store.as_backing_package_store(),
1044 tx_ctx.clone(),
1045 gas_charger,
1046 advance_epoch_safe_mode_pt,
1047 trace_builder_opt,
1048 )
1049 .map_err(|(e, _)| e)
1050 .expect("Advance epoch with safe mode must succeed");
1051 }
1052 }
1053
1054 if protocol_config.fresh_vm_on_framework_upgrade() {
1055 let new_vm = new_move_vm(
1056 all_natives(true, protocol_config),
1057 protocol_config,
1058 )
1059 .expect("Failed to create new MoveVM");
1060 process_system_packages(
1061 change_epoch,
1062 temporary_store,
1063 store,
1064 tx_ctx,
1065 &new_vm,
1066 gas_charger,
1067 protocol_config,
1068 metrics,
1069 trace_builder_opt,
1070 );
1071 } else {
1072 process_system_packages(
1073 change_epoch,
1074 temporary_store,
1075 store,
1076 tx_ctx,
1077 move_vm,
1078 gas_charger,
1079 protocol_config,
1080 metrics,
1081 trace_builder_opt,
1082 );
1083 }
1084 Ok(())
1085 }
1086
1087 fn process_system_packages(
1088 change_epoch: ChangeEpoch,
1089 temporary_store: &mut TemporaryStore<'_>,
1090 store: &dyn BackingStore,
1091 tx_ctx: Rc<RefCell<TxContext>>,
1092 move_vm: &MoveVM,
1093 gas_charger: &mut GasCharger,
1094 protocol_config: &ProtocolConfig,
1095 metrics: Arc<LimitsMetrics>,
1096 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1097 ) {
1098 let digest = tx_ctx.borrow().digest();
1099 let binary_config = protocol_config.binary_config(None);
1100 for (version, modules, dependencies) in change_epoch.system_packages.into_iter() {
1101 let deserialized_modules: Vec<_> = modules
1102 .iter()
1103 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1104 .collect();
1105
1106 if version == OBJECT_START_VERSION {
1107 let package_id = deserialized_modules.first().unwrap().address();
1108 info!("adding new system package {package_id}");
1109
1110 let publish_pt = {
1111 let mut b = ProgrammableTransactionBuilder::new();
1112 b.command(Command::Publish(modules, dependencies));
1113 b.finish()
1114 };
1115
1116 programmable_transactions::execution::execute::<execution_mode::System>(
1117 protocol_config,
1118 metrics.clone(),
1119 move_vm,
1120 temporary_store,
1121 store.as_backing_package_store(),
1122 tx_ctx.clone(),
1123 gas_charger,
1124 publish_pt,
1125 trace_builder_opt,
1126 )
1127 .map_err(|(e, _)| e)
1128 .expect("System Package Publish must succeed");
1129 } else {
1130 let mut new_package = Object::new_system_package(
1131 &deserialized_modules,
1132 version,
1133 dependencies,
1134 digest,
1135 );
1136
1137 info!(
1138 "upgraded system package {:?}",
1139 new_package.compute_object_reference()
1140 );
1141
1142 new_package
1145 .data
1146 .try_as_package_mut()
1147 .unwrap()
1148 .decrement_version();
1149
1150 temporary_store.upgrade_system_package(new_package);
1152 }
1153 }
1154 }
1155
1156 fn setup_consensus_commit(
1161 consensus_commit_timestamp_ms: CheckpointTimestamp,
1162 temporary_store: &mut TemporaryStore<'_>,
1163 store: &dyn BackingStore,
1164 tx_ctx: Rc<RefCell<TxContext>>,
1165 move_vm: &Arc<MoveVM>,
1166 gas_charger: &mut GasCharger,
1167 protocol_config: &ProtocolConfig,
1168 metrics: Arc<LimitsMetrics>,
1169 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1170 ) -> Result<(), ExecutionError> {
1171 let pt = {
1172 let mut builder = ProgrammableTransactionBuilder::new();
1173 let res = builder.move_call(
1174 SUI_FRAMEWORK_ADDRESS.into(),
1175 CLOCK_MODULE_NAME.to_owned(),
1176 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME.to_owned(),
1177 vec![],
1178 vec![
1179 CallArg::CLOCK_MUT,
1180 CallArg::Pure(bcs::to_bytes(&consensus_commit_timestamp_ms).unwrap()),
1181 ],
1182 );
1183 assert_invariant!(
1184 res.is_ok(),
1185 "Unable to generate consensus_commit_prologue transaction!"
1186 );
1187 builder.finish()
1188 };
1189 programmable_transactions::execution::execute::<execution_mode::System>(
1190 protocol_config,
1191 metrics,
1192 move_vm,
1193 temporary_store,
1194 store.as_backing_package_store(),
1195 tx_ctx,
1196 gas_charger,
1197 pt,
1198 trace_builder_opt,
1199 )
1200 .map_err(|(e, _)| e)?;
1201 Ok(())
1202 }
1203
1204 fn setup_authenticator_state_create(
1205 mut builder: ProgrammableTransactionBuilder,
1206 ) -> ProgrammableTransactionBuilder {
1207 builder
1208 .move_call(
1209 SUI_FRAMEWORK_ADDRESS.into(),
1210 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1211 AUTHENTICATOR_STATE_CREATE_FUNCTION_NAME.to_owned(),
1212 vec![],
1213 vec![],
1214 )
1215 .expect("Unable to generate authenticator_state_create transaction!");
1216 builder
1217 }
1218
1219 fn setup_randomness_state_create(
1220 mut builder: ProgrammableTransactionBuilder,
1221 ) -> ProgrammableTransactionBuilder {
1222 builder
1223 .move_call(
1224 SUI_FRAMEWORK_ADDRESS.into(),
1225 RANDOMNESS_MODULE_NAME.to_owned(),
1226 RANDOMNESS_STATE_CREATE_FUNCTION_NAME.to_owned(),
1227 vec![],
1228 vec![],
1229 )
1230 .expect("Unable to generate randomness_state_create transaction!");
1231 builder
1232 }
1233
1234 fn setup_bridge_create(
1235 mut builder: ProgrammableTransactionBuilder,
1236 chain_id: ChainIdentifier,
1237 ) -> ProgrammableTransactionBuilder {
1238 let bridge_uid = builder
1239 .input(CallArg::Pure(UID::new(SUI_BRIDGE_OBJECT_ID).to_bcs_bytes()))
1240 .expect("Unable to create Bridge object UID!");
1241
1242 let bridge_chain_id = if chain_id == get_mainnet_chain_identifier() {
1243 BridgeChainId::SuiMainnet as u8
1244 } else if chain_id == get_testnet_chain_identifier() {
1245 BridgeChainId::SuiTestnet as u8
1246 } else {
1247 BridgeChainId::SuiCustom as u8
1249 };
1250
1251 let bridge_chain_id = builder.pure(bridge_chain_id).unwrap();
1252 builder.programmable_move_call(
1253 BRIDGE_ADDRESS.into(),
1254 BRIDGE_MODULE_NAME.to_owned(),
1255 BRIDGE_CREATE_FUNCTION_NAME.to_owned(),
1256 vec![],
1257 vec![bridge_uid, bridge_chain_id],
1258 );
1259 builder
1260 }
1261
1262 fn setup_bridge_committee_update(
1263 mut builder: ProgrammableTransactionBuilder,
1264 bridge_shared_version: SequenceNumber,
1265 ) -> ProgrammableTransactionBuilder {
1266 let bridge = builder
1267 .obj(ObjectArg::SharedObject {
1268 id: SUI_BRIDGE_OBJECT_ID,
1269 initial_shared_version: bridge_shared_version,
1270 mutability: sui_types::transaction::SharedObjectMutability::Mutable,
1271 })
1272 .expect("Unable to create Bridge object arg!");
1273 let system_state = builder
1274 .obj(ObjectArg::SUI_SYSTEM_MUT)
1275 .expect("Unable to create System State object arg!");
1276
1277 let voting_power = builder.programmable_move_call(
1278 SUI_SYSTEM_PACKAGE_ID,
1279 SUI_SYSTEM_MODULE_NAME.to_owned(),
1280 ident_str!("validator_voting_powers").to_owned(),
1281 vec![],
1282 vec![system_state],
1283 );
1284
1285 let min_stake_participation_percentage = builder
1288 .input(CallArg::Pure(
1289 bcs::to_bytes(&BRIDGE_COMMITTEE_MINIMAL_VOTING_POWER).unwrap(),
1290 ))
1291 .unwrap();
1292
1293 builder.programmable_move_call(
1294 BRIDGE_ADDRESS.into(),
1295 BRIDGE_MODULE_NAME.to_owned(),
1296 BRIDGE_INIT_COMMITTEE_FUNCTION_NAME.to_owned(),
1297 vec![],
1298 vec![bridge, voting_power, min_stake_participation_percentage],
1299 );
1300 builder
1301 }
1302
1303 fn setup_authenticator_state_update(
1304 update: AuthenticatorStateUpdate,
1305 temporary_store: &mut TemporaryStore<'_>,
1306 store: &dyn BackingStore,
1307 tx_ctx: Rc<RefCell<TxContext>>,
1308 move_vm: &Arc<MoveVM>,
1309 gas_charger: &mut GasCharger,
1310 protocol_config: &ProtocolConfig,
1311 metrics: Arc<LimitsMetrics>,
1312 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1313 ) -> Result<(), ExecutionError> {
1314 let pt = {
1315 let mut builder = ProgrammableTransactionBuilder::new();
1316 let res = builder.move_call(
1317 SUI_FRAMEWORK_ADDRESS.into(),
1318 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1319 AUTHENTICATOR_STATE_UPDATE_FUNCTION_NAME.to_owned(),
1320 vec![],
1321 vec![
1322 CallArg::Object(ObjectArg::SharedObject {
1323 id: SUI_AUTHENTICATOR_STATE_OBJECT_ID,
1324 initial_shared_version: update.authenticator_obj_initial_shared_version,
1325 mutability: sui_types::transaction::SharedObjectMutability::Mutable,
1326 }),
1327 CallArg::Pure(bcs::to_bytes(&update.new_active_jwks).unwrap()),
1328 ],
1329 );
1330 assert_invariant!(
1331 res.is_ok(),
1332 "Unable to generate authenticator_state_update transaction!"
1333 );
1334 builder.finish()
1335 };
1336 programmable_transactions::execution::execute::<execution_mode::System>(
1337 protocol_config,
1338 metrics,
1339 move_vm,
1340 temporary_store,
1341 store.as_backing_package_store(),
1342 tx_ctx,
1343 gas_charger,
1344 pt,
1345 trace_builder_opt,
1346 )
1347 .map_err(|(e, _)| e)?;
1348 Ok(())
1349 }
1350
1351 fn setup_authenticator_state_expire(
1352 mut builder: ProgrammableTransactionBuilder,
1353 expire: AuthenticatorStateExpire,
1354 ) -> ProgrammableTransactionBuilder {
1355 builder
1356 .move_call(
1357 SUI_FRAMEWORK_ADDRESS.into(),
1358 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1359 AUTHENTICATOR_STATE_EXPIRE_JWKS_FUNCTION_NAME.to_owned(),
1360 vec![],
1361 vec![
1362 CallArg::Object(ObjectArg::SharedObject {
1363 id: SUI_AUTHENTICATOR_STATE_OBJECT_ID,
1364 initial_shared_version: expire.authenticator_obj_initial_shared_version,
1365 mutability: sui_types::transaction::SharedObjectMutability::Mutable,
1366 }),
1367 CallArg::Pure(bcs::to_bytes(&expire.min_epoch).unwrap()),
1368 ],
1369 )
1370 .expect("Unable to generate authenticator_state_expire transaction!");
1371 builder
1372 }
1373
1374 fn setup_randomness_state_update(
1375 update: RandomnessStateUpdate,
1376 temporary_store: &mut TemporaryStore<'_>,
1377 store: &dyn BackingStore,
1378 tx_ctx: Rc<RefCell<TxContext>>,
1379 move_vm: &Arc<MoveVM>,
1380 gas_charger: &mut GasCharger,
1381 protocol_config: &ProtocolConfig,
1382 metrics: Arc<LimitsMetrics>,
1383 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1384 ) -> Result<(), ExecutionError> {
1385 let pt = {
1386 let mut builder = ProgrammableTransactionBuilder::new();
1387 let res = builder.move_call(
1388 SUI_FRAMEWORK_ADDRESS.into(),
1389 RANDOMNESS_MODULE_NAME.to_owned(),
1390 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME.to_owned(),
1391 vec![],
1392 vec![
1393 CallArg::Object(ObjectArg::SharedObject {
1394 id: SUI_RANDOMNESS_STATE_OBJECT_ID,
1395 initial_shared_version: update.randomness_obj_initial_shared_version,
1396 mutability: sui_types::transaction::SharedObjectMutability::Mutable,
1397 }),
1398 CallArg::Pure(bcs::to_bytes(&update.randomness_round).unwrap()),
1399 CallArg::Pure(bcs::to_bytes(&update.random_bytes).unwrap()),
1400 ],
1401 );
1402 assert_invariant!(
1403 res.is_ok(),
1404 "Unable to generate randomness_state_update transaction!"
1405 );
1406 builder.finish()
1407 };
1408 programmable_transactions::execution::execute::<execution_mode::System>(
1409 protocol_config,
1410 metrics,
1411 move_vm,
1412 temporary_store,
1413 store.as_backing_package_store(),
1414 tx_ctx,
1415 gas_charger,
1416 pt,
1417 trace_builder_opt,
1418 )
1419 .map_err(|(e, _)| e)?;
1420 Ok(())
1421 }
1422
1423 fn setup_coin_deny_list_state_create(
1424 mut builder: ProgrammableTransactionBuilder,
1425 ) -> ProgrammableTransactionBuilder {
1426 builder
1427 .move_call(
1428 SUI_FRAMEWORK_ADDRESS.into(),
1429 DENY_LIST_MODULE.to_owned(),
1430 DENY_LIST_CREATE_FUNC.to_owned(),
1431 vec![],
1432 vec![],
1433 )
1434 .expect("Unable to generate coin_deny_list_create transaction!");
1435 builder
1436 }
1437
1438 fn setup_store_execution_time_estimates(
1439 mut builder: ProgrammableTransactionBuilder,
1440 estimates: StoredExecutionTimeObservations,
1441 ) -> ProgrammableTransactionBuilder {
1442 let system_state = builder.obj(ObjectArg::SUI_SYSTEM_MUT).unwrap();
1443 let estimates_bytes = bcs::to_bytes(&estimates).unwrap();
1446 let estimates_arg = builder.pure(estimates_bytes).unwrap();
1447 builder.programmable_move_call(
1448 SUI_SYSTEM_PACKAGE_ID,
1449 SUI_SYSTEM_MODULE_NAME.to_owned(),
1450 ident_str!("store_execution_time_estimates").to_owned(),
1451 vec![],
1452 vec![system_state, estimates_arg],
1453 );
1454 builder
1455 }
1456
1457 fn setup_store_execution_time_estimates_v2(
1458 mut builder: ProgrammableTransactionBuilder,
1459 estimates: StoredExecutionTimeObservations,
1460 chunk_size: usize,
1461 ) -> ProgrammableTransactionBuilder {
1462 let system_state = builder.obj(ObjectArg::SUI_SYSTEM_MUT).unwrap();
1463
1464 let estimate_chunks = estimates.chunk_observations(chunk_size);
1465
1466 let chunk_bytes: Vec<Vec<u8>> = estimate_chunks
1467 .into_iter()
1468 .map(|chunk| bcs::to_bytes(&chunk).unwrap())
1469 .collect();
1470
1471 let chunks_arg = builder.pure(chunk_bytes).unwrap();
1472
1473 builder.programmable_move_call(
1474 SUI_SYSTEM_PACKAGE_ID,
1475 SUI_SYSTEM_MODULE_NAME.to_owned(),
1476 ident_str!("store_execution_time_estimates_v2").to_owned(),
1477 vec![],
1478 vec![system_state, chunks_arg],
1479 );
1480 builder
1481 }
1482
1483 fn setup_accumulator_root_create(
1484 mut builder: ProgrammableTransactionBuilder,
1485 ) -> ProgrammableTransactionBuilder {
1486 builder
1487 .move_call(
1488 SUI_FRAMEWORK_ADDRESS.into(),
1489 ACCUMULATOR_ROOT_MODULE.to_owned(),
1490 ACCUMULATOR_ROOT_CREATE_FUNC.to_owned(),
1491 vec![],
1492 vec![],
1493 )
1494 .expect("Unable to generate accumulator_root_create transaction!");
1495 builder
1496 }
1497
1498 fn setup_coin_registry_create(
1499 mut builder: ProgrammableTransactionBuilder,
1500 ) -> ProgrammableTransactionBuilder {
1501 builder
1502 .move_call(
1503 SUI_FRAMEWORK_ADDRESS.into(),
1504 ident_str!("coin_registry").to_owned(),
1505 ident_str!("create").to_owned(),
1506 vec![],
1507 vec![],
1508 )
1509 .expect("Unable to generate coin_registry_create transaction!");
1510 builder
1511 }
1512
1513 fn setup_display_registry_create(
1514 mut builder: ProgrammableTransactionBuilder,
1515 ) -> ProgrammableTransactionBuilder {
1516 builder
1517 .move_call(
1518 SUI_FRAMEWORK_ADDRESS.into(),
1519 ident_str!("display_registry").to_owned(),
1520 ident_str!("create").to_owned(),
1521 vec![],
1522 vec![],
1523 )
1524 .expect("Unable to generate display_registry_create transaction!");
1525 builder
1526 }
1527
1528 fn setup_address_alias_state_create(
1529 mut builder: ProgrammableTransactionBuilder,
1530 ) -> ProgrammableTransactionBuilder {
1531 builder
1532 .move_call(
1533 SUI_FRAMEWORK_ADDRESS.into(),
1534 ident_str!("address_alias").to_owned(),
1535 ident_str!("create").to_owned(),
1536 vec![],
1537 vec![],
1538 )
1539 .expect("Unable to generate address_alias_state_create transaction!");
1540 builder
1541 }
1542}