1pub use checked::*;
6
7#[iota_macros::with_checked_arithmetic]
8mod checked {
9
10 use std::{
11 cell::RefCell,
12 collections::{BTreeMap, BTreeSet, HashSet},
13 rc::Rc,
14 sync::Arc,
15 };
16
17 use iota_move_natives::all_natives;
18 use iota_protocol_config::{LimitThresholdCrossed, ProtocolConfig, check_limit_by_meter};
19 use iota_sdk_types::{
20 Address, Argument, ChangeEpoch, ChangeEpochV2, ChangeEpochV3, ChangeEpochV4, Command,
21 EndOfEpochTransactionKind, ExecutionStatus, GasCostSummary, GasPayment, GenesisTransaction,
22 Identifier, MoveAuthenticator, ObjectId, ProgrammableTransaction, RandomnessStateUpdate,
23 SharedObjectReference, StructTag, SystemPackage, TransactionDenyRulesUpdate,
24 TransactionDigest, TransactionEffects, TransactionKind, TypeTag, Version,
25 };
26 #[cfg(msim)]
27 use iota_types::iota_system_state::advance_epoch_result_injection::maybe_modify_result;
28 use iota_types::{
29 account_abstraction::authenticator_function::{
30 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
31 AuthenticatorFunctionRefV1, MoveAuthenticatorForExecution,
32 MoveAuthenticatorsForExecution,
33 },
34 auth_context::{AuthContext, AuthContextData},
35 balance::{BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME},
36 base_types::TxContext,
37 clock::CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
38 committee::EpochId,
39 error::{ExecutionError, ExecutionErrorKind},
40 execution::{
41 ExecutionResults, ExecutionResultsV1, ExecutionTiming, ResultWithTimings, SharedInput,
42 is_certificate_denied,
43 },
44 execution_config_utils::to_binary_config,
45 gas::{IotaGasStatus, IotaGasStatusAPI},
46 inner_temporary_store::InnerTemporaryStore,
47 iota_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams},
48 messages_checkpoint::CheckpointTimestamp,
49 metrics::LimitsMetrics,
50 move_authenticator::MoveAuthenticatorExt,
51 object::{OBJECT_START_VERSION, Object, ObjectInner},
52 programmable_transaction_builder::ProgrammableTransactionBuilder,
53 randomness_state::RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
54 storage::{BackingStore, Storage},
55 transaction::{
56 CallArg, CancelledObjects, CheckedInputObjects, InputObjects, TransactionKindExt,
57 },
58 transaction_deny_rules::{
59 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME, TRANSACTION_DENY_RULES_MODULE,
60 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
61 },
62 };
63 use move_binary_format::CompiledModule;
64 use move_trace_format::format::MoveTraceBuilder;
65 use move_vm_runtime::move_vm::MoveVM;
66 use tracing::{info, instrument, trace, warn};
67
68 use crate::{
69 adapter::new_move_vm,
70 execution_mode::{self, ExecutionMode},
71 gas_charger::GasCharger,
72 programmable_transactions,
73 temporary_store::TemporaryStore,
74 type_layout_resolver::TypeLayoutResolver,
75 };
76
77 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
89 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
90 store: &dyn BackingStore,
91 input_objects: CheckedInputObjects,
92 gas_data: GasPayment,
93 gas_status: IotaGasStatus,
94 transaction_kind: TransactionKind,
95 transaction_signer: Address,
96 transaction_digest: TransactionDigest,
97 move_vm: &Arc<MoveVM>,
98 epoch_id: &EpochId,
99 epoch_timestamp_ms: u64,
100 protocol_config: &ProtocolConfig,
101 metrics: Arc<LimitsMetrics>,
102 enable_expensive_checks: bool,
103 certificate_deny_set: &HashSet<TransactionDigest>,
104 trace_builder_opt: &mut Option<MoveTraceBuilder>,
105 ) -> (
106 InnerTemporaryStore,
107 IotaGasStatus,
108 TransactionEffects,
109 Vec<ExecutionTiming>,
110 Result<Mode::ExecutionResults, ExecutionError>,
111 ) {
112 let input_objects = input_objects.into_inner();
113 let mutable_inputs = if enable_expensive_checks {
114 input_objects.mutable_inputs().keys().copied().collect()
115 } else {
116 HashSet::new()
117 };
118 let shared_object_refs = input_objects.filter_shared_objects();
119 let receiving_objects = transaction_kind.receiving_objects();
120 let transaction_dependencies = input_objects.transaction_dependencies();
121 let contains_deleted_input = input_objects.contains_deleted_objects();
122 let cancelled_objects = input_objects.get_cancelled_objects();
123
124 let temporary_store = TemporaryStore::new(
125 store,
126 input_objects,
127 receiving_objects,
128 transaction_digest,
129 protocol_config,
130 *epoch_id,
131 );
132
133 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
134 let gas_price = gas_status.gas_price();
135 let rgp = gas_status.reference_gas_price();
136 let gas_charger = GasCharger::new(
137 transaction_digest,
138 gas_data.objects,
139 gas_status,
140 protocol_config,
141 );
142
143 let tx_ctx = TxContext::new_from_components(
144 &transaction_signer,
145 &transaction_digest,
146 epoch_id,
147 epoch_timestamp_ms,
148 rgp,
149 gas_price,
150 gas_data.budget,
151 sponsor,
152 protocol_config,
153 );
154 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
155
156 execute_transaction_to_effects_inner::<Mode>(
157 temporary_store,
158 gas_charger,
159 tx_ctx,
160 &mutable_inputs,
161 shared_object_refs,
162 transaction_dependencies,
163 contains_deleted_input,
164 cancelled_objects,
165 transaction_kind,
166 transaction_signer,
167 transaction_digest,
168 move_vm,
169 epoch_id,
170 protocol_config,
171 metrics,
172 enable_expensive_checks,
173 certificate_deny_set,
174 trace_builder_opt,
175 None,
176 )
177 }
178
179 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
182 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
183 mut temporary_store: TemporaryStore,
184 mut gas_charger: GasCharger,
185 tx_ctx: Rc<RefCell<TxContext>>,
186 mutable_inputs: &HashSet<ObjectId>,
187 shared_object_refs: Vec<SharedInput>,
188 mut transaction_dependencies: BTreeSet<TransactionDigest>,
189 contains_deleted_input: bool,
190 cancelled_objects: Option<(CancelledObjects, Version)>,
191 transaction_kind: TransactionKind,
192 transaction_signer: Address,
193 transaction_digest: TransactionDigest,
194 move_vm: &Arc<MoveVM>,
195 epoch_id: &EpochId,
196 protocol_config: &ProtocolConfig,
197 metrics: Arc<LimitsMetrics>,
198 enable_expensive_checks: bool,
199 certificate_deny_set: &HashSet<TransactionDigest>,
200 trace_builder_opt: &mut Option<MoveTraceBuilder>,
201 pre_execution_result_opt: Option<
202 Result<
203 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
204 ExecutionError,
205 >,
206 >,
207 ) -> (
208 InnerTemporaryStore,
209 IotaGasStatus,
210 TransactionEffects,
211 Vec<ExecutionTiming>,
212 Result<Mode::ExecutionResults, ExecutionError>,
213 ) {
214 let is_epoch_change = transaction_kind.is_end_of_epoch();
215 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
216
217 let (gas_cost_summary, execution_result, timings) = execute_transaction::<Mode>(
218 &mut temporary_store,
219 transaction_kind,
220 &mut gas_charger,
221 tx_ctx,
222 move_vm,
223 protocol_config,
224 metrics,
225 enable_expensive_checks,
226 deny_cert,
227 contains_deleted_input,
228 cancelled_objects,
229 trace_builder_opt,
230 pre_execution_result_opt,
231 );
232
233 let status = if let Err(error) = &execution_result {
234 elaborate_error_logs(error, transaction_digest)
235 } else {
236 ExecutionStatus::Success
237 };
238
239 #[skip_checked_arithmetic]
240 trace!(
241 tx_digest = ?transaction_digest,
242 computation_gas_cost = gas_cost_summary.computation_cost,
243 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
244 storage_gas_cost = gas_cost_summary.storage_cost,
245 storage_gas_rebate = gas_cost_summary.storage_rebate,
246 "Finished execution of transaction with status {:?}",
247 status
248 );
249
250 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
254
255 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
256 temporary_store
257 .check_ownership_invariants(
258 &transaction_signer,
259 &mut gas_charger,
260 mutable_inputs,
261 is_epoch_change,
262 )
263 .unwrap()
264 } let (inner, effects) = temporary_store.into_effects(
267 shared_object_refs,
268 &transaction_digest,
269 transaction_dependencies,
270 gas_cost_summary,
271 status,
272 &mut gas_charger,
273 *epoch_id,
274 );
275
276 (
277 inner,
278 gas_charger.into_gas_status(),
279 effects,
280 timings,
281 execution_result,
282 )
283 }
284
285 #[instrument(
304 name = "tx_authenticate_then_execute_to_effects",
305 level = "debug",
306 skip_all
307 )]
308 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
309 store: &dyn BackingStore,
310 protocol_config: &ProtocolConfig,
312 metrics: Arc<LimitsMetrics>,
313 enable_expensive_checks: bool,
314 certificate_deny_set: &HashSet<TransactionDigest>,
315 epoch_id: &EpochId,
317 epoch_timestamp_ms: u64,
318 gas_data: GasPayment,
320 gas_status: IotaGasStatus,
321 authenticators: MoveAuthenticatorsForExecution,
323 authenticator_and_transaction_input_objects: CheckedInputObjects,
324 transaction_kind: TransactionKind,
326 transaction_signer: Address,
327 transaction_digest: TransactionDigest,
328 auth_context_data: AuthContextData,
329 trace_builder_opt: &mut Option<MoveTraceBuilder>,
331 move_vm: &Arc<MoveVM>,
333 ) -> (
334 InnerTemporaryStore,
335 IotaGasStatus,
336 TransactionEffects,
337 Vec<ExecutionTiming>,
338 Result<Mode::ExecutionResults, ExecutionError>,
339 ) {
340 let input_objects = authenticator_and_transaction_input_objects.into_inner();
346 let mutable_inputs = if enable_expensive_checks {
348 input_objects.mutable_inputs().keys().copied().collect()
349 } else {
350 HashSet::new()
351 };
352 let shared_object_refs = input_objects.filter_shared_objects();
354 let transaction_receiving_objects = transaction_kind.receiving_objects();
356 let transaction_dependencies = input_objects.transaction_dependencies();
358 let contains_deleted_input = input_objects.contains_deleted_objects();
361 let mut cancelled_objects = input_objects.get_cancelled_objects();
362
363 let mut temporary_store = TemporaryStore::new(
365 store,
366 input_objects,
367 transaction_receiving_objects,
368 transaction_digest,
369 protocol_config,
370 *epoch_id,
371 );
372
373 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
375 let gas_owner = gas_data.owner;
376 let gas_price = gas_status.gas_price();
377 let rgp = gas_status.reference_gas_price();
378 let mut gas_charger = GasCharger::new(
379 transaction_digest,
380 gas_data.objects,
381 gas_status,
382 protocol_config,
383 );
384
385 let tx_ctx = TxContext::new_from_components(
387 &transaction_signer,
388 &transaction_digest,
389 epoch_id,
390 epoch_timestamp_ms,
391 rgp,
392 gas_price,
393 gas_data.budget,
394 sponsor,
395 protocol_config,
396 );
397 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
398
399 let deterministic_validation = protocol_config.enable_pcool_flow();
400 let run_authenticator =
401 |temporary_store: &mut TemporaryStore<'_>,
402 gas_charger: &mut GasCharger,
403 trace_builder_opt: &mut Option<MoveTraceBuilder>,
404 authenticator: MoveAuthenticator,
405 authenticator_function_ref: AuthenticatorFunctionRef,
406 authenticator_input_objects: CheckedInputObjects| {
407 match authenticator_function_ref {
408 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
409 authenticate_transaction_inner(
410 temporary_store,
411 protocol_config,
412 metrics.clone(),
413 gas_charger,
414 authenticator,
415 authenticator_function_ref_v1,
416 &authenticator_input_objects.into_inner(),
417 transaction_kind.clone(),
418 transaction_digest,
419 auth_context_data.clone(),
420 tx_ctx.clone(),
421 trace_builder_opt,
422 move_vm,
423 )
424 }
425 }
426 };
427
428 let cancellation_check =
434 run_inputs_checks(protocol_config, false, false, cancelled_objects.take());
435
436 let (authentication_execution_result, gas_owner_authorized) = match cancellation_check {
450 Err(error) => {
453 let gas_owner_authorized = match &authenticators {
454 MoveAuthenticatorsForExecution::ResolutionFailed { accounts, .. } => {
455 !accounts.contains(&gas_owner)
456 }
457 MoveAuthenticatorsForExecution::Resolved(authenticators) => !authenticators
458 .iter()
459 .any(|authenticator| authenticator.authenticator.address() == gas_owner),
460 };
461 (Err(error), gas_owner_authorized)
462 }
463 Ok(()) => {
464 let (authentication_result, gas_owner_authorized) = match authenticators {
465 MoveAuthenticatorsForExecution::ResolutionFailed {
466 error,
467 accounts,
468 gas_owner: gas_owner_authenticator,
469 } => {
470 if !accounts.contains(&gas_owner) {
471 (Err(error), true)
472 } else {
473 match gas_owner_authenticator
474 .filter(|_| deterministic_validation)
475 .map(|gas_owner_authenticator| *gas_owner_authenticator)
476 {
477 Some(MoveAuthenticatorForExecution {
478 authenticator,
479 function_ref,
480 input_objects: authenticator_input_objects,
481 }) => {
482 let AuthenticatorFunctionRefForExecution {
483 authenticator_function_ref,
484 loaded_object_id,
485 loaded_object_metadata,
486 } = function_ref;
487 temporary_store.save_loaded_runtime_objects(BTreeMap::from([
488 (loaded_object_id, loaded_object_metadata),
489 ]));
490 match run_authenticator(
491 &mut temporary_store,
492 &mut gas_charger,
493 trace_builder_opt,
494 authenticator,
495 authenticator_function_ref,
496 authenticator_input_objects,
497 ) {
498 Ok(()) => (Err(error), true),
499 Err(gas_owner_error) => (Err(gas_owner_error), false),
500 }
501 }
502 None => (Err(error), false),
503 }
504 }
505 }
506 MoveAuthenticatorsForExecution::Resolved(authenticators) => {
507 let mut authenticators = authenticators
513 .into_iter()
514 .map(
515 |MoveAuthenticatorForExecution {
516 authenticator,
517 function_ref,
518 input_objects: authenticator_input_objects,
519 }| {
520 let AuthenticatorFunctionRefForExecution {
521 authenticator_function_ref,
522 loaded_object_id,
523 loaded_object_metadata,
524 } = function_ref;
525
526 temporary_store.save_loaded_runtime_objects(BTreeMap::from([
530 (loaded_object_id, loaded_object_metadata),
531 ]));
532
533 (
534 authenticator,
535 authenticator_function_ref,
536 authenticator_input_objects,
537 )
538 },
539 )
540 .collect::<Vec<_>>();
541
542 if deterministic_validation {
543 if let Some(position) =
544 authenticators.iter().position(|(authenticator, ..)| {
545 authenticator.address() == gas_owner
546 })
547 {
548 let gas_owner_authenticator = authenticators.remove(position);
549 authenticators.insert(0, gas_owner_authenticator);
550 }
551 }
552
553 let mut gas_owner_authorized = !authenticators
554 .iter()
555 .any(|(authenticator, ..)| authenticator.address() == gas_owner);
556
557 let result = authenticators.into_iter().try_for_each(
563 |(
564 authenticator,
565 authenticator_function_ref,
566 authenticator_input_objects,
567 )| {
568 let account = authenticator.address();
569 let result = run_authenticator(
570 &mut temporary_store,
571 &mut gas_charger,
572 trace_builder_opt,
573 authenticator,
574 authenticator_function_ref,
575 authenticator_input_objects,
576 );
577 if result.is_ok() && account == gas_owner {
578 gas_owner_authorized = true;
579 }
580 result
581 },
582 );
583 (result, gas_owner_authorized)
584 }
585 };
586
587 (
591 report_authentication_error(authentication_result, protocol_config),
592 gas_owner_authorized,
593 )
594 }
595 };
596
597 let authentication_execution_result = match authentication_execution_result {
601 Err(error) if !gas_owner_authorized && protocol_config.enable_pcool_flow() => {
602 return execute_without_gas_charge_to_effects::<Mode>(
603 temporary_store,
604 gas_charger,
605 shared_object_refs,
606 transaction_dependencies,
607 contains_deleted_input,
608 cancelled_objects,
609 transaction_digest,
610 epoch_id,
611 protocol_config,
612 certificate_deny_set,
613 error,
614 );
615 }
616 result => result,
617 };
618 execute_transaction_to_effects_inner::<Mode>(
626 temporary_store,
627 gas_charger,
628 tx_ctx,
629 &mutable_inputs,
630 shared_object_refs,
631 transaction_dependencies,
632 contains_deleted_input,
633 cancelled_objects,
634 transaction_kind,
635 transaction_signer,
636 transaction_digest,
637 move_vm,
638 epoch_id,
639 protocol_config,
640 metrics,
641 enable_expensive_checks,
642 certificate_deny_set,
643 trace_builder_opt,
644 Some(authentication_execution_result),
645 )
646 }
647
648 fn execute_without_gas_charge_to_effects<Mode: ExecutionMode>(
665 mut temporary_store: TemporaryStore,
666 mut gas_charger: GasCharger,
667 shared_object_refs: Vec<SharedInput>,
668 mut transaction_dependencies: BTreeSet<TransactionDigest>,
669 contains_deleted_input: bool,
670 cancelled_objects: Option<(CancelledObjects, Version)>,
671 transaction_digest: TransactionDigest,
672 epoch_id: &EpochId,
673 protocol_config: &ProtocolConfig,
674 certificate_deny_set: &HashSet<TransactionDigest>,
675 authentication_error: ExecutionError,
676 ) -> (
677 InnerTemporaryStore,
678 IotaGasStatus,
679 TransactionEffects,
680 Vec<ExecutionTiming>,
681 Result<Mode::ExecutionResults, ExecutionError>,
682 ) {
683 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
684 let error = run_inputs_checks(
685 protocol_config,
686 deny_cert,
687 contains_deleted_input,
688 cancelled_objects,
689 )
690 .err()
691 .unwrap_or(authentication_error);
692 let status = elaborate_error_logs(&error, transaction_digest);
693
694 temporary_store.drop_writes();
695 temporary_store.ensure_active_inputs_mutated();
696
697 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
701
702 gas_charger.set_gas_coin_without_smashing();
703 let (inner, effects) = temporary_store.into_effects(
704 shared_object_refs,
705 &transaction_digest,
706 transaction_dependencies,
707 GasCostSummary::default(),
708 status,
709 &mut gas_charger,
710 *epoch_id,
711 );
712
713 (
714 inner,
715 gas_charger.into_gas_status(),
716 effects,
717 vec![],
718 Err(error),
719 )
720 }
721
722 #[instrument(name = "tx_validate", level = "debug", skip_all)]
727 pub fn authenticate_transaction(
728 store: &dyn BackingStore,
729 protocol_config: &ProtocolConfig,
731 metrics: Arc<LimitsMetrics>,
732 epoch_id: &EpochId,
734 epoch_timestamp_ms: u64,
735 gas_data: GasPayment,
737 gas_status: IotaGasStatus,
738 authenticators: Vec<(
740 MoveAuthenticator,
741 AuthenticatorFunctionRef,
742 CheckedInputObjects,
743 )>,
744 aggregated_authenticator_input_objects: CheckedInputObjects,
745 transaction_kind: TransactionKind,
747 transaction_signer: Address,
748 transaction_digest: TransactionDigest,
749 auth_context_data: AuthContextData,
750 trace_builder_opt: &mut Option<MoveTraceBuilder>,
752 move_vm: &Arc<MoveVM>,
754 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
755 {
756 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
758 let gas_price = gas_status.gas_price();
759 let rgp = gas_status.reference_gas_price();
760 let mut gas_charger =
761 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
762
763 let tx_ctx = TxContext::new_from_components(
766 &transaction_signer,
767 &transaction_digest,
768 epoch_id,
769 epoch_timestamp_ms,
770 rgp,
771 gas_price,
772 gas_data.budget,
773 sponsor,
774 protocol_config,
775 );
776 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
777
778 let mut temporary_store = TemporaryStore::new(
779 store,
780 aggregated_authenticator_input_objects.into_inner(),
781 vec![],
782 transaction_digest,
783 protocol_config,
784 *epoch_id,
785 );
786
787 let authentication_execution_result = authenticators.into_iter().try_for_each(
789 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
790 match authenticator_function_ref {
791 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
792 authenticate_transaction_inner(
793 &mut temporary_store,
794 protocol_config,
795 metrics.clone(),
796 &mut gas_charger,
797 authenticator,
798 authenticator_function_ref_v1,
799 &authenticator_input_objects.into_inner(),
800 transaction_kind.clone(),
801 transaction_digest,
802 auth_context_data.clone(),
803 tx_ctx.clone(),
804 trace_builder_opt,
805 move_vm,
806 )
807 }
808 }
809 },
810 );
811
812 report_authentication_error(authentication_execution_result, protocol_config)
813 }
814
815 #[instrument(name = "tx_validate", level = "debug", skip_all)]
825 pub fn authenticate_transaction_inner(
826 temporary_store: &mut TemporaryStore<'_>,
827 protocol_config: &ProtocolConfig,
829 metrics: Arc<LimitsMetrics>,
830 gas_charger: &mut GasCharger,
832 authenticator: MoveAuthenticator,
834 authenticator_function_ref: AuthenticatorFunctionRefV1,
835 authenticator_input_objects: &InputObjects,
836 transaction_kind: TransactionKind,
838 transaction_digest: TransactionDigest,
839 auth_context_data: AuthContextData,
840 tx_ctx: Rc<RefCell<TxContext>>,
841 trace_builder_opt: &mut Option<MoveTraceBuilder>,
843 move_vm: &Arc<MoveVM>,
845 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
846 {
847 debug_assert!(
849 transaction_kind.is_programmable(),
850 "Only programmable transactions are allowed"
851 );
852 debug_assert!(
853 authenticator_input_objects
854 .mutable_inputs()
855 .keys()
856 .copied()
857 .collect::<HashSet<_>>()
858 .is_empty(),
859 "No mutable inputs are allowed"
860 );
861 debug_assert!(
862 authenticator.receiving_objects().is_empty(),
863 "No receiving inputs are allowed"
864 );
865
866 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
867 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
868
869 let auth_ctx = {
871 let TransactionKind::Programmable(ptb) = &transaction_kind else {
872 unreachable!("Only programmable transactions are allowed");
873 };
874 AuthContext::new_from_components(
875 authenticator.digest().into(),
876 auth_context_data.sender_auth_digest,
877 auth_context_data.sponsor_auth_digest,
878 auth_context_data
879 .sender_authenticator_function_ref
880 .and_then(Into::into),
881 auth_context_data
882 .sponsor_authenticator_function_ref
883 .and_then(Into::into),
884 ptb,
885 auth_context_data.transaction_data_bytes,
886 )
887 };
888 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
889
890 temporary_store.store_auth_context(auth_ctx);
894
895 let authentication_execution_result = execute_authenticator_move_call(
897 temporary_store,
898 authenticator,
899 authenticator_function_ref,
900 gas_charger,
901 tx_ctx,
902 move_vm,
903 protocol_config,
904 metrics,
905 false,
906 contains_deleted_input,
907 cancelled_objects,
908 trace_builder_opt,
909 );
910
911 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
913 elaborate_error_logs(error, transaction_digest)
914 } else {
915 ExecutionStatus::Success
916 };
917
918 #[skip_checked_arithmetic]
919 trace!(
920 tx_digest = ?transaction_digest,
921 computation_gas_cost = gas_charger.summary().gas_used(),
922 "Finished authenticator execution of transaction with status {:?}",
923 authentication_execution_status
924 );
925
926 authentication_execution_result
927 }
928
929 #[instrument(name = "auth_execute", level = "debug", skip_all)]
940 fn execute_authenticator_move_call(
941 temporary_store: &mut TemporaryStore<'_>,
942 authenticator: MoveAuthenticator,
943 authenticator_function_ref: AuthenticatorFunctionRefV1,
944 gas_charger: &mut GasCharger,
945 tx_ctx: Rc<RefCell<TxContext>>,
946 move_vm: &Arc<MoveVM>,
947 protocol_config: &ProtocolConfig,
948 metrics: Arc<LimitsMetrics>,
949 deny_cert: bool,
950 contains_deleted_input: bool,
951 cancelled_objects: Option<(CancelledObjects, Version)>,
952 trace_builder_opt: &mut Option<MoveTraceBuilder>,
953 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
954 {
955 run_inputs_checks(
959 protocol_config,
960 deny_cert,
961 contains_deleted_input,
962 cancelled_objects,
963 )
964 .and_then(|()| {
965 let authenticator_move_call =
966 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
967 programmable_transactions::execution::execute::<execution_mode::Authentication>(
968 protocol_config,
969 metrics.clone(),
970 move_vm,
971 temporary_store,
972 tx_ctx,
973 gas_charger,
974 authenticator_move_call,
975 trace_builder_opt,
976 )
977 .map_err(|(e, _)| e)
978 .and_then(|(ok_result, _timings)| {
979 temporary_store.check_move_authenticator_results_consistency()?;
980 Ok(ok_result)
981 })
982 })
983 }
984
985 pub fn execute_genesis_state_update(
992 store: &dyn BackingStore,
993 protocol_config: &ProtocolConfig,
994 metrics: Arc<LimitsMetrics>,
995 move_vm: &Arc<MoveVM>,
996 tx_context: Rc<RefCell<TxContext>>,
997 input_objects: CheckedInputObjects,
998 pt: ProgrammableTransaction,
999 ) -> Result<InnerTemporaryStore, ExecutionError> {
1000 let input_objects = input_objects.into_inner();
1001 let tx_digest = tx_context.borrow().digest();
1002
1003 let mut temporary_store =
1004 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
1005 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
1006 programmable_transactions::execution::execute::<execution_mode::Genesis>(
1007 protocol_config,
1008 metrics,
1009 move_vm,
1010 &mut temporary_store,
1011 tx_context,
1012 &mut gas_charger,
1013 pt,
1014 &mut None,
1015 )
1016 .map_err(|(e, _)| e)?;
1017 temporary_store.update_object_version_and_prev_tx();
1018 Ok(temporary_store.into_inner())
1019 }
1020
1021 #[instrument(name = "tx_execute", level = "debug", skip_all)]
1030 fn execute_transaction<Mode: ExecutionMode>(
1031 temporary_store: &mut TemporaryStore<'_>,
1032 transaction_kind: TransactionKind,
1033 gas_charger: &mut GasCharger,
1034 tx_ctx: Rc<RefCell<TxContext>>,
1035 move_vm: &Arc<MoveVM>,
1036 protocol_config: &ProtocolConfig,
1037 metrics: Arc<LimitsMetrics>,
1038 enable_expensive_checks: bool,
1039 deny_cert: bool,
1040 contains_deleted_input: bool,
1041 cancelled_objects: Option<(CancelledObjects, Version)>,
1042 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1043 pre_execution_result_opt: Option<
1044 Result<
1045 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
1046 ExecutionError,
1047 >,
1048 >,
1049 ) -> (
1050 GasCostSummary,
1051 Result<Mode::ExecutionResults, ExecutionError>,
1052 Vec<ExecutionTiming>,
1053 ) {
1054 gas_charger.smash_gas(temporary_store);
1055
1056 debug_assert!(
1059 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
1060 "No gas charges must be applied yet"
1061 );
1062
1063 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
1064 || transaction_kind.is_end_of_epoch();
1065
1066 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
1067
1068 let tx_digest = tx_ctx.borrow().digest();
1069
1070 let result = gas_charger.charge_input_objects(temporary_store);
1074 let result: ResultWithTimings<Mode::ExecutionResults, ExecutionError> =
1075 result.map_err(|e| (e, vec![])).and_then(
1076 |()| -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
1077 run_inputs_checks(
1078 protocol_config,
1079 deny_cert,
1080 contains_deleted_input,
1081 cancelled_objects,
1082 )
1083 .map_err(|e| (e, vec![]))?;
1084
1085 let mut execution_result = pre_execution_result_opt
1088 .unwrap_or(Ok(()))
1089 .map_err(|e| (e, vec![]))
1090 .and_then(|_| {
1091 execution_loop::<Mode>(
1092 temporary_store,
1093 transaction_kind,
1094 tx_ctx,
1095 move_vm,
1096 gas_charger,
1097 protocol_config,
1098 metrics.clone(),
1099 trace_builder_opt,
1100 )
1101 });
1102
1103 let meter_check = check_meter_limit(
1104 temporary_store,
1105 gas_charger,
1106 protocol_config,
1107 metrics.clone(),
1108 );
1109 if let Err(e) = meter_check {
1110 execution_result = Err((e, vec![]));
1111 }
1112
1113 if execution_result.is_ok() {
1114 let gas_check = check_written_objects_limit(
1115 temporary_store,
1116 gas_charger,
1117 protocol_config,
1118 metrics,
1119 );
1120 if let Err(e) = gas_check {
1121 execution_result = Err((e, vec![]));
1122 }
1123 }
1124
1125 execution_result
1126 },
1127 );
1128
1129 let (mut result, timings) = match result {
1130 Ok((r, t)) => (Ok(r), t),
1131 Err((e, t)) => (Err(e), t),
1132 };
1133
1134 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
1135 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
1144
1145 if let Err(e) = run_conservation_checks::<Mode>(
1146 temporary_store,
1147 gas_charger,
1148 tx_digest,
1149 move_vm,
1150 enable_expensive_checks,
1151 &cost_summary,
1152 is_genesis_or_epoch_change_tx,
1153 advance_epoch_gas_summary,
1154 ) {
1155 result = Err(e);
1157 }
1158
1159 (cost_summary, result, timings)
1160 }
1161
1162 fn report_authentication_error<T>(
1168 authentication_execution_result: Result<T, ExecutionError>,
1169 protocol_config: &ProtocolConfig,
1170 ) -> Result<T, ExecutionError> {
1171 if protocol_config.report_move_authentication_error() {
1172 authentication_execution_result.map_err(ExecutionError::into_move_authentication_error)
1173 } else {
1174 authentication_execution_result
1175 }
1176 }
1177
1178 fn elaborate_error_logs(
1181 execution_error: &ExecutionError,
1182 transaction_digest: TransactionDigest,
1183 ) -> ExecutionStatus {
1184 use ExecutionErrorKind as K;
1185 match execution_error.kind() {
1186 K::InvariantViolation | K::VmInvariantViolation => {
1187 #[skip_checked_arithmetic]
1188 tracing::error!(
1189 kind = ?execution_error.kind(),
1190 tx_digest = ?transaction_digest,
1191 "INVARIANT VIOLATION! Source: {:?}",
1192 execution_error.source(),
1193 );
1194 }
1195
1196 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
1197 #[skip_checked_arithmetic]
1198 tracing::debug!(
1199 kind = ?execution_error.kind(),
1200 tx_digest = ?transaction_digest,
1201 "Verification Error. Source: {:?}",
1202 execution_error.source(),
1203 );
1204 }
1205
1206 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
1207 #[skip_checked_arithmetic]
1208 tracing::debug!(
1209 kind = ?execution_error.kind(),
1210 tx_digest = ?transaction_digest,
1211 "Publish/Upgrade Error. Source: {:?}",
1212 execution_error.source(),
1213 )
1214 }
1215
1216 _ => (),
1217 };
1218
1219 let (status, command) = execution_error.to_execution_status();
1220 ExecutionStatus::new_failure(status, command)
1221 }
1222
1223 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
1232 fn run_conservation_checks<Mode: ExecutionMode>(
1233 temporary_store: &mut TemporaryStore<'_>,
1234 gas_charger: &mut GasCharger,
1235 tx_digest: TransactionDigest,
1236 move_vm: &Arc<MoveVM>,
1237 enable_expensive_checks: bool,
1238 cost_summary: &GasCostSummary,
1239 is_genesis_or_epoch_change_tx: bool,
1240 advance_epoch_gas_summary: Option<(u64, u64)>,
1241 ) -> Result<(), ExecutionError> {
1242 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
1243 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
1244 let conservation_result = {
1247 temporary_store
1248 .check_iota_conserved(cost_summary)
1249 .and_then(|()| {
1250 if enable_expensive_checks {
1251 let mut layout_resolver =
1254 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1255 temporary_store.check_iota_conserved_expensive(
1256 cost_summary,
1257 advance_epoch_gas_summary,
1258 &mut layout_resolver,
1259 )
1260 } else {
1261 Ok(())
1262 }
1263 })
1264 };
1265 if let Err(conservation_err) = conservation_result {
1266 result = Err(conservation_err);
1270 gas_charger.reset(temporary_store);
1271 gas_charger.charge_gas(temporary_store, &mut result);
1272 if let Err(recovery_err) = temporary_store
1274 .check_iota_conserved(cost_summary)
1275 .and_then(|()| {
1276 if enable_expensive_checks {
1277 let mut layout_resolver =
1280 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1281 temporary_store.check_iota_conserved_expensive(
1282 cost_summary,
1283 advance_epoch_gas_summary,
1284 &mut layout_resolver,
1285 )
1286 } else {
1287 Ok(())
1288 }
1289 })
1290 {
1291 panic!(
1295 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1296 tx_digest,
1297 recovery_err,
1298 gas_charger.summary()
1299 )
1300 }
1301 }
1302 } result
1306 }
1307
1308 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1319 fn run_inputs_checks(
1320 protocol_config: &ProtocolConfig,
1321 deny_cert: bool,
1322 contains_deleted_input: bool,
1323 cancelled_objects: Option<(CancelledObjects, Version)>,
1324 ) -> Result<(), ExecutionError> {
1325 if deny_cert {
1326 Err(ExecutionError::new(
1327 ExecutionErrorKind::CertificateDenied,
1328 None,
1329 ))
1330 } else if contains_deleted_input {
1331 Err(ExecutionError::new(
1332 ExecutionErrorKind::InputObjectDeleted,
1333 None,
1334 ))
1335 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1336 match reason {
1337 version if version.is_congested() => Err(ExecutionError::new(
1338 match cancelled_objects {
1339 CancelledObjects::GasObject => {
1343 ExecutionErrorKind::ExecutionCanceledDueToExecutionWorkerCongestion {
1344 suggested_gas_price: version
1345 .get_congested_version_suggested_gas_price()
1346 .expect(
1347 "execution-worker congestion control requires the gas \
1348 price feedback mechanism",
1349 ),
1350 }
1351 }
1352 CancelledObjects::SharedObjects(congested_objects) => {
1353 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1354 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestionV2 {
1355 congested_objects,
1356 suggested_gas_price: version
1357 .get_congested_version_suggested_gas_price()
1358 .unwrap(),
1359 }
1360 } else {
1361 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestion {
1366 congested_objects,
1367 }
1368 }
1369 }
1370 },
1371 None,
1372 )),
1373 Version::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1374 ExecutionErrorKind::ExecutionCanceledDueToRandomnessUnavailable,
1375 None,
1376 )),
1377 _ => panic!("invalid cancellation reason Version: {reason}"),
1378 }
1379 } else {
1380 Ok(())
1381 }
1382 }
1383
1384 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1389 fn check_meter_limit(
1390 temporary_store: &mut TemporaryStore<'_>,
1391 gas_charger: &mut GasCharger,
1392 protocol_config: &ProtocolConfig,
1393 metrics: Arc<LimitsMetrics>,
1394 ) -> Result<(), ExecutionError> {
1395 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1396
1397 match check_limit_by_meter!(
1402 !gas_charger.is_unmetered(),
1403 effects_estimated_size,
1404 protocol_config.max_serialized_tx_effects_size_bytes(),
1405 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1406 metrics.excessive_estimated_effects_size
1407 ) {
1408 LimitThresholdCrossed::None => Ok(()),
1409 LimitThresholdCrossed::Soft(_, limit) => {
1410 warn!(
1411 effects_estimated_size = effects_estimated_size,
1412 soft_limit = limit,
1413 "Estimated transaction effects size crossed soft limit",
1414 );
1415 Ok(())
1416 }
1417 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1418 ExecutionErrorKind::EffectsTooLarge {
1419 current_size: effects_estimated_size as u64,
1420 max_size: lim as u64,
1421 },
1422 "Transaction effects are too large",
1423 )),
1424 }
1425 }
1426
1427 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1432 fn check_written_objects_limit(
1433 temporary_store: &mut TemporaryStore<'_>,
1434 gas_charger: &mut GasCharger,
1435 protocol_config: &ProtocolConfig,
1436 metrics: Arc<LimitsMetrics>,
1437 ) -> Result<(), ExecutionError> {
1438 if let (Some(normal_lim), Some(system_lim)) = (
1439 protocol_config.max_size_written_objects_as_option(),
1440 protocol_config.max_size_written_objects_system_tx_as_option(),
1441 ) {
1442 let written_objects_size = temporary_store.written_objects_size();
1443
1444 match check_limit_by_meter!(
1445 !gas_charger.is_unmetered(),
1446 written_objects_size,
1447 normal_lim,
1448 system_lim,
1449 metrics.excessive_written_objects_size
1450 ) {
1451 LimitThresholdCrossed::None => (),
1452 LimitThresholdCrossed::Soft(_, limit) => {
1453 warn!(
1454 written_objects_size = written_objects_size,
1455 soft_limit = limit,
1456 "Written objects size crossed soft limit",
1457 )
1458 }
1459 LimitThresholdCrossed::Hard(_, lim) => {
1460 return Err(ExecutionError::new_with_source(
1461 ExecutionErrorKind::WrittenObjectsTooLarge {
1462 object_size: written_objects_size as u64,
1463 max_object_size: lim as u64,
1464 },
1465 "Written objects size crossed hard limit",
1466 ));
1467 }
1468 };
1469 }
1470
1471 Ok(())
1472 }
1473
1474 #[instrument(level = "debug", skip_all)]
1481 fn execution_loop<Mode: ExecutionMode>(
1482 temporary_store: &mut TemporaryStore<'_>,
1483 transaction_kind: TransactionKind,
1484 tx_ctx: Rc<RefCell<TxContext>>,
1485 move_vm: &Arc<MoveVM>,
1486 gas_charger: &mut GasCharger,
1487 protocol_config: &ProtocolConfig,
1488 metrics: Arc<LimitsMetrics>,
1489 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1490 ) -> ResultWithTimings<Mode::ExecutionResults, ExecutionError> {
1491 let result = match transaction_kind {
1492 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1493 if tx_ctx.borrow().epoch() != 0 {
1494 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1495 }
1496
1497 for genesis_object in objects {
1498 let object = ObjectInner {
1499 data: genesis_object.data,
1500 owner: genesis_object.owner,
1501 previous_transaction: tx_ctx.borrow().digest(),
1502 storage_rebate: 0,
1503 };
1504 temporary_store.create_object(object.into());
1505 }
1506
1507 temporary_store.record_execution_results(ExecutionResults::V1(
1508 ExecutionResultsV1 {
1509 user_events: events,
1510 ..Default::default()
1511 },
1512 ));
1513
1514 Ok((Mode::empty_results(), vec![]))
1515 }
1516 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1517 setup_consensus_commit(
1518 prologue.commit_timestamp_ms,
1519 temporary_store,
1520 tx_ctx,
1521 move_vm,
1522 gas_charger,
1523 protocol_config,
1524 metrics,
1525 trace_builder_opt,
1526 )
1527 .expect("ConsensusCommitPrologueV1 cannot fail");
1528 Ok((Mode::empty_results(), vec![]))
1529 }
1530 TransactionKind::Programmable(pt) => {
1531 programmable_transactions::execution::execute::<Mode>(
1532 protocol_config,
1533 metrics,
1534 move_vm,
1535 temporary_store,
1536 tx_ctx,
1537 gas_charger,
1538 pt,
1539 trace_builder_opt,
1540 )
1541 }
1542 TransactionKind::EndOfEpoch(txns) => {
1543 let mut builder = ProgrammableTransactionBuilder::new();
1547 let len = txns.len();
1548
1549 for (i, tx) in txns.into_iter().enumerate() {
1550 match tx {
1551 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1552 assert_eq!(i, len - 1);
1553 advance_epoch_v1(
1554 builder,
1555 change_epoch,
1556 temporary_store,
1557 tx_ctx,
1558 move_vm,
1559 gas_charger,
1560 protocol_config,
1561 metrics,
1562 trace_builder_opt,
1563 )
1564 .map_err(|e| (e, vec![]))?;
1565 return Ok((Mode::empty_results(), vec![]));
1566 }
1567 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1568 assert_eq!(i, len - 1);
1569 advance_epoch_v2(
1570 builder,
1571 change_epoch_v2,
1572 temporary_store,
1573 tx_ctx,
1574 move_vm,
1575 gas_charger,
1576 protocol_config,
1577 metrics,
1578 trace_builder_opt,
1579 )
1580 .map_err(|e| (e, vec![]))?;
1581 return Ok((Mode::empty_results(), vec![]));
1582 }
1583 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1584 assert_eq!(i, len - 1);
1585 advance_epoch_v3(
1586 builder,
1587 change_epoch_v3,
1588 temporary_store,
1589 tx_ctx,
1590 move_vm,
1591 gas_charger,
1592 protocol_config,
1593 metrics,
1594 trace_builder_opt,
1595 )
1596 .map_err(|e| (e, vec![]))?;
1597 return Ok((Mode::empty_results(), vec![]));
1598 }
1599 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1600 assert_eq!(i, len - 1);
1601 advance_epoch_v4(
1602 builder,
1603 change_epoch_v4,
1604 temporary_store,
1605 tx_ctx,
1606 move_vm,
1607 gas_charger,
1608 protocol_config,
1609 metrics,
1610 trace_builder_opt,
1611 )
1612 .map_err(|e| (e, vec![]))?;
1613 return Ok((Mode::empty_results(), vec![]));
1614 }
1615 EndOfEpochTransactionKind::TransactionDenyRulesCreate => {
1616 assert!(
1617 protocol_config.enable_pcool_flow(),
1618 "unexpected TransactionDenyRulesCreate: on-chain deny rule governance is not enabled"
1619 );
1620 builder = setup_transaction_deny_rules_create(builder)
1621 .map_err(|e| (e, vec![]))?;
1622 }
1623 _ => unimplemented!(
1624 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1625 ),
1626 }
1627 }
1628 unreachable!(
1629 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1630 )
1631 }
1632 #[allow(deprecated)]
1633 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1634 return Err((
1638 ExecutionError::new(
1639 ExecutionErrorKind::VmInvariantViolation,
1640 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1641 ),
1642 vec![],
1643 ));
1644 }
1645 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1646 setup_randomness_state_update(
1647 randomness_state_update,
1648 temporary_store,
1649 tx_ctx,
1650 move_vm,
1651 gas_charger,
1652 protocol_config,
1653 metrics,
1654 trace_builder_opt,
1655 )
1656 .map_err(|e| (e, vec![]))?;
1657 Ok((Mode::empty_results(), vec![]))
1658 }
1659 TransactionKind::TransactionDenyRulesUpdate(update) => {
1660 assert!(
1661 protocol_config.enable_pcool_flow(),
1662 "unexpected TransactionDenyRulesUpdate: on-chain deny rule governance is not enabled"
1663 );
1664 setup_transaction_deny_rules_update(
1665 update,
1666 temporary_store,
1667 tx_ctx,
1668 move_vm,
1669 gas_charger,
1670 protocol_config,
1671 metrics,
1672 trace_builder_opt,
1673 )
1674 .map_err(|e| (e, vec![]))?;
1675 Ok((Mode::empty_results(), vec![]))
1676 }
1677 _ => unimplemented!(
1678 "a new TransactionKind enum variant was added and needs to be handled"
1679 ),
1680 }?;
1681 temporary_store
1682 .check_execution_results_consistency()
1683 .map_err(|e| (e, vec![]))?;
1684 Ok(result)
1685 }
1686
1687 fn mint_epoch_rewards_in_pt(
1696 builder: &mut ProgrammableTransactionBuilder,
1697 params: &AdvanceEpochParams,
1698 ) -> (Argument, Argument) {
1699 let storage_charge_arg = builder
1701 .input(CallArg::pure(¶ms.storage_charge))
1702 .unwrap();
1703 let storage_charges = builder.programmable_move_call(
1704 ObjectId::FRAMEWORK,
1705 Identifier::BALANCE_MODULE,
1706 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1707 vec![TypeTag::from(StructTag::new_gas())],
1708 vec![storage_charge_arg],
1709 );
1710
1711 let computation_charge_arg = builder
1713 .input(CallArg::pure(¶ms.computation_charge))
1714 .unwrap();
1715 let computation_charges = builder.programmable_move_call(
1716 ObjectId::FRAMEWORK,
1717 Identifier::BALANCE_MODULE,
1718 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1719 vec![TypeTag::from(StructTag::new_gas())],
1720 vec![computation_charge_arg],
1721 );
1722 (storage_charges, computation_charges)
1723 }
1724
1725 pub fn construct_advance_epoch_pt_impl(
1733 mut builder: ProgrammableTransactionBuilder,
1734 params: &AdvanceEpochParams,
1735 call_arg_vec: Vec<CallArg>,
1736 ) -> Result<ProgrammableTransaction, ExecutionError> {
1737 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1739 let mut arguments = vec![
1740 builder
1741 .pure(params.validator_subsidy)
1742 .expect("bcs encoding a u64 should not fail"),
1743 storage_charges,
1744 computation_charges,
1745 ];
1746
1747 let call_arg_arguments = call_arg_vec
1748 .into_iter()
1749 .map(|a| builder.input(a))
1750 .collect::<Result<_, _>>();
1751
1752 assert_invariant!(
1753 call_arg_arguments.is_ok(),
1754 "Unable to generate args for advance_epoch transaction!"
1755 );
1756
1757 arguments.append(&mut call_arg_arguments.unwrap());
1758
1759 info!("Call arguments to advance_epoch transaction: {:?}", params);
1760
1761 let storage_rebates = builder.programmable_move_call(
1762 ObjectId::SYSTEM,
1763 Identifier::IOTA_SYSTEM_MODULE,
1764 ADVANCE_EPOCH_FUNCTION_NAME,
1765 vec![],
1766 arguments,
1767 );
1768
1769 builder.programmable_move_call(
1771 ObjectId::FRAMEWORK,
1772 Identifier::BALANCE_MODULE,
1773 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1774 vec![TypeTag::from(StructTag::new_gas())],
1775 vec![storage_rebates],
1776 );
1777 Ok(builder.finish())
1778 }
1779
1780 pub fn construct_advance_epoch_pt_v1(
1781 builder: ProgrammableTransactionBuilder,
1782 params: &AdvanceEpochParams,
1783 ) -> Result<ProgrammableTransaction, ExecutionError> {
1784 let call_arg_vec = vec![
1789 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), ];
1797 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1798 }
1799
1800 pub fn construct_advance_epoch_pt_v2(
1801 builder: ProgrammableTransactionBuilder,
1802 params: &AdvanceEpochParams,
1803 ) -> Result<ProgrammableTransaction, ExecutionError> {
1804 let call_arg_vec = vec![
1809 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), ];
1819 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1820 }
1821
1822 pub fn construct_advance_epoch_pt_v3(
1823 builder: ProgrammableTransactionBuilder,
1824 params: &AdvanceEpochParams,
1825 ) -> Result<ProgrammableTransaction, ExecutionError> {
1826 let call_arg_vec = vec![
1832 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), ];
1844 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1845 }
1846
1847 pub fn construct_advance_epoch_pt_v4(
1848 builder: ProgrammableTransactionBuilder,
1849 params: &AdvanceEpochParams,
1850 ) -> Result<ProgrammableTransaction, ExecutionError> {
1851 let call_arg_vec = vec![
1857 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), ];
1871 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1872 }
1873
1874 fn advance_epoch_impl(
1881 advance_epoch_pt: ProgrammableTransaction,
1882 params: AdvanceEpochParams,
1883 system_packages: Vec<SystemPackage>,
1884 temporary_store: &mut TemporaryStore<'_>,
1885 tx_ctx: Rc<RefCell<TxContext>>,
1886 move_vm: &Arc<MoveVM>,
1887 gas_charger: &mut GasCharger,
1888 protocol_config: &ProtocolConfig,
1889 metrics: Arc<LimitsMetrics>,
1890 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1891 ) -> Result<(), ExecutionError> {
1892 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1893 protocol_config,
1894 metrics.clone(),
1895 move_vm,
1896 temporary_store,
1897 tx_ctx.clone(),
1898 gas_charger,
1899 advance_epoch_pt,
1900 trace_builder_opt,
1901 );
1902
1903 #[cfg(msim)]
1904 let result = maybe_modify_result(result, params.epoch);
1905
1906 if let Err(err) = &result {
1907 tracing::error!(
1908 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1909 err.0,
1910 temporary_store.objects(),
1911 params,
1912 );
1913 temporary_store.drop_writes();
1914 gas_charger.reset_storage_cost_and_rebate();
1916
1917 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1918 }
1919
1920 let new_vm = new_move_vm(
1921 all_natives(true, protocol_config),
1922 protocol_config,
1923 None,
1925 )
1926 .expect("Failed to create new MoveVM");
1927 process_system_packages(
1928 system_packages,
1929 temporary_store,
1930 tx_ctx,
1931 &new_vm,
1932 gas_charger,
1933 protocol_config,
1934 metrics,
1935 trace_builder_opt,
1936 );
1937
1938 Ok(())
1939 }
1940
1941 fn advance_epoch_v1(
1945 builder: ProgrammableTransactionBuilder,
1946 change_epoch: ChangeEpoch,
1947 temporary_store: &mut TemporaryStore<'_>,
1948 tx_ctx: Rc<RefCell<TxContext>>,
1949 move_vm: &Arc<MoveVM>,
1950 gas_charger: &mut GasCharger,
1951 protocol_config: &ProtocolConfig,
1952 metrics: Arc<LimitsMetrics>,
1953 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1954 ) -> Result<(), ExecutionError> {
1955 let params = AdvanceEpochParams {
1956 epoch: change_epoch.epoch,
1957 next_protocol_version: change_epoch.protocol_version.into(),
1958 validator_subsidy: protocol_config.validator_target_reward(),
1959 storage_charge: change_epoch.storage_charge,
1960 computation_charge: change_epoch.computation_charge,
1961 computation_charge_burned: change_epoch.computation_charge,
1963 storage_rebate: change_epoch.storage_rebate,
1964 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1965 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1966 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1967 max_committee_members_count: 0,
1970 eligible_active_validators: vec![],
1971 scores: vec![],
1972 adjust_rewards_by_score: false,
1973 };
1974 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1975 advance_epoch_impl(
1976 advance_epoch_pt,
1977 params,
1978 change_epoch.system_packages,
1979 temporary_store,
1980 tx_ctx,
1981 move_vm,
1982 gas_charger,
1983 protocol_config,
1984 metrics,
1985 trace_builder_opt,
1986 )
1987 }
1988
1989 fn advance_epoch_v2(
1993 builder: ProgrammableTransactionBuilder,
1994 change_epoch_v2: ChangeEpochV2,
1995 temporary_store: &mut TemporaryStore<'_>,
1996 tx_ctx: Rc<RefCell<TxContext>>,
1997 move_vm: &Arc<MoveVM>,
1998 gas_charger: &mut GasCharger,
1999 protocol_config: &ProtocolConfig,
2000 metrics: Arc<LimitsMetrics>,
2001 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2002 ) -> Result<(), ExecutionError> {
2003 let params = AdvanceEpochParams {
2004 epoch: change_epoch_v2.epoch,
2005 next_protocol_version: change_epoch_v2.protocol_version.into(),
2006 validator_subsidy: protocol_config.validator_target_reward(),
2007 storage_charge: change_epoch_v2.storage_charge,
2008 computation_charge: change_epoch_v2.computation_charge,
2009 computation_charge_burned: change_epoch_v2.computation_charge_burned,
2010 storage_rebate: change_epoch_v2.storage_rebate,
2011 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
2012 reward_slashing_rate: protocol_config.reward_slashing_rate(),
2013 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
2014 max_committee_members_count: protocol_config.max_committee_members_count(),
2015 eligible_active_validators: vec![],
2018 scores: vec![],
2019 adjust_rewards_by_score: false,
2020 };
2021 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
2022 advance_epoch_impl(
2023 advance_epoch_pt,
2024 params,
2025 change_epoch_v2.system_packages,
2026 temporary_store,
2027 tx_ctx,
2028 move_vm,
2029 gas_charger,
2030 protocol_config,
2031 metrics,
2032 trace_builder_opt,
2033 )
2034 }
2035
2036 fn advance_epoch_v3(
2040 builder: ProgrammableTransactionBuilder,
2041 change_epoch_v3: ChangeEpochV3,
2042 temporary_store: &mut TemporaryStore<'_>,
2043 tx_ctx: Rc<RefCell<TxContext>>,
2044 move_vm: &Arc<MoveVM>,
2045 gas_charger: &mut GasCharger,
2046 protocol_config: &ProtocolConfig,
2047 metrics: Arc<LimitsMetrics>,
2048 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2049 ) -> Result<(), ExecutionError> {
2050 let params = AdvanceEpochParams {
2051 epoch: change_epoch_v3.epoch,
2052 next_protocol_version: change_epoch_v3.protocol_version.into(),
2053 validator_subsidy: protocol_config.validator_target_reward(),
2054 storage_charge: change_epoch_v3.storage_charge,
2055 computation_charge: change_epoch_v3.computation_charge,
2056 computation_charge_burned: change_epoch_v3.computation_charge_burned,
2057 storage_rebate: change_epoch_v3.storage_rebate,
2058 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
2059 reward_slashing_rate: protocol_config.reward_slashing_rate(),
2060 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
2061 max_committee_members_count: protocol_config.max_committee_members_count(),
2062 eligible_active_validators: change_epoch_v3.eligible_active_validators,
2063 scores: vec![],
2066 adjust_rewards_by_score: false,
2067 };
2068 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
2069 advance_epoch_impl(
2070 advance_epoch_pt,
2071 params,
2072 change_epoch_v3.system_packages,
2073 temporary_store,
2074 tx_ctx,
2075 move_vm,
2076 gas_charger,
2077 protocol_config,
2078 metrics,
2079 trace_builder_opt,
2080 )
2081 }
2082
2083 fn advance_epoch_v4(
2087 builder: ProgrammableTransactionBuilder,
2088 change_epoch_v4: ChangeEpochV4,
2089 temporary_store: &mut TemporaryStore<'_>,
2090 tx_ctx: Rc<RefCell<TxContext>>,
2091 move_vm: &Arc<MoveVM>,
2092 gas_charger: &mut GasCharger,
2093 protocol_config: &ProtocolConfig,
2094 metrics: Arc<LimitsMetrics>,
2095 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2096 ) -> Result<(), ExecutionError> {
2097 let params = AdvanceEpochParams {
2098 epoch: change_epoch_v4.epoch,
2099 next_protocol_version: change_epoch_v4.protocol_version.into(),
2100 validator_subsidy: protocol_config.validator_target_reward(),
2101 storage_charge: change_epoch_v4.storage_charge,
2102 computation_charge: change_epoch_v4.computation_charge,
2103 computation_charge_burned: change_epoch_v4.computation_charge_burned,
2104 storage_rebate: change_epoch_v4.storage_rebate,
2105 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
2106 reward_slashing_rate: protocol_config.reward_slashing_rate(),
2107 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
2108 max_committee_members_count: protocol_config.max_committee_members_count(),
2109 eligible_active_validators: change_epoch_v4.eligible_active_validators,
2110 scores: change_epoch_v4.scores,
2111 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
2112 };
2113 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
2114 advance_epoch_impl(
2115 advance_epoch_pt,
2116 params,
2117 change_epoch_v4.system_packages,
2118 temporary_store,
2119 tx_ctx,
2120 move_vm,
2121 gas_charger,
2122 protocol_config,
2123 metrics,
2124 trace_builder_opt,
2125 )
2126 }
2127
2128 fn process_system_packages(
2129 system_packages: Vec<SystemPackage>,
2130 temporary_store: &mut TemporaryStore<'_>,
2131 tx_ctx: Rc<RefCell<TxContext>>,
2132 move_vm: &MoveVM,
2133 gas_charger: &mut GasCharger,
2134 protocol_config: &ProtocolConfig,
2135 metrics: Arc<LimitsMetrics>,
2136 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2137 ) {
2138 let binary_config = to_binary_config(protocol_config, None);
2139 for SystemPackage {
2140 version,
2141 modules,
2142 dependencies,
2143 } in system_packages.into_iter()
2144 {
2145 let deserialized_modules: Vec<_> = modules
2146 .iter()
2147 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
2148 .collect();
2149
2150 if version == OBJECT_START_VERSION {
2151 let package_id = deserialized_modules.first().unwrap().address();
2152 info!("adding new system package {package_id}");
2153
2154 let publish_pt = {
2155 let mut b = ProgrammableTransactionBuilder::new();
2156 b.command(Command::new_publish(modules, dependencies));
2157 b.finish()
2158 };
2159
2160 programmable_transactions::execution::execute::<execution_mode::System>(
2161 protocol_config,
2162 metrics.clone(),
2163 move_vm,
2164 temporary_store,
2165 tx_ctx.clone(),
2166 gas_charger,
2167 publish_pt,
2168 trace_builder_opt,
2169 )
2170 .map_err(|(e, _)| e)
2171 .expect("System Package Publish must succeed");
2172 } else {
2173 let mut new_package = Object::new_system_package(
2174 &deserialized_modules,
2175 version,
2176 dependencies,
2177 tx_ctx.borrow().digest(),
2178 );
2179
2180 info!("upgraded system package {:?}", new_package.object_ref());
2181
2182 new_package
2185 .data
2186 .as_opt_mut_package()
2187 .unwrap()
2188 .decrement_version()
2189 .expect("package version should never underflow");
2190
2191 temporary_store.upgrade_system_package(new_package);
2193 }
2194 }
2195 }
2196
2197 fn setup_consensus_commit(
2203 consensus_commit_timestamp_ms: CheckpointTimestamp,
2204 temporary_store: &mut TemporaryStore<'_>,
2205 tx_ctx: Rc<RefCell<TxContext>>,
2206 move_vm: &Arc<MoveVM>,
2207 gas_charger: &mut GasCharger,
2208 protocol_config: &ProtocolConfig,
2209 metrics: Arc<LimitsMetrics>,
2210 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2211 ) -> Result<(), ExecutionError> {
2212 let pt = {
2213 let mut builder = ProgrammableTransactionBuilder::new();
2214 let res = builder.move_call(
2215 ObjectId::FRAMEWORK,
2216 Identifier::CLOCK_MODULE,
2217 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
2218 vec![],
2219 vec![
2220 CallArg::CLOCK_MUTABLE,
2221 CallArg::pure(&consensus_commit_timestamp_ms),
2222 ],
2223 );
2224 assert_invariant!(
2225 res.is_ok(),
2226 "Unable to generate consensus_commit_prologue transaction!"
2227 );
2228 builder.finish()
2229 };
2230 programmable_transactions::execution::execute::<execution_mode::System>(
2231 protocol_config,
2232 metrics,
2233 move_vm,
2234 temporary_store,
2235 tx_ctx,
2236 gas_charger,
2237 pt,
2238 trace_builder_opt,
2239 )
2240 .map_err(|(e, _)| e)?;
2241 Ok(())
2242 }
2243
2244 fn setup_randomness_state_update(
2250 update: RandomnessStateUpdate,
2251 temporary_store: &mut TemporaryStore<'_>,
2252 tx_ctx: Rc<RefCell<TxContext>>,
2253 move_vm: &Arc<MoveVM>,
2254 gas_charger: &mut GasCharger,
2255 protocol_config: &ProtocolConfig,
2256 metrics: Arc<LimitsMetrics>,
2257 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2258 ) -> Result<(), ExecutionError> {
2259 let pt = {
2260 let mut builder = ProgrammableTransactionBuilder::new();
2261 let res = builder.move_call(
2262 ObjectId::FRAMEWORK,
2263 Identifier::RANDOM_MODULE,
2264 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
2265 vec![],
2266 vec![
2267 CallArg::Shared(SharedObjectReference::new(
2268 ObjectId::RANDOMNESS_STATE,
2269 update.randomness_obj_initial_shared_version,
2270 true,
2271 )),
2272 CallArg::pure(&update.randomness_round),
2273 CallArg::pure(&update.random_bytes),
2274 ],
2275 );
2276 assert_invariant!(
2277 res.is_ok(),
2278 "Unable to generate randomness_state_update transaction!"
2279 );
2280 builder.finish()
2281 };
2282 programmable_transactions::execution::execute::<execution_mode::System>(
2283 protocol_config,
2284 metrics,
2285 move_vm,
2286 temporary_store,
2287 tx_ctx,
2288 gas_charger,
2289 pt,
2290 trace_builder_opt,
2291 )
2292 .map_err(|(e, _)| e)?;
2293 Ok(())
2294 }
2295
2296 fn setup_transaction_deny_rules_create(
2302 mut builder: ProgrammableTransactionBuilder,
2303 ) -> Result<ProgrammableTransactionBuilder, ExecutionError> {
2304 let res = builder.move_call(
2305 ObjectId::FRAMEWORK,
2306 TRANSACTION_DENY_RULES_MODULE,
2307 TRANSACTION_DENY_RULES_CREATE_FUNCTION_NAME,
2308 vec![],
2309 vec![],
2310 );
2311 assert_invariant!(
2312 res.is_ok(),
2313 "Unable to generate transaction_deny_rules create transaction!"
2314 );
2315 Ok(builder)
2316 }
2317
2318 fn setup_transaction_deny_rules_update(
2322 update: TransactionDenyRulesUpdate,
2323 temporary_store: &mut TemporaryStore<'_>,
2324 tx_ctx: Rc<RefCell<TxContext>>,
2325 move_vm: &Arc<MoveVM>,
2326 gas_charger: &mut GasCharger,
2327 protocol_config: &ProtocolConfig,
2328 metrics: Arc<LimitsMetrics>,
2329 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2330 ) -> Result<(), ExecutionError> {
2331 let pt = {
2332 let mut builder = ProgrammableTransactionBuilder::new();
2333 let res = builder.move_call(
2337 ObjectId::FRAMEWORK,
2338 TRANSACTION_DENY_RULES_MODULE,
2339 TRANSACTION_DENY_RULES_UPDATE_FUNCTION_NAME,
2340 vec![],
2341 vec![
2342 CallArg::Shared(SharedObjectReference::new(
2343 ObjectId::TRANSACTION_DENY_RULES,
2344 update.deny_rules_obj_initial_shared_version,
2345 true,
2346 )),
2347 CallArg::pure(&update.added_addresses),
2348 CallArg::pure(&update.removed_addresses),
2349 CallArg::pure(&update.added_objects),
2350 CallArg::pure(&update.removed_objects),
2351 CallArg::pure(&update.added_packages),
2352 CallArg::pure(&update.removed_packages),
2353 CallArg::pure(&update.package_publish_disabled),
2354 CallArg::pure(&update.package_upgrade_disabled),
2355 CallArg::pure(&update.shared_object_disabled),
2356 CallArg::pure(&update.user_transaction_disabled),
2357 CallArg::pure(&update.receiving_objects_disabled),
2358 CallArg::pure(&update.move_authenticator_disabled),
2359 ],
2360 );
2361 assert_invariant!(
2362 res.is_ok(),
2363 "Unable to generate transaction_deny_rules update transaction!"
2364 );
2365 builder.finish()
2366 };
2367 programmable_transactions::execution::execute::<execution_mode::System>(
2368 protocol_config,
2369 metrics,
2370 move_vm,
2371 temporary_store,
2372 tx_ctx,
2373 gas_charger,
2374 pt,
2375 trace_builder_opt,
2376 )
2377 .map(|(results, _timings)| results)
2378 .map_err(|(error, _timings)| error)
2379 }
2380
2381 fn setup_authenticator_move_call(
2388 authenticator: MoveAuthenticator,
2389 authenticator_function_ref: AuthenticatorFunctionRefV1,
2390 ) -> Result<ProgrammableTransaction, ExecutionError> {
2391 let mut builder = ProgrammableTransactionBuilder::new();
2392
2393 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
2394 args.extend(authenticator.call_args().to_owned());
2395
2396 let res = builder.move_call(
2397 authenticator_function_ref.package,
2398 Identifier::new(authenticator_function_ref.module.clone()).expect(
2399 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2400 ),
2401 Identifier::new(authenticator_function_ref.function).expect(
2402 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2403 ),
2404 authenticator.type_args().to_vec(),
2405 args,
2406 );
2407
2408 assert_invariant!(
2409 res.is_ok(),
2410 "Unable to generate an account authenticator call transaction!"
2411 );
2412
2413 Ok(builder.finish())
2414 }
2415
2416 fn resolve_sponsor(gas_data: &GasPayment, transaction_signer: &Address) -> Option<Address> {
2417 let gas_owner = gas_data.owner;
2418 if &gas_owner == transaction_signer {
2419 None
2420 } else {
2421 Some(gas_owner)
2422 }
2423 }
2424}