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