1pub use checked::*;
6
7#[iota_macros::with_checked_arithmetic]
8mod checked {
9
10 use std::{
11 cell::RefCell,
12 collections::{BTreeMap, BTreeSet, HashSet},
13 rc::Rc,
14 sync::Arc,
15 };
16
17 use iota_move_natives::all_natives;
18 use iota_protocol_config::{LimitThresholdCrossed, ProtocolConfig, check_limit_by_meter};
19 use iota_sdk_types::{
20 Address, Argument, ChangeEpoch, ChangeEpochV2, ChangeEpochV3, ChangeEpochV4, Command,
21 EndOfEpochTransactionKind, ExecutionStatus, GasPayment, GenesisTransaction, Identifier,
22 MoveAuthenticator, ObjectId, ProgrammableTransaction, RandomnessStateUpdate,
23 SharedObjectReference, SystemPackage, TransactionDigest, TransactionKind, Version,
24 gas::GasCostSummary,
25 };
26 #[cfg(msim)]
27 use iota_types::iota_system_state::advance_epoch_result_injection::maybe_modify_result;
28 use iota_types::{
29 account_abstraction::authenticator_function::{
30 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
31 AuthenticatorFunctionRefV1,
32 },
33 auth_context::{AuthContext, AuthContextData},
34 balance::{BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME},
35 base_types::TxContext,
36 clock::CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
37 committee::EpochId,
38 effects::TransactionEffects,
39 error::{ExecutionError, ExecutionErrorKind},
40 execution::{ExecutionResults, ExecutionResultsV1, SharedInput, is_certificate_denied},
41 execution_config_utils::to_binary_config,
42 gas::{IotaGasStatus, IotaGasStatusAPI},
43 gas_coin::GAS,
44 inner_temporary_store::InnerTemporaryStore,
45 iota_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams},
46 messages_checkpoint::CheckpointTimestamp,
47 metrics::LimitsMetrics,
48 move_authenticator::MoveAuthenticatorExt,
49 object::{OBJECT_START_VERSION, Object, ObjectInner},
50 programmable_transaction_builder::ProgrammableTransactionBuilder,
51 randomness_state::RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
52 storage::{BackingStore, Storage},
53 transaction::{CallArg, CheckedInputObjects, InputObjects, TransactionKindExt},
54 };
55 use move_binary_format::CompiledModule;
56 use move_trace_format::format::MoveTraceBuilder;
57 use move_vm_runtime::move_vm::MoveVM;
58 use tracing::{info, instrument, trace, warn};
59
60 use crate::{
61 adapter::new_move_vm,
62 execution_mode::{self, ExecutionMode},
63 gas_charger::GasCharger,
64 programmable_transactions,
65 temporary_store::TemporaryStore,
66 type_layout_resolver::TypeLayoutResolver,
67 };
68
69 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
81 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
82 store: &dyn BackingStore,
83 input_objects: CheckedInputObjects,
84 gas_data: GasPayment,
85 gas_status: IotaGasStatus,
86 transaction_kind: TransactionKind,
87 transaction_signer: Address,
88 transaction_digest: TransactionDigest,
89 move_vm: &Arc<MoveVM>,
90 epoch_id: &EpochId,
91 epoch_timestamp_ms: u64,
92 protocol_config: &ProtocolConfig,
93 metrics: Arc<LimitsMetrics>,
94 enable_expensive_checks: bool,
95 certificate_deny_set: &HashSet<TransactionDigest>,
96 trace_builder_opt: &mut Option<MoveTraceBuilder>,
97 ) -> (
98 InnerTemporaryStore,
99 IotaGasStatus,
100 TransactionEffects,
101 Result<Mode::ExecutionResults, ExecutionError>,
102 ) {
103 let input_objects = input_objects.into_inner();
104 let mutable_inputs = if enable_expensive_checks {
105 input_objects.mutable_inputs().keys().copied().collect()
106 } else {
107 HashSet::new()
108 };
109 let shared_object_refs = input_objects.filter_shared_objects();
110 let receiving_objects = transaction_kind.receiving_objects();
111 let transaction_dependencies = input_objects.transaction_dependencies();
112 let contains_deleted_input = input_objects.contains_deleted_objects();
113 let cancelled_objects = input_objects.get_cancelled_objects();
114
115 let temporary_store = TemporaryStore::new(
116 store,
117 input_objects,
118 receiving_objects,
119 transaction_digest,
120 protocol_config,
121 *epoch_id,
122 );
123
124 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
125 let gas_price = gas_status.gas_price();
126 let rgp = gas_status.reference_gas_price();
127 let gas_charger = GasCharger::new(
128 transaction_digest,
129 gas_data.objects,
130 gas_status,
131 protocol_config,
132 );
133
134 let tx_ctx = TxContext::new_from_components(
135 &transaction_signer,
136 &transaction_digest,
137 epoch_id,
138 epoch_timestamp_ms,
139 rgp,
140 gas_price,
141 gas_data.budget,
142 sponsor,
143 protocol_config,
144 );
145 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
146
147 execute_transaction_to_effects_inner::<Mode>(
148 temporary_store,
149 gas_charger,
150 tx_ctx,
151 &mutable_inputs,
152 shared_object_refs,
153 transaction_dependencies,
154 contains_deleted_input,
155 cancelled_objects,
156 transaction_kind,
157 transaction_signer,
158 transaction_digest,
159 move_vm,
160 epoch_id,
161 protocol_config,
162 metrics,
163 enable_expensive_checks,
164 certificate_deny_set,
165 trace_builder_opt,
166 None,
167 )
168 }
169
170 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
173 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
174 mut temporary_store: TemporaryStore,
175 mut gas_charger: GasCharger,
176 tx_ctx: Rc<RefCell<TxContext>>,
177 mutable_inputs: &HashSet<ObjectId>,
178 shared_object_refs: Vec<SharedInput>,
179 mut transaction_dependencies: BTreeSet<TransactionDigest>,
180 contains_deleted_input: bool,
181 cancelled_objects: Option<(Vec<ObjectId>, Version)>,
182 transaction_kind: TransactionKind,
183 transaction_signer: Address,
184 transaction_digest: TransactionDigest,
185 move_vm: &Arc<MoveVM>,
186 epoch_id: &EpochId,
187 protocol_config: &ProtocolConfig,
188 metrics: Arc<LimitsMetrics>,
189 enable_expensive_checks: bool,
190 certificate_deny_set: &HashSet<TransactionDigest>,
191 trace_builder_opt: &mut Option<MoveTraceBuilder>,
192 pre_execution_result_opt: Option<
193 Result<
194 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
195 ExecutionError,
196 >,
197 >,
198 ) -> (
199 InnerTemporaryStore,
200 IotaGasStatus,
201 TransactionEffects,
202 Result<Mode::ExecutionResults, ExecutionError>,
203 ) {
204 let is_epoch_change = transaction_kind.is_end_of_epoch();
205 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
206
207 let (gas_cost_summary, execution_result) = execute_transaction::<Mode>(
208 &mut temporary_store,
209 transaction_kind,
210 &mut gas_charger,
211 tx_ctx,
212 move_vm,
213 protocol_config,
214 metrics,
215 enable_expensive_checks,
216 deny_cert,
217 contains_deleted_input,
218 cancelled_objects,
219 trace_builder_opt,
220 pre_execution_result_opt,
221 );
222
223 let status = if let Err(error) = &execution_result {
224 elaborate_error_logs(error, transaction_digest)
225 } else {
226 ExecutionStatus::Success
227 };
228
229 #[skip_checked_arithmetic]
230 trace!(
231 tx_digest = ?transaction_digest,
232 computation_gas_cost = gas_cost_summary.computation_cost,
233 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
234 storage_gas_cost = gas_cost_summary.storage_cost,
235 storage_gas_rebate = gas_cost_summary.storage_rebate,
236 "Finished execution of transaction with status {:?}",
237 status
238 );
239
240 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
244
245 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
246 temporary_store
247 .check_ownership_invariants(
248 &transaction_signer,
249 &mut gas_charger,
250 mutable_inputs,
251 is_epoch_change,
252 )
253 .unwrap()
254 } let (inner, effects) = temporary_store.into_effects(
257 shared_object_refs,
258 &transaction_digest,
259 transaction_dependencies,
260 gas_cost_summary,
261 status,
262 &mut gas_charger,
263 *epoch_id,
264 );
265
266 (
267 inner,
268 gas_charger.into_gas_status(),
269 effects,
270 execution_result,
271 )
272 }
273
274 #[instrument(
288 name = "tx_authenticate_then_execute_to_effects",
289 level = "debug",
290 skip_all
291 )]
292 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
293 store: &dyn BackingStore,
294 protocol_config: &ProtocolConfig,
296 metrics: Arc<LimitsMetrics>,
297 enable_expensive_checks: bool,
298 certificate_deny_set: &HashSet<TransactionDigest>,
299 epoch_id: &EpochId,
301 epoch_timestamp_ms: u64,
302 gas_data: GasPayment,
304 gas_status: IotaGasStatus,
305 authenticators: Vec<(
307 MoveAuthenticator,
308 AuthenticatorFunctionRefForExecution,
309 CheckedInputObjects,
310 )>,
311 authenticator_and_transaction_input_objects: CheckedInputObjects,
312 transaction_kind: TransactionKind,
314 transaction_signer: Address,
315 transaction_digest: TransactionDigest,
316 auth_context_data: AuthContextData,
317 trace_builder_opt: &mut Option<MoveTraceBuilder>,
319 move_vm: &Arc<MoveVM>,
321 ) -> (
322 InnerTemporaryStore,
323 IotaGasStatus,
324 TransactionEffects,
325 Result<Mode::ExecutionResults, ExecutionError>,
326 ) {
327 let input_objects = authenticator_and_transaction_input_objects.into_inner();
333 let mutable_inputs = if enable_expensive_checks {
335 input_objects.mutable_inputs().keys().copied().collect()
336 } else {
337 HashSet::new()
338 };
339 let shared_object_refs = input_objects.filter_shared_objects();
341 let transaction_receiving_objects = transaction_kind.receiving_objects();
343 let transaction_dependencies = input_objects.transaction_dependencies();
345 let contains_deleted_input = input_objects.contains_deleted_objects();
348 let cancelled_objects = input_objects.get_cancelled_objects();
349
350 let mut temporary_store = TemporaryStore::new(
352 store,
353 input_objects,
354 transaction_receiving_objects,
355 transaction_digest,
356 protocol_config,
357 *epoch_id,
358 );
359
360 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
362 let gas_price = gas_status.gas_price();
363 let rgp = gas_status.reference_gas_price();
364 let mut gas_charger = GasCharger::new(
365 transaction_digest,
366 gas_data.objects,
367 gas_status,
368 protocol_config,
369 );
370
371 let tx_ctx = TxContext::new_from_components(
373 &transaction_signer,
374 &transaction_digest,
375 epoch_id,
376 epoch_timestamp_ms,
377 rgp,
378 gas_price,
379 gas_data.budget,
380 sponsor,
381 protocol_config,
382 );
383 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
384
385 let authenticators = authenticators
391 .into_iter()
392 .map(
393 |(
394 authenticator,
395 authenticator_function_ref_for_execution,
396 authenticator_input_objects,
397 )| {
398 let AuthenticatorFunctionRefForExecution {
399 authenticator_function_ref,
400 loaded_object_id,
401 loaded_object_metadata,
402 } = authenticator_function_ref_for_execution;
403
404 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
407 loaded_object_id,
408 loaded_object_metadata,
409 )]));
410
411 (
412 authenticator,
413 authenticator_function_ref,
414 authenticator_input_objects,
415 )
416 },
417 )
418 .collect::<Vec<_>>();
419
420 let authentication_execution_result = authenticators.into_iter().try_for_each(
426 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
427 match authenticator_function_ref {
428 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
429 authenticate_transaction_inner(
430 &mut temporary_store,
431 protocol_config,
432 metrics.clone(),
433 &mut gas_charger,
434 authenticator,
435 authenticator_function_ref_v1,
436 &authenticator_input_objects.into_inner(),
437 transaction_kind.clone(),
438 transaction_digest,
439 auth_context_data.clone(),
440 tx_ctx.clone(),
441 trace_builder_opt,
442 move_vm,
443 )
444 }
445 }
446 },
447 );
448
449 let authentication_execution_result =
450 report_authentication_error(authentication_execution_result, protocol_config);
451
452 execute_transaction_to_effects_inner::<Mode>(
460 temporary_store,
461 gas_charger,
462 tx_ctx,
463 &mutable_inputs,
464 shared_object_refs,
465 transaction_dependencies,
466 contains_deleted_input,
467 cancelled_objects,
468 transaction_kind,
469 transaction_signer,
470 transaction_digest,
471 move_vm,
472 epoch_id,
473 protocol_config,
474 metrics,
475 enable_expensive_checks,
476 certificate_deny_set,
477 trace_builder_opt,
478 Some(authentication_execution_result),
479 )
480 }
481
482 #[instrument(name = "tx_validate", level = "debug", skip_all)]
487 pub fn authenticate_transaction(
488 store: &dyn BackingStore,
489 protocol_config: &ProtocolConfig,
491 metrics: Arc<LimitsMetrics>,
492 epoch_id: &EpochId,
494 epoch_timestamp_ms: u64,
495 gas_data: GasPayment,
497 gas_status: IotaGasStatus,
498 authenticators: Vec<(
500 MoveAuthenticator,
501 AuthenticatorFunctionRef,
502 CheckedInputObjects,
503 )>,
504 aggregated_authenticator_input_objects: CheckedInputObjects,
505 transaction_kind: TransactionKind,
507 transaction_signer: Address,
508 transaction_digest: TransactionDigest,
509 auth_context_data: AuthContextData,
510 trace_builder_opt: &mut Option<MoveTraceBuilder>,
512 move_vm: &Arc<MoveVM>,
514 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
515 {
516 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
518 let gas_price = gas_status.gas_price();
519 let rgp = gas_status.reference_gas_price();
520 let mut gas_charger =
521 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
522
523 let tx_ctx = TxContext::new_from_components(
526 &transaction_signer,
527 &transaction_digest,
528 epoch_id,
529 epoch_timestamp_ms,
530 rgp,
531 gas_price,
532 gas_data.budget,
533 sponsor,
534 protocol_config,
535 );
536 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
537
538 let mut temporary_store = TemporaryStore::new(
539 store,
540 aggregated_authenticator_input_objects.into_inner(),
541 vec![],
542 transaction_digest,
543 protocol_config,
544 *epoch_id,
545 );
546
547 let authentication_execution_result = authenticators.into_iter().try_for_each(
549 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
550 match authenticator_function_ref {
551 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
552 authenticate_transaction_inner(
553 &mut temporary_store,
554 protocol_config,
555 metrics.clone(),
556 &mut gas_charger,
557 authenticator,
558 authenticator_function_ref_v1,
559 &authenticator_input_objects.into_inner(),
560 transaction_kind.clone(),
561 transaction_digest,
562 auth_context_data.clone(),
563 tx_ctx.clone(),
564 trace_builder_opt,
565 move_vm,
566 )
567 }
568 }
569 },
570 );
571
572 report_authentication_error(authentication_execution_result, protocol_config)
573 }
574
575 #[instrument(name = "tx_validate", level = "debug", skip_all)]
585 pub fn authenticate_transaction_inner(
586 temporary_store: &mut TemporaryStore<'_>,
587 protocol_config: &ProtocolConfig,
589 metrics: Arc<LimitsMetrics>,
590 gas_charger: &mut GasCharger,
592 authenticator: MoveAuthenticator,
594 authenticator_function_ref: AuthenticatorFunctionRefV1,
595 authenticator_input_objects: &InputObjects,
596 transaction_kind: TransactionKind,
598 transaction_digest: TransactionDigest,
599 auth_context_data: AuthContextData,
600 tx_ctx: Rc<RefCell<TxContext>>,
601 trace_builder_opt: &mut Option<MoveTraceBuilder>,
603 move_vm: &Arc<MoveVM>,
605 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
606 {
607 debug_assert!(
609 transaction_kind.is_programmable(),
610 "Only programmable transactions are allowed"
611 );
612 debug_assert!(
613 authenticator_input_objects
614 .mutable_inputs()
615 .keys()
616 .copied()
617 .collect::<HashSet<_>>()
618 .is_empty(),
619 "No mutable inputs are allowed"
620 );
621 debug_assert!(
622 authenticator.receiving_objects().is_empty(),
623 "No receiving inputs are allowed"
624 );
625
626 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
627 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
628
629 let auth_ctx = {
631 let TransactionKind::Programmable(ptb) = &transaction_kind else {
632 unreachable!("Only programmable transactions are allowed");
633 };
634 AuthContext::new_from_components(
635 authenticator.digest().into(),
636 auth_context_data.sender_auth_digest,
637 auth_context_data.sponsor_auth_digest,
638 auth_context_data
639 .sender_authenticator_function_ref
640 .and_then(Into::into),
641 auth_context_data
642 .sponsor_authenticator_function_ref
643 .and_then(Into::into),
644 ptb,
645 auth_context_data.transaction_data_bytes,
646 )
647 };
648 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
649
650 temporary_store.store_auth_context(auth_ctx);
654
655 let authentication_execution_result = execute_authenticator_move_call(
657 temporary_store,
658 authenticator,
659 authenticator_function_ref,
660 gas_charger,
661 tx_ctx,
662 move_vm,
663 protocol_config,
664 metrics,
665 false,
666 contains_deleted_input,
667 cancelled_objects,
668 trace_builder_opt,
669 );
670
671 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
673 elaborate_error_logs(error, transaction_digest)
674 } else {
675 ExecutionStatus::Success
676 };
677
678 #[skip_checked_arithmetic]
679 trace!(
680 tx_digest = ?transaction_digest,
681 computation_gas_cost = gas_charger.summary().gas_used(),
682 "Finished authenticator execution of transaction with status {:?}",
683 authentication_execution_status
684 );
685
686 authentication_execution_result
687 }
688
689 #[instrument(name = "auth_execute", level = "debug", skip_all)]
700 fn execute_authenticator_move_call(
701 temporary_store: &mut TemporaryStore<'_>,
702 authenticator: MoveAuthenticator,
703 authenticator_function_ref: AuthenticatorFunctionRefV1,
704 gas_charger: &mut GasCharger,
705 tx_ctx: Rc<RefCell<TxContext>>,
706 move_vm: &Arc<MoveVM>,
707 protocol_config: &ProtocolConfig,
708 metrics: Arc<LimitsMetrics>,
709 deny_cert: bool,
710 contains_deleted_input: bool,
711 cancelled_objects: Option<(Vec<ObjectId>, Version)>,
712 trace_builder_opt: &mut Option<MoveTraceBuilder>,
713 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
714 {
715 run_inputs_checks(
719 protocol_config,
720 deny_cert,
721 contains_deleted_input,
722 cancelled_objects,
723 )
724 .and_then(|()| {
725 let authenticator_move_call =
726 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
727 programmable_transactions::execution::execute::<execution_mode::Authentication>(
728 protocol_config,
729 metrics.clone(),
730 move_vm,
731 temporary_store,
732 tx_ctx,
733 gas_charger,
734 authenticator_move_call,
735 trace_builder_opt,
736 )
737 .and_then(|ok_result| {
738 temporary_store.check_move_authenticator_results_consistency()?;
739 Ok(ok_result)
740 })
741 })
742 }
743
744 pub fn execute_genesis_state_update(
751 store: &dyn BackingStore,
752 protocol_config: &ProtocolConfig,
753 metrics: Arc<LimitsMetrics>,
754 move_vm: &Arc<MoveVM>,
755 tx_context: Rc<RefCell<TxContext>>,
756 input_objects: CheckedInputObjects,
757 pt: ProgrammableTransaction,
758 ) -> Result<InnerTemporaryStore, ExecutionError> {
759 let input_objects = input_objects.into_inner();
760 let tx_digest = tx_context.borrow().digest();
761
762 let mut temporary_store =
763 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
764 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
765 programmable_transactions::execution::execute::<execution_mode::Genesis>(
766 protocol_config,
767 metrics,
768 move_vm,
769 &mut temporary_store,
770 tx_context,
771 &mut gas_charger,
772 pt,
773 &mut None,
774 )?;
775 temporary_store.update_object_version_and_prev_tx();
776 Ok(temporary_store.into_inner())
777 }
778
779 #[instrument(name = "tx_execute", level = "debug", skip_all)]
788 fn execute_transaction<Mode: ExecutionMode>(
789 temporary_store: &mut TemporaryStore<'_>,
790 transaction_kind: TransactionKind,
791 gas_charger: &mut GasCharger,
792 tx_ctx: Rc<RefCell<TxContext>>,
793 move_vm: &Arc<MoveVM>,
794 protocol_config: &ProtocolConfig,
795 metrics: Arc<LimitsMetrics>,
796 enable_expensive_checks: bool,
797 deny_cert: bool,
798 contains_deleted_input: bool,
799 cancelled_objects: Option<(Vec<ObjectId>, Version)>,
800 trace_builder_opt: &mut Option<MoveTraceBuilder>,
801 pre_execution_result_opt: Option<
802 Result<
803 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
804 ExecutionError,
805 >,
806 >,
807 ) -> (
808 GasCostSummary,
809 Result<Mode::ExecutionResults, ExecutionError>,
810 ) {
811 gas_charger.smash_gas(temporary_store);
812
813 debug_assert!(
816 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
817 "No gas charges must be applied yet"
818 );
819
820 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
821 || transaction_kind.is_end_of_epoch();
822
823 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
824
825 let tx_digest = tx_ctx.borrow().digest();
826
827 let result = gas_charger.charge_input_objects(temporary_store);
831 let mut result = result.and_then(|()| {
832 run_inputs_checks(
833 protocol_config,
834 deny_cert,
835 contains_deleted_input,
836 cancelled_objects,
837 )?;
838
839 let mut execution_result = pre_execution_result_opt.unwrap_or(Ok(())).and_then(|_| {
842 execution_loop::<Mode>(
843 temporary_store,
844 transaction_kind,
845 tx_ctx,
846 move_vm,
847 gas_charger,
848 protocol_config,
849 metrics.clone(),
850 trace_builder_opt,
851 )
852 });
853
854 let meter_check = check_meter_limit(
855 temporary_store,
856 gas_charger,
857 protocol_config,
858 metrics.clone(),
859 );
860 if let Err(e) = meter_check {
861 execution_result = Err(e);
862 }
863
864 if execution_result.is_ok() {
865 let gas_check = check_written_objects_limit(
866 temporary_store,
867 gas_charger,
868 protocol_config,
869 metrics,
870 );
871 if let Err(e) = gas_check {
872 execution_result = Err(e);
873 }
874 }
875
876 execution_result
877 });
878
879 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
880 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
889
890 if let Err(e) = run_conservation_checks::<Mode>(
891 temporary_store,
892 gas_charger,
893 tx_digest,
894 move_vm,
895 enable_expensive_checks,
896 &cost_summary,
897 is_genesis_or_epoch_change_tx,
898 advance_epoch_gas_summary,
899 ) {
900 result = Err(e);
902 }
903
904 (cost_summary, result)
905 }
906
907 fn report_authentication_error<T>(
913 authentication_execution_result: Result<T, ExecutionError>,
914 protocol_config: &ProtocolConfig,
915 ) -> Result<T, ExecutionError> {
916 if protocol_config.report_move_authentication_error() {
917 authentication_execution_result.map_err(ExecutionError::into_move_authentication_error)
918 } else {
919 authentication_execution_result
920 }
921 }
922
923 fn elaborate_error_logs(
926 execution_error: &ExecutionError,
927 transaction_digest: TransactionDigest,
928 ) -> ExecutionStatus {
929 use ExecutionErrorKind as K;
930 match execution_error.kind() {
931 K::InvariantViolation | K::VmInvariantViolation => {
932 #[skip_checked_arithmetic]
933 tracing::error!(
934 kind = ?execution_error.kind(),
935 tx_digest = ?transaction_digest,
936 "INVARIANT VIOLATION! Source: {:?}",
937 execution_error.source(),
938 );
939 }
940
941 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
942 #[skip_checked_arithmetic]
943 tracing::debug!(
944 kind = ?execution_error.kind(),
945 tx_digest = ?transaction_digest,
946 "Verification Error. Source: {:?}",
947 execution_error.source(),
948 );
949 }
950
951 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
952 #[skip_checked_arithmetic]
953 tracing::debug!(
954 kind = ?execution_error.kind(),
955 tx_digest = ?transaction_digest,
956 "Publish/Upgrade Error. Source: {:?}",
957 execution_error.source(),
958 )
959 }
960
961 _ => (),
962 };
963
964 let (status, command) = execution_error.to_execution_status();
965 ExecutionStatus::new_failure(status, command)
966 }
967
968 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
977 fn run_conservation_checks<Mode: ExecutionMode>(
978 temporary_store: &mut TemporaryStore<'_>,
979 gas_charger: &mut GasCharger,
980 tx_digest: TransactionDigest,
981 move_vm: &Arc<MoveVM>,
982 enable_expensive_checks: bool,
983 cost_summary: &GasCostSummary,
984 is_genesis_or_epoch_change_tx: bool,
985 advance_epoch_gas_summary: Option<(u64, u64)>,
986 ) -> Result<(), ExecutionError> {
987 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
988 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
989 let conservation_result = {
992 temporary_store
993 .check_iota_conserved(cost_summary)
994 .and_then(|()| {
995 if enable_expensive_checks {
996 let mut layout_resolver =
999 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1000 temporary_store.check_iota_conserved_expensive(
1001 cost_summary,
1002 advance_epoch_gas_summary,
1003 &mut layout_resolver,
1004 )
1005 } else {
1006 Ok(())
1007 }
1008 })
1009 };
1010 if let Err(conservation_err) = conservation_result {
1011 result = Err(conservation_err);
1015 gas_charger.reset(temporary_store);
1016 gas_charger.charge_gas(temporary_store, &mut result);
1017 if let Err(recovery_err) = {
1019 temporary_store
1020 .check_iota_conserved(cost_summary)
1021 .and_then(|()| {
1022 if enable_expensive_checks {
1023 let mut layout_resolver =
1026 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1027 temporary_store.check_iota_conserved_expensive(
1028 cost_summary,
1029 advance_epoch_gas_summary,
1030 &mut layout_resolver,
1031 )
1032 } else {
1033 Ok(())
1034 }
1035 })
1036 } {
1037 panic!(
1041 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1042 tx_digest,
1043 recovery_err,
1044 gas_charger.summary()
1045 )
1046 }
1047 }
1048 } result
1052 }
1053
1054 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1065 fn run_inputs_checks(
1066 protocol_config: &ProtocolConfig,
1067 deny_cert: bool,
1068 contains_deleted_input: bool,
1069 cancelled_objects: Option<(Vec<ObjectId>, Version)>,
1070 ) -> Result<(), ExecutionError> {
1071 if deny_cert {
1072 Err(ExecutionError::new(
1073 ExecutionErrorKind::CertificateDenied,
1074 None,
1075 ))
1076 } else if contains_deleted_input {
1077 Err(ExecutionError::new(
1078 ExecutionErrorKind::InputObjectDeleted,
1079 None,
1080 ))
1081 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1082 match reason {
1083 version if version.is_congested() => Err(ExecutionError::new(
1084 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1085 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestionV2 {
1086 congested_objects: cancelled_objects,
1087 suggested_gas_price: version
1088 .get_congested_version_suggested_gas_price()
1089 .unwrap(),
1090 }
1091 } else {
1092 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestion {
1097 congested_objects: cancelled_objects,
1098 }
1099 },
1100 None,
1101 )),
1102 Version::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1103 ExecutionErrorKind::ExecutionCancelledDueToRandomnessUnavailable,
1104 None,
1105 )),
1106 _ => panic!("invalid cancellation reason Version: {reason}"),
1107 }
1108 } else {
1109 Ok(())
1110 }
1111 }
1112
1113 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1118 fn check_meter_limit(
1119 temporary_store: &mut TemporaryStore<'_>,
1120 gas_charger: &mut GasCharger,
1121 protocol_config: &ProtocolConfig,
1122 metrics: Arc<LimitsMetrics>,
1123 ) -> Result<(), ExecutionError> {
1124 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1125
1126 match check_limit_by_meter!(
1131 !gas_charger.is_unmetered(),
1132 effects_estimated_size,
1133 protocol_config.max_serialized_tx_effects_size_bytes(),
1134 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1135 metrics.excessive_estimated_effects_size
1136 ) {
1137 LimitThresholdCrossed::None => Ok(()),
1138 LimitThresholdCrossed::Soft(_, limit) => {
1139 warn!(
1140 effects_estimated_size = effects_estimated_size,
1141 soft_limit = limit,
1142 "Estimated transaction effects size crossed soft limit",
1143 );
1144 Ok(())
1145 }
1146 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1147 ExecutionErrorKind::EffectsTooLarge {
1148 current_size: effects_estimated_size as u64,
1149 max_size: lim as u64,
1150 },
1151 "Transaction effects are too large",
1152 )),
1153 }
1154 }
1155
1156 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1161 fn check_written_objects_limit(
1162 temporary_store: &mut TemporaryStore<'_>,
1163 gas_charger: &mut GasCharger,
1164 protocol_config: &ProtocolConfig,
1165 metrics: Arc<LimitsMetrics>,
1166 ) -> Result<(), ExecutionError> {
1167 if let (Some(normal_lim), Some(system_lim)) = (
1168 protocol_config.max_size_written_objects_as_option(),
1169 protocol_config.max_size_written_objects_system_tx_as_option(),
1170 ) {
1171 let written_objects_size = temporary_store.written_objects_size();
1172
1173 match check_limit_by_meter!(
1174 !gas_charger.is_unmetered(),
1175 written_objects_size,
1176 normal_lim,
1177 system_lim,
1178 metrics.excessive_written_objects_size
1179 ) {
1180 LimitThresholdCrossed::None => (),
1181 LimitThresholdCrossed::Soft(_, limit) => {
1182 warn!(
1183 written_objects_size = written_objects_size,
1184 soft_limit = limit,
1185 "Written objects size crossed soft limit",
1186 )
1187 }
1188 LimitThresholdCrossed::Hard(_, lim) => {
1189 return Err(ExecutionError::new_with_source(
1190 ExecutionErrorKind::WrittenObjectsTooLarge {
1191 object_size: written_objects_size as u64,
1192 max_object_size: lim as u64,
1193 },
1194 "Written objects size crossed hard limit",
1195 ));
1196 }
1197 };
1198 }
1199
1200 Ok(())
1201 }
1202
1203 #[instrument(level = "debug", skip_all)]
1210 fn execution_loop<Mode: ExecutionMode>(
1211 temporary_store: &mut TemporaryStore<'_>,
1212 transaction_kind: TransactionKind,
1213 tx_ctx: Rc<RefCell<TxContext>>,
1214 move_vm: &Arc<MoveVM>,
1215 gas_charger: &mut GasCharger,
1216 protocol_config: &ProtocolConfig,
1217 metrics: Arc<LimitsMetrics>,
1218 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1219 ) -> Result<Mode::ExecutionResults, ExecutionError> {
1220 let result = match transaction_kind {
1221 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1222 if tx_ctx.borrow().epoch() != 0 {
1223 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1224 }
1225
1226 for genesis_object in objects {
1227 let object = ObjectInner {
1228 data: genesis_object.data,
1229 owner: genesis_object.owner,
1230 previous_transaction: tx_ctx.borrow().digest(),
1231 storage_rebate: 0,
1232 };
1233 temporary_store.create_object(object.into());
1234 }
1235
1236 temporary_store.record_execution_results(ExecutionResults::V1(
1237 ExecutionResultsV1 {
1238 user_events: events,
1239 ..Default::default()
1240 },
1241 ));
1242
1243 Ok(Mode::empty_results())
1244 }
1245 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1246 setup_consensus_commit(
1247 prologue.commit_timestamp_ms,
1248 temporary_store,
1249 tx_ctx,
1250 move_vm,
1251 gas_charger,
1252 protocol_config,
1253 metrics,
1254 trace_builder_opt,
1255 )
1256 .expect("ConsensusCommitPrologueV1 cannot fail");
1257 Ok(Mode::empty_results())
1258 }
1259 TransactionKind::Programmable(pt) => {
1260 programmable_transactions::execution::execute::<Mode>(
1261 protocol_config,
1262 metrics,
1263 move_vm,
1264 temporary_store,
1265 tx_ctx,
1266 gas_charger,
1267 pt,
1268 trace_builder_opt,
1269 )
1270 }
1271 TransactionKind::EndOfEpoch(txns) => {
1272 let builder = ProgrammableTransactionBuilder::new();
1273 let len = txns.len();
1274
1275 if let Some((i, tx)) = txns.into_iter().enumerate().next() {
1276 match tx {
1277 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1278 assert_eq!(i, len - 1);
1279 advance_epoch_v1(
1280 builder,
1281 change_epoch,
1282 temporary_store,
1283 tx_ctx,
1284 move_vm,
1285 gas_charger,
1286 protocol_config,
1287 metrics,
1288 trace_builder_opt,
1289 )?;
1290 return Ok(Mode::empty_results());
1291 }
1292 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1293 assert_eq!(i, len - 1);
1294 advance_epoch_v2(
1295 builder,
1296 change_epoch_v2,
1297 temporary_store,
1298 tx_ctx,
1299 move_vm,
1300 gas_charger,
1301 protocol_config,
1302 metrics,
1303 trace_builder_opt,
1304 )?;
1305 return Ok(Mode::empty_results());
1306 }
1307 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1308 assert_eq!(i, len - 1);
1309 advance_epoch_v3(
1310 builder,
1311 change_epoch_v3,
1312 temporary_store,
1313 tx_ctx,
1314 move_vm,
1315 gas_charger,
1316 protocol_config,
1317 metrics,
1318 trace_builder_opt,
1319 )?;
1320 return Ok(Mode::empty_results());
1321 }
1322 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1323 assert_eq!(i, len - 1);
1324 advance_epoch_v4(
1325 builder,
1326 change_epoch_v4,
1327 temporary_store,
1328 tx_ctx,
1329 move_vm,
1330 gas_charger,
1331 protocol_config,
1332 metrics,
1333 trace_builder_opt,
1334 )?;
1335 return Ok(Mode::empty_results());
1336 }
1337 _ => unimplemented!(
1338 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1339 ),
1340 }
1341 }
1342 unreachable!(
1343 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1344 )
1345 }
1346 #[allow(deprecated)]
1347 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1348 return Err(ExecutionError::new(
1352 ExecutionErrorKind::VmInvariantViolation,
1353 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1354 ));
1355 }
1356 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1357 setup_randomness_state_update(
1358 randomness_state_update,
1359 temporary_store,
1360 tx_ctx,
1361 move_vm,
1362 gas_charger,
1363 protocol_config,
1364 metrics,
1365 trace_builder_opt,
1366 )?;
1367 Ok(Mode::empty_results())
1368 }
1369 _ => unimplemented!(
1370 "a new TransactionKind enum variant was added and needs to be handled"
1371 ),
1372 }?;
1373 temporary_store.check_execution_results_consistency()?;
1374 Ok(result)
1375 }
1376
1377 fn mint_epoch_rewards_in_pt(
1386 builder: &mut ProgrammableTransactionBuilder,
1387 params: &AdvanceEpochParams,
1388 ) -> (Argument, Argument) {
1389 let storage_charge_arg = builder
1391 .input(CallArg::pure(¶ms.storage_charge))
1392 .unwrap();
1393 let storage_charges = builder.programmable_move_call(
1394 ObjectId::FRAMEWORK,
1395 Identifier::BALANCE_MODULE,
1396 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1397 vec![GAS::type_tag()],
1398 vec![storage_charge_arg],
1399 );
1400
1401 let computation_charge_arg = builder
1403 .input(CallArg::pure(¶ms.computation_charge))
1404 .unwrap();
1405 let computation_charges = builder.programmable_move_call(
1406 ObjectId::FRAMEWORK,
1407 Identifier::BALANCE_MODULE,
1408 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1409 vec![GAS::type_tag()],
1410 vec![computation_charge_arg],
1411 );
1412 (storage_charges, computation_charges)
1413 }
1414
1415 pub fn construct_advance_epoch_pt_impl(
1423 mut builder: ProgrammableTransactionBuilder,
1424 params: &AdvanceEpochParams,
1425 call_arg_vec: Vec<CallArg>,
1426 ) -> Result<ProgrammableTransaction, ExecutionError> {
1427 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1429 let mut arguments = vec![
1430 builder
1431 .pure(params.validator_subsidy)
1432 .expect("bcs encoding a u64 should not fail"),
1433 storage_charges,
1434 computation_charges,
1435 ];
1436
1437 let call_arg_arguments = call_arg_vec
1438 .into_iter()
1439 .map(|a| builder.input(a))
1440 .collect::<Result<_, _>>();
1441
1442 assert_invariant!(
1443 call_arg_arguments.is_ok(),
1444 "Unable to generate args for advance_epoch transaction!"
1445 );
1446
1447 arguments.append(&mut call_arg_arguments.unwrap());
1448
1449 info!("Call arguments to advance_epoch transaction: {:?}", params);
1450
1451 let storage_rebates = builder.programmable_move_call(
1452 ObjectId::SYSTEM,
1453 Identifier::IOTA_SYSTEM_MODULE,
1454 ADVANCE_EPOCH_FUNCTION_NAME,
1455 vec![],
1456 arguments,
1457 );
1458
1459 builder.programmable_move_call(
1461 ObjectId::FRAMEWORK,
1462 Identifier::BALANCE_MODULE,
1463 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1464 vec![GAS::type_tag()],
1465 vec![storage_rebates],
1466 );
1467 Ok(builder.finish())
1468 }
1469
1470 pub fn construct_advance_epoch_pt_v1(
1471 builder: ProgrammableTransactionBuilder,
1472 params: &AdvanceEpochParams,
1473 ) -> Result<ProgrammableTransaction, ExecutionError> {
1474 let call_arg_vec = vec![
1479 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), ];
1487 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1488 }
1489
1490 pub fn construct_advance_epoch_pt_v2(
1491 builder: ProgrammableTransactionBuilder,
1492 params: &AdvanceEpochParams,
1493 ) -> Result<ProgrammableTransaction, ExecutionError> {
1494 let call_arg_vec = vec![
1499 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), ];
1509 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1510 }
1511
1512 pub fn construct_advance_epoch_pt_v3(
1513 builder: ProgrammableTransactionBuilder,
1514 params: &AdvanceEpochParams,
1515 ) -> Result<ProgrammableTransaction, ExecutionError> {
1516 let call_arg_vec = vec![
1522 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), ];
1534 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1535 }
1536
1537 pub fn construct_advance_epoch_pt_v4(
1538 builder: ProgrammableTransactionBuilder,
1539 params: &AdvanceEpochParams,
1540 ) -> Result<ProgrammableTransaction, ExecutionError> {
1541 let call_arg_vec = vec![
1547 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), ];
1561 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1562 }
1563
1564 fn advance_epoch_impl(
1571 advance_epoch_pt: ProgrammableTransaction,
1572 params: AdvanceEpochParams,
1573 system_packages: Vec<SystemPackage>,
1574 temporary_store: &mut TemporaryStore<'_>,
1575 tx_ctx: Rc<RefCell<TxContext>>,
1576 move_vm: &Arc<MoveVM>,
1577 gas_charger: &mut GasCharger,
1578 protocol_config: &ProtocolConfig,
1579 metrics: Arc<LimitsMetrics>,
1580 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1581 ) -> Result<(), ExecutionError> {
1582 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1583 protocol_config,
1584 metrics.clone(),
1585 move_vm,
1586 temporary_store,
1587 tx_ctx.clone(),
1588 gas_charger,
1589 advance_epoch_pt,
1590 trace_builder_opt,
1591 );
1592
1593 #[cfg(msim)]
1594 let result = maybe_modify_result(result, params.epoch);
1595
1596 if result.is_err() {
1597 tracing::error!(
1598 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1599 result.as_ref().err(),
1600 temporary_store.objects(),
1601 params,
1602 );
1603 temporary_store.drop_writes();
1604 gas_charger.reset_storage_cost_and_rebate();
1606
1607 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1608 }
1609
1610 let new_vm = new_move_vm(
1611 all_natives(true, protocol_config),
1612 protocol_config,
1613 None,
1615 )
1616 .expect("Failed to create new MoveVM");
1617 process_system_packages(
1618 system_packages,
1619 temporary_store,
1620 tx_ctx,
1621 &new_vm,
1622 gas_charger,
1623 protocol_config,
1624 metrics,
1625 trace_builder_opt,
1626 );
1627
1628 Ok(())
1629 }
1630
1631 fn advance_epoch_v1(
1635 builder: ProgrammableTransactionBuilder,
1636 change_epoch: ChangeEpoch,
1637 temporary_store: &mut TemporaryStore<'_>,
1638 tx_ctx: Rc<RefCell<TxContext>>,
1639 move_vm: &Arc<MoveVM>,
1640 gas_charger: &mut GasCharger,
1641 protocol_config: &ProtocolConfig,
1642 metrics: Arc<LimitsMetrics>,
1643 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1644 ) -> Result<(), ExecutionError> {
1645 let params = AdvanceEpochParams {
1646 epoch: change_epoch.epoch,
1647 next_protocol_version: change_epoch.protocol_version.into(),
1648 validator_subsidy: protocol_config.validator_target_reward(),
1649 storage_charge: change_epoch.storage_charge,
1650 computation_charge: change_epoch.computation_charge,
1651 computation_charge_burned: change_epoch.computation_charge,
1653 storage_rebate: change_epoch.storage_rebate,
1654 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1655 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1656 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1657 max_committee_members_count: 0,
1660 eligible_active_validators: vec![],
1661 scores: vec![],
1662 adjust_rewards_by_score: false,
1663 };
1664 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1665 advance_epoch_impl(
1666 advance_epoch_pt,
1667 params,
1668 change_epoch.system_packages,
1669 temporary_store,
1670 tx_ctx,
1671 move_vm,
1672 gas_charger,
1673 protocol_config,
1674 metrics,
1675 trace_builder_opt,
1676 )
1677 }
1678
1679 fn advance_epoch_v2(
1683 builder: ProgrammableTransactionBuilder,
1684 change_epoch_v2: ChangeEpochV2,
1685 temporary_store: &mut TemporaryStore<'_>,
1686 tx_ctx: Rc<RefCell<TxContext>>,
1687 move_vm: &Arc<MoveVM>,
1688 gas_charger: &mut GasCharger,
1689 protocol_config: &ProtocolConfig,
1690 metrics: Arc<LimitsMetrics>,
1691 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1692 ) -> Result<(), ExecutionError> {
1693 let params = AdvanceEpochParams {
1694 epoch: change_epoch_v2.epoch,
1695 next_protocol_version: change_epoch_v2.protocol_version.into(),
1696 validator_subsidy: protocol_config.validator_target_reward(),
1697 storage_charge: change_epoch_v2.storage_charge,
1698 computation_charge: change_epoch_v2.computation_charge,
1699 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1700 storage_rebate: change_epoch_v2.storage_rebate,
1701 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1702 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1703 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1704 max_committee_members_count: protocol_config.max_committee_members_count(),
1705 eligible_active_validators: vec![],
1708 scores: vec![],
1709 adjust_rewards_by_score: false,
1710 };
1711 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1712 advance_epoch_impl(
1713 advance_epoch_pt,
1714 params,
1715 change_epoch_v2.system_packages,
1716 temporary_store,
1717 tx_ctx,
1718 move_vm,
1719 gas_charger,
1720 protocol_config,
1721 metrics,
1722 trace_builder_opt,
1723 )
1724 }
1725
1726 fn advance_epoch_v3(
1730 builder: ProgrammableTransactionBuilder,
1731 change_epoch_v3: ChangeEpochV3,
1732 temporary_store: &mut TemporaryStore<'_>,
1733 tx_ctx: Rc<RefCell<TxContext>>,
1734 move_vm: &Arc<MoveVM>,
1735 gas_charger: &mut GasCharger,
1736 protocol_config: &ProtocolConfig,
1737 metrics: Arc<LimitsMetrics>,
1738 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1739 ) -> Result<(), ExecutionError> {
1740 let params = AdvanceEpochParams {
1741 epoch: change_epoch_v3.epoch,
1742 next_protocol_version: change_epoch_v3.protocol_version.into(),
1743 validator_subsidy: protocol_config.validator_target_reward(),
1744 storage_charge: change_epoch_v3.storage_charge,
1745 computation_charge: change_epoch_v3.computation_charge,
1746 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1747 storage_rebate: change_epoch_v3.storage_rebate,
1748 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1749 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1750 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1751 max_committee_members_count: protocol_config.max_committee_members_count(),
1752 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1753 scores: vec![],
1756 adjust_rewards_by_score: false,
1757 };
1758 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1759 advance_epoch_impl(
1760 advance_epoch_pt,
1761 params,
1762 change_epoch_v3.system_packages,
1763 temporary_store,
1764 tx_ctx,
1765 move_vm,
1766 gas_charger,
1767 protocol_config,
1768 metrics,
1769 trace_builder_opt,
1770 )
1771 }
1772
1773 fn advance_epoch_v4(
1777 builder: ProgrammableTransactionBuilder,
1778 change_epoch_v4: ChangeEpochV4,
1779 temporary_store: &mut TemporaryStore<'_>,
1780 tx_ctx: Rc<RefCell<TxContext>>,
1781 move_vm: &Arc<MoveVM>,
1782 gas_charger: &mut GasCharger,
1783 protocol_config: &ProtocolConfig,
1784 metrics: Arc<LimitsMetrics>,
1785 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1786 ) -> Result<(), ExecutionError> {
1787 let params = AdvanceEpochParams {
1788 epoch: change_epoch_v4.epoch,
1789 next_protocol_version: change_epoch_v4.protocol_version.into(),
1790 validator_subsidy: protocol_config.validator_target_reward(),
1791 storage_charge: change_epoch_v4.storage_charge,
1792 computation_charge: change_epoch_v4.computation_charge,
1793 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1794 storage_rebate: change_epoch_v4.storage_rebate,
1795 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1796 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1797 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1798 max_committee_members_count: protocol_config.max_committee_members_count(),
1799 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1800 scores: change_epoch_v4.scores,
1801 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1802 };
1803 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1804 advance_epoch_impl(
1805 advance_epoch_pt,
1806 params,
1807 change_epoch_v4.system_packages,
1808 temporary_store,
1809 tx_ctx,
1810 move_vm,
1811 gas_charger,
1812 protocol_config,
1813 metrics,
1814 trace_builder_opt,
1815 )
1816 }
1817
1818 fn process_system_packages(
1819 system_packages: Vec<SystemPackage>,
1820 temporary_store: &mut TemporaryStore<'_>,
1821 tx_ctx: Rc<RefCell<TxContext>>,
1822 move_vm: &MoveVM,
1823 gas_charger: &mut GasCharger,
1824 protocol_config: &ProtocolConfig,
1825 metrics: Arc<LimitsMetrics>,
1826 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1827 ) {
1828 let binary_config = to_binary_config(protocol_config);
1829 for SystemPackage {
1830 version,
1831 modules,
1832 dependencies,
1833 } in system_packages.into_iter()
1834 {
1835 let deserialized_modules: Vec<_> = modules
1836 .iter()
1837 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1838 .collect();
1839
1840 if version == OBJECT_START_VERSION {
1841 let package_id = deserialized_modules.first().unwrap().address();
1842 info!("adding new system package {package_id}");
1843
1844 let publish_pt = {
1845 let mut b = ProgrammableTransactionBuilder::new();
1846 b.command(Command::new_publish(modules, dependencies));
1847 b.finish()
1848 };
1849
1850 programmable_transactions::execution::execute::<execution_mode::System>(
1851 protocol_config,
1852 metrics.clone(),
1853 move_vm,
1854 temporary_store,
1855 tx_ctx.clone(),
1856 gas_charger,
1857 publish_pt,
1858 trace_builder_opt,
1859 )
1860 .expect("System Package Publish must succeed");
1861 } else {
1862 let mut new_package = Object::new_system_package(
1863 &deserialized_modules,
1864 version,
1865 dependencies,
1866 tx_ctx.borrow().digest(),
1867 );
1868
1869 info!("upgraded system package {:?}", new_package.object_ref());
1870
1871 new_package
1874 .data
1875 .as_opt_mut_package()
1876 .unwrap()
1877 .decrement_version()
1878 .expect("package version should never underflow");
1879
1880 temporary_store.upgrade_system_package(new_package);
1882 }
1883 }
1884 }
1885
1886 fn setup_consensus_commit(
1892 consensus_commit_timestamp_ms: CheckpointTimestamp,
1893 temporary_store: &mut TemporaryStore<'_>,
1894 tx_ctx: Rc<RefCell<TxContext>>,
1895 move_vm: &Arc<MoveVM>,
1896 gas_charger: &mut GasCharger,
1897 protocol_config: &ProtocolConfig,
1898 metrics: Arc<LimitsMetrics>,
1899 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1900 ) -> Result<(), ExecutionError> {
1901 let pt = {
1902 let mut builder = ProgrammableTransactionBuilder::new();
1903 let res = builder.move_call(
1904 ObjectId::FRAMEWORK,
1905 Identifier::CLOCK_MODULE,
1906 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
1907 vec![],
1908 vec![
1909 CallArg::CLOCK_MUTABLE,
1910 CallArg::pure(&consensus_commit_timestamp_ms),
1911 ],
1912 );
1913 assert_invariant!(
1914 res.is_ok(),
1915 "Unable to generate consensus_commit_prologue transaction!"
1916 );
1917 builder.finish()
1918 };
1919 programmable_transactions::execution::execute::<execution_mode::System>(
1920 protocol_config,
1921 metrics,
1922 move_vm,
1923 temporary_store,
1924 tx_ctx,
1925 gas_charger,
1926 pt,
1927 trace_builder_opt,
1928 )
1929 }
1930
1931 fn setup_randomness_state_update(
1937 update: RandomnessStateUpdate,
1938 temporary_store: &mut TemporaryStore<'_>,
1939 tx_ctx: Rc<RefCell<TxContext>>,
1940 move_vm: &Arc<MoveVM>,
1941 gas_charger: &mut GasCharger,
1942 protocol_config: &ProtocolConfig,
1943 metrics: Arc<LimitsMetrics>,
1944 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1945 ) -> Result<(), ExecutionError> {
1946 let pt = {
1947 let mut builder = ProgrammableTransactionBuilder::new();
1948 let res = builder.move_call(
1949 ObjectId::FRAMEWORK,
1950 Identifier::RANDOM_MODULE,
1951 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
1952 vec![],
1953 vec![
1954 CallArg::Shared(SharedObjectReference::new(
1955 ObjectId::RANDOMNESS_STATE,
1956 update.randomness_obj_initial_shared_version,
1957 true,
1958 )),
1959 CallArg::pure(&update.randomness_round),
1960 CallArg::pure(&update.random_bytes),
1961 ],
1962 );
1963 assert_invariant!(
1964 res.is_ok(),
1965 "Unable to generate randomness_state_update transaction!"
1966 );
1967 builder.finish()
1968 };
1969 programmable_transactions::execution::execute::<execution_mode::System>(
1970 protocol_config,
1971 metrics,
1972 move_vm,
1973 temporary_store,
1974 tx_ctx,
1975 gas_charger,
1976 pt,
1977 trace_builder_opt,
1978 )
1979 }
1980
1981 fn setup_authenticator_move_call(
1988 authenticator: MoveAuthenticator,
1989 authenticator_function_ref: AuthenticatorFunctionRefV1,
1990 ) -> Result<ProgrammableTransaction, ExecutionError> {
1991 let mut builder = ProgrammableTransactionBuilder::new();
1992
1993 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
1994 args.extend(authenticator.call_args().to_owned());
1995
1996 let res = builder.move_call(
1997 authenticator_function_ref.package,
1998 Identifier::new(authenticator_function_ref.module.clone()).expect(
1999 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2000 ),
2001 Identifier::new(authenticator_function_ref.function).expect(
2002 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2003 ),
2004 authenticator.type_args().to_vec(),
2005 args,
2006 );
2007
2008 assert_invariant!(
2009 res.is_ok(),
2010 "Unable to generate an account authenticator call transaction!"
2011 );
2012
2013 Ok(builder.finish())
2014 }
2015
2016 fn resolve_sponsor(gas_data: &GasPayment, transaction_signer: &Address) -> Option<Address> {
2017 let gas_owner = gas_data.owner;
2018 if &gas_owner == transaction_signer {
2019 None
2020 } else {
2021 Some(gas_owner)
2022 }
2023 }
2024}