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