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,
32 },
33 auth_context::{AuthContext, AuthContextData},
34 balance::{BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME},
35 base_types::TxContext,
36 clock::CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
37 committee::EpochId,
38 error::{ExecutionError, ExecutionErrorKind},
39 execution::{
40 ExecutionResults, ExecutionResultsV1, ExecutionTiming, ResultWithTimings, SharedInput,
41 is_certificate_denied,
42 },
43 execution_config_utils::to_binary_config,
44 gas::{IotaGasStatus, IotaGasStatusAPI},
45 inner_temporary_store::InnerTemporaryStore,
46 iota_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams},
47 messages_checkpoint::CheckpointTimestamp,
48 metrics::LimitsMetrics,
49 move_authenticator::MoveAuthenticatorExt,
50 object::{OBJECT_START_VERSION, Object, ObjectInner},
51 programmable_transaction_builder::ProgrammableTransactionBuilder,
52 randomness_state::RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
53 storage::{BackingStore, Storage},
54 transaction::{
55 CallArg, CancelledObjects, CheckedInputObjects, InputObjects, TransactionKindExt,
56 },
57 transaction_deny_rules::{
58 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME, TRANSACTION_DENY_RULES_MODULE,
59 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
60 },
61 };
62 use move_binary_format::CompiledModule;
63 use move_trace_format::format::MoveTraceBuilder;
64 use move_vm_runtime::move_vm::MoveVM;
65 use tracing::{info, instrument, trace, warn};
66
67 use crate::{
68 adapter::new_move_vm,
69 execution_mode::{self, ExecutionMode},
70 gas_charger::GasCharger,
71 programmable_transactions,
72 temporary_store::TemporaryStore,
73 type_layout_resolver::TypeLayoutResolver,
74 };
75
76 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
88 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
89 store: &dyn BackingStore,
90 input_objects: CheckedInputObjects,
91 gas_data: GasPayment,
92 gas_status: IotaGasStatus,
93 transaction_kind: TransactionKind,
94 transaction_signer: Address,
95 transaction_digest: TransactionDigest,
96 move_vm: &Arc<MoveVM>,
97 epoch_id: &EpochId,
98 epoch_timestamp_ms: u64,
99 protocol_config: &ProtocolConfig,
100 metrics: Arc<LimitsMetrics>,
101 enable_expensive_checks: bool,
102 certificate_deny_set: &HashSet<TransactionDigest>,
103 trace_builder_opt: &mut Option<MoveTraceBuilder>,
104 ) -> (
105 InnerTemporaryStore,
106 IotaGasStatus,
107 TransactionEffects,
108 Vec<ExecutionTiming>,
109 Result<Mode::ExecutionResults, ExecutionError>,
110 ) {
111 let input_objects = input_objects.into_inner();
112 let mutable_inputs = if enable_expensive_checks {
113 input_objects.mutable_inputs().keys().copied().collect()
114 } else {
115 HashSet::new()
116 };
117 let shared_object_refs = input_objects.filter_shared_objects();
118 let receiving_objects = transaction_kind.receiving_objects();
119 let transaction_dependencies = input_objects.transaction_dependencies();
120 let contains_deleted_input = input_objects.contains_deleted_objects();
121 let cancelled_objects = input_objects.get_cancelled_objects();
122
123 let temporary_store = TemporaryStore::new(
124 store,
125 input_objects,
126 receiving_objects,
127 transaction_digest,
128 protocol_config,
129 *epoch_id,
130 );
131
132 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
133 let gas_price = gas_status.gas_price();
134 let rgp = gas_status.reference_gas_price();
135 let gas_charger = GasCharger::new(
136 transaction_digest,
137 gas_data.objects,
138 gas_status,
139 protocol_config,
140 );
141
142 let tx_ctx = TxContext::new_from_components(
143 &transaction_signer,
144 &transaction_digest,
145 epoch_id,
146 epoch_timestamp_ms,
147 rgp,
148 gas_price,
149 gas_data.budget,
150 sponsor,
151 protocol_config,
152 );
153 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
154
155 execute_transaction_to_effects_inner::<Mode>(
156 temporary_store,
157 gas_charger,
158 tx_ctx,
159 &mutable_inputs,
160 shared_object_refs,
161 transaction_dependencies,
162 contains_deleted_input,
163 cancelled_objects,
164 transaction_kind,
165 transaction_signer,
166 transaction_digest,
167 move_vm,
168 epoch_id,
169 protocol_config,
170 metrics,
171 enable_expensive_checks,
172 certificate_deny_set,
173 trace_builder_opt,
174 None,
175 )
176 }
177
178 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
181 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
182 mut temporary_store: TemporaryStore,
183 mut gas_charger: GasCharger,
184 tx_ctx: Rc<RefCell<TxContext>>,
185 mutable_inputs: &HashSet<ObjectId>,
186 shared_object_refs: Vec<SharedInput>,
187 mut transaction_dependencies: BTreeSet<TransactionDigest>,
188 contains_deleted_input: bool,
189 cancelled_objects: Option<(CancelledObjects, Version)>,
190 transaction_kind: TransactionKind,
191 transaction_signer: Address,
192 transaction_digest: TransactionDigest,
193 move_vm: &Arc<MoveVM>,
194 epoch_id: &EpochId,
195 protocol_config: &ProtocolConfig,
196 metrics: Arc<LimitsMetrics>,
197 enable_expensive_checks: bool,
198 certificate_deny_set: &HashSet<TransactionDigest>,
199 trace_builder_opt: &mut Option<MoveTraceBuilder>,
200 pre_execution_result_opt: Option<
201 Result<
202 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
203 ExecutionError,
204 >,
205 >,
206 ) -> (
207 InnerTemporaryStore,
208 IotaGasStatus,
209 TransactionEffects,
210 Vec<ExecutionTiming>,
211 Result<Mode::ExecutionResults, ExecutionError>,
212 ) {
213 let is_epoch_change = transaction_kind.is_end_of_epoch();
214 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
215
216 let (gas_cost_summary, execution_result, timings) = execute_transaction::<Mode>(
217 &mut temporary_store,
218 transaction_kind,
219 &mut gas_charger,
220 tx_ctx,
221 move_vm,
222 protocol_config,
223 metrics,
224 enable_expensive_checks,
225 deny_cert,
226 contains_deleted_input,
227 cancelled_objects,
228 trace_builder_opt,
229 pre_execution_result_opt,
230 );
231
232 let status = if let Err(error) = &execution_result {
233 elaborate_error_logs(error, transaction_digest)
234 } else {
235 ExecutionStatus::Success
236 };
237
238 #[skip_checked_arithmetic]
239 trace!(
240 tx_digest = ?transaction_digest,
241 computation_gas_cost = gas_cost_summary.computation_cost,
242 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
243 storage_gas_cost = gas_cost_summary.storage_cost,
244 storage_gas_rebate = gas_cost_summary.storage_rebate,
245 "Finished execution of transaction with status {:?}",
246 status
247 );
248
249 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
253
254 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
255 temporary_store
256 .check_ownership_invariants(
257 &transaction_signer,
258 &mut gas_charger,
259 mutable_inputs,
260 is_epoch_change,
261 )
262 .unwrap()
263 } let (inner, effects) = temporary_store.into_effects(
266 shared_object_refs,
267 &transaction_digest,
268 transaction_dependencies,
269 gas_cost_summary,
270 status,
271 &mut gas_charger,
272 *epoch_id,
273 );
274
275 (
276 inner,
277 gas_charger.into_gas_status(),
278 effects,
279 timings,
280 execution_result,
281 )
282 }
283
284 #[instrument(
297 name = "tx_authenticate_then_execute_to_effects",
298 level = "debug",
299 skip_all
300 )]
301 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
302 store: &dyn BackingStore,
303 protocol_config: &ProtocolConfig,
305 metrics: Arc<LimitsMetrics>,
306 enable_expensive_checks: bool,
307 certificate_deny_set: &HashSet<TransactionDigest>,
308 epoch_id: &EpochId,
310 epoch_timestamp_ms: u64,
311 gas_data: GasPayment,
313 gas_status: IotaGasStatus,
314 authenticators: Vec<(
316 MoveAuthenticator,
317 AuthenticatorFunctionRefForExecution,
318 CheckedInputObjects,
319 )>,
320 authenticator_and_transaction_input_objects: CheckedInputObjects,
321 transaction_kind: TransactionKind,
323 transaction_signer: Address,
324 transaction_digest: TransactionDigest,
325 auth_context_data: AuthContextData,
326 trace_builder_opt: &mut Option<MoveTraceBuilder>,
328 move_vm: &Arc<MoveVM>,
330 ) -> (
331 InnerTemporaryStore,
332 IotaGasStatus,
333 TransactionEffects,
334 Vec<ExecutionTiming>,
335 Result<Mode::ExecutionResults, ExecutionError>,
336 ) {
337 let input_objects = authenticator_and_transaction_input_objects.into_inner();
343 let mutable_inputs = if enable_expensive_checks {
345 input_objects.mutable_inputs().keys().copied().collect()
346 } else {
347 HashSet::new()
348 };
349 let shared_object_refs = input_objects.filter_shared_objects();
351 let transaction_receiving_objects = transaction_kind.receiving_objects();
353 let transaction_dependencies = input_objects.transaction_dependencies();
355 let contains_deleted_input = input_objects.contains_deleted_objects();
358 let cancelled_objects = input_objects.get_cancelled_objects();
359
360 let mut temporary_store = TemporaryStore::new(
362 store,
363 input_objects,
364 transaction_receiving_objects,
365 transaction_digest,
366 protocol_config,
367 *epoch_id,
368 );
369
370 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
372 let gas_price = gas_status.gas_price();
373 let rgp = gas_status.reference_gas_price();
374 let mut gas_charger = GasCharger::new(
375 transaction_digest,
376 gas_data.objects,
377 gas_status,
378 protocol_config,
379 );
380
381 let tx_ctx = TxContext::new_from_components(
383 &transaction_signer,
384 &transaction_digest,
385 epoch_id,
386 epoch_timestamp_ms,
387 rgp,
388 gas_price,
389 gas_data.budget,
390 sponsor,
391 protocol_config,
392 );
393 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
394
395 let authenticators = authenticators
401 .into_iter()
402 .map(
403 |(
404 authenticator,
405 authenticator_function_ref_for_execution,
406 authenticator_input_objects,
407 )| {
408 let AuthenticatorFunctionRefForExecution {
409 authenticator_function_ref,
410 loaded_object_id,
411 loaded_object_metadata,
412 } = authenticator_function_ref_for_execution;
413
414 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
417 loaded_object_id,
418 loaded_object_metadata,
419 )]));
420
421 (
422 authenticator,
423 authenticator_function_ref,
424 authenticator_input_objects,
425 )
426 },
427 )
428 .collect::<Vec<_>>();
429
430 let authentication_execution_result = authenticators.into_iter().try_for_each(
436 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
437 match authenticator_function_ref {
438 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
439 authenticate_transaction_inner(
440 &mut temporary_store,
441 protocol_config,
442 metrics.clone(),
443 &mut gas_charger,
444 authenticator,
445 authenticator_function_ref_v1,
446 &authenticator_input_objects.into_inner(),
447 transaction_kind.clone(),
448 transaction_digest,
449 auth_context_data.clone(),
450 tx_ctx.clone(),
451 trace_builder_opt,
452 move_vm,
453 )
454 }
455 }
456 },
457 );
458
459 let authentication_execution_result =
460 report_authentication_error(authentication_execution_result, protocol_config);
461
462 execute_transaction_to_effects_inner::<Mode>(
470 temporary_store,
471 gas_charger,
472 tx_ctx,
473 &mutable_inputs,
474 shared_object_refs,
475 transaction_dependencies,
476 contains_deleted_input,
477 cancelled_objects,
478 transaction_kind,
479 transaction_signer,
480 transaction_digest,
481 move_vm,
482 epoch_id,
483 protocol_config,
484 metrics,
485 enable_expensive_checks,
486 certificate_deny_set,
487 trace_builder_opt,
488 Some(authentication_execution_result),
489 )
490 }
491
492 #[instrument(name = "tx_validate", level = "debug", skip_all)]
497 pub fn authenticate_transaction(
498 store: &dyn BackingStore,
499 protocol_config: &ProtocolConfig,
501 metrics: Arc<LimitsMetrics>,
502 epoch_id: &EpochId,
504 epoch_timestamp_ms: u64,
505 gas_data: GasPayment,
507 gas_status: IotaGasStatus,
508 authenticators: Vec<(
510 MoveAuthenticator,
511 AuthenticatorFunctionRef,
512 CheckedInputObjects,
513 )>,
514 aggregated_authenticator_input_objects: CheckedInputObjects,
515 transaction_kind: TransactionKind,
517 transaction_signer: Address,
518 transaction_digest: TransactionDigest,
519 auth_context_data: AuthContextData,
520 trace_builder_opt: &mut Option<MoveTraceBuilder>,
522 move_vm: &Arc<MoveVM>,
524 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
525 {
526 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
528 let gas_price = gas_status.gas_price();
529 let rgp = gas_status.reference_gas_price();
530 let mut gas_charger =
531 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
532
533 let tx_ctx = TxContext::new_from_components(
536 &transaction_signer,
537 &transaction_digest,
538 epoch_id,
539 epoch_timestamp_ms,
540 rgp,
541 gas_price,
542 gas_data.budget,
543 sponsor,
544 protocol_config,
545 );
546 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
547
548 let mut temporary_store = TemporaryStore::new(
549 store,
550 aggregated_authenticator_input_objects.into_inner(),
551 vec![],
552 transaction_digest,
553 protocol_config,
554 *epoch_id,
555 );
556
557 let authentication_execution_result = authenticators.into_iter().try_for_each(
559 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
560 match authenticator_function_ref {
561 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
562 authenticate_transaction_inner(
563 &mut temporary_store,
564 protocol_config,
565 metrics.clone(),
566 &mut gas_charger,
567 authenticator,
568 authenticator_function_ref_v1,
569 &authenticator_input_objects.into_inner(),
570 transaction_kind.clone(),
571 transaction_digest,
572 auth_context_data.clone(),
573 tx_ctx.clone(),
574 trace_builder_opt,
575 move_vm,
576 )
577 }
578 }
579 },
580 );
581
582 report_authentication_error(authentication_execution_result, protocol_config)
583 }
584
585 #[instrument(name = "tx_validate", level = "debug", skip_all)]
595 pub fn authenticate_transaction_inner(
596 temporary_store: &mut TemporaryStore<'_>,
597 protocol_config: &ProtocolConfig,
599 metrics: Arc<LimitsMetrics>,
600 gas_charger: &mut GasCharger,
602 authenticator: MoveAuthenticator,
604 authenticator_function_ref: AuthenticatorFunctionRefV1,
605 authenticator_input_objects: &InputObjects,
606 transaction_kind: TransactionKind,
608 transaction_digest: TransactionDigest,
609 auth_context_data: AuthContextData,
610 tx_ctx: Rc<RefCell<TxContext>>,
611 trace_builder_opt: &mut Option<MoveTraceBuilder>,
613 move_vm: &Arc<MoveVM>,
615 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
616 {
617 debug_assert!(
619 transaction_kind.is_programmable(),
620 "Only programmable transactions are allowed"
621 );
622 debug_assert!(
623 authenticator_input_objects
624 .mutable_inputs()
625 .keys()
626 .copied()
627 .collect::<HashSet<_>>()
628 .is_empty(),
629 "No mutable inputs are allowed"
630 );
631 debug_assert!(
632 authenticator.receiving_objects().is_empty(),
633 "No receiving inputs are allowed"
634 );
635
636 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
637 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
638
639 let auth_ctx = {
641 let TransactionKind::Programmable(ptb) = &transaction_kind else {
642 unreachable!("Only programmable transactions are allowed");
643 };
644 AuthContext::new_from_components(
645 authenticator.digest().into(),
646 auth_context_data.sender_auth_digest,
647 auth_context_data.sponsor_auth_digest,
648 auth_context_data
649 .sender_authenticator_function_ref
650 .and_then(Into::into),
651 auth_context_data
652 .sponsor_authenticator_function_ref
653 .and_then(Into::into),
654 ptb,
655 auth_context_data.transaction_data_bytes,
656 )
657 };
658 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
659
660 temporary_store.store_auth_context(auth_ctx);
664
665 let authentication_execution_result = execute_authenticator_move_call(
667 temporary_store,
668 authenticator,
669 authenticator_function_ref,
670 gas_charger,
671 tx_ctx,
672 move_vm,
673 protocol_config,
674 metrics,
675 false,
676 contains_deleted_input,
677 cancelled_objects,
678 trace_builder_opt,
679 );
680
681 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
683 elaborate_error_logs(error, transaction_digest)
684 } else {
685 ExecutionStatus::Success
686 };
687
688 #[skip_checked_arithmetic]
689 trace!(
690 tx_digest = ?transaction_digest,
691 computation_gas_cost = gas_charger.summary().gas_used(),
692 "Finished authenticator execution of transaction with status {:?}",
693 authentication_execution_status
694 );
695
696 authentication_execution_result
697 }
698
699 #[instrument(name = "auth_execute", level = "debug", skip_all)]
710 fn execute_authenticator_move_call(
711 temporary_store: &mut TemporaryStore<'_>,
712 authenticator: MoveAuthenticator,
713 authenticator_function_ref: AuthenticatorFunctionRefV1,
714 gas_charger: &mut GasCharger,
715 tx_ctx: Rc<RefCell<TxContext>>,
716 move_vm: &Arc<MoveVM>,
717 protocol_config: &ProtocolConfig,
718 metrics: Arc<LimitsMetrics>,
719 deny_cert: bool,
720 contains_deleted_input: bool,
721 cancelled_objects: Option<(CancelledObjects, Version)>,
722 trace_builder_opt: &mut Option<MoveTraceBuilder>,
723 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
724 {
725 run_inputs_checks(
729 protocol_config,
730 deny_cert,
731 contains_deleted_input,
732 cancelled_objects,
733 )
734 .and_then(|()| {
735 let authenticator_move_call =
736 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
737 programmable_transactions::execution::execute::<execution_mode::Authentication>(
738 protocol_config,
739 metrics.clone(),
740 move_vm,
741 temporary_store,
742 tx_ctx,
743 gas_charger,
744 authenticator_move_call,
745 trace_builder_opt,
746 )
747 .map_err(|(e, _)| e)
748 .and_then(|(ok_result, _timings)| {
749 temporary_store.check_move_authenticator_results_consistency()?;
750 Ok(ok_result)
751 })
752 })
753 }
754
755 pub fn execute_genesis_state_update(
762 store: &dyn BackingStore,
763 protocol_config: &ProtocolConfig,
764 metrics: Arc<LimitsMetrics>,
765 move_vm: &Arc<MoveVM>,
766 tx_context: Rc<RefCell<TxContext>>,
767 input_objects: CheckedInputObjects,
768 pt: ProgrammableTransaction,
769 ) -> Result<InnerTemporaryStore, ExecutionError> {
770 let input_objects = input_objects.into_inner();
771 let tx_digest = tx_context.borrow().digest();
772
773 let mut temporary_store =
774 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
775 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
776 programmable_transactions::execution::execute::<execution_mode::Genesis>(
777 protocol_config,
778 metrics,
779 move_vm,
780 &mut temporary_store,
781 tx_context,
782 &mut gas_charger,
783 pt,
784 &mut None,
785 )
786 .map_err(|(e, _)| e)?;
787 temporary_store.update_object_version_and_prev_tx();
788 Ok(temporary_store.into_inner())
789 }
790
791 #[instrument(name = "tx_execute", level = "debug", skip_all)]
800 fn execute_transaction<Mode: ExecutionMode>(
801 temporary_store: &mut TemporaryStore<'_>,
802 transaction_kind: TransactionKind,
803 gas_charger: &mut GasCharger,
804 tx_ctx: Rc<RefCell<TxContext>>,
805 move_vm: &Arc<MoveVM>,
806 protocol_config: &ProtocolConfig,
807 metrics: Arc<LimitsMetrics>,
808 enable_expensive_checks: bool,
809 deny_cert: bool,
810 contains_deleted_input: bool,
811 cancelled_objects: Option<(CancelledObjects, Version)>,
812 trace_builder_opt: &mut Option<MoveTraceBuilder>,
813 pre_execution_result_opt: Option<
814 Result<
815 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
816 ExecutionError,
817 >,
818 >,
819 ) -> (
820 GasCostSummary,
821 Result<Mode::ExecutionResults, ExecutionError>,
822 Vec<ExecutionTiming>,
823 ) {
824 gas_charger.smash_gas(temporary_store);
825
826 debug_assert!(
829 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
830 "No gas charges must be applied yet"
831 );
832
833 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
834 || transaction_kind.is_end_of_epoch();
835
836 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
837
838 let tx_digest = tx_ctx.borrow().digest();
839
840 let result = gas_charger.charge_input_objects(temporary_store);
844 let result: ResultWithTimings<Mode::ExecutionResults, ExecutionError> =
845 result.map_err(|e| (e, vec![])).and_then(
846 |()| -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
847 run_inputs_checks(
848 protocol_config,
849 deny_cert,
850 contains_deleted_input,
851 cancelled_objects,
852 )
853 .map_err(|e| (e, vec![]))?;
854
855 let mut execution_result = pre_execution_result_opt
858 .unwrap_or(Ok(()))
859 .map_err(|e| (e, vec![]))
860 .and_then(|_| {
861 execution_loop::<Mode>(
862 temporary_store,
863 transaction_kind,
864 tx_ctx,
865 move_vm,
866 gas_charger,
867 protocol_config,
868 metrics.clone(),
869 trace_builder_opt,
870 )
871 });
872
873 let meter_check = check_meter_limit(
874 temporary_store,
875 gas_charger,
876 protocol_config,
877 metrics.clone(),
878 );
879 if let Err(e) = meter_check {
880 execution_result = Err((e, vec![]));
881 }
882
883 if execution_result.is_ok() {
884 let gas_check = check_written_objects_limit(
885 temporary_store,
886 gas_charger,
887 protocol_config,
888 metrics,
889 );
890 if let Err(e) = gas_check {
891 execution_result = Err((e, vec![]));
892 }
893 }
894
895 execution_result
896 },
897 );
898
899 let (mut result, timings) = match result {
900 Ok((r, t)) => (Ok(r), t),
901 Err((e, t)) => (Err(e), t),
902 };
903
904 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
905 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
914
915 if let Err(e) = run_conservation_checks::<Mode>(
916 temporary_store,
917 gas_charger,
918 tx_digest,
919 move_vm,
920 enable_expensive_checks,
921 &cost_summary,
922 is_genesis_or_epoch_change_tx,
923 advance_epoch_gas_summary,
924 ) {
925 result = Err(e);
927 }
928
929 (cost_summary, result, timings)
930 }
931
932 fn report_authentication_error<T>(
938 authentication_execution_result: Result<T, ExecutionError>,
939 protocol_config: &ProtocolConfig,
940 ) -> Result<T, ExecutionError> {
941 if protocol_config.report_move_authentication_error() {
942 authentication_execution_result.map_err(ExecutionError::into_move_authentication_error)
943 } else {
944 authentication_execution_result
945 }
946 }
947
948 fn elaborate_error_logs(
951 execution_error: &ExecutionError,
952 transaction_digest: TransactionDigest,
953 ) -> ExecutionStatus {
954 use ExecutionErrorKind as K;
955 match execution_error.kind() {
956 K::InvariantViolation | K::VmInvariantViolation => {
957 #[skip_checked_arithmetic]
958 tracing::error!(
959 kind = ?execution_error.kind(),
960 tx_digest = ?transaction_digest,
961 "INVARIANT VIOLATION! Source: {:?}",
962 execution_error.source(),
963 );
964 }
965
966 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
967 #[skip_checked_arithmetic]
968 tracing::debug!(
969 kind = ?execution_error.kind(),
970 tx_digest = ?transaction_digest,
971 "Verification Error. Source: {:?}",
972 execution_error.source(),
973 );
974 }
975
976 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
977 #[skip_checked_arithmetic]
978 tracing::debug!(
979 kind = ?execution_error.kind(),
980 tx_digest = ?transaction_digest,
981 "Publish/Upgrade Error. Source: {:?}",
982 execution_error.source(),
983 )
984 }
985
986 _ => (),
987 };
988
989 let (status, command) = execution_error.to_execution_status();
990 ExecutionStatus::new_failure(status, command)
991 }
992
993 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
1002 fn run_conservation_checks<Mode: ExecutionMode>(
1003 temporary_store: &mut TemporaryStore<'_>,
1004 gas_charger: &mut GasCharger,
1005 tx_digest: TransactionDigest,
1006 move_vm: &Arc<MoveVM>,
1007 enable_expensive_checks: bool,
1008 cost_summary: &GasCostSummary,
1009 is_genesis_or_epoch_change_tx: bool,
1010 advance_epoch_gas_summary: Option<(u64, u64)>,
1011 ) -> Result<(), ExecutionError> {
1012 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
1013 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
1014 let conservation_result = {
1017 temporary_store
1018 .check_iota_conserved(cost_summary)
1019 .and_then(|()| {
1020 if enable_expensive_checks {
1021 let mut layout_resolver =
1024 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1025 temporary_store.check_iota_conserved_expensive(
1026 cost_summary,
1027 advance_epoch_gas_summary,
1028 &mut layout_resolver,
1029 )
1030 } else {
1031 Ok(())
1032 }
1033 })
1034 };
1035 if let Err(conservation_err) = conservation_result {
1036 result = Err(conservation_err);
1040 gas_charger.reset(temporary_store);
1041 gas_charger.charge_gas(temporary_store, &mut result);
1042 if let Err(recovery_err) = {
1044 temporary_store
1045 .check_iota_conserved(cost_summary)
1046 .and_then(|()| {
1047 if enable_expensive_checks {
1048 let mut layout_resolver =
1051 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1052 temporary_store.check_iota_conserved_expensive(
1053 cost_summary,
1054 advance_epoch_gas_summary,
1055 &mut layout_resolver,
1056 )
1057 } else {
1058 Ok(())
1059 }
1060 })
1061 } {
1062 panic!(
1066 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1067 tx_digest,
1068 recovery_err,
1069 gas_charger.summary()
1070 )
1071 }
1072 }
1073 } result
1077 }
1078
1079 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1090 fn run_inputs_checks(
1091 protocol_config: &ProtocolConfig,
1092 deny_cert: bool,
1093 contains_deleted_input: bool,
1094 cancelled_objects: Option<(CancelledObjects, Version)>,
1095 ) -> Result<(), ExecutionError> {
1096 if deny_cert {
1097 Err(ExecutionError::new(
1098 ExecutionErrorKind::CertificateDenied,
1099 None,
1100 ))
1101 } else if contains_deleted_input {
1102 Err(ExecutionError::new(
1103 ExecutionErrorKind::InputObjectDeleted,
1104 None,
1105 ))
1106 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1107 match reason {
1108 version if version.is_congested() => Err(ExecutionError::new(
1109 match cancelled_objects {
1110 CancelledObjects::GasObject => {
1114 ExecutionErrorKind::ExecutionCanceledDueToExecutionWorkerCongestion {
1115 suggested_gas_price: version
1116 .get_congested_version_suggested_gas_price()
1117 .expect(
1118 "execution-worker congestion control requires the gas \
1119 price feedback mechanism",
1120 ),
1121 }
1122 }
1123 CancelledObjects::SharedObjects(congested_objects) => {
1124 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1125 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestionV2 {
1126 congested_objects,
1127 suggested_gas_price: version
1128 .get_congested_version_suggested_gas_price()
1129 .unwrap(),
1130 }
1131 } else {
1132 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestion {
1137 congested_objects,
1138 }
1139 }
1140 }
1141 },
1142 None,
1143 )),
1144 Version::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1145 ExecutionErrorKind::ExecutionCanceledDueToRandomnessUnavailable,
1146 None,
1147 )),
1148 _ => panic!("invalid cancellation reason Version: {reason}"),
1149 }
1150 } else {
1151 Ok(())
1152 }
1153 }
1154
1155 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1160 fn check_meter_limit(
1161 temporary_store: &mut TemporaryStore<'_>,
1162 gas_charger: &mut GasCharger,
1163 protocol_config: &ProtocolConfig,
1164 metrics: Arc<LimitsMetrics>,
1165 ) -> Result<(), ExecutionError> {
1166 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1167
1168 match check_limit_by_meter!(
1173 !gas_charger.is_unmetered(),
1174 effects_estimated_size,
1175 protocol_config.max_serialized_tx_effects_size_bytes(),
1176 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1177 metrics.excessive_estimated_effects_size
1178 ) {
1179 LimitThresholdCrossed::None => Ok(()),
1180 LimitThresholdCrossed::Soft(_, limit) => {
1181 warn!(
1182 effects_estimated_size = effects_estimated_size,
1183 soft_limit = limit,
1184 "Estimated transaction effects size crossed soft limit",
1185 );
1186 Ok(())
1187 }
1188 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1189 ExecutionErrorKind::EffectsTooLarge {
1190 current_size: effects_estimated_size as u64,
1191 max_size: lim as u64,
1192 },
1193 "Transaction effects are too large",
1194 )),
1195 }
1196 }
1197
1198 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1203 fn check_written_objects_limit(
1204 temporary_store: &mut TemporaryStore<'_>,
1205 gas_charger: &mut GasCharger,
1206 protocol_config: &ProtocolConfig,
1207 metrics: Arc<LimitsMetrics>,
1208 ) -> Result<(), ExecutionError> {
1209 if let (Some(normal_lim), Some(system_lim)) = (
1210 protocol_config.max_size_written_objects_as_option(),
1211 protocol_config.max_size_written_objects_system_tx_as_option(),
1212 ) {
1213 let written_objects_size = temporary_store.written_objects_size();
1214
1215 match check_limit_by_meter!(
1216 !gas_charger.is_unmetered(),
1217 written_objects_size,
1218 normal_lim,
1219 system_lim,
1220 metrics.excessive_written_objects_size
1221 ) {
1222 LimitThresholdCrossed::None => (),
1223 LimitThresholdCrossed::Soft(_, limit) => {
1224 warn!(
1225 written_objects_size = written_objects_size,
1226 soft_limit = limit,
1227 "Written objects size crossed soft limit",
1228 )
1229 }
1230 LimitThresholdCrossed::Hard(_, lim) => {
1231 return Err(ExecutionError::new_with_source(
1232 ExecutionErrorKind::WrittenObjectsTooLarge {
1233 object_size: written_objects_size as u64,
1234 max_object_size: lim as u64,
1235 },
1236 "Written objects size crossed hard limit",
1237 ));
1238 }
1239 };
1240 }
1241
1242 Ok(())
1243 }
1244
1245 #[instrument(level = "debug", skip_all)]
1252 fn execution_loop<Mode: ExecutionMode>(
1253 temporary_store: &mut TemporaryStore<'_>,
1254 transaction_kind: TransactionKind,
1255 tx_ctx: Rc<RefCell<TxContext>>,
1256 move_vm: &Arc<MoveVM>,
1257 gas_charger: &mut GasCharger,
1258 protocol_config: &ProtocolConfig,
1259 metrics: Arc<LimitsMetrics>,
1260 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1261 ) -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
1262 let result = match transaction_kind {
1263 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1264 if tx_ctx.borrow().epoch() != 0 {
1265 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1266 }
1267
1268 for genesis_object in objects {
1269 let object = ObjectInner {
1270 data: genesis_object.data,
1271 owner: genesis_object.owner,
1272 previous_transaction: tx_ctx.borrow().digest(),
1273 storage_rebate: 0,
1274 };
1275 temporary_store.create_object(object.into());
1276 }
1277
1278 temporary_store.record_execution_results(ExecutionResults::V1(
1279 ExecutionResultsV1 {
1280 user_events: events,
1281 ..Default::default()
1282 },
1283 ));
1284
1285 Ok((Mode::empty_results(), vec![]))
1286 }
1287 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1288 setup_consensus_commit(
1289 prologue.commit_timestamp_ms,
1290 temporary_store,
1291 tx_ctx,
1292 move_vm,
1293 gas_charger,
1294 protocol_config,
1295 metrics,
1296 trace_builder_opt,
1297 )
1298 .expect("ConsensusCommitPrologueV1 cannot fail");
1299 Ok((Mode::empty_results(), vec![]))
1300 }
1301 TransactionKind::Programmable(pt) => {
1302 programmable_transactions::execution::execute::<Mode>(
1303 protocol_config,
1304 metrics,
1305 move_vm,
1306 temporary_store,
1307 tx_ctx,
1308 gas_charger,
1309 pt,
1310 trace_builder_opt,
1311 )
1312 }
1313 TransactionKind::EndOfEpoch(txns) => {
1314 let mut builder = ProgrammableTransactionBuilder::new();
1318 let len = txns.len();
1319
1320 for (i, tx) in txns.into_iter().enumerate() {
1321 match tx {
1322 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1323 assert_eq!(i, len - 1);
1324 advance_epoch_v1(
1325 builder,
1326 change_epoch,
1327 temporary_store,
1328 tx_ctx,
1329 move_vm,
1330 gas_charger,
1331 protocol_config,
1332 metrics,
1333 trace_builder_opt,
1334 )
1335 .map_err(|e| (e, vec![]))?;
1336 return Ok((Mode::empty_results(), vec![]));
1337 }
1338 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1339 assert_eq!(i, len - 1);
1340 advance_epoch_v2(
1341 builder,
1342 change_epoch_v2,
1343 temporary_store,
1344 tx_ctx,
1345 move_vm,
1346 gas_charger,
1347 protocol_config,
1348 metrics,
1349 trace_builder_opt,
1350 )
1351 .map_err(|e| (e, vec![]))?;
1352 return Ok((Mode::empty_results(), vec![]));
1353 }
1354 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1355 assert_eq!(i, len - 1);
1356 advance_epoch_v3(
1357 builder,
1358 change_epoch_v3,
1359 temporary_store,
1360 tx_ctx,
1361 move_vm,
1362 gas_charger,
1363 protocol_config,
1364 metrics,
1365 trace_builder_opt,
1366 )
1367 .map_err(|e| (e, vec![]))?;
1368 return Ok((Mode::empty_results(), vec![]));
1369 }
1370 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1371 assert_eq!(i, len - 1);
1372 advance_epoch_v4(
1373 builder,
1374 change_epoch_v4,
1375 temporary_store,
1376 tx_ctx,
1377 move_vm,
1378 gas_charger,
1379 protocol_config,
1380 metrics,
1381 trace_builder_opt,
1382 )
1383 .map_err(|e| (e, vec![]))?;
1384 return Ok((Mode::empty_results(), vec![]));
1385 }
1386 EndOfEpochTransactionKind::TransactionDenyRulesCreate => {
1387 assert!(
1388 protocol_config.deny_rule_governance_on_chain(),
1389 "unexpected TransactionDenyRulesCreate: on-chain deny rule governance is not enabled"
1390 );
1391 builder = setup_transaction_deny_rules_create(builder)
1392 .map_err(|e| (e, vec![]))?;
1393 }
1394 _ => unimplemented!(
1395 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1396 ),
1397 }
1398 }
1399 unreachable!(
1400 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1401 )
1402 }
1403 #[allow(deprecated)]
1404 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1405 return Err((
1409 ExecutionError::new(
1410 ExecutionErrorKind::VmInvariantViolation,
1411 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1412 ),
1413 vec![],
1414 ));
1415 }
1416 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1417 setup_randomness_state_update(
1418 randomness_state_update,
1419 temporary_store,
1420 tx_ctx,
1421 move_vm,
1422 gas_charger,
1423 protocol_config,
1424 metrics,
1425 trace_builder_opt,
1426 )
1427 .map_err(|e| (e, vec![]))?;
1428 Ok((Mode::empty_results(), vec![]))
1429 }
1430 TransactionKind::TransactionDenyRulesUpdate(update) => {
1431 assert!(
1432 protocol_config.deny_rule_governance_on_chain(),
1433 "unexpected TransactionDenyRulesUpdate: on-chain deny rule governance is not enabled"
1434 );
1435 setup_transaction_deny_rules_update(
1436 update,
1437 temporary_store,
1438 tx_ctx,
1439 move_vm,
1440 gas_charger,
1441 protocol_config,
1442 metrics,
1443 trace_builder_opt,
1444 )
1445 .map_err(|e| (e, vec![]))?;
1446 Ok((Mode::empty_results(), vec![]))
1447 }
1448 _ => unimplemented!(
1449 "a new TransactionKind enum variant was added and needs to be handled"
1450 ),
1451 }?;
1452 temporary_store
1453 .check_execution_results_consistency()
1454 .map_err(|e| (e, vec![]))?;
1455 Ok(result)
1456 }
1457
1458 fn mint_epoch_rewards_in_pt(
1467 builder: &mut ProgrammableTransactionBuilder,
1468 params: &AdvanceEpochParams,
1469 ) -> (Argument, Argument) {
1470 let storage_charge_arg = builder
1472 .input(CallArg::pure(¶ms.storage_charge))
1473 .unwrap();
1474 let storage_charges = builder.programmable_move_call(
1475 ObjectId::FRAMEWORK,
1476 Identifier::BALANCE_MODULE,
1477 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1478 vec![TypeTag::from(StructTag::new_gas())],
1479 vec![storage_charge_arg],
1480 );
1481
1482 let computation_charge_arg = builder
1484 .input(CallArg::pure(¶ms.computation_charge))
1485 .unwrap();
1486 let computation_charges = builder.programmable_move_call(
1487 ObjectId::FRAMEWORK,
1488 Identifier::BALANCE_MODULE,
1489 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1490 vec![TypeTag::from(StructTag::new_gas())],
1491 vec![computation_charge_arg],
1492 );
1493 (storage_charges, computation_charges)
1494 }
1495
1496 pub fn construct_advance_epoch_pt_impl(
1504 mut builder: ProgrammableTransactionBuilder,
1505 params: &AdvanceEpochParams,
1506 call_arg_vec: Vec<CallArg>,
1507 ) -> Result<ProgrammableTransaction, ExecutionError> {
1508 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1510 let mut arguments = vec![
1511 builder
1512 .pure(params.validator_subsidy)
1513 .expect("bcs encoding a u64 should not fail"),
1514 storage_charges,
1515 computation_charges,
1516 ];
1517
1518 let call_arg_arguments = call_arg_vec
1519 .into_iter()
1520 .map(|a| builder.input(a))
1521 .collect::<Result<_, _>>();
1522
1523 assert_invariant!(
1524 call_arg_arguments.is_ok(),
1525 "Unable to generate args for advance_epoch transaction!"
1526 );
1527
1528 arguments.append(&mut call_arg_arguments.unwrap());
1529
1530 info!("Call arguments to advance_epoch transaction: {:?}", params);
1531
1532 let storage_rebates = builder.programmable_move_call(
1533 ObjectId::SYSTEM,
1534 Identifier::IOTA_SYSTEM_MODULE,
1535 ADVANCE_EPOCH_FUNCTION_NAME,
1536 vec![],
1537 arguments,
1538 );
1539
1540 builder.programmable_move_call(
1542 ObjectId::FRAMEWORK,
1543 Identifier::BALANCE_MODULE,
1544 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1545 vec![TypeTag::from(StructTag::new_gas())],
1546 vec![storage_rebates],
1547 );
1548 Ok(builder.finish())
1549 }
1550
1551 pub fn construct_advance_epoch_pt_v1(
1552 builder: ProgrammableTransactionBuilder,
1553 params: &AdvanceEpochParams,
1554 ) -> Result<ProgrammableTransaction, ExecutionError> {
1555 let call_arg_vec = vec![
1560 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), ];
1568 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1569 }
1570
1571 pub fn construct_advance_epoch_pt_v2(
1572 builder: ProgrammableTransactionBuilder,
1573 params: &AdvanceEpochParams,
1574 ) -> Result<ProgrammableTransaction, ExecutionError> {
1575 let call_arg_vec = vec![
1580 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), ];
1590 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1591 }
1592
1593 pub fn construct_advance_epoch_pt_v3(
1594 builder: ProgrammableTransactionBuilder,
1595 params: &AdvanceEpochParams,
1596 ) -> Result<ProgrammableTransaction, ExecutionError> {
1597 let call_arg_vec = vec![
1603 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), ];
1615 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1616 }
1617
1618 pub fn construct_advance_epoch_pt_v4(
1619 builder: ProgrammableTransactionBuilder,
1620 params: &AdvanceEpochParams,
1621 ) -> Result<ProgrammableTransaction, ExecutionError> {
1622 let call_arg_vec = vec![
1628 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), ];
1642 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1643 }
1644
1645 fn advance_epoch_impl(
1652 advance_epoch_pt: ProgrammableTransaction,
1653 params: AdvanceEpochParams,
1654 system_packages: Vec<SystemPackage>,
1655 temporary_store: &mut TemporaryStore<'_>,
1656 tx_ctx: Rc<RefCell<TxContext>>,
1657 move_vm: &Arc<MoveVM>,
1658 gas_charger: &mut GasCharger,
1659 protocol_config: &ProtocolConfig,
1660 metrics: Arc<LimitsMetrics>,
1661 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1662 ) -> Result<(), ExecutionError> {
1663 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1664 protocol_config,
1665 metrics.clone(),
1666 move_vm,
1667 temporary_store,
1668 tx_ctx.clone(),
1669 gas_charger,
1670 advance_epoch_pt,
1671 trace_builder_opt,
1672 );
1673
1674 #[cfg(msim)]
1675 let result = maybe_modify_result(result, params.epoch);
1676
1677 if let Err(err) = &result {
1678 tracing::error!(
1679 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1680 err.0,
1681 temporary_store.objects(),
1682 params,
1683 );
1684 temporary_store.drop_writes();
1685 gas_charger.reset_storage_cost_and_rebate();
1687
1688 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1689 }
1690
1691 let new_vm = new_move_vm(
1692 all_natives(true, protocol_config),
1693 protocol_config,
1694 None,
1696 )
1697 .expect("Failed to create new MoveVM");
1698 process_system_packages(
1699 system_packages,
1700 temporary_store,
1701 tx_ctx,
1702 &new_vm,
1703 gas_charger,
1704 protocol_config,
1705 metrics,
1706 trace_builder_opt,
1707 );
1708
1709 Ok(())
1710 }
1711
1712 fn advance_epoch_v1(
1716 builder: ProgrammableTransactionBuilder,
1717 change_epoch: ChangeEpoch,
1718 temporary_store: &mut TemporaryStore<'_>,
1719 tx_ctx: Rc<RefCell<TxContext>>,
1720 move_vm: &Arc<MoveVM>,
1721 gas_charger: &mut GasCharger,
1722 protocol_config: &ProtocolConfig,
1723 metrics: Arc<LimitsMetrics>,
1724 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1725 ) -> Result<(), ExecutionError> {
1726 let params = AdvanceEpochParams {
1727 epoch: change_epoch.epoch,
1728 next_protocol_version: change_epoch.protocol_version.into(),
1729 validator_subsidy: protocol_config.validator_target_reward(),
1730 storage_charge: change_epoch.storage_charge,
1731 computation_charge: change_epoch.computation_charge,
1732 computation_charge_burned: change_epoch.computation_charge,
1734 storage_rebate: change_epoch.storage_rebate,
1735 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1736 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1737 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1738 max_committee_members_count: 0,
1741 eligible_active_validators: vec![],
1742 scores: vec![],
1743 adjust_rewards_by_score: false,
1744 };
1745 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1746 advance_epoch_impl(
1747 advance_epoch_pt,
1748 params,
1749 change_epoch.system_packages,
1750 temporary_store,
1751 tx_ctx,
1752 move_vm,
1753 gas_charger,
1754 protocol_config,
1755 metrics,
1756 trace_builder_opt,
1757 )
1758 }
1759
1760 fn advance_epoch_v2(
1764 builder: ProgrammableTransactionBuilder,
1765 change_epoch_v2: ChangeEpochV2,
1766 temporary_store: &mut TemporaryStore<'_>,
1767 tx_ctx: Rc<RefCell<TxContext>>,
1768 move_vm: &Arc<MoveVM>,
1769 gas_charger: &mut GasCharger,
1770 protocol_config: &ProtocolConfig,
1771 metrics: Arc<LimitsMetrics>,
1772 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1773 ) -> Result<(), ExecutionError> {
1774 let params = AdvanceEpochParams {
1775 epoch: change_epoch_v2.epoch,
1776 next_protocol_version: change_epoch_v2.protocol_version.into(),
1777 validator_subsidy: protocol_config.validator_target_reward(),
1778 storage_charge: change_epoch_v2.storage_charge,
1779 computation_charge: change_epoch_v2.computation_charge,
1780 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1781 storage_rebate: change_epoch_v2.storage_rebate,
1782 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1783 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1784 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1785 max_committee_members_count: protocol_config.max_committee_members_count(),
1786 eligible_active_validators: vec![],
1789 scores: vec![],
1790 adjust_rewards_by_score: false,
1791 };
1792 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1793 advance_epoch_impl(
1794 advance_epoch_pt,
1795 params,
1796 change_epoch_v2.system_packages,
1797 temporary_store,
1798 tx_ctx,
1799 move_vm,
1800 gas_charger,
1801 protocol_config,
1802 metrics,
1803 trace_builder_opt,
1804 )
1805 }
1806
1807 fn advance_epoch_v3(
1811 builder: ProgrammableTransactionBuilder,
1812 change_epoch_v3: ChangeEpochV3,
1813 temporary_store: &mut TemporaryStore<'_>,
1814 tx_ctx: Rc<RefCell<TxContext>>,
1815 move_vm: &Arc<MoveVM>,
1816 gas_charger: &mut GasCharger,
1817 protocol_config: &ProtocolConfig,
1818 metrics: Arc<LimitsMetrics>,
1819 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1820 ) -> Result<(), ExecutionError> {
1821 let params = AdvanceEpochParams {
1822 epoch: change_epoch_v3.epoch,
1823 next_protocol_version: change_epoch_v3.protocol_version.into(),
1824 validator_subsidy: protocol_config.validator_target_reward(),
1825 storage_charge: change_epoch_v3.storage_charge,
1826 computation_charge: change_epoch_v3.computation_charge,
1827 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1828 storage_rebate: change_epoch_v3.storage_rebate,
1829 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1830 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1831 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1832 max_committee_members_count: protocol_config.max_committee_members_count(),
1833 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1834 scores: vec![],
1837 adjust_rewards_by_score: false,
1838 };
1839 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1840 advance_epoch_impl(
1841 advance_epoch_pt,
1842 params,
1843 change_epoch_v3.system_packages,
1844 temporary_store,
1845 tx_ctx,
1846 move_vm,
1847 gas_charger,
1848 protocol_config,
1849 metrics,
1850 trace_builder_opt,
1851 )
1852 }
1853
1854 fn advance_epoch_v4(
1858 builder: ProgrammableTransactionBuilder,
1859 change_epoch_v4: ChangeEpochV4,
1860 temporary_store: &mut TemporaryStore<'_>,
1861 tx_ctx: Rc<RefCell<TxContext>>,
1862 move_vm: &Arc<MoveVM>,
1863 gas_charger: &mut GasCharger,
1864 protocol_config: &ProtocolConfig,
1865 metrics: Arc<LimitsMetrics>,
1866 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1867 ) -> Result<(), ExecutionError> {
1868 let params = AdvanceEpochParams {
1869 epoch: change_epoch_v4.epoch,
1870 next_protocol_version: change_epoch_v4.protocol_version.into(),
1871 validator_subsidy: protocol_config.validator_target_reward(),
1872 storage_charge: change_epoch_v4.storage_charge,
1873 computation_charge: change_epoch_v4.computation_charge,
1874 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1875 storage_rebate: change_epoch_v4.storage_rebate,
1876 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1877 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1878 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1879 max_committee_members_count: protocol_config.max_committee_members_count(),
1880 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1881 scores: change_epoch_v4.scores,
1882 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1883 };
1884 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1885 advance_epoch_impl(
1886 advance_epoch_pt,
1887 params,
1888 change_epoch_v4.system_packages,
1889 temporary_store,
1890 tx_ctx,
1891 move_vm,
1892 gas_charger,
1893 protocol_config,
1894 metrics,
1895 trace_builder_opt,
1896 )
1897 }
1898
1899 fn process_system_packages(
1900 system_packages: Vec<SystemPackage>,
1901 temporary_store: &mut TemporaryStore<'_>,
1902 tx_ctx: Rc<RefCell<TxContext>>,
1903 move_vm: &MoveVM,
1904 gas_charger: &mut GasCharger,
1905 protocol_config: &ProtocolConfig,
1906 metrics: Arc<LimitsMetrics>,
1907 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1908 ) {
1909 let binary_config = to_binary_config(protocol_config, None);
1910 for SystemPackage {
1911 version,
1912 modules,
1913 dependencies,
1914 } in system_packages.into_iter()
1915 {
1916 let deserialized_modules: Vec<_> = modules
1917 .iter()
1918 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1919 .collect();
1920
1921 if version == OBJECT_START_VERSION {
1922 let package_id = deserialized_modules.first().unwrap().address();
1923 info!("adding new system package {package_id}");
1924
1925 let publish_pt = {
1926 let mut b = ProgrammableTransactionBuilder::new();
1927 b.command(Command::new_publish(modules, dependencies));
1928 b.finish()
1929 };
1930
1931 programmable_transactions::execution::execute::<execution_mode::System>(
1932 protocol_config,
1933 metrics.clone(),
1934 move_vm,
1935 temporary_store,
1936 tx_ctx.clone(),
1937 gas_charger,
1938 publish_pt,
1939 trace_builder_opt,
1940 )
1941 .map_err(|(e, _)| e)
1942 .expect("System Package Publish must succeed");
1943 } else {
1944 let mut new_package = Object::new_system_package(
1945 &deserialized_modules,
1946 version,
1947 dependencies,
1948 tx_ctx.borrow().digest(),
1949 );
1950
1951 info!("upgraded system package {:?}", new_package.object_ref());
1952
1953 new_package
1956 .data
1957 .as_opt_mut_package()
1958 .unwrap()
1959 .decrement_version()
1960 .expect("package version should never underflow");
1961
1962 temporary_store.upgrade_system_package(new_package);
1964 }
1965 }
1966 }
1967
1968 fn setup_consensus_commit(
1974 consensus_commit_timestamp_ms: CheckpointTimestamp,
1975 temporary_store: &mut TemporaryStore<'_>,
1976 tx_ctx: Rc<RefCell<TxContext>>,
1977 move_vm: &Arc<MoveVM>,
1978 gas_charger: &mut GasCharger,
1979 protocol_config: &ProtocolConfig,
1980 metrics: Arc<LimitsMetrics>,
1981 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1982 ) -> Result<(), ExecutionError> {
1983 let pt = {
1984 let mut builder = ProgrammableTransactionBuilder::new();
1985 let res = builder.move_call(
1986 ObjectId::FRAMEWORK,
1987 Identifier::CLOCK_MODULE,
1988 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
1989 vec![],
1990 vec![
1991 CallArg::CLOCK_MUTABLE,
1992 CallArg::pure(&consensus_commit_timestamp_ms),
1993 ],
1994 );
1995 assert_invariant!(
1996 res.is_ok(),
1997 "Unable to generate consensus_commit_prologue transaction!"
1998 );
1999 builder.finish()
2000 };
2001 programmable_transactions::execution::execute::<execution_mode::System>(
2002 protocol_config,
2003 metrics,
2004 move_vm,
2005 temporary_store,
2006 tx_ctx,
2007 gas_charger,
2008 pt,
2009 trace_builder_opt,
2010 )
2011 .map_err(|(e, _)| e)?;
2012 Ok(())
2013 }
2014
2015 fn setup_randomness_state_update(
2021 update: RandomnessStateUpdate,
2022 temporary_store: &mut TemporaryStore<'_>,
2023 tx_ctx: Rc<RefCell<TxContext>>,
2024 move_vm: &Arc<MoveVM>,
2025 gas_charger: &mut GasCharger,
2026 protocol_config: &ProtocolConfig,
2027 metrics: Arc<LimitsMetrics>,
2028 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2029 ) -> Result<(), ExecutionError> {
2030 let pt = {
2031 let mut builder = ProgrammableTransactionBuilder::new();
2032 let res = builder.move_call(
2033 ObjectId::FRAMEWORK,
2034 Identifier::RANDOM_MODULE,
2035 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
2036 vec![],
2037 vec![
2038 CallArg::Shared(SharedObjectReference::new(
2039 ObjectId::RANDOMNESS_STATE,
2040 update.randomness_obj_initial_shared_version,
2041 true,
2042 )),
2043 CallArg::pure(&update.randomness_round),
2044 CallArg::pure(&update.random_bytes),
2045 ],
2046 );
2047 assert_invariant!(
2048 res.is_ok(),
2049 "Unable to generate randomness_state_update transaction!"
2050 );
2051 builder.finish()
2052 };
2053 programmable_transactions::execution::execute::<execution_mode::System>(
2054 protocol_config,
2055 metrics,
2056 move_vm,
2057 temporary_store,
2058 tx_ctx,
2059 gas_charger,
2060 pt,
2061 trace_builder_opt,
2062 )
2063 .map_err(|(e, _)| e)?;
2064 Ok(())
2065 }
2066
2067 fn setup_transaction_deny_rules_create(
2073 mut builder: ProgrammableTransactionBuilder,
2074 ) -> Result<ProgrammableTransactionBuilder, ExecutionError> {
2075 let res = builder.move_call(
2076 ObjectId::FRAMEWORK,
2077 TRANSACTION_DENY_RULES_MODULE,
2078 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME,
2079 vec![],
2080 vec![],
2081 );
2082 assert_invariant!(
2083 res.is_ok(),
2084 "Unable to generate transaction_deny_rules create transaction!"
2085 );
2086 Ok(builder)
2087 }
2088
2089 fn setup_transaction_deny_rules_update(
2093 update: TransactionDenyRulesUpdate,
2094 temporary_store: &mut TemporaryStore<'_>,
2095 tx_ctx: Rc<RefCell<TxContext>>,
2096 move_vm: &Arc<MoveVM>,
2097 gas_charger: &mut GasCharger,
2098 protocol_config: &ProtocolConfig,
2099 metrics: Arc<LimitsMetrics>,
2100 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2101 ) -> Result<(), ExecutionError> {
2102 let pt = {
2103 let mut builder = ProgrammableTransactionBuilder::new();
2104 let res = builder.move_call(
2108 ObjectId::FRAMEWORK,
2109 TRANSACTION_DENY_RULES_MODULE,
2110 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
2111 vec![],
2112 vec![
2113 CallArg::Shared(SharedObjectReference::new(
2114 ObjectId::TRANSACTION_DENY_RULES,
2115 update.deny_rules_obj_initial_shared_version,
2116 true,
2117 )),
2118 CallArg::pure(&update.added_addresses),
2119 CallArg::pure(&update.removed_addresses),
2120 CallArg::pure(&update.added_objects),
2121 CallArg::pure(&update.removed_objects),
2122 CallArg::pure(&update.added_packages),
2123 CallArg::pure(&update.removed_packages),
2124 CallArg::pure(&update.package_publish_disabled),
2125 CallArg::pure(&update.package_upgrade_disabled),
2126 CallArg::pure(&update.shared_object_disabled),
2127 CallArg::pure(&update.user_transaction_disabled),
2128 CallArg::pure(&update.receiving_objects_disabled),
2129 CallArg::pure(&update.move_authenticator_disabled),
2130 ],
2131 );
2132 assert_invariant!(
2133 res.is_ok(),
2134 "Unable to generate transaction_deny_rules update transaction!"
2135 );
2136 builder.finish()
2137 };
2138 programmable_transactions::execution::execute::<execution_mode::System>(
2139 protocol_config,
2140 metrics,
2141 move_vm,
2142 temporary_store,
2143 tx_ctx,
2144 gas_charger,
2145 pt,
2146 trace_builder_opt,
2147 )
2148 .map(|(results, _timings)| results)
2149 .map_err(|(error, _timings)| error)
2150 }
2151
2152 fn setup_authenticator_move_call(
2159 authenticator: MoveAuthenticator,
2160 authenticator_function_ref: AuthenticatorFunctionRefV1,
2161 ) -> Result<ProgrammableTransaction, ExecutionError> {
2162 let mut builder = ProgrammableTransactionBuilder::new();
2163
2164 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
2165 args.extend(authenticator.call_args().to_owned());
2166
2167 let res = builder.move_call(
2168 authenticator_function_ref.package,
2169 Identifier::new(authenticator_function_ref.module.clone()).expect(
2170 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2171 ),
2172 Identifier::new(authenticator_function_ref.function).expect(
2173 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2174 ),
2175 authenticator.type_args().to_vec(),
2176 args,
2177 );
2178
2179 assert_invariant!(
2180 res.is_ok(),
2181 "Unable to generate an account authenticator call transaction!"
2182 );
2183
2184 Ok(builder.finish())
2185 }
2186
2187 fn resolve_sponsor(gas_data: &GasPayment, transaction_signer: &Address) -> Option<Address> {
2188 let gas_owner = gas_data.owner;
2189 if &gas_owner == transaction_signer {
2190 None
2191 } else {
2192 Some(gas_owner)
2193 }
2194 }
2195}