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, GasPayment, GenesisTransaction, Identifier,
22 MoveAuthenticator, ObjectId, ProgrammableTransaction, RandomnessStateUpdate,
23 SharedObjectReference, StructTag, SystemPackage, TransactionDenyRulesUpdate,
24 TransactionDigest, TransactionEffects, TransactionKind, TypeTag, Version,
25 gas::GasCostSummary,
26 };
27 #[cfg(msim)]
28 use iota_types::iota_system_state::advance_epoch_result_injection::maybe_modify_result;
29 use iota_types::{
30 account_abstraction::authenticator_function::{
31 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
32 AuthenticatorFunctionRefV1,
33 },
34 auth_context::{AuthContext, AuthContextData},
35 balance::{BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME},
36 base_types::TxContext,
37 clock::CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
38 committee::EpochId,
39 error::{ExecutionError, ExecutionErrorKind},
40 execution::{ExecutionResults, ExecutionResultsV1, SharedInput, is_certificate_denied},
41 execution_config_utils::to_binary_config,
42 gas::{IotaGasStatus, IotaGasStatusAPI},
43 inner_temporary_store::InnerTemporaryStore,
44 iota_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams},
45 messages_checkpoint::CheckpointTimestamp,
46 metrics::LimitsMetrics,
47 move_authenticator::MoveAuthenticatorExt,
48 object::{OBJECT_START_VERSION, Object, ObjectInner},
49 programmable_transaction_builder::ProgrammableTransactionBuilder,
50 randomness_state::RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
51 storage::{BackingStore, Storage},
52 transaction::{
53 CallArg, CancelledObjects, CheckedInputObjects, InputObjects, TransactionKindExt,
54 },
55 transaction_deny_rules::{
56 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME, TRANSACTION_DENY_RULES_MODULE,
57 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
58 },
59 };
60 use move_binary_format::CompiledModule;
61 use move_trace_format::format::MoveTraceBuilder;
62 use move_vm_runtime::move_vm::MoveVM;
63 use tracing::{info, instrument, trace, warn};
64
65 use crate::{
66 adapter::new_move_vm,
67 execution_mode::{self, ExecutionMode},
68 gas_charger::GasCharger,
69 programmable_transactions,
70 temporary_store::TemporaryStore,
71 type_layout_resolver::TypeLayoutResolver,
72 };
73
74 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
86 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
87 store: &dyn BackingStore,
88 input_objects: CheckedInputObjects,
89 gas_data: GasPayment,
90 gas_status: IotaGasStatus,
91 transaction_kind: TransactionKind,
92 transaction_signer: Address,
93 transaction_digest: TransactionDigest,
94 move_vm: &Arc<MoveVM>,
95 epoch_id: &EpochId,
96 epoch_timestamp_ms: u64,
97 protocol_config: &ProtocolConfig,
98 metrics: Arc<LimitsMetrics>,
99 enable_expensive_checks: bool,
100 certificate_deny_set: &HashSet<TransactionDigest>,
101 trace_builder_opt: &mut Option<MoveTraceBuilder>,
102 ) -> (
103 InnerTemporaryStore,
104 IotaGasStatus,
105 TransactionEffects,
106 Result<Mode::ExecutionResults, ExecutionError>,
107 ) {
108 let input_objects = input_objects.into_inner();
109 let mutable_inputs = if enable_expensive_checks {
110 input_objects.mutable_inputs().keys().copied().collect()
111 } else {
112 HashSet::new()
113 };
114 let shared_object_refs = input_objects.filter_shared_objects();
115 let receiving_objects = transaction_kind.receiving_objects();
116 let transaction_dependencies = input_objects.transaction_dependencies();
117 let contains_deleted_input = input_objects.contains_deleted_objects();
118 let cancelled_objects = input_objects.get_cancelled_objects();
119
120 let temporary_store = TemporaryStore::new(
121 store,
122 input_objects,
123 receiving_objects,
124 transaction_digest,
125 protocol_config,
126 *epoch_id,
127 );
128
129 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
130 let gas_price = gas_status.gas_price();
131 let rgp = gas_status.reference_gas_price();
132 let gas_charger = GasCharger::new(
133 transaction_digest,
134 gas_data.objects,
135 gas_status,
136 protocol_config,
137 );
138
139 let tx_ctx = TxContext::new_from_components(
140 &transaction_signer,
141 &transaction_digest,
142 epoch_id,
143 epoch_timestamp_ms,
144 rgp,
145 gas_price,
146 gas_data.budget,
147 sponsor,
148 protocol_config,
149 );
150 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
151
152 execute_transaction_to_effects_inner::<Mode>(
153 temporary_store,
154 gas_charger,
155 tx_ctx,
156 &mutable_inputs,
157 shared_object_refs,
158 transaction_dependencies,
159 contains_deleted_input,
160 cancelled_objects,
161 transaction_kind,
162 transaction_signer,
163 transaction_digest,
164 move_vm,
165 epoch_id,
166 protocol_config,
167 metrics,
168 enable_expensive_checks,
169 certificate_deny_set,
170 trace_builder_opt,
171 None,
172 )
173 }
174
175 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
178 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
179 mut temporary_store: TemporaryStore,
180 mut gas_charger: GasCharger,
181 tx_ctx: Rc<RefCell<TxContext>>,
182 mutable_inputs: &HashSet<ObjectId>,
183 shared_object_refs: Vec<SharedInput>,
184 mut transaction_dependencies: BTreeSet<TransactionDigest>,
185 contains_deleted_input: bool,
186 cancelled_objects: Option<(CancelledObjects, Version)>,
187 transaction_kind: TransactionKind,
188 transaction_signer: Address,
189 transaction_digest: TransactionDigest,
190 move_vm: &Arc<MoveVM>,
191 epoch_id: &EpochId,
192 protocol_config: &ProtocolConfig,
193 metrics: Arc<LimitsMetrics>,
194 enable_expensive_checks: bool,
195 certificate_deny_set: &HashSet<TransactionDigest>,
196 trace_builder_opt: &mut Option<MoveTraceBuilder>,
197 pre_execution_result_opt: Option<
198 Result<
199 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
200 ExecutionError,
201 >,
202 >,
203 ) -> (
204 InnerTemporaryStore,
205 IotaGasStatus,
206 TransactionEffects,
207 Result<Mode::ExecutionResults, ExecutionError>,
208 ) {
209 let is_epoch_change = transaction_kind.is_end_of_epoch();
210 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
211
212 let (gas_cost_summary, execution_result) = execute_transaction::<Mode>(
213 &mut temporary_store,
214 transaction_kind,
215 &mut gas_charger,
216 tx_ctx,
217 move_vm,
218 protocol_config,
219 metrics,
220 enable_expensive_checks,
221 deny_cert,
222 contains_deleted_input,
223 cancelled_objects,
224 trace_builder_opt,
225 pre_execution_result_opt,
226 );
227
228 let status = if let Err(error) = &execution_result {
229 elaborate_error_logs(error, transaction_digest)
230 } else {
231 ExecutionStatus::Success
232 };
233
234 #[skip_checked_arithmetic]
235 trace!(
236 tx_digest = ?transaction_digest,
237 computation_gas_cost = gas_cost_summary.computation_cost,
238 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
239 storage_gas_cost = gas_cost_summary.storage_cost,
240 storage_gas_rebate = gas_cost_summary.storage_rebate,
241 "Finished execution of transaction with status {:?}",
242 status
243 );
244
245 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
249
250 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
251 temporary_store
252 .check_ownership_invariants(
253 &transaction_signer,
254 &mut gas_charger,
255 mutable_inputs,
256 is_epoch_change,
257 )
258 .unwrap()
259 } let (inner, effects) = temporary_store.into_effects(
262 shared_object_refs,
263 &transaction_digest,
264 transaction_dependencies,
265 gas_cost_summary,
266 status,
267 &mut gas_charger,
268 *epoch_id,
269 );
270
271 (
272 inner,
273 gas_charger.into_gas_status(),
274 effects,
275 execution_result,
276 )
277 }
278
279 #[instrument(
293 name = "tx_authenticate_then_execute_to_effects",
294 level = "debug",
295 skip_all
296 )]
297 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
298 store: &dyn BackingStore,
299 protocol_config: &ProtocolConfig,
301 metrics: Arc<LimitsMetrics>,
302 enable_expensive_checks: bool,
303 certificate_deny_set: &HashSet<TransactionDigest>,
304 epoch_id: &EpochId,
306 epoch_timestamp_ms: u64,
307 gas_data: GasPayment,
309 gas_status: IotaGasStatus,
310 authenticators: Vec<(
312 MoveAuthenticator,
313 AuthenticatorFunctionRefForExecution,
314 CheckedInputObjects,
315 )>,
316 authenticator_and_transaction_input_objects: CheckedInputObjects,
317 transaction_kind: TransactionKind,
319 transaction_signer: Address,
320 transaction_digest: TransactionDigest,
321 auth_context_data: AuthContextData,
322 trace_builder_opt: &mut Option<MoveTraceBuilder>,
324 move_vm: &Arc<MoveVM>,
326 ) -> (
327 InnerTemporaryStore,
328 IotaGasStatus,
329 TransactionEffects,
330 Result<Mode::ExecutionResults, ExecutionError>,
331 ) {
332 let input_objects = authenticator_and_transaction_input_objects.into_inner();
338 let mutable_inputs = if enable_expensive_checks {
340 input_objects.mutable_inputs().keys().copied().collect()
341 } else {
342 HashSet::new()
343 };
344 let shared_object_refs = input_objects.filter_shared_objects();
346 let transaction_receiving_objects = transaction_kind.receiving_objects();
348 let transaction_dependencies = input_objects.transaction_dependencies();
350 let contains_deleted_input = input_objects.contains_deleted_objects();
353 let cancelled_objects = input_objects.get_cancelled_objects();
354
355 let mut temporary_store = TemporaryStore::new(
357 store,
358 input_objects,
359 transaction_receiving_objects,
360 transaction_digest,
361 protocol_config,
362 *epoch_id,
363 );
364
365 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
367 let gas_price = gas_status.gas_price();
368 let rgp = gas_status.reference_gas_price();
369 let mut gas_charger = GasCharger::new(
370 transaction_digest,
371 gas_data.objects,
372 gas_status,
373 protocol_config,
374 );
375
376 let tx_ctx = TxContext::new_from_components(
378 &transaction_signer,
379 &transaction_digest,
380 epoch_id,
381 epoch_timestamp_ms,
382 rgp,
383 gas_price,
384 gas_data.budget,
385 sponsor,
386 protocol_config,
387 );
388 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
389
390 let authenticators = authenticators
396 .into_iter()
397 .map(
398 |(
399 authenticator,
400 authenticator_function_ref_for_execution,
401 authenticator_input_objects,
402 )| {
403 let AuthenticatorFunctionRefForExecution {
404 authenticator_function_ref,
405 loaded_object_id,
406 loaded_object_metadata,
407 } = authenticator_function_ref_for_execution;
408
409 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
412 loaded_object_id,
413 loaded_object_metadata,
414 )]));
415
416 (
417 authenticator,
418 authenticator_function_ref,
419 authenticator_input_objects,
420 )
421 },
422 )
423 .collect::<Vec<_>>();
424
425 let authentication_execution_result = authenticators.into_iter().try_for_each(
431 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
432 match authenticator_function_ref {
433 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
434 authenticate_transaction_inner(
435 &mut temporary_store,
436 protocol_config,
437 metrics.clone(),
438 &mut gas_charger,
439 authenticator,
440 authenticator_function_ref_v1,
441 &authenticator_input_objects.into_inner(),
442 transaction_kind.clone(),
443 transaction_digest,
444 auth_context_data.clone(),
445 tx_ctx.clone(),
446 trace_builder_opt,
447 move_vm,
448 )
449 }
450 }
451 },
452 );
453
454 let authentication_execution_result =
455 report_authentication_error(authentication_execution_result, protocol_config);
456
457 execute_transaction_to_effects_inner::<Mode>(
465 temporary_store,
466 gas_charger,
467 tx_ctx,
468 &mutable_inputs,
469 shared_object_refs,
470 transaction_dependencies,
471 contains_deleted_input,
472 cancelled_objects,
473 transaction_kind,
474 transaction_signer,
475 transaction_digest,
476 move_vm,
477 epoch_id,
478 protocol_config,
479 metrics,
480 enable_expensive_checks,
481 certificate_deny_set,
482 trace_builder_opt,
483 Some(authentication_execution_result),
484 )
485 }
486
487 #[instrument(name = "tx_validate", level = "debug", skip_all)]
492 pub fn authenticate_transaction(
493 store: &dyn BackingStore,
494 protocol_config: &ProtocolConfig,
496 metrics: Arc<LimitsMetrics>,
497 epoch_id: &EpochId,
499 epoch_timestamp_ms: u64,
500 gas_data: GasPayment,
502 gas_status: IotaGasStatus,
503 authenticators: Vec<(
505 MoveAuthenticator,
506 AuthenticatorFunctionRef,
507 CheckedInputObjects,
508 )>,
509 aggregated_authenticator_input_objects: CheckedInputObjects,
510 transaction_kind: TransactionKind,
512 transaction_signer: Address,
513 transaction_digest: TransactionDigest,
514 auth_context_data: AuthContextData,
515 trace_builder_opt: &mut Option<MoveTraceBuilder>,
517 move_vm: &Arc<MoveVM>,
519 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
520 {
521 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
523 let gas_price = gas_status.gas_price();
524 let rgp = gas_status.reference_gas_price();
525 let mut gas_charger =
526 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
527
528 let tx_ctx = TxContext::new_from_components(
531 &transaction_signer,
532 &transaction_digest,
533 epoch_id,
534 epoch_timestamp_ms,
535 rgp,
536 gas_price,
537 gas_data.budget,
538 sponsor,
539 protocol_config,
540 );
541 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
542
543 let mut temporary_store = TemporaryStore::new(
544 store,
545 aggregated_authenticator_input_objects.into_inner(),
546 vec![],
547 transaction_digest,
548 protocol_config,
549 *epoch_id,
550 );
551
552 let authentication_execution_result = authenticators.into_iter().try_for_each(
554 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
555 match authenticator_function_ref {
556 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
557 authenticate_transaction_inner(
558 &mut temporary_store,
559 protocol_config,
560 metrics.clone(),
561 &mut gas_charger,
562 authenticator,
563 authenticator_function_ref_v1,
564 &authenticator_input_objects.into_inner(),
565 transaction_kind.clone(),
566 transaction_digest,
567 auth_context_data.clone(),
568 tx_ctx.clone(),
569 trace_builder_opt,
570 move_vm,
571 )
572 }
573 }
574 },
575 );
576
577 report_authentication_error(authentication_execution_result, protocol_config)
578 }
579
580 #[instrument(name = "tx_validate", level = "debug", skip_all)]
590 pub fn authenticate_transaction_inner(
591 temporary_store: &mut TemporaryStore<'_>,
592 protocol_config: &ProtocolConfig,
594 metrics: Arc<LimitsMetrics>,
595 gas_charger: &mut GasCharger,
597 authenticator: MoveAuthenticator,
599 authenticator_function_ref: AuthenticatorFunctionRefV1,
600 authenticator_input_objects: &InputObjects,
601 transaction_kind: TransactionKind,
603 transaction_digest: TransactionDigest,
604 auth_context_data: AuthContextData,
605 tx_ctx: Rc<RefCell<TxContext>>,
606 trace_builder_opt: &mut Option<MoveTraceBuilder>,
608 move_vm: &Arc<MoveVM>,
610 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
611 {
612 debug_assert!(
614 transaction_kind.is_programmable(),
615 "Only programmable transactions are allowed"
616 );
617 debug_assert!(
618 authenticator_input_objects
619 .mutable_inputs()
620 .keys()
621 .copied()
622 .collect::<HashSet<_>>()
623 .is_empty(),
624 "No mutable inputs are allowed"
625 );
626 debug_assert!(
627 authenticator.receiving_objects().is_empty(),
628 "No receiving inputs are allowed"
629 );
630
631 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
632 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
633
634 let auth_ctx = {
636 let TransactionKind::Programmable(ptb) = &transaction_kind else {
637 unreachable!("Only programmable transactions are allowed");
638 };
639 AuthContext::new_from_components(
640 authenticator.digest().into(),
641 auth_context_data.sender_auth_digest,
642 auth_context_data.sponsor_auth_digest,
643 auth_context_data
644 .sender_authenticator_function_ref
645 .and_then(Into::into),
646 auth_context_data
647 .sponsor_authenticator_function_ref
648 .and_then(Into::into),
649 ptb,
650 auth_context_data.transaction_data_bytes,
651 )
652 };
653 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
654
655 temporary_store.store_auth_context(auth_ctx);
659
660 let authentication_execution_result = execute_authenticator_move_call(
662 temporary_store,
663 authenticator,
664 authenticator_function_ref,
665 gas_charger,
666 tx_ctx,
667 move_vm,
668 protocol_config,
669 metrics,
670 false,
671 contains_deleted_input,
672 cancelled_objects,
673 trace_builder_opt,
674 );
675
676 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
678 elaborate_error_logs(error, transaction_digest)
679 } else {
680 ExecutionStatus::Success
681 };
682
683 #[skip_checked_arithmetic]
684 trace!(
685 tx_digest = ?transaction_digest,
686 computation_gas_cost = gas_charger.summary().gas_used(),
687 "Finished authenticator execution of transaction with status {:?}",
688 authentication_execution_status
689 );
690
691 authentication_execution_result
692 }
693
694 #[instrument(name = "auth_execute", level = "debug", skip_all)]
705 fn execute_authenticator_move_call(
706 temporary_store: &mut TemporaryStore<'_>,
707 authenticator: MoveAuthenticator,
708 authenticator_function_ref: AuthenticatorFunctionRefV1,
709 gas_charger: &mut GasCharger,
710 tx_ctx: Rc<RefCell<TxContext>>,
711 move_vm: &Arc<MoveVM>,
712 protocol_config: &ProtocolConfig,
713 metrics: Arc<LimitsMetrics>,
714 deny_cert: bool,
715 contains_deleted_input: bool,
716 cancelled_objects: Option<(CancelledObjects, Version)>,
717 trace_builder_opt: &mut Option<MoveTraceBuilder>,
718 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
719 {
720 run_inputs_checks(
724 protocol_config,
725 deny_cert,
726 contains_deleted_input,
727 cancelled_objects,
728 )
729 .and_then(|()| {
730 let authenticator_move_call =
731 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
732 programmable_transactions::execution::execute::<execution_mode::Authentication>(
733 protocol_config,
734 metrics.clone(),
735 move_vm,
736 temporary_store,
737 tx_ctx,
738 gas_charger,
739 authenticator_move_call,
740 trace_builder_opt,
741 )
742 .and_then(|ok_result| {
743 temporary_store.check_move_authenticator_results_consistency()?;
744 Ok(ok_result)
745 })
746 })
747 }
748
749 pub fn execute_genesis_state_update(
756 store: &dyn BackingStore,
757 protocol_config: &ProtocolConfig,
758 metrics: Arc<LimitsMetrics>,
759 move_vm: &Arc<MoveVM>,
760 tx_context: Rc<RefCell<TxContext>>,
761 input_objects: CheckedInputObjects,
762 pt: ProgrammableTransaction,
763 ) -> Result<InnerTemporaryStore, ExecutionError> {
764 let input_objects = input_objects.into_inner();
765 let tx_digest = tx_context.borrow().digest();
766
767 let mut temporary_store =
768 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
769 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
770 programmable_transactions::execution::execute::<execution_mode::Genesis>(
771 protocol_config,
772 metrics,
773 move_vm,
774 &mut temporary_store,
775 tx_context,
776 &mut gas_charger,
777 pt,
778 &mut None,
779 )?;
780 temporary_store.update_object_version_and_prev_tx();
781 Ok(temporary_store.into_inner())
782 }
783
784 #[instrument(name = "tx_execute", level = "debug", skip_all)]
793 fn execute_transaction<Mode: ExecutionMode>(
794 temporary_store: &mut TemporaryStore<'_>,
795 transaction_kind: TransactionKind,
796 gas_charger: &mut GasCharger,
797 tx_ctx: Rc<RefCell<TxContext>>,
798 move_vm: &Arc<MoveVM>,
799 protocol_config: &ProtocolConfig,
800 metrics: Arc<LimitsMetrics>,
801 enable_expensive_checks: bool,
802 deny_cert: bool,
803 contains_deleted_input: bool,
804 cancelled_objects: Option<(CancelledObjects, Version)>,
805 trace_builder_opt: &mut Option<MoveTraceBuilder>,
806 pre_execution_result_opt: Option<
807 Result<
808 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
809 ExecutionError,
810 >,
811 >,
812 ) -> (
813 GasCostSummary,
814 Result<Mode::ExecutionResults, ExecutionError>,
815 ) {
816 gas_charger.smash_gas(temporary_store);
817
818 debug_assert!(
821 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
822 "No gas charges must be applied yet"
823 );
824
825 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
826 || transaction_kind.is_end_of_epoch();
827
828 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
829
830 let tx_digest = tx_ctx.borrow().digest();
831
832 let result = gas_charger.charge_input_objects(temporary_store);
836 let mut result = result.and_then(|()| {
837 run_inputs_checks(
838 protocol_config,
839 deny_cert,
840 contains_deleted_input,
841 cancelled_objects,
842 )?;
843
844 let mut execution_result = pre_execution_result_opt.unwrap_or(Ok(())).and_then(|_| {
847 execution_loop::<Mode>(
848 temporary_store,
849 transaction_kind,
850 tx_ctx,
851 move_vm,
852 gas_charger,
853 protocol_config,
854 metrics.clone(),
855 trace_builder_opt,
856 )
857 });
858
859 let meter_check = check_meter_limit(
860 temporary_store,
861 gas_charger,
862 protocol_config,
863 metrics.clone(),
864 );
865 if let Err(e) = meter_check {
866 execution_result = Err(e);
867 }
868
869 if execution_result.is_ok() {
870 let gas_check = check_written_objects_limit(
871 temporary_store,
872 gas_charger,
873 protocol_config,
874 metrics,
875 );
876 if let Err(e) = gas_check {
877 execution_result = Err(e);
878 }
879 }
880
881 execution_result
882 });
883
884 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
885 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
894
895 if let Err(e) = run_conservation_checks::<Mode>(
896 temporary_store,
897 gas_charger,
898 tx_digest,
899 move_vm,
900 enable_expensive_checks,
901 &cost_summary,
902 is_genesis_or_epoch_change_tx,
903 advance_epoch_gas_summary,
904 ) {
905 result = Err(e);
907 }
908
909 (cost_summary, result)
910 }
911
912 fn report_authentication_error<T>(
918 authentication_execution_result: Result<T, ExecutionError>,
919 protocol_config: &ProtocolConfig,
920 ) -> Result<T, ExecutionError> {
921 if protocol_config.report_move_authentication_error() {
922 authentication_execution_result.map_err(ExecutionError::into_move_authentication_error)
923 } else {
924 authentication_execution_result
925 }
926 }
927
928 fn elaborate_error_logs(
931 execution_error: &ExecutionError,
932 transaction_digest: TransactionDigest,
933 ) -> ExecutionStatus {
934 use ExecutionErrorKind as K;
935 match execution_error.kind() {
936 K::InvariantViolation | K::VmInvariantViolation => {
937 #[skip_checked_arithmetic]
938 tracing::error!(
939 kind = ?execution_error.kind(),
940 tx_digest = ?transaction_digest,
941 "INVARIANT VIOLATION! Source: {:?}",
942 execution_error.source(),
943 );
944 }
945
946 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
947 #[skip_checked_arithmetic]
948 tracing::debug!(
949 kind = ?execution_error.kind(),
950 tx_digest = ?transaction_digest,
951 "Verification Error. Source: {:?}",
952 execution_error.source(),
953 );
954 }
955
956 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
957 #[skip_checked_arithmetic]
958 tracing::debug!(
959 kind = ?execution_error.kind(),
960 tx_digest = ?transaction_digest,
961 "Publish/Upgrade Error. Source: {:?}",
962 execution_error.source(),
963 )
964 }
965
966 _ => (),
967 };
968
969 let (status, command) = execution_error.to_execution_status();
970 ExecutionStatus::new_failure(status, command)
971 }
972
973 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
982 fn run_conservation_checks<Mode: ExecutionMode>(
983 temporary_store: &mut TemporaryStore<'_>,
984 gas_charger: &mut GasCharger,
985 tx_digest: TransactionDigest,
986 move_vm: &Arc<MoveVM>,
987 enable_expensive_checks: bool,
988 cost_summary: &GasCostSummary,
989 is_genesis_or_epoch_change_tx: bool,
990 advance_epoch_gas_summary: Option<(u64, u64)>,
991 ) -> Result<(), ExecutionError> {
992 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
993 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
994 let conservation_result = {
997 temporary_store
998 .check_iota_conserved(cost_summary)
999 .and_then(|()| {
1000 if enable_expensive_checks {
1001 let mut layout_resolver =
1004 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1005 temporary_store.check_iota_conserved_expensive(
1006 cost_summary,
1007 advance_epoch_gas_summary,
1008 &mut layout_resolver,
1009 )
1010 } else {
1011 Ok(())
1012 }
1013 })
1014 };
1015 if let Err(conservation_err) = conservation_result {
1016 result = Err(conservation_err);
1020 gas_charger.reset(temporary_store);
1021 gas_charger.charge_gas(temporary_store, &mut result);
1022 if let Err(recovery_err) = {
1024 temporary_store
1025 .check_iota_conserved(cost_summary)
1026 .and_then(|()| {
1027 if enable_expensive_checks {
1028 let mut layout_resolver =
1031 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1032 temporary_store.check_iota_conserved_expensive(
1033 cost_summary,
1034 advance_epoch_gas_summary,
1035 &mut layout_resolver,
1036 )
1037 } else {
1038 Ok(())
1039 }
1040 })
1041 } {
1042 panic!(
1046 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1047 tx_digest,
1048 recovery_err,
1049 gas_charger.summary()
1050 )
1051 }
1052 }
1053 } result
1057 }
1058
1059 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1070 fn run_inputs_checks(
1071 protocol_config: &ProtocolConfig,
1072 deny_cert: bool,
1073 contains_deleted_input: bool,
1074 cancelled_objects: Option<(CancelledObjects, Version)>,
1075 ) -> Result<(), ExecutionError> {
1076 if deny_cert {
1077 Err(ExecutionError::new(
1078 ExecutionErrorKind::CertificateDenied,
1079 None,
1080 ))
1081 } else if contains_deleted_input {
1082 Err(ExecutionError::new(
1083 ExecutionErrorKind::InputObjectDeleted,
1084 None,
1085 ))
1086 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1087 match reason {
1088 version if version.is_congested() => Err(ExecutionError::new(
1089 match cancelled_objects {
1090 CancelledObjects::GasObject => {
1094 ExecutionErrorKind::ExecutionCanceledDueToExecutionWorkerCongestion {
1095 suggested_gas_price: version
1096 .get_congested_version_suggested_gas_price()
1097 .expect(
1098 "execution-worker congestion control requires the gas \
1099 price feedback mechanism",
1100 ),
1101 }
1102 }
1103 CancelledObjects::SharedObjects(congested_objects) => {
1104 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1105 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestionV2 {
1106 congested_objects,
1107 suggested_gas_price: version
1108 .get_congested_version_suggested_gas_price()
1109 .unwrap(),
1110 }
1111 } else {
1112 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestion {
1117 congested_objects,
1118 }
1119 }
1120 }
1121 },
1122 None,
1123 )),
1124 Version::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1125 ExecutionErrorKind::ExecutionCanceledDueToRandomnessUnavailable,
1126 None,
1127 )),
1128 _ => panic!("invalid cancellation reason Version: {reason}"),
1129 }
1130 } else {
1131 Ok(())
1132 }
1133 }
1134
1135 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1140 fn check_meter_limit(
1141 temporary_store: &mut TemporaryStore<'_>,
1142 gas_charger: &mut GasCharger,
1143 protocol_config: &ProtocolConfig,
1144 metrics: Arc<LimitsMetrics>,
1145 ) -> Result<(), ExecutionError> {
1146 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1147
1148 match check_limit_by_meter!(
1153 !gas_charger.is_unmetered(),
1154 effects_estimated_size,
1155 protocol_config.max_serialized_tx_effects_size_bytes(),
1156 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1157 metrics.excessive_estimated_effects_size
1158 ) {
1159 LimitThresholdCrossed::None => Ok(()),
1160 LimitThresholdCrossed::Soft(_, limit) => {
1161 warn!(
1162 effects_estimated_size = effects_estimated_size,
1163 soft_limit = limit,
1164 "Estimated transaction effects size crossed soft limit",
1165 );
1166 Ok(())
1167 }
1168 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1169 ExecutionErrorKind::EffectsTooLarge {
1170 current_size: effects_estimated_size as u64,
1171 max_size: lim as u64,
1172 },
1173 "Transaction effects are too large",
1174 )),
1175 }
1176 }
1177
1178 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1183 fn check_written_objects_limit(
1184 temporary_store: &mut TemporaryStore<'_>,
1185 gas_charger: &mut GasCharger,
1186 protocol_config: &ProtocolConfig,
1187 metrics: Arc<LimitsMetrics>,
1188 ) -> Result<(), ExecutionError> {
1189 if let (Some(normal_lim), Some(system_lim)) = (
1190 protocol_config.max_size_written_objects_as_option(),
1191 protocol_config.max_size_written_objects_system_tx_as_option(),
1192 ) {
1193 let written_objects_size = temporary_store.written_objects_size();
1194
1195 match check_limit_by_meter!(
1196 !gas_charger.is_unmetered(),
1197 written_objects_size,
1198 normal_lim,
1199 system_lim,
1200 metrics.excessive_written_objects_size
1201 ) {
1202 LimitThresholdCrossed::None => (),
1203 LimitThresholdCrossed::Soft(_, limit) => {
1204 warn!(
1205 written_objects_size = written_objects_size,
1206 soft_limit = limit,
1207 "Written objects size crossed soft limit",
1208 )
1209 }
1210 LimitThresholdCrossed::Hard(_, lim) => {
1211 return Err(ExecutionError::new_with_source(
1212 ExecutionErrorKind::WrittenObjectsTooLarge {
1213 object_size: written_objects_size as u64,
1214 max_object_size: lim as u64,
1215 },
1216 "Written objects size crossed hard limit",
1217 ));
1218 }
1219 };
1220 }
1221
1222 Ok(())
1223 }
1224
1225 #[instrument(level = "debug", skip_all)]
1232 fn execution_loop<Mode: ExecutionMode>(
1233 temporary_store: &mut TemporaryStore<'_>,
1234 transaction_kind: TransactionKind,
1235 tx_ctx: Rc<RefCell<TxContext>>,
1236 move_vm: &Arc<MoveVM>,
1237 gas_charger: &mut GasCharger,
1238 protocol_config: &ProtocolConfig,
1239 metrics: Arc<LimitsMetrics>,
1240 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1241 ) -> Result<Mode::ExecutionResults, ExecutionError> {
1242 let result = match transaction_kind {
1243 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1244 if tx_ctx.borrow().epoch() != 0 {
1245 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1246 }
1247
1248 for genesis_object in objects {
1249 let object = ObjectInner {
1250 data: genesis_object.data,
1251 owner: genesis_object.owner,
1252 previous_transaction: tx_ctx.borrow().digest(),
1253 storage_rebate: 0,
1254 };
1255 temporary_store.create_object(object.into());
1256 }
1257
1258 temporary_store.record_execution_results(ExecutionResults::V1(
1259 ExecutionResultsV1 {
1260 user_events: events,
1261 ..Default::default()
1262 },
1263 ));
1264
1265 Ok(Mode::empty_results())
1266 }
1267 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1268 setup_consensus_commit(
1269 prologue.commit_timestamp_ms,
1270 temporary_store,
1271 tx_ctx,
1272 move_vm,
1273 gas_charger,
1274 protocol_config,
1275 metrics,
1276 trace_builder_opt,
1277 )
1278 .expect("ConsensusCommitPrologueV1 cannot fail");
1279 Ok(Mode::empty_results())
1280 }
1281 TransactionKind::Programmable(pt) => {
1282 programmable_transactions::execution::execute::<Mode>(
1283 protocol_config,
1284 metrics,
1285 move_vm,
1286 temporary_store,
1287 tx_ctx,
1288 gas_charger,
1289 pt,
1290 trace_builder_opt,
1291 )
1292 }
1293 TransactionKind::EndOfEpoch(txns) => {
1294 let mut builder = ProgrammableTransactionBuilder::new();
1298 let len = txns.len();
1299
1300 for (i, tx) in txns.into_iter().enumerate() {
1301 match tx {
1302 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1303 assert_eq!(i, len - 1);
1304 advance_epoch_v1(
1305 builder,
1306 change_epoch,
1307 temporary_store,
1308 tx_ctx,
1309 move_vm,
1310 gas_charger,
1311 protocol_config,
1312 metrics,
1313 trace_builder_opt,
1314 )?;
1315 return Ok(Mode::empty_results());
1316 }
1317 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1318 assert_eq!(i, len - 1);
1319 advance_epoch_v2(
1320 builder,
1321 change_epoch_v2,
1322 temporary_store,
1323 tx_ctx,
1324 move_vm,
1325 gas_charger,
1326 protocol_config,
1327 metrics,
1328 trace_builder_opt,
1329 )?;
1330 return Ok(Mode::empty_results());
1331 }
1332 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1333 assert_eq!(i, len - 1);
1334 advance_epoch_v3(
1335 builder,
1336 change_epoch_v3,
1337 temporary_store,
1338 tx_ctx,
1339 move_vm,
1340 gas_charger,
1341 protocol_config,
1342 metrics,
1343 trace_builder_opt,
1344 )?;
1345 return Ok(Mode::empty_results());
1346 }
1347 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1348 assert_eq!(i, len - 1);
1349 advance_epoch_v4(
1350 builder,
1351 change_epoch_v4,
1352 temporary_store,
1353 tx_ctx,
1354 move_vm,
1355 gas_charger,
1356 protocol_config,
1357 metrics,
1358 trace_builder_opt,
1359 )?;
1360 return Ok(Mode::empty_results());
1361 }
1362 EndOfEpochTransactionKind::TransactionDenyRulesCreate => {
1363 assert!(
1364 protocol_config.deny_rule_governance_on_chain(),
1365 "unexpected TransactionDenyRulesCreate: on-chain deny rule governance is not enabled"
1366 );
1367 builder = setup_transaction_deny_rules_create(builder)?;
1368 }
1369 _ => unimplemented!(
1370 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1371 ),
1372 }
1373 }
1374 unreachable!(
1375 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1376 )
1377 }
1378 #[allow(deprecated)]
1379 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1380 return Err(ExecutionError::new(
1384 ExecutionErrorKind::VmInvariantViolation,
1385 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1386 ));
1387 }
1388 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1389 setup_randomness_state_update(
1390 randomness_state_update,
1391 temporary_store,
1392 tx_ctx,
1393 move_vm,
1394 gas_charger,
1395 protocol_config,
1396 metrics,
1397 trace_builder_opt,
1398 )?;
1399 Ok(Mode::empty_results())
1400 }
1401 TransactionKind::TransactionDenyRulesUpdate(update) => {
1402 assert!(
1403 protocol_config.deny_rule_governance_on_chain(),
1404 "unexpected TransactionDenyRulesUpdate: on-chain deny rule governance is not enabled"
1405 );
1406 setup_transaction_deny_rules_update(
1407 update,
1408 temporary_store,
1409 tx_ctx,
1410 move_vm,
1411 gas_charger,
1412 protocol_config,
1413 metrics,
1414 trace_builder_opt,
1415 )?;
1416 Ok(Mode::empty_results())
1417 }
1418 _ => unimplemented!(
1419 "a new TransactionKind enum variant was added and needs to be handled"
1420 ),
1421 }?;
1422 temporary_store.check_execution_results_consistency()?;
1423 Ok(result)
1424 }
1425
1426 fn mint_epoch_rewards_in_pt(
1435 builder: &mut ProgrammableTransactionBuilder,
1436 params: &AdvanceEpochParams,
1437 ) -> (Argument, Argument) {
1438 let storage_charge_arg = builder
1440 .input(CallArg::pure(¶ms.storage_charge))
1441 .unwrap();
1442 let storage_charges = builder.programmable_move_call(
1443 ObjectId::FRAMEWORK,
1444 Identifier::BALANCE_MODULE,
1445 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1446 vec![TypeTag::from(StructTag::new_gas())],
1447 vec![storage_charge_arg],
1448 );
1449
1450 let computation_charge_arg = builder
1452 .input(CallArg::pure(¶ms.computation_charge))
1453 .unwrap();
1454 let computation_charges = builder.programmable_move_call(
1455 ObjectId::FRAMEWORK,
1456 Identifier::BALANCE_MODULE,
1457 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1458 vec![TypeTag::from(StructTag::new_gas())],
1459 vec![computation_charge_arg],
1460 );
1461 (storage_charges, computation_charges)
1462 }
1463
1464 pub fn construct_advance_epoch_pt_impl(
1472 mut builder: ProgrammableTransactionBuilder,
1473 params: &AdvanceEpochParams,
1474 call_arg_vec: Vec<CallArg>,
1475 ) -> Result<ProgrammableTransaction, ExecutionError> {
1476 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1478 let mut arguments = vec![
1479 builder
1480 .pure(params.validator_subsidy)
1481 .expect("bcs encoding a u64 should not fail"),
1482 storage_charges,
1483 computation_charges,
1484 ];
1485
1486 let call_arg_arguments = call_arg_vec
1487 .into_iter()
1488 .map(|a| builder.input(a))
1489 .collect::<Result<_, _>>();
1490
1491 assert_invariant!(
1492 call_arg_arguments.is_ok(),
1493 "Unable to generate args for advance_epoch transaction!"
1494 );
1495
1496 arguments.append(&mut call_arg_arguments.unwrap());
1497
1498 info!("Call arguments to advance_epoch transaction: {:?}", params);
1499
1500 let storage_rebates = builder.programmable_move_call(
1501 ObjectId::SYSTEM,
1502 Identifier::IOTA_SYSTEM_MODULE,
1503 ADVANCE_EPOCH_FUNCTION_NAME,
1504 vec![],
1505 arguments,
1506 );
1507
1508 builder.programmable_move_call(
1510 ObjectId::FRAMEWORK,
1511 Identifier::BALANCE_MODULE,
1512 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1513 vec![TypeTag::from(StructTag::new_gas())],
1514 vec![storage_rebates],
1515 );
1516 Ok(builder.finish())
1517 }
1518
1519 pub fn construct_advance_epoch_pt_v1(
1520 builder: ProgrammableTransactionBuilder,
1521 params: &AdvanceEpochParams,
1522 ) -> Result<ProgrammableTransaction, ExecutionError> {
1523 let call_arg_vec = vec![
1528 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), ];
1536 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1537 }
1538
1539 pub fn construct_advance_epoch_pt_v2(
1540 builder: ProgrammableTransactionBuilder,
1541 params: &AdvanceEpochParams,
1542 ) -> Result<ProgrammableTransaction, ExecutionError> {
1543 let call_arg_vec = vec![
1548 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), ];
1558 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1559 }
1560
1561 pub fn construct_advance_epoch_pt_v3(
1562 builder: ProgrammableTransactionBuilder,
1563 params: &AdvanceEpochParams,
1564 ) -> Result<ProgrammableTransaction, ExecutionError> {
1565 let call_arg_vec = vec![
1571 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), ];
1583 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1584 }
1585
1586 pub fn construct_advance_epoch_pt_v4(
1587 builder: ProgrammableTransactionBuilder,
1588 params: &AdvanceEpochParams,
1589 ) -> Result<ProgrammableTransaction, ExecutionError> {
1590 let call_arg_vec = vec![
1596 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), ];
1610 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1611 }
1612
1613 fn advance_epoch_impl(
1620 advance_epoch_pt: ProgrammableTransaction,
1621 params: AdvanceEpochParams,
1622 system_packages: Vec<SystemPackage>,
1623 temporary_store: &mut TemporaryStore<'_>,
1624 tx_ctx: Rc<RefCell<TxContext>>,
1625 move_vm: &Arc<MoveVM>,
1626 gas_charger: &mut GasCharger,
1627 protocol_config: &ProtocolConfig,
1628 metrics: Arc<LimitsMetrics>,
1629 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1630 ) -> Result<(), ExecutionError> {
1631 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1632 protocol_config,
1633 metrics.clone(),
1634 move_vm,
1635 temporary_store,
1636 tx_ctx.clone(),
1637 gas_charger,
1638 advance_epoch_pt,
1639 trace_builder_opt,
1640 );
1641
1642 #[cfg(msim)]
1643 let result = maybe_modify_result(result, params.epoch);
1644
1645 if result.is_err() {
1646 tracing::error!(
1647 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1648 result.as_ref().err(),
1649 temporary_store.objects(),
1650 params,
1651 );
1652 temporary_store.drop_writes();
1653 gas_charger.reset_storage_cost_and_rebate();
1655
1656 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1657 }
1658
1659 let new_vm = new_move_vm(
1660 all_natives(true, protocol_config),
1661 protocol_config,
1662 None,
1664 )
1665 .expect("Failed to create new MoveVM");
1666 process_system_packages(
1667 system_packages,
1668 temporary_store,
1669 tx_ctx,
1670 &new_vm,
1671 gas_charger,
1672 protocol_config,
1673 metrics,
1674 trace_builder_opt,
1675 );
1676
1677 Ok(())
1678 }
1679
1680 fn advance_epoch_v1(
1684 builder: ProgrammableTransactionBuilder,
1685 change_epoch: ChangeEpoch,
1686 temporary_store: &mut TemporaryStore<'_>,
1687 tx_ctx: Rc<RefCell<TxContext>>,
1688 move_vm: &Arc<MoveVM>,
1689 gas_charger: &mut GasCharger,
1690 protocol_config: &ProtocolConfig,
1691 metrics: Arc<LimitsMetrics>,
1692 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1693 ) -> Result<(), ExecutionError> {
1694 let params = AdvanceEpochParams {
1695 epoch: change_epoch.epoch,
1696 next_protocol_version: change_epoch.protocol_version.into(),
1697 validator_subsidy: protocol_config.validator_target_reward(),
1698 storage_charge: change_epoch.storage_charge,
1699 computation_charge: change_epoch.computation_charge,
1700 computation_charge_burned: change_epoch.computation_charge,
1702 storage_rebate: change_epoch.storage_rebate,
1703 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1704 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1705 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1706 max_committee_members_count: 0,
1709 eligible_active_validators: vec![],
1710 scores: vec![],
1711 adjust_rewards_by_score: false,
1712 };
1713 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1714 advance_epoch_impl(
1715 advance_epoch_pt,
1716 params,
1717 change_epoch.system_packages,
1718 temporary_store,
1719 tx_ctx,
1720 move_vm,
1721 gas_charger,
1722 protocol_config,
1723 metrics,
1724 trace_builder_opt,
1725 )
1726 }
1727
1728 fn advance_epoch_v2(
1732 builder: ProgrammableTransactionBuilder,
1733 change_epoch_v2: ChangeEpochV2,
1734 temporary_store: &mut TemporaryStore<'_>,
1735 tx_ctx: Rc<RefCell<TxContext>>,
1736 move_vm: &Arc<MoveVM>,
1737 gas_charger: &mut GasCharger,
1738 protocol_config: &ProtocolConfig,
1739 metrics: Arc<LimitsMetrics>,
1740 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1741 ) -> Result<(), ExecutionError> {
1742 let params = AdvanceEpochParams {
1743 epoch: change_epoch_v2.epoch,
1744 next_protocol_version: change_epoch_v2.protocol_version.into(),
1745 validator_subsidy: protocol_config.validator_target_reward(),
1746 storage_charge: change_epoch_v2.storage_charge,
1747 computation_charge: change_epoch_v2.computation_charge,
1748 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1749 storage_rebate: change_epoch_v2.storage_rebate,
1750 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1751 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1752 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1753 max_committee_members_count: protocol_config.max_committee_members_count(),
1754 eligible_active_validators: vec![],
1757 scores: vec![],
1758 adjust_rewards_by_score: false,
1759 };
1760 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1761 advance_epoch_impl(
1762 advance_epoch_pt,
1763 params,
1764 change_epoch_v2.system_packages,
1765 temporary_store,
1766 tx_ctx,
1767 move_vm,
1768 gas_charger,
1769 protocol_config,
1770 metrics,
1771 trace_builder_opt,
1772 )
1773 }
1774
1775 fn advance_epoch_v3(
1779 builder: ProgrammableTransactionBuilder,
1780 change_epoch_v3: ChangeEpochV3,
1781 temporary_store: &mut TemporaryStore<'_>,
1782 tx_ctx: Rc<RefCell<TxContext>>,
1783 move_vm: &Arc<MoveVM>,
1784 gas_charger: &mut GasCharger,
1785 protocol_config: &ProtocolConfig,
1786 metrics: Arc<LimitsMetrics>,
1787 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1788 ) -> Result<(), ExecutionError> {
1789 let params = AdvanceEpochParams {
1790 epoch: change_epoch_v3.epoch,
1791 next_protocol_version: change_epoch_v3.protocol_version.into(),
1792 validator_subsidy: protocol_config.validator_target_reward(),
1793 storage_charge: change_epoch_v3.storage_charge,
1794 computation_charge: change_epoch_v3.computation_charge,
1795 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1796 storage_rebate: change_epoch_v3.storage_rebate,
1797 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1798 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1799 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1800 max_committee_members_count: protocol_config.max_committee_members_count(),
1801 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1802 scores: vec![],
1805 adjust_rewards_by_score: false,
1806 };
1807 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1808 advance_epoch_impl(
1809 advance_epoch_pt,
1810 params,
1811 change_epoch_v3.system_packages,
1812 temporary_store,
1813 tx_ctx,
1814 move_vm,
1815 gas_charger,
1816 protocol_config,
1817 metrics,
1818 trace_builder_opt,
1819 )
1820 }
1821
1822 fn advance_epoch_v4(
1826 builder: ProgrammableTransactionBuilder,
1827 change_epoch_v4: ChangeEpochV4,
1828 temporary_store: &mut TemporaryStore<'_>,
1829 tx_ctx: Rc<RefCell<TxContext>>,
1830 move_vm: &Arc<MoveVM>,
1831 gas_charger: &mut GasCharger,
1832 protocol_config: &ProtocolConfig,
1833 metrics: Arc<LimitsMetrics>,
1834 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1835 ) -> Result<(), ExecutionError> {
1836 let params = AdvanceEpochParams {
1837 epoch: change_epoch_v4.epoch,
1838 next_protocol_version: change_epoch_v4.protocol_version.into(),
1839 validator_subsidy: protocol_config.validator_target_reward(),
1840 storage_charge: change_epoch_v4.storage_charge,
1841 computation_charge: change_epoch_v4.computation_charge,
1842 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1843 storage_rebate: change_epoch_v4.storage_rebate,
1844 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1845 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1846 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1847 max_committee_members_count: protocol_config.max_committee_members_count(),
1848 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1849 scores: change_epoch_v4.scores,
1850 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1851 };
1852 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1853 advance_epoch_impl(
1854 advance_epoch_pt,
1855 params,
1856 change_epoch_v4.system_packages,
1857 temporary_store,
1858 tx_ctx,
1859 move_vm,
1860 gas_charger,
1861 protocol_config,
1862 metrics,
1863 trace_builder_opt,
1864 )
1865 }
1866
1867 fn process_system_packages(
1868 system_packages: Vec<SystemPackage>,
1869 temporary_store: &mut TemporaryStore<'_>,
1870 tx_ctx: Rc<RefCell<TxContext>>,
1871 move_vm: &MoveVM,
1872 gas_charger: &mut GasCharger,
1873 protocol_config: &ProtocolConfig,
1874 metrics: Arc<LimitsMetrics>,
1875 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1876 ) {
1877 let binary_config = to_binary_config(protocol_config);
1878 for SystemPackage {
1879 version,
1880 modules,
1881 dependencies,
1882 } in system_packages.into_iter()
1883 {
1884 let deserialized_modules: Vec<_> = modules
1885 .iter()
1886 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1887 .collect();
1888
1889 if version == OBJECT_START_VERSION {
1890 let package_id = deserialized_modules.first().unwrap().address();
1891 info!("adding new system package {package_id}");
1892
1893 let publish_pt = {
1894 let mut b = ProgrammableTransactionBuilder::new();
1895 b.command(Command::new_publish(modules, dependencies));
1896 b.finish()
1897 };
1898
1899 programmable_transactions::execution::execute::<execution_mode::System>(
1900 protocol_config,
1901 metrics.clone(),
1902 move_vm,
1903 temporary_store,
1904 tx_ctx.clone(),
1905 gas_charger,
1906 publish_pt,
1907 trace_builder_opt,
1908 )
1909 .expect("System Package Publish must succeed");
1910 } else {
1911 let mut new_package = Object::new_system_package(
1912 &deserialized_modules,
1913 version,
1914 dependencies,
1915 tx_ctx.borrow().digest(),
1916 );
1917
1918 info!("upgraded system package {:?}", new_package.object_ref());
1919
1920 new_package
1923 .data
1924 .as_opt_mut_package()
1925 .unwrap()
1926 .decrement_version()
1927 .expect("package version should never underflow");
1928
1929 temporary_store.upgrade_system_package(new_package);
1931 }
1932 }
1933 }
1934
1935 fn setup_consensus_commit(
1941 consensus_commit_timestamp_ms: CheckpointTimestamp,
1942 temporary_store: &mut TemporaryStore<'_>,
1943 tx_ctx: Rc<RefCell<TxContext>>,
1944 move_vm: &Arc<MoveVM>,
1945 gas_charger: &mut GasCharger,
1946 protocol_config: &ProtocolConfig,
1947 metrics: Arc<LimitsMetrics>,
1948 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1949 ) -> Result<(), ExecutionError> {
1950 let pt = {
1951 let mut builder = ProgrammableTransactionBuilder::new();
1952 let res = builder.move_call(
1953 ObjectId::FRAMEWORK,
1954 Identifier::CLOCK_MODULE,
1955 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
1956 vec![],
1957 vec![
1958 CallArg::CLOCK_MUTABLE,
1959 CallArg::pure(&consensus_commit_timestamp_ms),
1960 ],
1961 );
1962 assert_invariant!(
1963 res.is_ok(),
1964 "Unable to generate consensus_commit_prologue transaction!"
1965 );
1966 builder.finish()
1967 };
1968 programmable_transactions::execution::execute::<execution_mode::System>(
1969 protocol_config,
1970 metrics,
1971 move_vm,
1972 temporary_store,
1973 tx_ctx,
1974 gas_charger,
1975 pt,
1976 trace_builder_opt,
1977 )
1978 }
1979
1980 fn setup_randomness_state_update(
1986 update: RandomnessStateUpdate,
1987 temporary_store: &mut TemporaryStore<'_>,
1988 tx_ctx: Rc<RefCell<TxContext>>,
1989 move_vm: &Arc<MoveVM>,
1990 gas_charger: &mut GasCharger,
1991 protocol_config: &ProtocolConfig,
1992 metrics: Arc<LimitsMetrics>,
1993 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1994 ) -> Result<(), ExecutionError> {
1995 let pt = {
1996 let mut builder = ProgrammableTransactionBuilder::new();
1997 let res = builder.move_call(
1998 ObjectId::FRAMEWORK,
1999 Identifier::RANDOM_MODULE,
2000 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
2001 vec![],
2002 vec![
2003 CallArg::Shared(SharedObjectReference::new(
2004 ObjectId::RANDOMNESS_STATE,
2005 update.randomness_obj_initial_shared_version,
2006 true,
2007 )),
2008 CallArg::pure(&update.randomness_round),
2009 CallArg::pure(&update.random_bytes),
2010 ],
2011 );
2012 assert_invariant!(
2013 res.is_ok(),
2014 "Unable to generate randomness_state_update transaction!"
2015 );
2016 builder.finish()
2017 };
2018 programmable_transactions::execution::execute::<execution_mode::System>(
2019 protocol_config,
2020 metrics,
2021 move_vm,
2022 temporary_store,
2023 tx_ctx,
2024 gas_charger,
2025 pt,
2026 trace_builder_opt,
2027 )
2028 }
2029
2030 fn setup_transaction_deny_rules_create(
2036 mut builder: ProgrammableTransactionBuilder,
2037 ) -> Result<ProgrammableTransactionBuilder, ExecutionError> {
2038 let res = builder.move_call(
2039 ObjectId::FRAMEWORK,
2040 TRANSACTION_DENY_RULES_MODULE,
2041 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME,
2042 vec![],
2043 vec![],
2044 );
2045 assert_invariant!(
2046 res.is_ok(),
2047 "Unable to generate transaction_deny_rules create transaction!"
2048 );
2049 Ok(builder)
2050 }
2051
2052 fn setup_transaction_deny_rules_update(
2056 update: TransactionDenyRulesUpdate,
2057 temporary_store: &mut TemporaryStore<'_>,
2058 tx_ctx: Rc<RefCell<TxContext>>,
2059 move_vm: &Arc<MoveVM>,
2060 gas_charger: &mut GasCharger,
2061 protocol_config: &ProtocolConfig,
2062 metrics: Arc<LimitsMetrics>,
2063 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2064 ) -> Result<(), ExecutionError> {
2065 let pt = {
2066 let mut builder = ProgrammableTransactionBuilder::new();
2067 let res = builder.move_call(
2071 ObjectId::FRAMEWORK,
2072 TRANSACTION_DENY_RULES_MODULE,
2073 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
2074 vec![],
2075 vec![
2076 CallArg::Shared(SharedObjectReference::new(
2077 ObjectId::TRANSACTION_DENY_RULES,
2078 update.deny_rules_obj_initial_shared_version,
2079 true,
2080 )),
2081 CallArg::pure(&update.added_addresses),
2082 CallArg::pure(&update.removed_addresses),
2083 CallArg::pure(&update.added_objects),
2084 CallArg::pure(&update.removed_objects),
2085 CallArg::pure(&update.added_packages),
2086 CallArg::pure(&update.removed_packages),
2087 CallArg::pure(&update.package_publish_disabled),
2088 CallArg::pure(&update.package_upgrade_disabled),
2089 CallArg::pure(&update.shared_object_disabled),
2090 CallArg::pure(&update.user_transaction_disabled),
2091 CallArg::pure(&update.receiving_objects_disabled),
2092 CallArg::pure(&update.move_authenticator_disabled),
2093 ],
2094 );
2095 assert_invariant!(
2096 res.is_ok(),
2097 "Unable to generate transaction_deny_rules update transaction!"
2098 );
2099 builder.finish()
2100 };
2101 programmable_transactions::execution::execute::<execution_mode::System>(
2102 protocol_config,
2103 metrics,
2104 move_vm,
2105 temporary_store,
2106 tx_ctx,
2107 gas_charger,
2108 pt,
2109 trace_builder_opt,
2110 )
2111 }
2112
2113 fn setup_authenticator_move_call(
2120 authenticator: MoveAuthenticator,
2121 authenticator_function_ref: AuthenticatorFunctionRefV1,
2122 ) -> Result<ProgrammableTransaction, ExecutionError> {
2123 let mut builder = ProgrammableTransactionBuilder::new();
2124
2125 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
2126 args.extend(authenticator.call_args().to_owned());
2127
2128 let res = builder.move_call(
2129 authenticator_function_ref.package,
2130 Identifier::new(authenticator_function_ref.module.clone()).expect(
2131 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2132 ),
2133 Identifier::new(authenticator_function_ref.function).expect(
2134 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2135 ),
2136 authenticator.type_args().to_vec(),
2137 args,
2138 );
2139
2140 assert_invariant!(
2141 res.is_ok(),
2142 "Unable to generate an account authenticator call transaction!"
2143 );
2144
2145 Ok(builder.finish())
2146 }
2147
2148 fn resolve_sponsor(gas_data: &GasPayment, transaction_signer: &Address) -> Option<Address> {
2149 let gas_owner = gas_data.owner;
2150 if &gas_owner == transaction_signer {
2151 None
2152 } else {
2153 Some(gas_owner)
2154 }
2155 }
2156}