1pub use checked::*;
6
7#[iota_macros::with_checked_arithmetic]
8mod checked {
9
10 use std::{
11 cell::RefCell,
12 collections::{BTreeMap, BTreeSet, HashSet},
13 rc::Rc,
14 sync::Arc,
15 };
16
17 use iota_move_natives::all_natives;
18 use iota_protocol_config::{LimitThresholdCrossed, ProtocolConfig, check_limit_by_meter};
19 use iota_sdk_types::{
20 Address, Argument, ChangeEpoch, ChangeEpochV2, ChangeEpochV3, ChangeEpochV4, Command,
21 EndOfEpochTransactionKind, ExecutionStatus, GasCostSummary, GasPayment, GenesisTransaction,
22 Identifier, MoveAuthenticator, ObjectId, ProgrammableTransaction, RandomnessStateUpdate,
23 SharedObjectReference, StructTag, SystemPackage, TransactionDenyRulesUpdate,
24 TransactionDigest, TransactionEffects, TransactionKind, TypeTag, Version,
25 };
26 #[cfg(msim)]
27 use iota_types::iota_system_state::advance_epoch_result_injection::maybe_modify_result;
28 use iota_types::{
29 account_abstraction::authenticator_function::{
30 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
31 AuthenticatorFunctionRefV1, MoveAuthenticatorForExecution,
32 MoveAuthenticatorsForExecution,
33 },
34 auth_context::{AuthContext, AuthContextData},
35 balance::{BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME},
36 base_types::TxContext,
37 clock::CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
38 committee::EpochId,
39 error::{ExecutionError, ExecutionErrorKind},
40 execution::{
41 ExecutionResults, ExecutionResultsV1, ExecutionTiming, ResultWithTimings, SharedInput,
42 is_certificate_denied,
43 },
44 execution_config_utils::to_binary_config,
45 gas::{IotaGasStatus, IotaGasStatusAPI},
46 inner_temporary_store::InnerTemporaryStore,
47 iota_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams},
48 messages_checkpoint::CheckpointTimestamp,
49 metrics::LimitsMetrics,
50 move_authenticator::MoveAuthenticatorExt,
51 object::{OBJECT_START_VERSION, Object, ObjectInner},
52 programmable_transaction_builder::ProgrammableTransactionBuilder,
53 randomness_state::RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
54 storage::{BackingStore, Storage},
55 transaction::{
56 CallArg, CancelledObjects, CheckedInputObjects, InputObjects, TransactionKindExt,
57 },
58 transaction_deny_rules::{
59 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME, TRANSACTION_DENY_RULES_MODULE,
60 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
61 },
62 };
63 use move_binary_format::CompiledModule;
64 use move_trace_format::format::MoveTraceBuilder;
65 use move_vm_runtime::move_vm::MoveVM;
66 use tracing::{info, instrument, trace, warn};
67
68 use crate::{
69 adapter::new_move_vm,
70 execution_mode::{self, ExecutionMode},
71 gas_charger::GasCharger,
72 programmable_transactions,
73 temporary_store::TemporaryStore,
74 type_layout_resolver::TypeLayoutResolver,
75 };
76
77 #[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: GasPayment,
93 gas_status: IotaGasStatus,
94 transaction_kind: TransactionKind,
95 transaction_signer: Address,
96 transaction_digest: TransactionDigest,
97 move_vm: &Arc<MoveVM>,
98 epoch_id: &EpochId,
99 epoch_timestamp_ms: u64,
100 protocol_config: &ProtocolConfig,
101 metrics: Arc<LimitsMetrics>,
102 enable_expensive_checks: bool,
103 certificate_deny_set: &HashSet<TransactionDigest>,
104 trace_builder_opt: &mut Option<MoveTraceBuilder>,
105 ) -> (
106 InnerTemporaryStore,
107 IotaGasStatus,
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.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 transaction_dependencies = input_objects.transaction_dependencies();
121 let contains_deleted_input = input_objects.contains_deleted_objects();
122 let cancelled_objects = input_objects.get_cancelled_objects();
123
124 let temporary_store = TemporaryStore::new(
125 store,
126 input_objects,
127 receiving_objects,
128 transaction_digest,
129 protocol_config,
130 *epoch_id,
131 );
132
133 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
134 let gas_price = gas_status.gas_price();
135 let rgp = gas_status.reference_gas_price();
136 let gas_charger = GasCharger::new(
137 transaction_digest,
138 gas_data.objects,
139 gas_status,
140 protocol_config,
141 );
142
143 let tx_ctx = TxContext::new_from_components(
144 &transaction_signer,
145 &transaction_digest,
146 epoch_id,
147 epoch_timestamp_ms,
148 rgp,
149 gas_price,
150 gas_data.budget,
151 sponsor,
152 protocol_config,
153 );
154 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
155
156 execute_transaction_to_effects_inner::<Mode>(
157 temporary_store,
158 gas_charger,
159 tx_ctx,
160 &mutable_inputs,
161 shared_object_refs,
162 transaction_dependencies,
163 contains_deleted_input,
164 cancelled_objects,
165 transaction_kind,
166 transaction_signer,
167 transaction_digest,
168 move_vm,
169 epoch_id,
170 protocol_config,
171 metrics,
172 enable_expensive_checks,
173 certificate_deny_set,
174 trace_builder_opt,
175 None,
176 )
177 }
178
179 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
182 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
183 mut temporary_store: TemporaryStore,
184 mut gas_charger: GasCharger,
185 tx_ctx: Rc<RefCell<TxContext>>,
186 mutable_inputs: &HashSet<ObjectId>,
187 shared_object_refs: Vec<SharedInput>,
188 mut transaction_dependencies: BTreeSet<TransactionDigest>,
189 contains_deleted_input: bool,
190 cancelled_objects: Option<(CancelledObjects, Version)>,
191 transaction_kind: TransactionKind,
192 transaction_signer: Address,
193 transaction_digest: TransactionDigest,
194 move_vm: &Arc<MoveVM>,
195 epoch_id: &EpochId,
196 protocol_config: &ProtocolConfig,
197 metrics: Arc<LimitsMetrics>,
198 enable_expensive_checks: bool,
199 certificate_deny_set: &HashSet<TransactionDigest>,
200 trace_builder_opt: &mut Option<MoveTraceBuilder>,
201 pre_execution_result_opt: Option<
202 Result<
203 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
204 ExecutionError,
205 >,
206 >,
207 ) -> (
208 InnerTemporaryStore,
209 IotaGasStatus,
210 TransactionEffects,
211 Vec<ExecutionTiming>,
212 Result<Mode::ExecutionResults, ExecutionError>,
213 ) {
214 let is_epoch_change = transaction_kind.is_end_of_epoch();
215 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
216
217 let (gas_cost_summary, execution_result, timings) = execute_transaction::<Mode>(
218 &mut temporary_store,
219 transaction_kind,
220 &mut gas_charger,
221 tx_ctx,
222 move_vm,
223 protocol_config,
224 metrics,
225 enable_expensive_checks,
226 deny_cert,
227 contains_deleted_input,
228 cancelled_objects,
229 trace_builder_opt,
230 pre_execution_result_opt,
231 );
232
233 let status = if let Err(error) = &execution_result {
234 elaborate_error_logs(error, transaction_digest)
235 } else {
236 ExecutionStatus::Success
237 };
238
239 #[skip_checked_arithmetic]
240 trace!(
241 tx_digest = ?transaction_digest,
242 computation_gas_cost = gas_cost_summary.computation_cost,
243 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
244 storage_gas_cost = gas_cost_summary.storage_cost,
245 storage_gas_rebate = gas_cost_summary.storage_rebate,
246 "Finished execution of transaction with status {:?}",
247 status
248 );
249
250 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
254
255 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
256 temporary_store
257 .check_ownership_invariants(
258 &transaction_signer,
259 &mut gas_charger,
260 mutable_inputs,
261 is_epoch_change,
262 )
263 .unwrap()
264 } let (inner, effects) = temporary_store.into_effects(
267 shared_object_refs,
268 &transaction_digest,
269 transaction_dependencies,
270 gas_cost_summary,
271 status,
272 &mut gas_charger,
273 *epoch_id,
274 );
275
276 (
277 inner,
278 gas_charger.into_gas_status(),
279 effects,
280 timings,
281 execution_result,
282 )
283 }
284
285 #[instrument(
298 name = "tx_authenticate_then_execute_to_effects",
299 level = "debug",
300 skip_all
301 )]
302 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
303 store: &dyn BackingStore,
304 protocol_config: &ProtocolConfig,
306 metrics: Arc<LimitsMetrics>,
307 enable_expensive_checks: bool,
308 certificate_deny_set: &HashSet<TransactionDigest>,
309 epoch_id: &EpochId,
311 epoch_timestamp_ms: u64,
312 gas_data: GasPayment,
314 gas_status: IotaGasStatus,
315 authenticators: MoveAuthenticatorsForExecution,
317 authenticator_and_transaction_input_objects: CheckedInputObjects,
318 transaction_kind: TransactionKind,
320 transaction_signer: Address,
321 transaction_digest: TransactionDigest,
322 auth_context_data: AuthContextData,
323 trace_builder_opt: &mut Option<MoveTraceBuilder>,
325 move_vm: &Arc<MoveVM>,
327 ) -> (
328 InnerTemporaryStore,
329 IotaGasStatus,
330 TransactionEffects,
331 Vec<ExecutionTiming>,
332 Result<Mode::ExecutionResults, ExecutionError>,
333 ) {
334 let input_objects = authenticator_and_transaction_input_objects.into_inner();
340 let mutable_inputs = if enable_expensive_checks {
342 input_objects.mutable_inputs().keys().copied().collect()
343 } else {
344 HashSet::new()
345 };
346 let shared_object_refs = input_objects.filter_shared_objects();
348 let transaction_receiving_objects = transaction_kind.receiving_objects();
350 let transaction_dependencies = input_objects.transaction_dependencies();
352 let contains_deleted_input = input_objects.contains_deleted_objects();
355 let cancelled_objects = input_objects.get_cancelled_objects();
356
357 let mut temporary_store = TemporaryStore::new(
359 store,
360 input_objects,
361 transaction_receiving_objects,
362 transaction_digest,
363 protocol_config,
364 *epoch_id,
365 );
366
367 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
369 let gas_price = gas_status.gas_price();
370 let rgp = gas_status.reference_gas_price();
371 let mut gas_charger = GasCharger::new(
372 transaction_digest,
373 gas_data.objects,
374 gas_status,
375 protocol_config,
376 );
377
378 let tx_ctx = TxContext::new_from_components(
380 &transaction_signer,
381 &transaction_digest,
382 epoch_id,
383 epoch_timestamp_ms,
384 rgp,
385 gas_price,
386 gas_data.budget,
387 sponsor,
388 protocol_config,
389 );
390 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
391
392 let authentication_execution_result = match authenticators {
396 MoveAuthenticatorsForExecution::ResolutionFailed(error) => Err(error),
397 MoveAuthenticatorsForExecution::Resolved(authenticators) => {
398 let authenticators = authenticators
404 .into_iter()
405 .map(
406 |MoveAuthenticatorForExecution {
407 authenticator,
408 function_ref,
409 input_objects: authenticator_input_objects,
410 }| {
411 let AuthenticatorFunctionRefForExecution {
412 authenticator_function_ref,
413 loaded_object_id,
414 loaded_object_metadata,
415 } = function_ref;
416
417 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
420 loaded_object_id,
421 loaded_object_metadata,
422 )]));
423
424 (
425 authenticator,
426 authenticator_function_ref,
427 authenticator_input_objects,
428 )
429 },
430 )
431 .collect::<Vec<_>>();
432
433 authenticators.into_iter().try_for_each(
439 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
440 match authenticator_function_ref {
441 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
442 authenticate_transaction_inner(
443 &mut temporary_store,
444 protocol_config,
445 metrics.clone(),
446 &mut gas_charger,
447 authenticator,
448 authenticator_function_ref_v1,
449 &authenticator_input_objects.into_inner(),
450 transaction_kind.clone(),
451 transaction_digest,
452 auth_context_data.clone(),
453 tx_ctx.clone(),
454 trace_builder_opt,
455 move_vm,
456 )
457 }
458 }
459 },
460 )
461 }
462 };
463
464 let authentication_execution_result =
468 report_authentication_error(authentication_execution_result, protocol_config);
469
470 execute_transaction_to_effects_inner::<Mode>(
478 temporary_store,
479 gas_charger,
480 tx_ctx,
481 &mutable_inputs,
482 shared_object_refs,
483 transaction_dependencies,
484 contains_deleted_input,
485 cancelled_objects,
486 transaction_kind,
487 transaction_signer,
488 transaction_digest,
489 move_vm,
490 epoch_id,
491 protocol_config,
492 metrics,
493 enable_expensive_checks,
494 certificate_deny_set,
495 trace_builder_opt,
496 Some(authentication_execution_result),
497 )
498 }
499
500 #[instrument(name = "tx_validate", level = "debug", skip_all)]
505 pub fn authenticate_transaction(
506 store: &dyn BackingStore,
507 protocol_config: &ProtocolConfig,
509 metrics: Arc<LimitsMetrics>,
510 epoch_id: &EpochId,
512 epoch_timestamp_ms: u64,
513 gas_data: GasPayment,
515 gas_status: IotaGasStatus,
516 authenticators: Vec<(
518 MoveAuthenticator,
519 AuthenticatorFunctionRef,
520 CheckedInputObjects,
521 )>,
522 aggregated_authenticator_input_objects: CheckedInputObjects,
523 transaction_kind: TransactionKind,
525 transaction_signer: Address,
526 transaction_digest: TransactionDigest,
527 auth_context_data: AuthContextData,
528 trace_builder_opt: &mut Option<MoveTraceBuilder>,
530 move_vm: &Arc<MoveVM>,
532 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
533 {
534 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
536 let gas_price = gas_status.gas_price();
537 let rgp = gas_status.reference_gas_price();
538 let mut gas_charger =
539 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
540
541 let tx_ctx = TxContext::new_from_components(
544 &transaction_signer,
545 &transaction_digest,
546 epoch_id,
547 epoch_timestamp_ms,
548 rgp,
549 gas_price,
550 gas_data.budget,
551 sponsor,
552 protocol_config,
553 );
554 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
555
556 let mut temporary_store = TemporaryStore::new(
557 store,
558 aggregated_authenticator_input_objects.into_inner(),
559 vec![],
560 transaction_digest,
561 protocol_config,
562 *epoch_id,
563 );
564
565 let authentication_execution_result = authenticators.into_iter().try_for_each(
567 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
568 match authenticator_function_ref {
569 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
570 authenticate_transaction_inner(
571 &mut temporary_store,
572 protocol_config,
573 metrics.clone(),
574 &mut gas_charger,
575 authenticator,
576 authenticator_function_ref_v1,
577 &authenticator_input_objects.into_inner(),
578 transaction_kind.clone(),
579 transaction_digest,
580 auth_context_data.clone(),
581 tx_ctx.clone(),
582 trace_builder_opt,
583 move_vm,
584 )
585 }
586 }
587 },
588 );
589
590 report_authentication_error(authentication_execution_result, protocol_config)
591 }
592
593 #[instrument(name = "tx_validate", level = "debug", skip_all)]
603 pub fn authenticate_transaction_inner(
604 temporary_store: &mut TemporaryStore<'_>,
605 protocol_config: &ProtocolConfig,
607 metrics: Arc<LimitsMetrics>,
608 gas_charger: &mut GasCharger,
610 authenticator: MoveAuthenticator,
612 authenticator_function_ref: AuthenticatorFunctionRefV1,
613 authenticator_input_objects: &InputObjects,
614 transaction_kind: TransactionKind,
616 transaction_digest: TransactionDigest,
617 auth_context_data: AuthContextData,
618 tx_ctx: Rc<RefCell<TxContext>>,
619 trace_builder_opt: &mut Option<MoveTraceBuilder>,
621 move_vm: &Arc<MoveVM>,
623 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
624 {
625 debug_assert!(
627 transaction_kind.is_programmable(),
628 "Only programmable transactions are allowed"
629 );
630 debug_assert!(
631 authenticator_input_objects
632 .mutable_inputs()
633 .keys()
634 .copied()
635 .collect::<HashSet<_>>()
636 .is_empty(),
637 "No mutable inputs are allowed"
638 );
639 debug_assert!(
640 authenticator.receiving_objects().is_empty(),
641 "No receiving inputs are allowed"
642 );
643
644 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
645 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
646
647 let auth_ctx = {
649 let TransactionKind::Programmable(ptb) = &transaction_kind else {
650 unreachable!("Only programmable transactions are allowed");
651 };
652 AuthContext::new_from_components(
653 authenticator.digest().into(),
654 auth_context_data.sender_auth_digest,
655 auth_context_data.sponsor_auth_digest,
656 auth_context_data
657 .sender_authenticator_function_ref
658 .and_then(Into::into),
659 auth_context_data
660 .sponsor_authenticator_function_ref
661 .and_then(Into::into),
662 ptb,
663 auth_context_data.transaction_data_bytes,
664 )
665 };
666 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
667
668 temporary_store.store_auth_context(auth_ctx);
672
673 let authentication_execution_result = execute_authenticator_move_call(
675 temporary_store,
676 authenticator,
677 authenticator_function_ref,
678 gas_charger,
679 tx_ctx,
680 move_vm,
681 protocol_config,
682 metrics,
683 false,
684 contains_deleted_input,
685 cancelled_objects,
686 trace_builder_opt,
687 );
688
689 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
691 elaborate_error_logs(error, transaction_digest)
692 } else {
693 ExecutionStatus::Success
694 };
695
696 #[skip_checked_arithmetic]
697 trace!(
698 tx_digest = ?transaction_digest,
699 computation_gas_cost = gas_charger.summary().gas_used(),
700 "Finished authenticator execution of transaction with status {:?}",
701 authentication_execution_status
702 );
703
704 authentication_execution_result
705 }
706
707 #[instrument(name = "auth_execute", level = "debug", skip_all)]
718 fn execute_authenticator_move_call(
719 temporary_store: &mut TemporaryStore<'_>,
720 authenticator: MoveAuthenticator,
721 authenticator_function_ref: AuthenticatorFunctionRefV1,
722 gas_charger: &mut GasCharger,
723 tx_ctx: Rc<RefCell<TxContext>>,
724 move_vm: &Arc<MoveVM>,
725 protocol_config: &ProtocolConfig,
726 metrics: Arc<LimitsMetrics>,
727 deny_cert: bool,
728 contains_deleted_input: bool,
729 cancelled_objects: Option<(CancelledObjects, Version)>,
730 trace_builder_opt: &mut Option<MoveTraceBuilder>,
731 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
732 {
733 run_inputs_checks(
737 protocol_config,
738 deny_cert,
739 contains_deleted_input,
740 cancelled_objects,
741 )
742 .and_then(|()| {
743 let authenticator_move_call =
744 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
745 programmable_transactions::execution::execute::<execution_mode::Authentication>(
746 protocol_config,
747 metrics.clone(),
748 move_vm,
749 temporary_store,
750 tx_ctx,
751 gas_charger,
752 authenticator_move_call,
753 trace_builder_opt,
754 )
755 .map_err(|(e, _)| e)
756 .and_then(|(ok_result, _timings)| {
757 temporary_store.check_move_authenticator_results_consistency()?;
758 Ok(ok_result)
759 })
760 })
761 }
762
763 pub fn execute_genesis_state_update(
770 store: &dyn BackingStore,
771 protocol_config: &ProtocolConfig,
772 metrics: Arc<LimitsMetrics>,
773 move_vm: &Arc<MoveVM>,
774 tx_context: Rc<RefCell<TxContext>>,
775 input_objects: CheckedInputObjects,
776 pt: ProgrammableTransaction,
777 ) -> Result<InnerTemporaryStore, ExecutionError> {
778 let input_objects = input_objects.into_inner();
779 let tx_digest = tx_context.borrow().digest();
780
781 let mut temporary_store =
782 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
783 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
784 programmable_transactions::execution::execute::<execution_mode::Genesis>(
785 protocol_config,
786 metrics,
787 move_vm,
788 &mut temporary_store,
789 tx_context,
790 &mut gas_charger,
791 pt,
792 &mut None,
793 )
794 .map_err(|(e, _)| e)?;
795 temporary_store.update_object_version_and_prev_tx();
796 Ok(temporary_store.into_inner())
797 }
798
799 #[instrument(name = "tx_execute", level = "debug", skip_all)]
808 fn execute_transaction<Mode: ExecutionMode>(
809 temporary_store: &mut TemporaryStore<'_>,
810 transaction_kind: TransactionKind,
811 gas_charger: &mut GasCharger,
812 tx_ctx: Rc<RefCell<TxContext>>,
813 move_vm: &Arc<MoveVM>,
814 protocol_config: &ProtocolConfig,
815 metrics: Arc<LimitsMetrics>,
816 enable_expensive_checks: bool,
817 deny_cert: bool,
818 contains_deleted_input: bool,
819 cancelled_objects: Option<(CancelledObjects, Version)>,
820 trace_builder_opt: &mut Option<MoveTraceBuilder>,
821 pre_execution_result_opt: Option<
822 Result<
823 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
824 ExecutionError,
825 >,
826 >,
827 ) -> (
828 GasCostSummary,
829 Result<Mode::ExecutionResults, ExecutionError>,
830 Vec<ExecutionTiming>,
831 ) {
832 gas_charger.smash_gas(temporary_store);
833
834 debug_assert!(
837 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
838 "No gas charges must be applied yet"
839 );
840
841 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
842 || transaction_kind.is_end_of_epoch();
843
844 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
845
846 let tx_digest = tx_ctx.borrow().digest();
847
848 let result = gas_charger.charge_input_objects(temporary_store);
852 let result: ResultWithTimings<Mode::ExecutionResults, ExecutionError> =
853 result.map_err(|e| (e, vec![])).and_then(
854 |()| -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
855 run_inputs_checks(
856 protocol_config,
857 deny_cert,
858 contains_deleted_input,
859 cancelled_objects,
860 )
861 .map_err(|e| (e, vec![]))?;
862
863 let mut execution_result = pre_execution_result_opt
866 .unwrap_or(Ok(()))
867 .map_err(|e| (e, vec![]))
868 .and_then(|_| {
869 execution_loop::<Mode>(
870 temporary_store,
871 transaction_kind,
872 tx_ctx,
873 move_vm,
874 gas_charger,
875 protocol_config,
876 metrics.clone(),
877 trace_builder_opt,
878 )
879 });
880
881 let meter_check = check_meter_limit(
882 temporary_store,
883 gas_charger,
884 protocol_config,
885 metrics.clone(),
886 );
887 if let Err(e) = meter_check {
888 execution_result = Err((e, vec![]));
889 }
890
891 if execution_result.is_ok() {
892 let gas_check = check_written_objects_limit(
893 temporary_store,
894 gas_charger,
895 protocol_config,
896 metrics,
897 );
898 if let Err(e) = gas_check {
899 execution_result = Err((e, vec![]));
900 }
901 }
902
903 execution_result
904 },
905 );
906
907 let (mut result, timings) = match result {
908 Ok((r, t)) => (Ok(r), t),
909 Err((e, t)) => (Err(e), t),
910 };
911
912 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
913 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
922
923 if let Err(e) = run_conservation_checks::<Mode>(
924 temporary_store,
925 gas_charger,
926 tx_digest,
927 move_vm,
928 enable_expensive_checks,
929 &cost_summary,
930 is_genesis_or_epoch_change_tx,
931 advance_epoch_gas_summary,
932 ) {
933 result = Err(e);
935 }
936
937 (cost_summary, result, timings)
938 }
939
940 fn report_authentication_error<T>(
946 authentication_execution_result: Result<T, ExecutionError>,
947 protocol_config: &ProtocolConfig,
948 ) -> Result<T, ExecutionError> {
949 if protocol_config.report_move_authentication_error() {
950 authentication_execution_result.map_err(ExecutionError::into_move_authentication_error)
951 } else {
952 authentication_execution_result
953 }
954 }
955
956 fn elaborate_error_logs(
959 execution_error: &ExecutionError,
960 transaction_digest: TransactionDigest,
961 ) -> ExecutionStatus {
962 use ExecutionErrorKind as K;
963 match execution_error.kind() {
964 K::InvariantViolation | K::VmInvariantViolation => {
965 #[skip_checked_arithmetic]
966 tracing::error!(
967 kind = ?execution_error.kind(),
968 tx_digest = ?transaction_digest,
969 "INVARIANT VIOLATION! Source: {:?}",
970 execution_error.source(),
971 );
972 }
973
974 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
975 #[skip_checked_arithmetic]
976 tracing::debug!(
977 kind = ?execution_error.kind(),
978 tx_digest = ?transaction_digest,
979 "Verification Error. Source: {:?}",
980 execution_error.source(),
981 );
982 }
983
984 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
985 #[skip_checked_arithmetic]
986 tracing::debug!(
987 kind = ?execution_error.kind(),
988 tx_digest = ?transaction_digest,
989 "Publish/Upgrade Error. Source: {:?}",
990 execution_error.source(),
991 )
992 }
993
994 _ => (),
995 };
996
997 let (status, command) = execution_error.to_execution_status();
998 ExecutionStatus::new_failure(status, command)
999 }
1000
1001 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
1010 fn run_conservation_checks<Mode: ExecutionMode>(
1011 temporary_store: &mut TemporaryStore<'_>,
1012 gas_charger: &mut GasCharger,
1013 tx_digest: TransactionDigest,
1014 move_vm: &Arc<MoveVM>,
1015 enable_expensive_checks: bool,
1016 cost_summary: &GasCostSummary,
1017 is_genesis_or_epoch_change_tx: bool,
1018 advance_epoch_gas_summary: Option<(u64, u64)>,
1019 ) -> Result<(), ExecutionError> {
1020 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
1021 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
1022 let conservation_result = {
1025 temporary_store
1026 .check_iota_conserved(cost_summary)
1027 .and_then(|()| {
1028 if enable_expensive_checks {
1029 let mut layout_resolver =
1032 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1033 temporary_store.check_iota_conserved_expensive(
1034 cost_summary,
1035 advance_epoch_gas_summary,
1036 &mut layout_resolver,
1037 )
1038 } else {
1039 Ok(())
1040 }
1041 })
1042 };
1043 if let Err(conservation_err) = conservation_result {
1044 result = Err(conservation_err);
1048 gas_charger.reset(temporary_store);
1049 gas_charger.charge_gas(temporary_store, &mut result);
1050 if let Err(recovery_err) = temporary_store
1052 .check_iota_conserved(cost_summary)
1053 .and_then(|()| {
1054 if enable_expensive_checks {
1055 let mut layout_resolver =
1058 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1059 temporary_store.check_iota_conserved_expensive(
1060 cost_summary,
1061 advance_epoch_gas_summary,
1062 &mut layout_resolver,
1063 )
1064 } else {
1065 Ok(())
1066 }
1067 })
1068 {
1069 panic!(
1073 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1074 tx_digest,
1075 recovery_err,
1076 gas_charger.summary()
1077 )
1078 }
1079 }
1080 } result
1084 }
1085
1086 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1097 fn run_inputs_checks(
1098 protocol_config: &ProtocolConfig,
1099 deny_cert: bool,
1100 contains_deleted_input: bool,
1101 cancelled_objects: Option<(CancelledObjects, Version)>,
1102 ) -> Result<(), ExecutionError> {
1103 if deny_cert {
1104 Err(ExecutionError::new(
1105 ExecutionErrorKind::CertificateDenied,
1106 None,
1107 ))
1108 } else if contains_deleted_input {
1109 Err(ExecutionError::new(
1110 ExecutionErrorKind::InputObjectDeleted,
1111 None,
1112 ))
1113 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1114 match reason {
1115 version if version.is_congested() => Err(ExecutionError::new(
1116 match cancelled_objects {
1117 CancelledObjects::GasObject => {
1121 ExecutionErrorKind::ExecutionCanceledDueToExecutionWorkerCongestion {
1122 suggested_gas_price: version
1123 .get_congested_version_suggested_gas_price()
1124 .expect(
1125 "execution-worker congestion control requires the gas \
1126 price feedback mechanism",
1127 ),
1128 }
1129 }
1130 CancelledObjects::SharedObjects(congested_objects) => {
1131 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1132 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestionV2 {
1133 congested_objects,
1134 suggested_gas_price: version
1135 .get_congested_version_suggested_gas_price()
1136 .unwrap(),
1137 }
1138 } else {
1139 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestion {
1144 congested_objects,
1145 }
1146 }
1147 }
1148 },
1149 None,
1150 )),
1151 Version::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1152 ExecutionErrorKind::ExecutionCanceledDueToRandomnessUnavailable,
1153 None,
1154 )),
1155 _ => panic!("invalid cancellation reason Version: {reason}"),
1156 }
1157 } else {
1158 Ok(())
1159 }
1160 }
1161
1162 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1167 fn check_meter_limit(
1168 temporary_store: &mut TemporaryStore<'_>,
1169 gas_charger: &mut GasCharger,
1170 protocol_config: &ProtocolConfig,
1171 metrics: Arc<LimitsMetrics>,
1172 ) -> Result<(), ExecutionError> {
1173 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1174
1175 match check_limit_by_meter!(
1180 !gas_charger.is_unmetered(),
1181 effects_estimated_size,
1182 protocol_config.max_serialized_tx_effects_size_bytes(),
1183 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1184 metrics.excessive_estimated_effects_size
1185 ) {
1186 LimitThresholdCrossed::None => Ok(()),
1187 LimitThresholdCrossed::Soft(_, limit) => {
1188 warn!(
1189 effects_estimated_size = effects_estimated_size,
1190 soft_limit = limit,
1191 "Estimated transaction effects size crossed soft limit",
1192 );
1193 Ok(())
1194 }
1195 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1196 ExecutionErrorKind::EffectsTooLarge {
1197 current_size: effects_estimated_size as u64,
1198 max_size: lim as u64,
1199 },
1200 "Transaction effects are too large",
1201 )),
1202 }
1203 }
1204
1205 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1210 fn check_written_objects_limit(
1211 temporary_store: &mut TemporaryStore<'_>,
1212 gas_charger: &mut GasCharger,
1213 protocol_config: &ProtocolConfig,
1214 metrics: Arc<LimitsMetrics>,
1215 ) -> Result<(), ExecutionError> {
1216 if let (Some(normal_lim), Some(system_lim)) = (
1217 protocol_config.max_size_written_objects_as_option(),
1218 protocol_config.max_size_written_objects_system_tx_as_option(),
1219 ) {
1220 let written_objects_size = temporary_store.written_objects_size();
1221
1222 match check_limit_by_meter!(
1223 !gas_charger.is_unmetered(),
1224 written_objects_size,
1225 normal_lim,
1226 system_lim,
1227 metrics.excessive_written_objects_size
1228 ) {
1229 LimitThresholdCrossed::None => (),
1230 LimitThresholdCrossed::Soft(_, limit) => {
1231 warn!(
1232 written_objects_size = written_objects_size,
1233 soft_limit = limit,
1234 "Written objects size crossed soft limit",
1235 )
1236 }
1237 LimitThresholdCrossed::Hard(_, lim) => {
1238 return Err(ExecutionError::new_with_source(
1239 ExecutionErrorKind::WrittenObjectsTooLarge {
1240 object_size: written_objects_size as u64,
1241 max_object_size: lim as u64,
1242 },
1243 "Written objects size crossed hard limit",
1244 ));
1245 }
1246 };
1247 }
1248
1249 Ok(())
1250 }
1251
1252 #[instrument(level = "debug", skip_all)]
1259 fn execution_loop<Mode: ExecutionMode>(
1260 temporary_store: &mut TemporaryStore<'_>,
1261 transaction_kind: TransactionKind,
1262 tx_ctx: Rc<RefCell<TxContext>>,
1263 move_vm: &Arc<MoveVM>,
1264 gas_charger: &mut GasCharger,
1265 protocol_config: &ProtocolConfig,
1266 metrics: Arc<LimitsMetrics>,
1267 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1268 ) -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
1269 let result = match transaction_kind {
1270 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1271 if tx_ctx.borrow().epoch() != 0 {
1272 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1273 }
1274
1275 for genesis_object in objects {
1276 let object = ObjectInner {
1277 data: genesis_object.data,
1278 owner: genesis_object.owner,
1279 previous_transaction: tx_ctx.borrow().digest(),
1280 storage_rebate: 0,
1281 };
1282 temporary_store.create_object(object.into());
1283 }
1284
1285 temporary_store.record_execution_results(ExecutionResults::V1(
1286 ExecutionResultsV1 {
1287 user_events: events,
1288 ..Default::default()
1289 },
1290 ));
1291
1292 Ok((Mode::empty_results(), vec![]))
1293 }
1294 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1295 setup_consensus_commit(
1296 prologue.commit_timestamp_ms,
1297 temporary_store,
1298 tx_ctx,
1299 move_vm,
1300 gas_charger,
1301 protocol_config,
1302 metrics,
1303 trace_builder_opt,
1304 )
1305 .expect("ConsensusCommitPrologueV1 cannot fail");
1306 Ok((Mode::empty_results(), vec![]))
1307 }
1308 TransactionKind::Programmable(pt) => {
1309 programmable_transactions::execution::execute::<Mode>(
1310 protocol_config,
1311 metrics,
1312 move_vm,
1313 temporary_store,
1314 tx_ctx,
1315 gas_charger,
1316 pt,
1317 trace_builder_opt,
1318 )
1319 }
1320 TransactionKind::EndOfEpoch(txns) => {
1321 let mut builder = ProgrammableTransactionBuilder::new();
1325 let len = txns.len();
1326
1327 for (i, tx) in txns.into_iter().enumerate() {
1328 match tx {
1329 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1330 assert_eq!(i, len - 1);
1331 advance_epoch_v1(
1332 builder,
1333 change_epoch,
1334 temporary_store,
1335 tx_ctx,
1336 move_vm,
1337 gas_charger,
1338 protocol_config,
1339 metrics,
1340 trace_builder_opt,
1341 )
1342 .map_err(|e| (e, vec![]))?;
1343 return Ok((Mode::empty_results(), vec![]));
1344 }
1345 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1346 assert_eq!(i, len - 1);
1347 advance_epoch_v2(
1348 builder,
1349 change_epoch_v2,
1350 temporary_store,
1351 tx_ctx,
1352 move_vm,
1353 gas_charger,
1354 protocol_config,
1355 metrics,
1356 trace_builder_opt,
1357 )
1358 .map_err(|e| (e, vec![]))?;
1359 return Ok((Mode::empty_results(), vec![]));
1360 }
1361 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1362 assert_eq!(i, len - 1);
1363 advance_epoch_v3(
1364 builder,
1365 change_epoch_v3,
1366 temporary_store,
1367 tx_ctx,
1368 move_vm,
1369 gas_charger,
1370 protocol_config,
1371 metrics,
1372 trace_builder_opt,
1373 )
1374 .map_err(|e| (e, vec![]))?;
1375 return Ok((Mode::empty_results(), vec![]));
1376 }
1377 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1378 assert_eq!(i, len - 1);
1379 advance_epoch_v4(
1380 builder,
1381 change_epoch_v4,
1382 temporary_store,
1383 tx_ctx,
1384 move_vm,
1385 gas_charger,
1386 protocol_config,
1387 metrics,
1388 trace_builder_opt,
1389 )
1390 .map_err(|e| (e, vec![]))?;
1391 return Ok((Mode::empty_results(), vec![]));
1392 }
1393 EndOfEpochTransactionKind::TransactionDenyRulesCreate => {
1394 assert!(
1395 protocol_config.deny_rule_governance_on_chain(),
1396 "unexpected TransactionDenyRulesCreate: on-chain deny rule governance is not enabled"
1397 );
1398 builder = setup_transaction_deny_rules_create(builder)
1399 .map_err(|e| (e, vec![]))?;
1400 }
1401 _ => unimplemented!(
1402 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1403 ),
1404 }
1405 }
1406 unreachable!(
1407 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1408 )
1409 }
1410 #[allow(deprecated)]
1411 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1412 return Err((
1416 ExecutionError::new(
1417 ExecutionErrorKind::VmInvariantViolation,
1418 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1419 ),
1420 vec![],
1421 ));
1422 }
1423 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1424 setup_randomness_state_update(
1425 randomness_state_update,
1426 temporary_store,
1427 tx_ctx,
1428 move_vm,
1429 gas_charger,
1430 protocol_config,
1431 metrics,
1432 trace_builder_opt,
1433 )
1434 .map_err(|e| (e, vec![]))?;
1435 Ok((Mode::empty_results(), vec![]))
1436 }
1437 TransactionKind::TransactionDenyRulesUpdate(update) => {
1438 assert!(
1439 protocol_config.deny_rule_governance_on_chain(),
1440 "unexpected TransactionDenyRulesUpdate: on-chain deny rule governance is not enabled"
1441 );
1442 setup_transaction_deny_rules_update(
1443 update,
1444 temporary_store,
1445 tx_ctx,
1446 move_vm,
1447 gas_charger,
1448 protocol_config,
1449 metrics,
1450 trace_builder_opt,
1451 )
1452 .map_err(|e| (e, vec![]))?;
1453 Ok((Mode::empty_results(), vec![]))
1454 }
1455 _ => unimplemented!(
1456 "a new TransactionKind enum variant was added and needs to be handled"
1457 ),
1458 }?;
1459 temporary_store
1460 .check_execution_results_consistency()
1461 .map_err(|e| (e, vec![]))?;
1462 Ok(result)
1463 }
1464
1465 fn mint_epoch_rewards_in_pt(
1474 builder: &mut ProgrammableTransactionBuilder,
1475 params: &AdvanceEpochParams,
1476 ) -> (Argument, Argument) {
1477 let storage_charge_arg = builder
1479 .input(CallArg::pure(¶ms.storage_charge))
1480 .unwrap();
1481 let storage_charges = builder.programmable_move_call(
1482 ObjectId::FRAMEWORK,
1483 Identifier::BALANCE_MODULE,
1484 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1485 vec![TypeTag::from(StructTag::new_gas())],
1486 vec![storage_charge_arg],
1487 );
1488
1489 let computation_charge_arg = builder
1491 .input(CallArg::pure(¶ms.computation_charge))
1492 .unwrap();
1493 let computation_charges = builder.programmable_move_call(
1494 ObjectId::FRAMEWORK,
1495 Identifier::BALANCE_MODULE,
1496 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1497 vec![TypeTag::from(StructTag::new_gas())],
1498 vec![computation_charge_arg],
1499 );
1500 (storage_charges, computation_charges)
1501 }
1502
1503 pub fn construct_advance_epoch_pt_impl(
1511 mut builder: ProgrammableTransactionBuilder,
1512 params: &AdvanceEpochParams,
1513 call_arg_vec: Vec<CallArg>,
1514 ) -> Result<ProgrammableTransaction, ExecutionError> {
1515 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1517 let mut arguments = vec![
1518 builder
1519 .pure(params.validator_subsidy)
1520 .expect("bcs encoding a u64 should not fail"),
1521 storage_charges,
1522 computation_charges,
1523 ];
1524
1525 let call_arg_arguments = call_arg_vec
1526 .into_iter()
1527 .map(|a| builder.input(a))
1528 .collect::<Result<_, _>>();
1529
1530 assert_invariant!(
1531 call_arg_arguments.is_ok(),
1532 "Unable to generate args for advance_epoch transaction!"
1533 );
1534
1535 arguments.append(&mut call_arg_arguments.unwrap());
1536
1537 info!("Call arguments to advance_epoch transaction: {:?}", params);
1538
1539 let storage_rebates = builder.programmable_move_call(
1540 ObjectId::SYSTEM,
1541 Identifier::IOTA_SYSTEM_MODULE,
1542 ADVANCE_EPOCH_FUNCTION_NAME,
1543 vec![],
1544 arguments,
1545 );
1546
1547 builder.programmable_move_call(
1549 ObjectId::FRAMEWORK,
1550 Identifier::BALANCE_MODULE,
1551 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1552 vec![TypeTag::from(StructTag::new_gas())],
1553 vec![storage_rebates],
1554 );
1555 Ok(builder.finish())
1556 }
1557
1558 pub fn construct_advance_epoch_pt_v1(
1559 builder: ProgrammableTransactionBuilder,
1560 params: &AdvanceEpochParams,
1561 ) -> Result<ProgrammableTransaction, ExecutionError> {
1562 let call_arg_vec = vec![
1567 CallArg::IOTA_SYSTEM_MUTABLE, CallArg::pure(¶ms.epoch), CallArg::pure(¶ms.next_protocol_version.as_u64()), CallArg::pure(¶ms.storage_rebate), CallArg::pure(¶ms.non_refundable_storage_fee), CallArg::pure(¶ms.reward_slashing_rate), CallArg::pure(¶ms.epoch_start_timestamp_ms), ];
1575 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1576 }
1577
1578 pub fn construct_advance_epoch_pt_v2(
1579 builder: ProgrammableTransactionBuilder,
1580 params: &AdvanceEpochParams,
1581 ) -> Result<ProgrammableTransaction, ExecutionError> {
1582 let call_arg_vec = vec![
1587 CallArg::pure(¶ms.computation_charge_burned), CallArg::IOTA_SYSTEM_MUTABLE, CallArg::pure(¶ms.epoch), CallArg::pure(¶ms.next_protocol_version.as_u64()), CallArg::pure(¶ms.storage_rebate), CallArg::pure(¶ms.non_refundable_storage_fee), CallArg::pure(¶ms.reward_slashing_rate), CallArg::pure(¶ms.epoch_start_timestamp_ms), CallArg::pure(¶ms.max_committee_members_count), ];
1597 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1598 }
1599
1600 pub fn construct_advance_epoch_pt_v3(
1601 builder: ProgrammableTransactionBuilder,
1602 params: &AdvanceEpochParams,
1603 ) -> Result<ProgrammableTransaction, ExecutionError> {
1604 let call_arg_vec = vec![
1610 CallArg::pure(¶ms.computation_charge_burned), CallArg::IOTA_SYSTEM_MUTABLE, CallArg::pure(¶ms.epoch), CallArg::pure(¶ms.next_protocol_version.as_u64()), CallArg::pure(¶ms.storage_rebate), CallArg::pure(¶ms.non_refundable_storage_fee), CallArg::pure(¶ms.reward_slashing_rate), CallArg::pure(¶ms.epoch_start_timestamp_ms), CallArg::pure(¶ms.max_committee_members_count), CallArg::pure(¶ms.eligible_active_validators), ];
1622 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1623 }
1624
1625 pub fn construct_advance_epoch_pt_v4(
1626 builder: ProgrammableTransactionBuilder,
1627 params: &AdvanceEpochParams,
1628 ) -> Result<ProgrammableTransaction, ExecutionError> {
1629 let call_arg_vec = vec![
1635 CallArg::pure(¶ms.computation_charge_burned), CallArg::IOTA_SYSTEM_MUTABLE, CallArg::pure(¶ms.epoch), CallArg::pure(¶ms.next_protocol_version.as_u64()), CallArg::pure(¶ms.storage_rebate), CallArg::pure(¶ms.non_refundable_storage_fee), CallArg::pure(¶ms.reward_slashing_rate), CallArg::pure(¶ms.epoch_start_timestamp_ms), CallArg::pure(¶ms.max_committee_members_count), CallArg::pure(¶ms.eligible_active_validators), CallArg::pure(¶ms.scores), CallArg::pure(¶ms.adjust_rewards_by_score), ];
1649 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1650 }
1651
1652 fn advance_epoch_impl(
1659 advance_epoch_pt: ProgrammableTransaction,
1660 params: AdvanceEpochParams,
1661 system_packages: Vec<SystemPackage>,
1662 temporary_store: &mut TemporaryStore<'_>,
1663 tx_ctx: Rc<RefCell<TxContext>>,
1664 move_vm: &Arc<MoveVM>,
1665 gas_charger: &mut GasCharger,
1666 protocol_config: &ProtocolConfig,
1667 metrics: Arc<LimitsMetrics>,
1668 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1669 ) -> Result<(), ExecutionError> {
1670 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1671 protocol_config,
1672 metrics.clone(),
1673 move_vm,
1674 temporary_store,
1675 tx_ctx.clone(),
1676 gas_charger,
1677 advance_epoch_pt,
1678 trace_builder_opt,
1679 );
1680
1681 #[cfg(msim)]
1682 let result = maybe_modify_result(result, params.epoch);
1683
1684 if let Err(err) = &result {
1685 tracing::error!(
1686 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1687 err.0,
1688 temporary_store.objects(),
1689 params,
1690 );
1691 temporary_store.drop_writes();
1692 gas_charger.reset_storage_cost_and_rebate();
1694
1695 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1696 }
1697
1698 let new_vm = new_move_vm(
1699 all_natives(true, protocol_config),
1700 protocol_config,
1701 None,
1703 )
1704 .expect("Failed to create new MoveVM");
1705 process_system_packages(
1706 system_packages,
1707 temporary_store,
1708 tx_ctx,
1709 &new_vm,
1710 gas_charger,
1711 protocol_config,
1712 metrics,
1713 trace_builder_opt,
1714 );
1715
1716 Ok(())
1717 }
1718
1719 fn advance_epoch_v1(
1723 builder: ProgrammableTransactionBuilder,
1724 change_epoch: ChangeEpoch,
1725 temporary_store: &mut TemporaryStore<'_>,
1726 tx_ctx: Rc<RefCell<TxContext>>,
1727 move_vm: &Arc<MoveVM>,
1728 gas_charger: &mut GasCharger,
1729 protocol_config: &ProtocolConfig,
1730 metrics: Arc<LimitsMetrics>,
1731 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1732 ) -> Result<(), ExecutionError> {
1733 let params = AdvanceEpochParams {
1734 epoch: change_epoch.epoch,
1735 next_protocol_version: change_epoch.protocol_version.into(),
1736 validator_subsidy: protocol_config.validator_target_reward(),
1737 storage_charge: change_epoch.storage_charge,
1738 computation_charge: change_epoch.computation_charge,
1739 computation_charge_burned: change_epoch.computation_charge,
1741 storage_rebate: change_epoch.storage_rebate,
1742 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1743 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1744 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1745 max_committee_members_count: 0,
1748 eligible_active_validators: vec![],
1749 scores: vec![],
1750 adjust_rewards_by_score: false,
1751 };
1752 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1753 advance_epoch_impl(
1754 advance_epoch_pt,
1755 params,
1756 change_epoch.system_packages,
1757 temporary_store,
1758 tx_ctx,
1759 move_vm,
1760 gas_charger,
1761 protocol_config,
1762 metrics,
1763 trace_builder_opt,
1764 )
1765 }
1766
1767 fn advance_epoch_v2(
1771 builder: ProgrammableTransactionBuilder,
1772 change_epoch_v2: ChangeEpochV2,
1773 temporary_store: &mut TemporaryStore<'_>,
1774 tx_ctx: Rc<RefCell<TxContext>>,
1775 move_vm: &Arc<MoveVM>,
1776 gas_charger: &mut GasCharger,
1777 protocol_config: &ProtocolConfig,
1778 metrics: Arc<LimitsMetrics>,
1779 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1780 ) -> Result<(), ExecutionError> {
1781 let params = AdvanceEpochParams {
1782 epoch: change_epoch_v2.epoch,
1783 next_protocol_version: change_epoch_v2.protocol_version.into(),
1784 validator_subsidy: protocol_config.validator_target_reward(),
1785 storage_charge: change_epoch_v2.storage_charge,
1786 computation_charge: change_epoch_v2.computation_charge,
1787 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1788 storage_rebate: change_epoch_v2.storage_rebate,
1789 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1790 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1791 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1792 max_committee_members_count: protocol_config.max_committee_members_count(),
1793 eligible_active_validators: vec![],
1796 scores: vec![],
1797 adjust_rewards_by_score: false,
1798 };
1799 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1800 advance_epoch_impl(
1801 advance_epoch_pt,
1802 params,
1803 change_epoch_v2.system_packages,
1804 temporary_store,
1805 tx_ctx,
1806 move_vm,
1807 gas_charger,
1808 protocol_config,
1809 metrics,
1810 trace_builder_opt,
1811 )
1812 }
1813
1814 fn advance_epoch_v3(
1818 builder: ProgrammableTransactionBuilder,
1819 change_epoch_v3: ChangeEpochV3,
1820 temporary_store: &mut TemporaryStore<'_>,
1821 tx_ctx: Rc<RefCell<TxContext>>,
1822 move_vm: &Arc<MoveVM>,
1823 gas_charger: &mut GasCharger,
1824 protocol_config: &ProtocolConfig,
1825 metrics: Arc<LimitsMetrics>,
1826 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1827 ) -> Result<(), ExecutionError> {
1828 let params = AdvanceEpochParams {
1829 epoch: change_epoch_v3.epoch,
1830 next_protocol_version: change_epoch_v3.protocol_version.into(),
1831 validator_subsidy: protocol_config.validator_target_reward(),
1832 storage_charge: change_epoch_v3.storage_charge,
1833 computation_charge: change_epoch_v3.computation_charge,
1834 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1835 storage_rebate: change_epoch_v3.storage_rebate,
1836 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1837 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1838 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1839 max_committee_members_count: protocol_config.max_committee_members_count(),
1840 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1841 scores: vec![],
1844 adjust_rewards_by_score: false,
1845 };
1846 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1847 advance_epoch_impl(
1848 advance_epoch_pt,
1849 params,
1850 change_epoch_v3.system_packages,
1851 temporary_store,
1852 tx_ctx,
1853 move_vm,
1854 gas_charger,
1855 protocol_config,
1856 metrics,
1857 trace_builder_opt,
1858 )
1859 }
1860
1861 fn advance_epoch_v4(
1865 builder: ProgrammableTransactionBuilder,
1866 change_epoch_v4: ChangeEpochV4,
1867 temporary_store: &mut TemporaryStore<'_>,
1868 tx_ctx: Rc<RefCell<TxContext>>,
1869 move_vm: &Arc<MoveVM>,
1870 gas_charger: &mut GasCharger,
1871 protocol_config: &ProtocolConfig,
1872 metrics: Arc<LimitsMetrics>,
1873 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1874 ) -> Result<(), ExecutionError> {
1875 let params = AdvanceEpochParams {
1876 epoch: change_epoch_v4.epoch,
1877 next_protocol_version: change_epoch_v4.protocol_version.into(),
1878 validator_subsidy: protocol_config.validator_target_reward(),
1879 storage_charge: change_epoch_v4.storage_charge,
1880 computation_charge: change_epoch_v4.computation_charge,
1881 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1882 storage_rebate: change_epoch_v4.storage_rebate,
1883 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1884 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1885 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1886 max_committee_members_count: protocol_config.max_committee_members_count(),
1887 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1888 scores: change_epoch_v4.scores,
1889 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1890 };
1891 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1892 advance_epoch_impl(
1893 advance_epoch_pt,
1894 params,
1895 change_epoch_v4.system_packages,
1896 temporary_store,
1897 tx_ctx,
1898 move_vm,
1899 gas_charger,
1900 protocol_config,
1901 metrics,
1902 trace_builder_opt,
1903 )
1904 }
1905
1906 fn process_system_packages(
1907 system_packages: Vec<SystemPackage>,
1908 temporary_store: &mut TemporaryStore<'_>,
1909 tx_ctx: Rc<RefCell<TxContext>>,
1910 move_vm: &MoveVM,
1911 gas_charger: &mut GasCharger,
1912 protocol_config: &ProtocolConfig,
1913 metrics: Arc<LimitsMetrics>,
1914 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1915 ) {
1916 let binary_config = to_binary_config(protocol_config, None);
1917 for SystemPackage {
1918 version,
1919 modules,
1920 dependencies,
1921 } in system_packages.into_iter()
1922 {
1923 let deserialized_modules: Vec<_> = modules
1924 .iter()
1925 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1926 .collect();
1927
1928 if version == OBJECT_START_VERSION {
1929 let package_id = deserialized_modules.first().unwrap().address();
1930 info!("adding new system package {package_id}");
1931
1932 let publish_pt = {
1933 let mut b = ProgrammableTransactionBuilder::new();
1934 b.command(Command::new_publish(modules, dependencies));
1935 b.finish()
1936 };
1937
1938 programmable_transactions::execution::execute::<execution_mode::System>(
1939 protocol_config,
1940 metrics.clone(),
1941 move_vm,
1942 temporary_store,
1943 tx_ctx.clone(),
1944 gas_charger,
1945 publish_pt,
1946 trace_builder_opt,
1947 )
1948 .map_err(|(e, _)| e)
1949 .expect("System Package Publish must succeed");
1950 } else {
1951 let mut new_package = Object::new_system_package(
1952 &deserialized_modules,
1953 version,
1954 dependencies,
1955 tx_ctx.borrow().digest(),
1956 );
1957
1958 info!("upgraded system package {:?}", new_package.object_ref());
1959
1960 new_package
1963 .data
1964 .as_opt_mut_package()
1965 .unwrap()
1966 .decrement_version()
1967 .expect("package version should never underflow");
1968
1969 temporary_store.upgrade_system_package(new_package);
1971 }
1972 }
1973 }
1974
1975 fn setup_consensus_commit(
1981 consensus_commit_timestamp_ms: CheckpointTimestamp,
1982 temporary_store: &mut TemporaryStore<'_>,
1983 tx_ctx: Rc<RefCell<TxContext>>,
1984 move_vm: &Arc<MoveVM>,
1985 gas_charger: &mut GasCharger,
1986 protocol_config: &ProtocolConfig,
1987 metrics: Arc<LimitsMetrics>,
1988 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1989 ) -> Result<(), ExecutionError> {
1990 let pt = {
1991 let mut builder = ProgrammableTransactionBuilder::new();
1992 let res = builder.move_call(
1993 ObjectId::FRAMEWORK,
1994 Identifier::CLOCK_MODULE,
1995 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
1996 vec![],
1997 vec![
1998 CallArg::CLOCK_MUTABLE,
1999 CallArg::pure(&consensus_commit_timestamp_ms),
2000 ],
2001 );
2002 assert_invariant!(
2003 res.is_ok(),
2004 "Unable to generate consensus_commit_prologue transaction!"
2005 );
2006 builder.finish()
2007 };
2008 programmable_transactions::execution::execute::<execution_mode::System>(
2009 protocol_config,
2010 metrics,
2011 move_vm,
2012 temporary_store,
2013 tx_ctx,
2014 gas_charger,
2015 pt,
2016 trace_builder_opt,
2017 )
2018 .map_err(|(e, _)| e)?;
2019 Ok(())
2020 }
2021
2022 fn setup_randomness_state_update(
2028 update: RandomnessStateUpdate,
2029 temporary_store: &mut TemporaryStore<'_>,
2030 tx_ctx: Rc<RefCell<TxContext>>,
2031 move_vm: &Arc<MoveVM>,
2032 gas_charger: &mut GasCharger,
2033 protocol_config: &ProtocolConfig,
2034 metrics: Arc<LimitsMetrics>,
2035 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2036 ) -> Result<(), ExecutionError> {
2037 let pt = {
2038 let mut builder = ProgrammableTransactionBuilder::new();
2039 let res = builder.move_call(
2040 ObjectId::FRAMEWORK,
2041 Identifier::RANDOM_MODULE,
2042 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
2043 vec![],
2044 vec![
2045 CallArg::Shared(SharedObjectReference::new(
2046 ObjectId::RANDOMNESS_STATE,
2047 update.randomness_obj_initial_shared_version,
2048 true,
2049 )),
2050 CallArg::pure(&update.randomness_round),
2051 CallArg::pure(&update.random_bytes),
2052 ],
2053 );
2054 assert_invariant!(
2055 res.is_ok(),
2056 "Unable to generate randomness_state_update transaction!"
2057 );
2058 builder.finish()
2059 };
2060 programmable_transactions::execution::execute::<execution_mode::System>(
2061 protocol_config,
2062 metrics,
2063 move_vm,
2064 temporary_store,
2065 tx_ctx,
2066 gas_charger,
2067 pt,
2068 trace_builder_opt,
2069 )
2070 .map_err(|(e, _)| e)?;
2071 Ok(())
2072 }
2073
2074 fn setup_transaction_deny_rules_create(
2080 mut builder: ProgrammableTransactionBuilder,
2081 ) -> Result<ProgrammableTransactionBuilder, ExecutionError> {
2082 let res = builder.move_call(
2083 ObjectId::FRAMEWORK,
2084 TRANSACTION_DENY_RULES_MODULE,
2085 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME,
2086 vec![],
2087 vec![],
2088 );
2089 assert_invariant!(
2090 res.is_ok(),
2091 "Unable to generate transaction_deny_rules create transaction!"
2092 );
2093 Ok(builder)
2094 }
2095
2096 fn setup_transaction_deny_rules_update(
2100 update: TransactionDenyRulesUpdate,
2101 temporary_store: &mut TemporaryStore<'_>,
2102 tx_ctx: Rc<RefCell<TxContext>>,
2103 move_vm: &Arc<MoveVM>,
2104 gas_charger: &mut GasCharger,
2105 protocol_config: &ProtocolConfig,
2106 metrics: Arc<LimitsMetrics>,
2107 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2108 ) -> Result<(), ExecutionError> {
2109 let pt = {
2110 let mut builder = ProgrammableTransactionBuilder::new();
2111 let res = builder.move_call(
2115 ObjectId::FRAMEWORK,
2116 TRANSACTION_DENY_RULES_MODULE,
2117 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
2118 vec![],
2119 vec![
2120 CallArg::Shared(SharedObjectReference::new(
2121 ObjectId::TRANSACTION_DENY_RULES,
2122 update.deny_rules_obj_initial_shared_version,
2123 true,
2124 )),
2125 CallArg::pure(&update.added_addresses),
2126 CallArg::pure(&update.removed_addresses),
2127 CallArg::pure(&update.added_objects),
2128 CallArg::pure(&update.removed_objects),
2129 CallArg::pure(&update.added_packages),
2130 CallArg::pure(&update.removed_packages),
2131 CallArg::pure(&update.package_publish_disabled),
2132 CallArg::pure(&update.package_upgrade_disabled),
2133 CallArg::pure(&update.shared_object_disabled),
2134 CallArg::pure(&update.user_transaction_disabled),
2135 CallArg::pure(&update.receiving_objects_disabled),
2136 CallArg::pure(&update.move_authenticator_disabled),
2137 ],
2138 );
2139 assert_invariant!(
2140 res.is_ok(),
2141 "Unable to generate transaction_deny_rules update transaction!"
2142 );
2143 builder.finish()
2144 };
2145 programmable_transactions::execution::execute::<execution_mode::System>(
2146 protocol_config,
2147 metrics,
2148 move_vm,
2149 temporary_store,
2150 tx_ctx,
2151 gas_charger,
2152 pt,
2153 trace_builder_opt,
2154 )
2155 .map(|(results, _timings)| results)
2156 .map_err(|(error, _timings)| error)
2157 }
2158
2159 fn setup_authenticator_move_call(
2166 authenticator: MoveAuthenticator,
2167 authenticator_function_ref: AuthenticatorFunctionRefV1,
2168 ) -> Result<ProgrammableTransaction, ExecutionError> {
2169 let mut builder = ProgrammableTransactionBuilder::new();
2170
2171 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
2172 args.extend(authenticator.call_args().to_owned());
2173
2174 let res = builder.move_call(
2175 authenticator_function_ref.package,
2176 Identifier::new(authenticator_function_ref.module.clone()).expect(
2177 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2178 ),
2179 Identifier::new(authenticator_function_ref.function).expect(
2180 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2181 ),
2182 authenticator.type_args().to_vec(),
2183 args,
2184 );
2185
2186 assert_invariant!(
2187 res.is_ok(),
2188 "Unable to generate an account authenticator call transaction!"
2189 );
2190
2191 Ok(builder.finish())
2192 }
2193
2194 fn resolve_sponsor(gas_data: &GasPayment, transaction_signer: &Address) -> Option<Address> {
2195 let gas_owner = gas_data.owner;
2196 if &gas_owner == transaction_signer {
2197 None
2198 } else {
2199 Some(gas_owner)
2200 }
2201 }
2202}