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