1pub use checked::*;
6
7#[iota_macros::with_checked_arithmetic]
8mod checked {
9
10 use std::{
11 cell::RefCell,
12 collections::{BTreeMap, BTreeSet, HashSet},
13 rc::Rc,
14 sync::Arc,
15 };
16
17 use iota_move_natives::all_natives;
18 use iota_protocol_config::{LimitThresholdCrossed, ProtocolConfig, check_limit_by_meter};
19 use iota_sdk_types::{
20 Address, Argument, ChangeEpoch, ChangeEpochV2, ChangeEpochV3, ChangeEpochV4, Command,
21 EndOfEpochTransactionKind, ExecutionStatus, GasCostSummary, GasPayment, GenesisTransaction,
22 Identifier, MoveAuthenticator, ObjectId, ProgrammableTransaction, RandomnessStateUpdate,
23 SharedObjectReference, StructTag, SystemPackage, TransactionDenyRulesUpdate,
24 TransactionDigest, TransactionEffects, TransactionKind, TypeTag, Version,
25 };
26 #[cfg(msim)]
27 use iota_types::iota_system_state::advance_epoch_result_injection::maybe_modify_result;
28 use iota_types::{
29 account_abstraction::authenticator_function::{
30 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
31 AuthenticatorFunctionRefV1, MoveAuthenticatorForExecution,
32 MoveAuthenticatorsForExecution,
33 },
34 auth_context::{AuthContext, AuthContextData},
35 balance::{BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME},
36 base_types::TxContext,
37 clock::CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
38 committee::EpochId,
39 error::{ExecutionError, ExecutionErrorKind},
40 execution::{
41 AuthenticateThenExecuteOutput, ExecutionResults, ExecutionResultsV1, ExecutionTiming,
42 ResultWithTimings, SharedInput, is_any_invariant_violation, is_cancellation,
43 is_certificate_denied, unwrap_move_authentication_error,
44 },
45 execution_config_utils::to_binary_config,
46 gas::{IotaGasStatus, IotaGasStatusAPI},
47 inner_temporary_store::InnerTemporaryStore,
48 iota_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams},
49 messages_checkpoint::CheckpointTimestamp,
50 metrics::LimitsMetrics,
51 move_authenticator::MoveAuthenticatorExt,
52 object::{OBJECT_START_VERSION, Object, ObjectInner},
53 programmable_transaction_builder::ProgrammableTransactionBuilder,
54 randomness_state::RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
55 storage::{BackingStore, Storage},
56 transaction::{
57 CallArg, CancelledObjects, CheckedInputObjects, InputObjects, TransactionKindExt,
58 },
59 transaction_deny_rules::{
60 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME, TRANSACTION_DENY_RULES_MODULE,
61 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
62 },
63 };
64 use move_binary_format::CompiledModule;
65 use move_trace_format::format::MoveTraceBuilder;
66 use move_vm_runtime::move_vm::MoveVM;
67 use tracing::{info, instrument, trace, warn};
68
69 use crate::{
70 adapter::new_move_vm,
71 execution_mode::{self, ExecutionMode},
72 gas_charger::GasCharger,
73 programmable_transactions,
74 temporary_store::TemporaryStore,
75 type_layout_resolver::TypeLayoutResolver,
76 };
77
78 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
90 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
91 store: &dyn BackingStore,
92 input_objects: CheckedInputObjects,
93 gas_data: GasPayment,
94 gas_status: IotaGasStatus,
95 transaction_kind: TransactionKind,
96 transaction_signer: Address,
97 transaction_digest: TransactionDigest,
98 move_vm: &Arc<MoveVM>,
99 epoch_id: &EpochId,
100 epoch_timestamp_ms: u64,
101 protocol_config: &ProtocolConfig,
102 metrics: Arc<LimitsMetrics>,
103 enable_expensive_checks: bool,
104 certificate_deny_set: &HashSet<TransactionDigest>,
105 trace_builder_opt: &mut Option<MoveTraceBuilder>,
106 ) -> (
107 InnerTemporaryStore,
108 IotaGasStatus,
109 TransactionEffects,
110 Vec<ExecutionTiming>,
111 Result<Mode::ExecutionResults, ExecutionError>,
112 ) {
113 let input_objects = input_objects.into_inner();
114 let mutable_inputs = if enable_expensive_checks {
115 input_objects.mutable_inputs().keys().copied().collect()
116 } else {
117 HashSet::new()
118 };
119 let shared_object_refs = input_objects.filter_shared_objects();
120 let receiving_objects = transaction_kind.receiving_objects();
121 let transaction_dependencies = input_objects.transaction_dependencies();
122 let contains_deleted_input = input_objects.contains_deleted_objects();
123 let cancelled_objects = input_objects.get_cancelled_objects();
124
125 let temporary_store = TemporaryStore::new(
126 store,
127 input_objects,
128 receiving_objects,
129 transaction_digest,
130 protocol_config,
131 *epoch_id,
132 );
133
134 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
135 let gas_price = gas_status.gas_price();
136 let rgp = gas_status.reference_gas_price();
137 let gas_charger = GasCharger::new(
138 transaction_digest,
139 gas_data.objects,
140 gas_status,
141 protocol_config,
142 );
143
144 let tx_ctx = TxContext::new_from_components(
145 &transaction_signer,
146 &transaction_digest,
147 epoch_id,
148 epoch_timestamp_ms,
149 rgp,
150 gas_price,
151 gas_data.budget,
152 sponsor,
153 protocol_config,
154 );
155 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
156
157 execute_transaction_to_effects_inner::<Mode>(
158 temporary_store,
159 gas_charger,
160 tx_ctx,
161 &mutable_inputs,
162 shared_object_refs,
163 transaction_dependencies,
164 contains_deleted_input,
165 cancelled_objects,
166 transaction_kind,
167 transaction_signer,
168 transaction_digest,
169 move_vm,
170 epoch_id,
171 protocol_config,
172 metrics,
173 enable_expensive_checks,
174 certificate_deny_set,
175 trace_builder_opt,
176 None,
177 )
178 }
179
180 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
183 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
184 mut temporary_store: TemporaryStore,
185 mut gas_charger: GasCharger,
186 tx_ctx: Rc<RefCell<TxContext>>,
187 mutable_inputs: &HashSet<ObjectId>,
188 shared_object_refs: Vec<SharedInput>,
189 mut transaction_dependencies: BTreeSet<TransactionDigest>,
190 contains_deleted_input: bool,
191 cancelled_objects: Option<(CancelledObjects, Version)>,
192 transaction_kind: TransactionKind,
193 transaction_signer: Address,
194 transaction_digest: TransactionDigest,
195 move_vm: &Arc<MoveVM>,
196 epoch_id: &EpochId,
197 protocol_config: &ProtocolConfig,
198 metrics: Arc<LimitsMetrics>,
199 enable_expensive_checks: bool,
200 certificate_deny_set: &HashSet<TransactionDigest>,
201 trace_builder_opt: &mut Option<MoveTraceBuilder>,
202 pre_execution_result_opt: Option<
203 Result<
204 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
205 ExecutionError,
206 >,
207 >,
208 ) -> (
209 InnerTemporaryStore,
210 IotaGasStatus,
211 TransactionEffects,
212 Vec<ExecutionTiming>,
213 Result<Mode::ExecutionResults, ExecutionError>,
214 ) {
215 let is_epoch_change = transaction_kind.is_end_of_epoch();
216 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
217
218 let (gas_cost_summary, execution_result, timings) = execute_transaction::<Mode>(
219 &mut temporary_store,
220 transaction_kind,
221 &mut gas_charger,
222 tx_ctx,
223 move_vm,
224 protocol_config,
225 metrics,
226 enable_expensive_checks,
227 deny_cert,
228 contains_deleted_input,
229 cancelled_objects,
230 trace_builder_opt,
231 pre_execution_result_opt,
232 );
233
234 let status = if let Err(error) = &execution_result {
235 elaborate_error_logs(error, transaction_digest)
236 } else {
237 ExecutionStatus::Success
238 };
239
240 #[skip_checked_arithmetic]
241 trace!(
242 tx_digest = ?transaction_digest,
243 computation_gas_cost = gas_cost_summary.computation_cost,
244 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
245 storage_gas_cost = gas_cost_summary.storage_cost,
246 storage_gas_rebate = gas_cost_summary.storage_rebate,
247 "Finished execution of transaction with status {:?}",
248 status
249 );
250
251 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
255
256 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
257 temporary_store
258 .check_ownership_invariants(
259 &transaction_signer,
260 &mut gas_charger,
261 mutable_inputs,
262 is_epoch_change,
263 )
264 .unwrap()
265 } let (inner, effects) = temporary_store.into_effects(
268 shared_object_refs,
269 &transaction_digest,
270 transaction_dependencies,
271 gas_cost_summary,
272 status,
273 &mut gas_charger,
274 *epoch_id,
275 );
276
277 (
278 inner,
279 gas_charger.into_gas_status(),
280 effects,
281 timings,
282 execution_result,
283 )
284 }
285
286 #[instrument(
307 name = "tx_authenticate_then_execute_to_effects",
308 level = "debug",
309 skip_all
310 )]
311 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
312 store: &dyn BackingStore,
313 protocol_config: &ProtocolConfig,
315 metrics: Arc<LimitsMetrics>,
316 enable_expensive_checks: bool,
317 certificate_deny_set: &HashSet<TransactionDigest>,
318 epoch_id: &EpochId,
320 epoch_timestamp_ms: u64,
321 gas_data: GasPayment,
323 gas_status: IotaGasStatus,
324 authenticators: MoveAuthenticatorsForExecution,
326 authenticator_and_transaction_input_objects: CheckedInputObjects,
327 gas_owner_pays: Option<&dyn Fn(&ExecutionErrorKind) -> bool>,
328 transaction_kind: TransactionKind,
330 transaction_signer: Address,
331 transaction_digest: TransactionDigest,
332 auth_context_data: AuthContextData,
333 trace_builder_opt: &mut Option<MoveTraceBuilder>,
335 move_vm: &Arc<MoveVM>,
337 ) -> AuthenticateThenExecuteOutput<Mode::ExecutionResults> {
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 mut 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_owner = gas_data.owner;
374 let gas_price = gas_status.gas_price();
375 let rgp = gas_status.reference_gas_price();
376 let mut gas_charger = GasCharger::new(
377 transaction_digest,
378 gas_data.objects,
379 gas_status,
380 protocol_config,
381 );
382
383 let tx_ctx = TxContext::new_from_components(
385 &transaction_signer,
386 &transaction_digest,
387 epoch_id,
388 epoch_timestamp_ms,
389 rgp,
390 gas_price,
391 gas_data.budget,
392 sponsor,
393 protocol_config,
394 );
395 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
396
397 let enable_pcool = protocol_config.enable_pcool_flow();
398 let run_authenticator =
399 |temporary_store: &mut TemporaryStore<'_>,
400 gas_charger: &mut GasCharger,
401 trace_builder_opt: &mut Option<MoveTraceBuilder>,
402 authenticator: MoveAuthenticator,
403 authenticator_function_ref: AuthenticatorFunctionRef,
404 authenticator_input_objects: CheckedInputObjects| {
405 match authenticator_function_ref {
406 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
407 authenticate_transaction_inner(
408 temporary_store,
409 protocol_config,
410 metrics.clone(),
411 gas_charger,
412 authenticator,
413 authenticator_function_ref_v1,
414 &authenticator_input_objects.into_inner(),
415 transaction_kind.clone(),
416 transaction_digest,
417 auth_context_data.clone(),
418 tx_ctx.clone(),
419 trace_builder_opt,
420 move_vm,
421 )
422 }
423 }
424 };
425
426 let cancellation_check =
432 run_inputs_checks(protocol_config, false, false, cancelled_objects.take());
433
434 let (authentication_execution_result, gas_owner_authorized) = match cancellation_check {
448 Err(error) => {
451 let gas_owner_authorized = match &authenticators {
452 MoveAuthenticatorsForExecution::ResolutionFailed { accounts, .. } => {
453 !accounts.contains(&gas_owner)
454 }
455 MoveAuthenticatorsForExecution::Resolved(authenticators) => !authenticators
456 .iter()
457 .any(|authenticator| authenticator.authenticator.address() == gas_owner),
458 };
459 (Err(error), gas_owner_authorized)
460 }
461 Ok(()) => {
462 let (authentication_result, gas_owner_authorized) = match authenticators {
463 MoveAuthenticatorsForExecution::ResolutionFailed {
464 error,
465 accounts,
466 gas_owner: gas_owner_authenticator,
467 } => {
468 if !accounts.contains(&gas_owner) {
469 (Err(error), true)
470 } else {
471 match gas_owner_authenticator
472 .filter(|_| enable_pcool)
473 .map(|gas_owner_authenticator| *gas_owner_authenticator)
474 {
475 Some(MoveAuthenticatorForExecution {
476 authenticator,
477 function_ref,
478 input_objects: authenticator_input_objects,
479 }) => {
480 let AuthenticatorFunctionRefForExecution {
481 authenticator_function_ref,
482 loaded_object_id,
483 loaded_object_metadata,
484 } = function_ref;
485 temporary_store.save_loaded_runtime_objects(BTreeMap::from([
486 (loaded_object_id, loaded_object_metadata),
487 ]));
488 match run_authenticator(
489 &mut temporary_store,
490 &mut gas_charger,
491 trace_builder_opt,
492 authenticator,
493 authenticator_function_ref,
494 authenticator_input_objects,
495 ) {
496 Ok(()) => (Err(error), true),
497 Err(gas_owner_error) => (Err(gas_owner_error), false),
498 }
499 }
500 None => (Err(error), false),
501 }
502 }
503 }
504 MoveAuthenticatorsForExecution::Resolved(authenticators) => {
505 let mut authenticators = authenticators
511 .into_iter()
512 .map(
513 |MoveAuthenticatorForExecution {
514 authenticator,
515 function_ref,
516 input_objects: authenticator_input_objects,
517 }| {
518 let AuthenticatorFunctionRefForExecution {
519 authenticator_function_ref,
520 loaded_object_id,
521 loaded_object_metadata,
522 } = function_ref;
523
524 temporary_store.save_loaded_runtime_objects(BTreeMap::from([
528 (loaded_object_id, loaded_object_metadata),
529 ]));
530
531 (
532 authenticator,
533 authenticator_function_ref,
534 authenticator_input_objects,
535 )
536 },
537 )
538 .collect::<Vec<_>>();
539
540 if enable_pcool {
541 if let Some(position) =
542 authenticators.iter().position(|(authenticator, ..)| {
543 authenticator.address() == gas_owner
544 })
545 {
546 let gas_owner_authenticator = authenticators.remove(position);
547 authenticators.insert(0, gas_owner_authenticator);
548 }
549 }
550
551 let mut gas_owner_authorized = !authenticators
552 .iter()
553 .any(|(authenticator, ..)| authenticator.address() == gas_owner);
554
555 let result = authenticators.into_iter().try_for_each(
561 |(
562 authenticator,
563 authenticator_function_ref,
564 authenticator_input_objects,
565 )| {
566 let account = authenticator.address();
567 let result = run_authenticator(
568 &mut temporary_store,
569 &mut gas_charger,
570 trace_builder_opt,
571 authenticator,
572 authenticator_function_ref,
573 authenticator_input_objects,
574 );
575 if result.is_ok() && account == gas_owner {
576 gas_owner_authorized = true;
577 }
578 result
579 },
580 );
581 (result, gas_owner_authorized)
582 }
583 };
584
585 (
589 report_authentication_error(authentication_result, protocol_config),
590 gas_owner_authorized,
591 )
592 }
593 };
594
595 let authentication_error = authentication_execution_result
598 .as_ref()
599 .err()
600 .map(|error| error.kind().clone());
601
602 let authentication_execution_result = match authentication_execution_result {
606 Err(error)
607 if !gas_owner_authorized
608 && protocol_config.enable_pcool_flow()
609 && !charge_gas_owner(protocol_config, &error, gas_owner_pays) =>
610 {
611 let (inner_temp_store, gas_status, effects, timings, execution_result) =
612 execute_without_gas_charge_to_effects::<Mode>(
613 temporary_store,
614 gas_charger,
615 shared_object_refs,
616 transaction_dependencies,
617 contains_deleted_input,
618 cancelled_objects,
619 transaction_digest,
620 epoch_id,
621 protocol_config,
622 certificate_deny_set,
623 error,
624 );
625
626 return (
627 inner_temp_store,
628 gas_status,
629 effects,
630 timings,
631 execution_result,
632 authentication_error,
633 );
634 }
635 result => result,
638 };
639 let (inner_temp_store, gas_status, effects, timings, execution_result) =
647 execute_transaction_to_effects_inner::<Mode>(
648 temporary_store,
649 gas_charger,
650 tx_ctx,
651 &mutable_inputs,
652 shared_object_refs,
653 transaction_dependencies,
654 contains_deleted_input,
655 cancelled_objects,
656 transaction_kind,
657 transaction_signer,
658 transaction_digest,
659 move_vm,
660 epoch_id,
661 protocol_config,
662 metrics,
663 enable_expensive_checks,
664 certificate_deny_set,
665 trace_builder_opt,
666 Some(authentication_execution_result),
667 );
668 (
669 inner_temp_store,
670 gas_status,
671 effects,
672 timings,
673 execution_result,
674 authentication_error,
675 )
676 }
677
678 fn charge_gas_owner(
685 protocol_config: &ProtocolConfig,
686 error: &ExecutionError,
687 gas_owner_pays: Option<&dyn Fn(&ExecutionErrorKind) -> bool>,
688 ) -> bool {
689 let kind = unwrap_move_authentication_error(error.kind());
690
691 protocol_config.enable_validator_attestation()
692 && !is_cancellation(kind)
693 && !is_any_invariant_violation(kind)
694 && gas_owner_pays.is_some_and(|pays| pays(kind))
695 }
696
697 fn execute_without_gas_charge_to_effects<Mode: ExecutionMode>(
714 mut temporary_store: TemporaryStore,
715 mut gas_charger: GasCharger,
716 shared_object_refs: Vec<SharedInput>,
717 mut transaction_dependencies: BTreeSet<TransactionDigest>,
718 contains_deleted_input: bool,
719 cancelled_objects: Option<(CancelledObjects, Version)>,
720 transaction_digest: TransactionDigest,
721 epoch_id: &EpochId,
722 protocol_config: &ProtocolConfig,
723 certificate_deny_set: &HashSet<TransactionDigest>,
724 authentication_error: ExecutionError,
725 ) -> (
726 InnerTemporaryStore,
727 IotaGasStatus,
728 TransactionEffects,
729 Vec<ExecutionTiming>,
730 Result<Mode::ExecutionResults, ExecutionError>,
731 ) {
732 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
733 let error = run_inputs_checks(
734 protocol_config,
735 deny_cert,
736 contains_deleted_input,
737 cancelled_objects,
738 )
739 .err()
740 .unwrap_or(authentication_error);
741 let status = elaborate_error_logs(&error, transaction_digest);
742
743 temporary_store.drop_writes();
744 temporary_store.ensure_active_inputs_mutated();
745
746 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
750
751 gas_charger.set_gas_coin_without_smashing();
752 let (inner, effects) = temporary_store.into_effects(
753 shared_object_refs,
754 &transaction_digest,
755 transaction_dependencies,
756 GasCostSummary::default(),
757 status,
758 &mut gas_charger,
759 *epoch_id,
760 );
761
762 (
763 inner,
764 gas_charger.into_gas_status(),
765 effects,
766 vec![],
767 Err(error),
768 )
769 }
770
771 #[instrument(name = "tx_validate", level = "debug", skip_all)]
777 pub fn authenticate_transaction(
778 store: &dyn BackingStore,
779 protocol_config: &ProtocolConfig,
781 metrics: Arc<LimitsMetrics>,
782 epoch_id: &EpochId,
784 epoch_timestamp_ms: u64,
785 gas_data: GasPayment,
787 gas_status: IotaGasStatus,
788 authenticators: Vec<(
790 MoveAuthenticator,
791 AuthenticatorFunctionRef,
792 CheckedInputObjects,
793 )>,
794 aggregated_authenticator_input_objects: CheckedInputObjects,
795 transaction_kind: TransactionKind,
797 transaction_signer: Address,
798 transaction_digest: TransactionDigest,
799 auth_context_data: AuthContextData,
800 trace_builder_opt: &mut Option<MoveTraceBuilder>,
802 move_vm: &Arc<MoveVM>,
804 ) -> (
805 IotaGasStatus,
806 Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>,
807 ) {
808 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
810 let gas_price = gas_status.gas_price();
811 let rgp = gas_status.reference_gas_price();
812 let mut gas_charger =
813 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
814
815 let tx_ctx = TxContext::new_from_components(
818 &transaction_signer,
819 &transaction_digest,
820 epoch_id,
821 epoch_timestamp_ms,
822 rgp,
823 gas_price,
824 gas_data.budget,
825 sponsor,
826 protocol_config,
827 );
828 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
829
830 let mut temporary_store = TemporaryStore::new(
831 store,
832 aggregated_authenticator_input_objects.into_inner(),
833 vec![],
834 transaction_digest,
835 protocol_config,
836 *epoch_id,
837 );
838
839 let authentication_execution_result = authenticators.into_iter().try_for_each(
841 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
842 match authenticator_function_ref {
843 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
844 authenticate_transaction_inner(
845 &mut temporary_store,
846 protocol_config,
847 metrics.clone(),
848 &mut gas_charger,
849 authenticator,
850 authenticator_function_ref_v1,
851 &authenticator_input_objects.into_inner(),
852 transaction_kind.clone(),
853 transaction_digest,
854 auth_context_data.clone(),
855 tx_ctx.clone(),
856 trace_builder_opt,
857 move_vm,
858 )
859 }
860 }
861 },
862 );
863
864 let result = report_authentication_error(authentication_execution_result, protocol_config);
865 (gas_charger.into_gas_status(), result)
866 }
867
868 #[instrument(name = "tx_validate", level = "debug", skip_all)]
878 pub fn authenticate_transaction_inner(
879 temporary_store: &mut TemporaryStore<'_>,
880 protocol_config: &ProtocolConfig,
882 metrics: Arc<LimitsMetrics>,
883 gas_charger: &mut GasCharger,
885 authenticator: MoveAuthenticator,
887 authenticator_function_ref: AuthenticatorFunctionRefV1,
888 authenticator_input_objects: &InputObjects,
889 transaction_kind: TransactionKind,
891 transaction_digest: TransactionDigest,
892 auth_context_data: AuthContextData,
893 tx_ctx: Rc<RefCell<TxContext>>,
894 trace_builder_opt: &mut Option<MoveTraceBuilder>,
896 move_vm: &Arc<MoveVM>,
898 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
899 {
900 debug_assert!(
902 transaction_kind.is_programmable(),
903 "Only programmable transactions are allowed"
904 );
905 debug_assert!(
906 authenticator_input_objects
907 .mutable_inputs()
908 .keys()
909 .copied()
910 .collect::<HashSet<_>>()
911 .is_empty(),
912 "No mutable inputs are allowed"
913 );
914 debug_assert!(
915 authenticator.receiving_objects().is_empty(),
916 "No receiving inputs are allowed"
917 );
918
919 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
920 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
921
922 let auth_ctx = {
924 let TransactionKind::Programmable(ptb) = &transaction_kind else {
925 unreachable!("Only programmable transactions are allowed");
926 };
927 AuthContext::new_from_components(
928 authenticator.digest().into(),
929 auth_context_data.sender_auth_digest,
930 auth_context_data.sponsor_auth_digest,
931 auth_context_data
932 .sender_authenticator_function_ref
933 .and_then(Into::into),
934 auth_context_data
935 .sponsor_authenticator_function_ref
936 .and_then(Into::into),
937 ptb,
938 auth_context_data.transaction_data_bytes,
939 )
940 };
941 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
942
943 temporary_store.store_auth_context(auth_ctx);
947
948 let authentication_execution_result = execute_authenticator_move_call(
950 temporary_store,
951 authenticator,
952 authenticator_function_ref,
953 gas_charger,
954 tx_ctx,
955 move_vm,
956 protocol_config,
957 metrics,
958 false,
959 contains_deleted_input,
960 cancelled_objects,
961 trace_builder_opt,
962 );
963
964 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
966 elaborate_error_logs(error, transaction_digest)
967 } else {
968 ExecutionStatus::Success
969 };
970
971 #[skip_checked_arithmetic]
972 trace!(
973 tx_digest = ?transaction_digest,
974 computation_gas_cost = gas_charger.summary().gas_used(),
975 "Finished authenticator execution of transaction with status {:?}",
976 authentication_execution_status
977 );
978
979 authentication_execution_result
980 }
981
982 #[instrument(name = "auth_execute", level = "debug", skip_all)]
993 fn execute_authenticator_move_call(
994 temporary_store: &mut TemporaryStore<'_>,
995 authenticator: MoveAuthenticator,
996 authenticator_function_ref: AuthenticatorFunctionRefV1,
997 gas_charger: &mut GasCharger,
998 tx_ctx: Rc<RefCell<TxContext>>,
999 move_vm: &Arc<MoveVM>,
1000 protocol_config: &ProtocolConfig,
1001 metrics: Arc<LimitsMetrics>,
1002 deny_cert: bool,
1003 contains_deleted_input: bool,
1004 cancelled_objects: Option<(CancelledObjects, Version)>,
1005 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1006 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
1007 {
1008 run_inputs_checks(
1012 protocol_config,
1013 deny_cert,
1014 contains_deleted_input,
1015 cancelled_objects,
1016 )
1017 .and_then(|()| {
1018 let authenticator_move_call =
1019 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
1020 programmable_transactions::execution::execute::<execution_mode::Authentication>(
1021 protocol_config,
1022 metrics.clone(),
1023 move_vm,
1024 temporary_store,
1025 tx_ctx,
1026 gas_charger,
1027 authenticator_move_call,
1028 trace_builder_opt,
1029 )
1030 .map_err(|(e, _)| e)
1031 .and_then(|(ok_result, _timings)| {
1032 temporary_store.check_move_authenticator_results_consistency()?;
1033 Ok(ok_result)
1034 })
1035 })
1036 }
1037
1038 pub fn execute_genesis_state_update(
1045 store: &dyn BackingStore,
1046 protocol_config: &ProtocolConfig,
1047 metrics: Arc<LimitsMetrics>,
1048 move_vm: &Arc<MoveVM>,
1049 tx_context: Rc<RefCell<TxContext>>,
1050 input_objects: CheckedInputObjects,
1051 pt: ProgrammableTransaction,
1052 ) -> Result<InnerTemporaryStore, ExecutionError> {
1053 let input_objects = input_objects.into_inner();
1054 let tx_digest = tx_context.borrow().digest();
1055
1056 let mut temporary_store =
1057 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
1058 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
1059 programmable_transactions::execution::execute::<execution_mode::Genesis>(
1060 protocol_config,
1061 metrics,
1062 move_vm,
1063 &mut temporary_store,
1064 tx_context,
1065 &mut gas_charger,
1066 pt,
1067 &mut None,
1068 )
1069 .map_err(|(e, _)| e)?;
1070 temporary_store.update_object_version_and_prev_tx();
1071 Ok(temporary_store.into_inner())
1072 }
1073
1074 #[instrument(name = "tx_execute", level = "debug", skip_all)]
1083 fn execute_transaction<Mode: ExecutionMode>(
1084 temporary_store: &mut TemporaryStore<'_>,
1085 transaction_kind: TransactionKind,
1086 gas_charger: &mut GasCharger,
1087 tx_ctx: Rc<RefCell<TxContext>>,
1088 move_vm: &Arc<MoveVM>,
1089 protocol_config: &ProtocolConfig,
1090 metrics: Arc<LimitsMetrics>,
1091 enable_expensive_checks: bool,
1092 deny_cert: bool,
1093 contains_deleted_input: bool,
1094 cancelled_objects: Option<(CancelledObjects, Version)>,
1095 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1096 pre_execution_result_opt: Option<
1097 Result<
1098 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
1099 ExecutionError,
1100 >,
1101 >,
1102 ) -> (
1103 GasCostSummary,
1104 Result<Mode::ExecutionResults, ExecutionError>,
1105 Vec<ExecutionTiming>,
1106 ) {
1107 gas_charger.smash_gas(temporary_store);
1108
1109 debug_assert!(
1112 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
1113 "No gas charges must be applied yet"
1114 );
1115
1116 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
1117 || transaction_kind.is_end_of_epoch();
1118
1119 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
1120
1121 let tx_digest = tx_ctx.borrow().digest();
1122
1123 let result = gas_charger.charge_input_objects(temporary_store);
1127 let result: ResultWithTimings<Mode::ExecutionResults, ExecutionError> =
1128 result.map_err(|e| (e, vec![])).and_then(
1129 |()| -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
1130 run_inputs_checks(
1131 protocol_config,
1132 deny_cert,
1133 contains_deleted_input,
1134 cancelled_objects,
1135 )
1136 .map_err(|e| (e, vec![]))?;
1137
1138 let mut execution_result = pre_execution_result_opt
1141 .unwrap_or(Ok(()))
1142 .map_err(|e| (e, vec![]))
1143 .and_then(|_| {
1144 execution_loop::<Mode>(
1145 temporary_store,
1146 transaction_kind,
1147 tx_ctx,
1148 move_vm,
1149 gas_charger,
1150 protocol_config,
1151 metrics.clone(),
1152 trace_builder_opt,
1153 )
1154 });
1155
1156 let meter_check = check_meter_limit(
1157 temporary_store,
1158 gas_charger,
1159 protocol_config,
1160 metrics.clone(),
1161 );
1162 if let Err(e) = meter_check {
1163 execution_result = Err((e, vec![]));
1164 }
1165
1166 if execution_result.is_ok() {
1167 let gas_check = check_written_objects_limit(
1168 temporary_store,
1169 gas_charger,
1170 protocol_config,
1171 metrics,
1172 );
1173 if let Err(e) = gas_check {
1174 execution_result = Err((e, vec![]));
1175 }
1176 }
1177
1178 execution_result
1179 },
1180 );
1181
1182 let (mut result, timings) = match result {
1183 Ok((r, t)) => (Ok(r), t),
1184 Err((e, t)) => (Err(e), t),
1185 };
1186
1187 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
1188 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
1197
1198 if let Err(e) = run_conservation_checks::<Mode>(
1199 temporary_store,
1200 gas_charger,
1201 tx_digest,
1202 move_vm,
1203 enable_expensive_checks,
1204 &cost_summary,
1205 is_genesis_or_epoch_change_tx,
1206 advance_epoch_gas_summary,
1207 ) {
1208 result = Err(e);
1210 }
1211
1212 (cost_summary, result, timings)
1213 }
1214
1215 fn report_authentication_error<T>(
1221 authentication_execution_result: Result<T, ExecutionError>,
1222 protocol_config: &ProtocolConfig,
1223 ) -> Result<T, ExecutionError> {
1224 if protocol_config.report_move_authentication_error() {
1225 authentication_execution_result.map_err(ExecutionError::into_move_authentication_error)
1226 } else {
1227 authentication_execution_result
1228 }
1229 }
1230
1231 fn elaborate_error_logs(
1234 execution_error: &ExecutionError,
1235 transaction_digest: TransactionDigest,
1236 ) -> ExecutionStatus {
1237 use ExecutionErrorKind as K;
1238 match execution_error.kind() {
1239 K::InvariantViolation | K::VmInvariantViolation => {
1240 #[skip_checked_arithmetic]
1241 tracing::error!(
1242 kind = ?execution_error.kind(),
1243 tx_digest = ?transaction_digest,
1244 "INVARIANT VIOLATION! Source: {:?}",
1245 execution_error.source(),
1246 );
1247 }
1248
1249 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
1250 #[skip_checked_arithmetic]
1251 tracing::debug!(
1252 kind = ?execution_error.kind(),
1253 tx_digest = ?transaction_digest,
1254 "Verification Error. Source: {:?}",
1255 execution_error.source(),
1256 );
1257 }
1258
1259 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
1260 #[skip_checked_arithmetic]
1261 tracing::debug!(
1262 kind = ?execution_error.kind(),
1263 tx_digest = ?transaction_digest,
1264 "Publish/Upgrade Error. Source: {:?}",
1265 execution_error.source(),
1266 )
1267 }
1268
1269 _ => (),
1270 };
1271
1272 let (status, command) = execution_error.to_execution_status();
1273 ExecutionStatus::new_failure(status, command)
1274 }
1275
1276 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
1285 fn run_conservation_checks<Mode: ExecutionMode>(
1286 temporary_store: &mut TemporaryStore<'_>,
1287 gas_charger: &mut GasCharger,
1288 tx_digest: TransactionDigest,
1289 move_vm: &Arc<MoveVM>,
1290 enable_expensive_checks: bool,
1291 cost_summary: &GasCostSummary,
1292 is_genesis_or_epoch_change_tx: bool,
1293 advance_epoch_gas_summary: Option<(u64, u64)>,
1294 ) -> Result<(), ExecutionError> {
1295 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
1296 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
1297 let conservation_result = {
1300 temporary_store
1301 .check_iota_conserved(cost_summary)
1302 .and_then(|()| {
1303 if enable_expensive_checks {
1304 let mut layout_resolver =
1307 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1308 temporary_store.check_iota_conserved_expensive(
1309 cost_summary,
1310 advance_epoch_gas_summary,
1311 &mut layout_resolver,
1312 )
1313 } else {
1314 Ok(())
1315 }
1316 })
1317 };
1318 if let Err(conservation_err) = conservation_result {
1319 result = Err(conservation_err);
1323 gas_charger.reset(temporary_store);
1324 gas_charger.charge_gas(temporary_store, &mut result);
1325 if let Err(recovery_err) = temporary_store
1327 .check_iota_conserved(cost_summary)
1328 .and_then(|()| {
1329 if enable_expensive_checks {
1330 let mut layout_resolver =
1333 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1334 temporary_store.check_iota_conserved_expensive(
1335 cost_summary,
1336 advance_epoch_gas_summary,
1337 &mut layout_resolver,
1338 )
1339 } else {
1340 Ok(())
1341 }
1342 })
1343 {
1344 panic!(
1348 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1349 tx_digest,
1350 recovery_err,
1351 gas_charger.summary()
1352 )
1353 }
1354 }
1355 } result
1359 }
1360
1361 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1372 fn run_inputs_checks(
1373 protocol_config: &ProtocolConfig,
1374 deny_cert: bool,
1375 contains_deleted_input: bool,
1376 cancelled_objects: Option<(CancelledObjects, Version)>,
1377 ) -> Result<(), ExecutionError> {
1378 if deny_cert {
1379 Err(ExecutionError::new(
1380 ExecutionErrorKind::CertificateDenied,
1381 None,
1382 ))
1383 } else if contains_deleted_input {
1384 Err(ExecutionError::new(
1385 ExecutionErrorKind::InputObjectDeleted,
1386 None,
1387 ))
1388 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1389 match reason {
1390 version if version.is_congested() => Err(ExecutionError::new(
1391 match cancelled_objects {
1392 CancelledObjects::GasObject => {
1396 ExecutionErrorKind::ExecutionCanceledDueToExecutionWorkerCongestion {
1397 suggested_gas_price: version
1398 .get_congested_version_suggested_gas_price()
1399 .expect(
1400 "execution-worker congestion control requires the gas \
1401 price feedback mechanism",
1402 ),
1403 }
1404 }
1405 CancelledObjects::SharedObjects(congested_objects) => {
1406 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1407 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestionV2 {
1408 congested_objects,
1409 suggested_gas_price: version
1410 .get_congested_version_suggested_gas_price()
1411 .unwrap(),
1412 }
1413 } else {
1414 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestion {
1419 congested_objects,
1420 }
1421 }
1422 }
1423 },
1424 None,
1425 )),
1426 Version::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1427 ExecutionErrorKind::ExecutionCanceledDueToRandomnessUnavailable,
1428 None,
1429 )),
1430 _ => panic!("invalid cancellation reason Version: {reason}"),
1431 }
1432 } else {
1433 Ok(())
1434 }
1435 }
1436
1437 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1442 fn check_meter_limit(
1443 temporary_store: &mut TemporaryStore<'_>,
1444 gas_charger: &mut GasCharger,
1445 protocol_config: &ProtocolConfig,
1446 metrics: Arc<LimitsMetrics>,
1447 ) -> Result<(), ExecutionError> {
1448 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1449
1450 match check_limit_by_meter!(
1455 !gas_charger.is_unmetered(),
1456 effects_estimated_size,
1457 protocol_config.max_serialized_tx_effects_size_bytes(),
1458 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1459 metrics.excessive_estimated_effects_size
1460 ) {
1461 LimitThresholdCrossed::None => Ok(()),
1462 LimitThresholdCrossed::Soft(_, limit) => {
1463 warn!(
1464 effects_estimated_size = effects_estimated_size,
1465 soft_limit = limit,
1466 "Estimated transaction effects size crossed soft limit",
1467 );
1468 Ok(())
1469 }
1470 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1471 ExecutionErrorKind::EffectsTooLarge {
1472 current_size: effects_estimated_size as u64,
1473 max_size: lim as u64,
1474 },
1475 "Transaction effects are too large",
1476 )),
1477 }
1478 }
1479
1480 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1485 fn check_written_objects_limit(
1486 temporary_store: &mut TemporaryStore<'_>,
1487 gas_charger: &mut GasCharger,
1488 protocol_config: &ProtocolConfig,
1489 metrics: Arc<LimitsMetrics>,
1490 ) -> Result<(), ExecutionError> {
1491 if let (Some(normal_lim), Some(system_lim)) = (
1492 protocol_config.max_size_written_objects_as_option(),
1493 protocol_config.max_size_written_objects_system_tx_as_option(),
1494 ) {
1495 let written_objects_size = temporary_store.written_objects_size();
1496
1497 match check_limit_by_meter!(
1498 !gas_charger.is_unmetered(),
1499 written_objects_size,
1500 normal_lim,
1501 system_lim,
1502 metrics.excessive_written_objects_size
1503 ) {
1504 LimitThresholdCrossed::None => (),
1505 LimitThresholdCrossed::Soft(_, limit) => {
1506 warn!(
1507 written_objects_size = written_objects_size,
1508 soft_limit = limit,
1509 "Written objects size crossed soft limit",
1510 )
1511 }
1512 LimitThresholdCrossed::Hard(_, lim) => {
1513 return Err(ExecutionError::new_with_source(
1514 ExecutionErrorKind::WrittenObjectsTooLarge {
1515 object_size: written_objects_size as u64,
1516 max_object_size: lim as u64,
1517 },
1518 "Written objects size crossed hard limit",
1519 ));
1520 }
1521 };
1522 }
1523
1524 Ok(())
1525 }
1526
1527 #[instrument(level = "debug", skip_all)]
1534 fn execution_loop<Mode: ExecutionMode>(
1535 temporary_store: &mut TemporaryStore<'_>,
1536 transaction_kind: TransactionKind,
1537 tx_ctx: Rc<RefCell<TxContext>>,
1538 move_vm: &Arc<MoveVM>,
1539 gas_charger: &mut GasCharger,
1540 protocol_config: &ProtocolConfig,
1541 metrics: Arc<LimitsMetrics>,
1542 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1543 ) -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
1544 let result = match transaction_kind {
1545 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1546 if tx_ctx.borrow().epoch() != 0 {
1547 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1548 }
1549
1550 for genesis_object in objects {
1551 let object = ObjectInner {
1552 data: genesis_object.data,
1553 owner: genesis_object.owner,
1554 previous_transaction: tx_ctx.borrow().digest(),
1555 storage_rebate: 0,
1556 };
1557 temporary_store.create_object(object.into());
1558 }
1559
1560 temporary_store.record_execution_results(ExecutionResults::V1(
1561 ExecutionResultsV1 {
1562 user_events: events,
1563 ..Default::default()
1564 },
1565 ));
1566
1567 Ok((Mode::empty_results(), vec![]))
1568 }
1569 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1570 setup_consensus_commit(
1571 prologue.commit_timestamp_ms,
1572 temporary_store,
1573 tx_ctx,
1574 move_vm,
1575 gas_charger,
1576 protocol_config,
1577 metrics,
1578 trace_builder_opt,
1579 )
1580 .expect("ConsensusCommitPrologueV1 cannot fail");
1581 Ok((Mode::empty_results(), vec![]))
1582 }
1583 TransactionKind::Programmable(pt) => {
1584 programmable_transactions::execution::execute::<Mode>(
1585 protocol_config,
1586 metrics,
1587 move_vm,
1588 temporary_store,
1589 tx_ctx,
1590 gas_charger,
1591 pt,
1592 trace_builder_opt,
1593 )
1594 }
1595 TransactionKind::EndOfEpoch(txns) => {
1596 let mut builder = ProgrammableTransactionBuilder::new();
1600 let len = txns.len();
1601
1602 for (i, tx) in txns.into_iter().enumerate() {
1603 match tx {
1604 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1605 assert_eq!(i, len - 1);
1606 advance_epoch_v1(
1607 builder,
1608 change_epoch,
1609 temporary_store,
1610 tx_ctx,
1611 move_vm,
1612 gas_charger,
1613 protocol_config,
1614 metrics,
1615 trace_builder_opt,
1616 )
1617 .map_err(|e| (e, vec![]))?;
1618 return Ok((Mode::empty_results(), vec![]));
1619 }
1620 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1621 assert_eq!(i, len - 1);
1622 advance_epoch_v2(
1623 builder,
1624 change_epoch_v2,
1625 temporary_store,
1626 tx_ctx,
1627 move_vm,
1628 gas_charger,
1629 protocol_config,
1630 metrics,
1631 trace_builder_opt,
1632 )
1633 .map_err(|e| (e, vec![]))?;
1634 return Ok((Mode::empty_results(), vec![]));
1635 }
1636 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1637 assert_eq!(i, len - 1);
1638 advance_epoch_v3(
1639 builder,
1640 change_epoch_v3,
1641 temporary_store,
1642 tx_ctx,
1643 move_vm,
1644 gas_charger,
1645 protocol_config,
1646 metrics,
1647 trace_builder_opt,
1648 )
1649 .map_err(|e| (e, vec![]))?;
1650 return Ok((Mode::empty_results(), vec![]));
1651 }
1652 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1653 assert_eq!(i, len - 1);
1654 advance_epoch_v4(
1655 builder,
1656 change_epoch_v4,
1657 temporary_store,
1658 tx_ctx,
1659 move_vm,
1660 gas_charger,
1661 protocol_config,
1662 metrics,
1663 trace_builder_opt,
1664 )
1665 .map_err(|e| (e, vec![]))?;
1666 return Ok((Mode::empty_results(), vec![]));
1667 }
1668 EndOfEpochTransactionKind::TransactionDenyRulesCreate => {
1669 assert!(
1670 protocol_config.enable_pcool_flow(),
1671 "unexpected TransactionDenyRulesCreate: on-chain deny rule governance is not enabled"
1672 );
1673 builder = setup_transaction_deny_rules_create(builder)
1674 .map_err(|e| (e, vec![]))?;
1675 }
1676 _ => unimplemented!(
1677 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1678 ),
1679 }
1680 }
1681 unreachable!(
1682 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1683 )
1684 }
1685 #[allow(deprecated)]
1686 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1687 return Err((
1691 ExecutionError::new(
1692 ExecutionErrorKind::VmInvariantViolation,
1693 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1694 ),
1695 vec![],
1696 ));
1697 }
1698 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1699 setup_randomness_state_update(
1700 randomness_state_update,
1701 temporary_store,
1702 tx_ctx,
1703 move_vm,
1704 gas_charger,
1705 protocol_config,
1706 metrics,
1707 trace_builder_opt,
1708 )
1709 .map_err(|e| (e, vec![]))?;
1710 Ok((Mode::empty_results(), vec![]))
1711 }
1712 TransactionKind::TransactionDenyRulesUpdate(update) => {
1713 assert!(
1714 protocol_config.enable_pcool_flow(),
1715 "unexpected TransactionDenyRulesUpdate: on-chain deny rule governance is not enabled"
1716 );
1717 setup_transaction_deny_rules_update(
1718 update,
1719 temporary_store,
1720 tx_ctx,
1721 move_vm,
1722 gas_charger,
1723 protocol_config,
1724 metrics,
1725 trace_builder_opt,
1726 )
1727 .map_err(|e| (e, vec![]))?;
1728 Ok((Mode::empty_results(), vec![]))
1729 }
1730 _ => unimplemented!(
1731 "a new TransactionKind enum variant was added and needs to be handled"
1732 ),
1733 }?;
1734 temporary_store
1735 .check_execution_results_consistency()
1736 .map_err(|e| (e, vec![]))?;
1737 Ok(result)
1738 }
1739
1740 fn mint_epoch_rewards_in_pt(
1749 builder: &mut ProgrammableTransactionBuilder,
1750 params: &AdvanceEpochParams,
1751 ) -> (Argument, Argument) {
1752 let storage_charge_arg = builder
1754 .input(CallArg::pure(¶ms.storage_charge))
1755 .unwrap();
1756 let storage_charges = builder.programmable_move_call(
1757 ObjectId::FRAMEWORK,
1758 Identifier::BALANCE_MODULE,
1759 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1760 vec![TypeTag::from(StructTag::new_gas())],
1761 vec![storage_charge_arg],
1762 );
1763
1764 let computation_charge_arg = builder
1766 .input(CallArg::pure(¶ms.computation_charge))
1767 .unwrap();
1768 let computation_charges = builder.programmable_move_call(
1769 ObjectId::FRAMEWORK,
1770 Identifier::BALANCE_MODULE,
1771 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1772 vec![TypeTag::from(StructTag::new_gas())],
1773 vec![computation_charge_arg],
1774 );
1775 (storage_charges, computation_charges)
1776 }
1777
1778 pub fn construct_advance_epoch_pt_impl(
1786 mut builder: ProgrammableTransactionBuilder,
1787 params: &AdvanceEpochParams,
1788 call_arg_vec: Vec<CallArg>,
1789 ) -> Result<ProgrammableTransaction, ExecutionError> {
1790 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1792 let mut arguments = vec![
1793 builder
1794 .pure(params.validator_subsidy)
1795 .expect("bcs encoding a u64 should not fail"),
1796 storage_charges,
1797 computation_charges,
1798 ];
1799
1800 let call_arg_arguments = call_arg_vec
1801 .into_iter()
1802 .map(|a| builder.input(a))
1803 .collect::<Result<_, _>>();
1804
1805 assert_invariant!(
1806 call_arg_arguments.is_ok(),
1807 "Unable to generate args for advance_epoch transaction!"
1808 );
1809
1810 arguments.append(&mut call_arg_arguments.unwrap());
1811
1812 info!("Call arguments to advance_epoch transaction: {:?}", params);
1813
1814 let storage_rebates = builder.programmable_move_call(
1815 ObjectId::SYSTEM,
1816 Identifier::IOTA_SYSTEM_MODULE,
1817 ADVANCE_EPOCH_FUNCTION_NAME,
1818 vec![],
1819 arguments,
1820 );
1821
1822 builder.programmable_move_call(
1824 ObjectId::FRAMEWORK,
1825 Identifier::BALANCE_MODULE,
1826 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1827 vec![TypeTag::from(StructTag::new_gas())],
1828 vec![storage_rebates],
1829 );
1830 Ok(builder.finish())
1831 }
1832
1833 pub fn construct_advance_epoch_pt_v1(
1834 builder: ProgrammableTransactionBuilder,
1835 params: &AdvanceEpochParams,
1836 ) -> Result<ProgrammableTransaction, ExecutionError> {
1837 let call_arg_vec = vec![
1842 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), ];
1850 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1851 }
1852
1853 pub fn construct_advance_epoch_pt_v2(
1854 builder: ProgrammableTransactionBuilder,
1855 params: &AdvanceEpochParams,
1856 ) -> Result<ProgrammableTransaction, ExecutionError> {
1857 let call_arg_vec = vec![
1862 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), ];
1872 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1873 }
1874
1875 pub fn construct_advance_epoch_pt_v3(
1876 builder: ProgrammableTransactionBuilder,
1877 params: &AdvanceEpochParams,
1878 ) -> Result<ProgrammableTransaction, ExecutionError> {
1879 let call_arg_vec = vec![
1885 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), ];
1897 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1898 }
1899
1900 pub fn construct_advance_epoch_pt_v4(
1901 builder: ProgrammableTransactionBuilder,
1902 params: &AdvanceEpochParams,
1903 ) -> Result<ProgrammableTransaction, ExecutionError> {
1904 let call_arg_vec = vec![
1910 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), ];
1924 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1925 }
1926
1927 fn advance_epoch_impl(
1934 advance_epoch_pt: ProgrammableTransaction,
1935 params: AdvanceEpochParams,
1936 system_packages: Vec<SystemPackage>,
1937 temporary_store: &mut TemporaryStore<'_>,
1938 tx_ctx: Rc<RefCell<TxContext>>,
1939 move_vm: &Arc<MoveVM>,
1940 gas_charger: &mut GasCharger,
1941 protocol_config: &ProtocolConfig,
1942 metrics: Arc<LimitsMetrics>,
1943 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1944 ) -> Result<(), ExecutionError> {
1945 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1946 protocol_config,
1947 metrics.clone(),
1948 move_vm,
1949 temporary_store,
1950 tx_ctx.clone(),
1951 gas_charger,
1952 advance_epoch_pt,
1953 trace_builder_opt,
1954 );
1955
1956 #[cfg(msim)]
1957 let result = maybe_modify_result(result, params.epoch);
1958
1959 if let Err(err) = &result {
1960 tracing::error!(
1961 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1962 err.0,
1963 temporary_store.objects(),
1964 params,
1965 );
1966 temporary_store.drop_writes();
1967 gas_charger.reset_storage_cost_and_rebate();
1969
1970 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1971 }
1972
1973 let new_vm = new_move_vm(
1974 all_natives(true, protocol_config),
1975 protocol_config,
1976 None,
1978 )
1979 .expect("Failed to create new MoveVM");
1980 process_system_packages(
1981 system_packages,
1982 temporary_store,
1983 tx_ctx,
1984 &new_vm,
1985 gas_charger,
1986 protocol_config,
1987 metrics,
1988 trace_builder_opt,
1989 );
1990
1991 Ok(())
1992 }
1993
1994 fn advance_epoch_v1(
1998 builder: ProgrammableTransactionBuilder,
1999 change_epoch: ChangeEpoch,
2000 temporary_store: &mut TemporaryStore<'_>,
2001 tx_ctx: Rc<RefCell<TxContext>>,
2002 move_vm: &Arc<MoveVM>,
2003 gas_charger: &mut GasCharger,
2004 protocol_config: &ProtocolConfig,
2005 metrics: Arc<LimitsMetrics>,
2006 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2007 ) -> Result<(), ExecutionError> {
2008 let params = AdvanceEpochParams {
2009 epoch: change_epoch.epoch,
2010 next_protocol_version: change_epoch.protocol_version.into(),
2011 validator_subsidy: protocol_config.validator_target_reward(),
2012 storage_charge: change_epoch.storage_charge,
2013 computation_charge: change_epoch.computation_charge,
2014 computation_charge_burned: change_epoch.computation_charge,
2016 storage_rebate: change_epoch.storage_rebate,
2017 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
2018 reward_slashing_rate: protocol_config.reward_slashing_rate(),
2019 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
2020 max_committee_members_count: 0,
2023 eligible_active_validators: vec![],
2024 scores: vec![],
2025 adjust_rewards_by_score: false,
2026 };
2027 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
2028 advance_epoch_impl(
2029 advance_epoch_pt,
2030 params,
2031 change_epoch.system_packages,
2032 temporary_store,
2033 tx_ctx,
2034 move_vm,
2035 gas_charger,
2036 protocol_config,
2037 metrics,
2038 trace_builder_opt,
2039 )
2040 }
2041
2042 fn advance_epoch_v2(
2046 builder: ProgrammableTransactionBuilder,
2047 change_epoch_v2: ChangeEpochV2,
2048 temporary_store: &mut TemporaryStore<'_>,
2049 tx_ctx: Rc<RefCell<TxContext>>,
2050 move_vm: &Arc<MoveVM>,
2051 gas_charger: &mut GasCharger,
2052 protocol_config: &ProtocolConfig,
2053 metrics: Arc<LimitsMetrics>,
2054 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2055 ) -> Result<(), ExecutionError> {
2056 let params = AdvanceEpochParams {
2057 epoch: change_epoch_v2.epoch,
2058 next_protocol_version: change_epoch_v2.protocol_version.into(),
2059 validator_subsidy: protocol_config.validator_target_reward(),
2060 storage_charge: change_epoch_v2.storage_charge,
2061 computation_charge: change_epoch_v2.computation_charge,
2062 computation_charge_burned: change_epoch_v2.computation_charge_burned,
2063 storage_rebate: change_epoch_v2.storage_rebate,
2064 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
2065 reward_slashing_rate: protocol_config.reward_slashing_rate(),
2066 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
2067 max_committee_members_count: protocol_config.max_committee_members_count(),
2068 eligible_active_validators: vec![],
2071 scores: vec![],
2072 adjust_rewards_by_score: false,
2073 };
2074 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
2075 advance_epoch_impl(
2076 advance_epoch_pt,
2077 params,
2078 change_epoch_v2.system_packages,
2079 temporary_store,
2080 tx_ctx,
2081 move_vm,
2082 gas_charger,
2083 protocol_config,
2084 metrics,
2085 trace_builder_opt,
2086 )
2087 }
2088
2089 fn advance_epoch_v3(
2093 builder: ProgrammableTransactionBuilder,
2094 change_epoch_v3: ChangeEpochV3,
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 params = AdvanceEpochParams {
2104 epoch: change_epoch_v3.epoch,
2105 next_protocol_version: change_epoch_v3.protocol_version.into(),
2106 validator_subsidy: protocol_config.validator_target_reward(),
2107 storage_charge: change_epoch_v3.storage_charge,
2108 computation_charge: change_epoch_v3.computation_charge,
2109 computation_charge_burned: change_epoch_v3.computation_charge_burned,
2110 storage_rebate: change_epoch_v3.storage_rebate,
2111 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
2112 reward_slashing_rate: protocol_config.reward_slashing_rate(),
2113 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
2114 max_committee_members_count: protocol_config.max_committee_members_count(),
2115 eligible_active_validators: change_epoch_v3.eligible_active_validators,
2116 scores: vec![],
2119 adjust_rewards_by_score: false,
2120 };
2121 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
2122 advance_epoch_impl(
2123 advance_epoch_pt,
2124 params,
2125 change_epoch_v3.system_packages,
2126 temporary_store,
2127 tx_ctx,
2128 move_vm,
2129 gas_charger,
2130 protocol_config,
2131 metrics,
2132 trace_builder_opt,
2133 )
2134 }
2135
2136 fn advance_epoch_v4(
2140 builder: ProgrammableTransactionBuilder,
2141 change_epoch_v4: ChangeEpochV4,
2142 temporary_store: &mut TemporaryStore<'_>,
2143 tx_ctx: Rc<RefCell<TxContext>>,
2144 move_vm: &Arc<MoveVM>,
2145 gas_charger: &mut GasCharger,
2146 protocol_config: &ProtocolConfig,
2147 metrics: Arc<LimitsMetrics>,
2148 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2149 ) -> Result<(), ExecutionError> {
2150 let params = AdvanceEpochParams {
2151 epoch: change_epoch_v4.epoch,
2152 next_protocol_version: change_epoch_v4.protocol_version.into(),
2153 validator_subsidy: protocol_config.validator_target_reward(),
2154 storage_charge: change_epoch_v4.storage_charge,
2155 computation_charge: change_epoch_v4.computation_charge,
2156 computation_charge_burned: change_epoch_v4.computation_charge_burned,
2157 storage_rebate: change_epoch_v4.storage_rebate,
2158 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
2159 reward_slashing_rate: protocol_config.reward_slashing_rate(),
2160 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
2161 max_committee_members_count: protocol_config.max_committee_members_count(),
2162 eligible_active_validators: change_epoch_v4.eligible_active_validators,
2163 scores: change_epoch_v4.scores,
2164 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
2165 };
2166 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
2167 advance_epoch_impl(
2168 advance_epoch_pt,
2169 params,
2170 change_epoch_v4.system_packages,
2171 temporary_store,
2172 tx_ctx,
2173 move_vm,
2174 gas_charger,
2175 protocol_config,
2176 metrics,
2177 trace_builder_opt,
2178 )
2179 }
2180
2181 fn process_system_packages(
2182 system_packages: Vec<SystemPackage>,
2183 temporary_store: &mut TemporaryStore<'_>,
2184 tx_ctx: Rc<RefCell<TxContext>>,
2185 move_vm: &MoveVM,
2186 gas_charger: &mut GasCharger,
2187 protocol_config: &ProtocolConfig,
2188 metrics: Arc<LimitsMetrics>,
2189 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2190 ) {
2191 let binary_config = to_binary_config(protocol_config, None);
2192 for SystemPackage {
2193 version,
2194 modules,
2195 dependencies,
2196 } in system_packages.into_iter()
2197 {
2198 let deserialized_modules: Vec<_> = modules
2199 .iter()
2200 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
2201 .collect();
2202
2203 if version == OBJECT_START_VERSION {
2204 let package_id = deserialized_modules.first().unwrap().address();
2205 info!("adding new system package {package_id}");
2206
2207 let publish_pt = {
2208 let mut b = ProgrammableTransactionBuilder::new();
2209 b.command(Command::new_publish(modules, dependencies));
2210 b.finish()
2211 };
2212
2213 programmable_transactions::execution::execute::<execution_mode::System>(
2214 protocol_config,
2215 metrics.clone(),
2216 move_vm,
2217 temporary_store,
2218 tx_ctx.clone(),
2219 gas_charger,
2220 publish_pt,
2221 trace_builder_opt,
2222 )
2223 .map_err(|(e, _)| e)
2224 .expect("System Package Publish must succeed");
2225 } else {
2226 let mut new_package = Object::new_system_package(
2227 &deserialized_modules,
2228 version,
2229 dependencies,
2230 tx_ctx.borrow().digest(),
2231 );
2232
2233 info!("upgraded system package {:?}", new_package.object_ref());
2234
2235 new_package
2238 .data
2239 .as_opt_mut_package()
2240 .unwrap()
2241 .decrement_version()
2242 .expect("package version should never underflow");
2243
2244 temporary_store.upgrade_system_package(new_package);
2246 }
2247 }
2248 }
2249
2250 fn setup_consensus_commit(
2256 consensus_commit_timestamp_ms: CheckpointTimestamp,
2257 temporary_store: &mut TemporaryStore<'_>,
2258 tx_ctx: Rc<RefCell<TxContext>>,
2259 move_vm: &Arc<MoveVM>,
2260 gas_charger: &mut GasCharger,
2261 protocol_config: &ProtocolConfig,
2262 metrics: Arc<LimitsMetrics>,
2263 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2264 ) -> Result<(), ExecutionError> {
2265 let pt = {
2266 let mut builder = ProgrammableTransactionBuilder::new();
2267 let res = builder.move_call(
2268 ObjectId::FRAMEWORK,
2269 Identifier::CLOCK_MODULE,
2270 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
2271 vec![],
2272 vec![
2273 CallArg::CLOCK_MUTABLE,
2274 CallArg::pure(&consensus_commit_timestamp_ms),
2275 ],
2276 );
2277 assert_invariant!(
2278 res.is_ok(),
2279 "Unable to generate consensus_commit_prologue transaction!"
2280 );
2281 builder.finish()
2282 };
2283 programmable_transactions::execution::execute::<execution_mode::System>(
2284 protocol_config,
2285 metrics,
2286 move_vm,
2287 temporary_store,
2288 tx_ctx,
2289 gas_charger,
2290 pt,
2291 trace_builder_opt,
2292 )
2293 .map_err(|(e, _)| e)?;
2294 Ok(())
2295 }
2296
2297 fn setup_randomness_state_update(
2303 update: RandomnessStateUpdate,
2304 temporary_store: &mut TemporaryStore<'_>,
2305 tx_ctx: Rc<RefCell<TxContext>>,
2306 move_vm: &Arc<MoveVM>,
2307 gas_charger: &mut GasCharger,
2308 protocol_config: &ProtocolConfig,
2309 metrics: Arc<LimitsMetrics>,
2310 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2311 ) -> Result<(), ExecutionError> {
2312 let pt = {
2313 let mut builder = ProgrammableTransactionBuilder::new();
2314 let res = builder.move_call(
2315 ObjectId::FRAMEWORK,
2316 Identifier::RANDOM_MODULE,
2317 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
2318 vec![],
2319 vec![
2320 CallArg::Shared(SharedObjectReference::new(
2321 ObjectId::RANDOMNESS_STATE,
2322 update.randomness_obj_initial_shared_version,
2323 true,
2324 )),
2325 CallArg::pure(&update.randomness_round),
2326 CallArg::pure(&update.random_bytes),
2327 ],
2328 );
2329 assert_invariant!(
2330 res.is_ok(),
2331 "Unable to generate randomness_state_update transaction!"
2332 );
2333 builder.finish()
2334 };
2335 programmable_transactions::execution::execute::<execution_mode::System>(
2336 protocol_config,
2337 metrics,
2338 move_vm,
2339 temporary_store,
2340 tx_ctx,
2341 gas_charger,
2342 pt,
2343 trace_builder_opt,
2344 )
2345 .map_err(|(e, _)| e)?;
2346 Ok(())
2347 }
2348
2349 fn setup_transaction_deny_rules_create(
2355 mut builder: ProgrammableTransactionBuilder,
2356 ) -> Result<ProgrammableTransactionBuilder, ExecutionError> {
2357 let res = builder.move_call(
2358 ObjectId::FRAMEWORK,
2359 TRANSACTION_DENY_RULES_MODULE,
2360 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME,
2361 vec![],
2362 vec![],
2363 );
2364 assert_invariant!(
2365 res.is_ok(),
2366 "Unable to generate transaction_deny_rules create transaction!"
2367 );
2368 Ok(builder)
2369 }
2370
2371 fn setup_transaction_deny_rules_update(
2375 update: TransactionDenyRulesUpdate,
2376 temporary_store: &mut TemporaryStore<'_>,
2377 tx_ctx: Rc<RefCell<TxContext>>,
2378 move_vm: &Arc<MoveVM>,
2379 gas_charger: &mut GasCharger,
2380 protocol_config: &ProtocolConfig,
2381 metrics: Arc<LimitsMetrics>,
2382 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2383 ) -> Result<(), ExecutionError> {
2384 let pt = {
2385 let mut builder = ProgrammableTransactionBuilder::new();
2386 let res = builder.move_call(
2390 ObjectId::FRAMEWORK,
2391 TRANSACTION_DENY_RULES_MODULE,
2392 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
2393 vec![],
2394 vec![
2395 CallArg::Shared(SharedObjectReference::new(
2396 ObjectId::TRANSACTION_DENY_RULES,
2397 update.deny_rules_obj_initial_shared_version,
2398 true,
2399 )),
2400 CallArg::pure(&update.added_addresses),
2401 CallArg::pure(&update.removed_addresses),
2402 CallArg::pure(&update.added_objects),
2403 CallArg::pure(&update.removed_objects),
2404 CallArg::pure(&update.added_packages),
2405 CallArg::pure(&update.removed_packages),
2406 CallArg::pure(&update.package_publish_disabled),
2407 CallArg::pure(&update.package_upgrade_disabled),
2408 CallArg::pure(&update.shared_object_disabled),
2409 CallArg::pure(&update.user_transaction_disabled),
2410 CallArg::pure(&update.receiving_objects_disabled),
2411 CallArg::pure(&update.move_authenticator_disabled),
2412 ],
2413 );
2414 assert_invariant!(
2415 res.is_ok(),
2416 "Unable to generate transaction_deny_rules update transaction!"
2417 );
2418 builder.finish()
2419 };
2420 programmable_transactions::execution::execute::<execution_mode::System>(
2421 protocol_config,
2422 metrics,
2423 move_vm,
2424 temporary_store,
2425 tx_ctx,
2426 gas_charger,
2427 pt,
2428 trace_builder_opt,
2429 )
2430 .map(|(results, _timings)| results)
2431 .map_err(|(error, _timings)| error)
2432 }
2433
2434 fn setup_authenticator_move_call(
2441 authenticator: MoveAuthenticator,
2442 authenticator_function_ref: AuthenticatorFunctionRefV1,
2443 ) -> Result<ProgrammableTransaction, ExecutionError> {
2444 let mut builder = ProgrammableTransactionBuilder::new();
2445
2446 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
2447 args.extend(authenticator.call_args().to_owned());
2448
2449 let res = builder.move_call(
2450 authenticator_function_ref.package,
2451 Identifier::new(authenticator_function_ref.module.clone()).expect(
2452 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2453 ),
2454 Identifier::new(authenticator_function_ref.function).expect(
2455 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2456 ),
2457 authenticator.type_args().to_vec(),
2458 args,
2459 );
2460
2461 assert_invariant!(
2462 res.is_ok(),
2463 "Unable to generate an account authenticator call transaction!"
2464 );
2465
2466 Ok(builder.finish())
2467 }
2468
2469 fn resolve_sponsor(gas_data: &GasPayment, transaction_signer: &Address) -> Option<Address> {
2470 let gas_owner = gas_data.owner;
2471 if &gas_owner == transaction_signer {
2472 None
2473 } else {
2474 Some(gas_owner)
2475 }
2476 }
2477}