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