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, GenesisTransaction, Identifier, ObjectId,
22 ProgrammableTransaction, RandomnessStateUpdate, TransactionKind, Version,
23 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::{TransactionDigest, 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::{
53 CallArg, CheckedInputObjects, GasData, InputObjects, SharedObjectRef, SystemPackage,
54 TransactionKindExt,
55 },
56 };
57 use move_binary_format::CompiledModule;
58 use move_trace_format::format::MoveTraceBuilder;
59 use move_vm_runtime::move_vm::MoveVM;
60 use tracing::{info, instrument, trace, warn};
61
62 use crate::{
63 adapter::new_move_vm,
64 execution_mode::{self, ExecutionMode},
65 gas_charger::GasCharger,
66 programmable_transactions,
67 temporary_store::TemporaryStore,
68 type_layout_resolver::TypeLayoutResolver,
69 };
70
71 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
83 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
84 store: &dyn BackingStore,
85 input_objects: CheckedInputObjects,
86 gas_data: GasData,
87 gas_status: IotaGasStatus,
88 transaction_kind: TransactionKind,
89 transaction_signer: Address,
90 transaction_digest: TransactionDigest,
91 move_vm: &Arc<MoveVM>,
92 epoch_id: &EpochId,
93 epoch_timestamp_ms: u64,
94 protocol_config: &ProtocolConfig,
95 metrics: Arc<LimitsMetrics>,
96 enable_expensive_checks: bool,
97 certificate_deny_set: &HashSet<TransactionDigest>,
98 trace_builder_opt: &mut Option<MoveTraceBuilder>,
99 ) -> (
100 InnerTemporaryStore,
101 IotaGasStatus,
102 TransactionEffects,
103 Result<Mode::ExecutionResults, ExecutionError>,
104 ) {
105 let input_objects = input_objects.into_inner();
106 let mutable_inputs = if enable_expensive_checks {
107 input_objects.mutable_inputs().keys().copied().collect()
108 } else {
109 HashSet::new()
110 };
111 let shared_object_refs = input_objects.filter_shared_objects();
112 let receiving_objects = transaction_kind.receiving_objects();
113 let transaction_dependencies = input_objects.transaction_dependencies();
114 let contains_deleted_input = input_objects.contains_deleted_objects();
115 let cancelled_objects = input_objects.get_cancelled_objects();
116
117 let temporary_store = TemporaryStore::new(
118 store,
119 input_objects,
120 receiving_objects,
121 transaction_digest,
122 protocol_config,
123 *epoch_id,
124 );
125
126 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
127 let gas_price = gas_status.gas_price();
128 let rgp = gas_status.reference_gas_price();
129 let gas_charger = GasCharger::new(
130 transaction_digest,
131 gas_data.objects,
132 gas_status,
133 protocol_config,
134 );
135
136 let tx_ctx = TxContext::new_from_components(
137 &transaction_signer,
138 &transaction_digest,
139 epoch_id,
140 epoch_timestamp_ms,
141 rgp,
142 gas_price,
143 gas_data.budget,
144 sponsor,
145 protocol_config,
146 );
147 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
148
149 execute_transaction_to_effects_inner::<Mode>(
150 temporary_store,
151 gas_charger,
152 tx_ctx,
153 &mutable_inputs,
154 shared_object_refs,
155 transaction_dependencies,
156 contains_deleted_input,
157 cancelled_objects,
158 transaction_kind,
159 transaction_signer,
160 transaction_digest,
161 move_vm,
162 epoch_id,
163 protocol_config,
164 metrics,
165 enable_expensive_checks,
166 certificate_deny_set,
167 trace_builder_opt,
168 None,
169 )
170 }
171
172 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
175 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
176 mut temporary_store: TemporaryStore,
177 mut gas_charger: GasCharger,
178 tx_ctx: Rc<RefCell<TxContext>>,
179 mutable_inputs: &HashSet<ObjectId>,
180 shared_object_refs: Vec<SharedInput>,
181 mut transaction_dependencies: BTreeSet<TransactionDigest>,
182 contains_deleted_input: bool,
183 cancelled_objects: Option<(Vec<ObjectId>, Version)>,
184 transaction_kind: TransactionKind,
185 transaction_signer: Address,
186 transaction_digest: TransactionDigest,
187 move_vm: &Arc<MoveVM>,
188 epoch_id: &EpochId,
189 protocol_config: &ProtocolConfig,
190 metrics: Arc<LimitsMetrics>,
191 enable_expensive_checks: bool,
192 certificate_deny_set: &HashSet<TransactionDigest>,
193 trace_builder_opt: &mut Option<MoveTraceBuilder>,
194 pre_execution_result_opt: Option<
195 Result<
196 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
197 ExecutionError,
198 >,
199 >,
200 ) -> (
201 InnerTemporaryStore,
202 IotaGasStatus,
203 TransactionEffects,
204 Result<Mode::ExecutionResults, ExecutionError>,
205 ) {
206 let is_epoch_change = transaction_kind.is_end_of_epoch();
207 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
208
209 let (gas_cost_summary, execution_result) = execute_transaction::<Mode>(
210 &mut temporary_store,
211 transaction_kind,
212 &mut gas_charger,
213 tx_ctx,
214 move_vm,
215 protocol_config,
216 metrics,
217 enable_expensive_checks,
218 deny_cert,
219 contains_deleted_input,
220 cancelled_objects,
221 trace_builder_opt,
222 pre_execution_result_opt,
223 );
224
225 let status = if let Err(error) = &execution_result {
226 elaborate_error_logs(error, transaction_digest)
227 } else {
228 ExecutionStatus::Success
229 };
230
231 #[skip_checked_arithmetic]
232 trace!(
233 tx_digest = ?transaction_digest,
234 computation_gas_cost = gas_cost_summary.computation_cost,
235 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
236 storage_gas_cost = gas_cost_summary.storage_cost,
237 storage_gas_rebate = gas_cost_summary.storage_rebate,
238 "Finished execution of transaction with status {:?}",
239 status
240 );
241
242 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
246
247 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
248 temporary_store
249 .check_ownership_invariants(
250 &transaction_signer,
251 &mut gas_charger,
252 mutable_inputs,
253 is_epoch_change,
254 )
255 .unwrap()
256 } let (inner, effects) = temporary_store.into_effects(
259 shared_object_refs,
260 &transaction_digest,
261 transaction_dependencies,
262 gas_cost_summary,
263 status,
264 &mut gas_charger,
265 *epoch_id,
266 );
267
268 (
269 inner,
270 gas_charger.into_gas_status(),
271 effects,
272 execution_result,
273 )
274 }
275
276 #[instrument(
290 name = "tx_authenticate_then_execute_to_effects",
291 level = "debug",
292 skip_all
293 )]
294 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
295 store: &dyn BackingStore,
296 protocol_config: &ProtocolConfig,
298 metrics: Arc<LimitsMetrics>,
299 enable_expensive_checks: bool,
300 certificate_deny_set: &HashSet<TransactionDigest>,
301 epoch_id: &EpochId,
303 epoch_timestamp_ms: u64,
304 gas_data: GasData,
306 gas_status: IotaGasStatus,
307 authenticators: Vec<(
309 MoveAuthenticator,
310 AuthenticatorFunctionRefForExecution,
311 CheckedInputObjects,
312 )>,
313 authenticator_and_transaction_input_objects: CheckedInputObjects,
314 transaction_kind: TransactionKind,
316 transaction_signer: Address,
317 transaction_digest: TransactionDigest,
318 auth_context_data: AuthContextData,
319 trace_builder_opt: &mut Option<MoveTraceBuilder>,
321 move_vm: &Arc<MoveVM>,
323 ) -> (
324 InnerTemporaryStore,
325 IotaGasStatus,
326 TransactionEffects,
327 Result<Mode::ExecutionResults, ExecutionError>,
328 ) {
329 let input_objects = authenticator_and_transaction_input_objects.into_inner();
335 let mutable_inputs = if enable_expensive_checks {
337 input_objects.mutable_inputs().keys().copied().collect()
338 } else {
339 HashSet::new()
340 };
341 let shared_object_refs = input_objects.filter_shared_objects();
343 let transaction_receiving_objects = transaction_kind.receiving_objects();
345 let transaction_dependencies = input_objects.transaction_dependencies();
347 let contains_deleted_input = input_objects.contains_deleted_objects();
350 let cancelled_objects = input_objects.get_cancelled_objects();
351
352 let mut temporary_store = TemporaryStore::new(
354 store,
355 input_objects,
356 transaction_receiving_objects,
357 transaction_digest,
358 protocol_config,
359 *epoch_id,
360 );
361
362 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
364 let gas_price = gas_status.gas_price();
365 let rgp = gas_status.reference_gas_price();
366 let mut gas_charger = GasCharger::new(
367 transaction_digest,
368 gas_data.objects,
369 gas_status,
370 protocol_config,
371 );
372
373 let tx_ctx = TxContext::new_from_components(
375 &transaction_signer,
376 &transaction_digest,
377 epoch_id,
378 epoch_timestamp_ms,
379 rgp,
380 gas_price,
381 gas_data.budget,
382 sponsor,
383 protocol_config,
384 );
385 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
386
387 let authenticators = authenticators
393 .into_iter()
394 .map(
395 |(
396 authenticator,
397 authenticator_function_ref_for_execution,
398 authenticator_input_objects,
399 )| {
400 let AuthenticatorFunctionRefForExecution {
401 authenticator_function_ref,
402 loaded_object_id,
403 loaded_object_metadata,
404 } = authenticator_function_ref_for_execution;
405
406 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
409 loaded_object_id,
410 loaded_object_metadata,
411 )]));
412
413 (
414 authenticator,
415 authenticator_function_ref,
416 authenticator_input_objects,
417 )
418 },
419 )
420 .collect::<Vec<_>>();
421
422 let authentication_execution_result = authenticators.into_iter().try_for_each(
428 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
429 match authenticator_function_ref {
430 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
431 authenticate_transaction_inner(
432 &mut temporary_store,
433 protocol_config,
434 metrics.clone(),
435 &mut gas_charger,
436 authenticator,
437 authenticator_function_ref_v1,
438 &authenticator_input_objects.into_inner(),
439 transaction_kind.clone(),
440 transaction_digest,
441 auth_context_data.clone(),
442 tx_ctx.clone(),
443 trace_builder_opt,
444 move_vm,
445 )
446 }
447 }
448 },
449 );
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: GasData,
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 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
572 #[instrument(name = "tx_validate", level = "debug", skip_all)]
582 pub fn authenticate_transaction_inner(
583 temporary_store: &mut TemporaryStore<'_>,
584 protocol_config: &ProtocolConfig,
586 metrics: Arc<LimitsMetrics>,
587 gas_charger: &mut GasCharger,
589 authenticator: MoveAuthenticator,
591 authenticator_function_ref: AuthenticatorFunctionRefV1,
592 authenticator_input_objects: &InputObjects,
593 transaction_kind: TransactionKind,
595 transaction_digest: TransactionDigest,
596 auth_context_data: AuthContextData,
597 tx_ctx: Rc<RefCell<TxContext>>,
598 trace_builder_opt: &mut Option<MoveTraceBuilder>,
600 move_vm: &Arc<MoveVM>,
602 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
603 {
604 debug_assert!(
606 transaction_kind.is_programmable(),
607 "Only programmable transactions are allowed"
608 );
609 debug_assert!(
610 authenticator_input_objects
611 .mutable_inputs()
612 .keys()
613 .copied()
614 .collect::<HashSet<_>>()
615 .is_empty(),
616 "No mutable inputs are allowed"
617 );
618 debug_assert!(
619 authenticator.receiving_objects().is_empty(),
620 "No receiving inputs are allowed"
621 );
622
623 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
624 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
625
626 let auth_ctx = {
628 let TransactionKind::Programmable(ptb) = &transaction_kind else {
629 unreachable!("Only programmable transactions are allowed");
630 };
631 AuthContext::new_from_components(
632 authenticator.digest().into(),
633 auth_context_data.sender_auth_digest,
634 auth_context_data.sponsor_auth_digest,
635 auth_context_data
636 .sender_authenticator_function_ref
637 .and_then(Into::into),
638 auth_context_data
639 .sponsor_authenticator_function_ref
640 .and_then(Into::into),
641 ptb,
642 auth_context_data.transaction_data_bytes,
643 )
644 };
645 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
646
647 temporary_store.store_auth_context(auth_ctx);
651
652 let authentication_execution_result = execute_authenticator_move_call(
654 temporary_store,
655 authenticator,
656 authenticator_function_ref,
657 gas_charger,
658 tx_ctx,
659 move_vm,
660 protocol_config,
661 metrics,
662 false,
663 contains_deleted_input,
664 cancelled_objects,
665 trace_builder_opt,
666 );
667
668 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
670 elaborate_error_logs(error, transaction_digest)
671 } else {
672 ExecutionStatus::Success
673 };
674
675 #[skip_checked_arithmetic]
676 trace!(
677 tx_digest = ?transaction_digest,
678 computation_gas_cost = gas_charger.summary().gas_used(),
679 "Finished authenticator execution of transaction with status {:?}",
680 authentication_execution_status
681 );
682
683 authentication_execution_result
684 }
685
686 #[instrument(name = "auth_execute", level = "debug", skip_all)]
697 fn execute_authenticator_move_call(
698 temporary_store: &mut TemporaryStore<'_>,
699 authenticator: MoveAuthenticator,
700 authenticator_function_ref: AuthenticatorFunctionRefV1,
701 gas_charger: &mut GasCharger,
702 tx_ctx: Rc<RefCell<TxContext>>,
703 move_vm: &Arc<MoveVM>,
704 protocol_config: &ProtocolConfig,
705 metrics: Arc<LimitsMetrics>,
706 deny_cert: bool,
707 contains_deleted_input: bool,
708 cancelled_objects: Option<(Vec<ObjectId>, Version)>,
709 trace_builder_opt: &mut Option<MoveTraceBuilder>,
710 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
711 {
712 run_inputs_checks(
716 protocol_config,
717 deny_cert,
718 contains_deleted_input,
719 cancelled_objects,
720 )
721 .and_then(|()| {
722 let authenticator_move_call =
723 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
724 programmable_transactions::execution::execute::<execution_mode::Authentication>(
725 protocol_config,
726 metrics.clone(),
727 move_vm,
728 temporary_store,
729 tx_ctx,
730 gas_charger,
731 authenticator_move_call,
732 trace_builder_opt,
733 )
734 .and_then(|ok_result| {
735 temporary_store.check_move_authenticator_results_consistency()?;
736 Ok(ok_result)
737 })
738 })
739 }
740
741 pub fn execute_genesis_state_update(
748 store: &dyn BackingStore,
749 protocol_config: &ProtocolConfig,
750 metrics: Arc<LimitsMetrics>,
751 move_vm: &Arc<MoveVM>,
752 tx_context: Rc<RefCell<TxContext>>,
753 input_objects: CheckedInputObjects,
754 pt: ProgrammableTransaction,
755 ) -> Result<InnerTemporaryStore, ExecutionError> {
756 let input_objects = input_objects.into_inner();
757 let tx_digest = tx_context.borrow().digest();
758
759 let mut temporary_store =
760 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
761 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
762 programmable_transactions::execution::execute::<execution_mode::Genesis>(
763 protocol_config,
764 metrics,
765 move_vm,
766 &mut temporary_store,
767 tx_context,
768 &mut gas_charger,
769 pt,
770 &mut None,
771 )?;
772 temporary_store.update_object_version_and_prev_tx();
773 Ok(temporary_store.into_inner())
774 }
775
776 #[instrument(name = "tx_execute", level = "debug", skip_all)]
785 fn execute_transaction<Mode: ExecutionMode>(
786 temporary_store: &mut TemporaryStore<'_>,
787 transaction_kind: TransactionKind,
788 gas_charger: &mut GasCharger,
789 tx_ctx: Rc<RefCell<TxContext>>,
790 move_vm: &Arc<MoveVM>,
791 protocol_config: &ProtocolConfig,
792 metrics: Arc<LimitsMetrics>,
793 enable_expensive_checks: bool,
794 deny_cert: bool,
795 contains_deleted_input: bool,
796 cancelled_objects: Option<(Vec<ObjectId>, Version)>,
797 trace_builder_opt: &mut Option<MoveTraceBuilder>,
798 pre_execution_result_opt: Option<
799 Result<
800 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
801 ExecutionError,
802 >,
803 >,
804 ) -> (
805 GasCostSummary,
806 Result<Mode::ExecutionResults, ExecutionError>,
807 ) {
808 gas_charger.smash_gas(temporary_store);
809
810 debug_assert!(
813 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
814 "No gas charges must be applied yet"
815 );
816
817 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
818 || transaction_kind.is_end_of_epoch();
819
820 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
821
822 let tx_digest = tx_ctx.borrow().digest();
823
824 let result = gas_charger.charge_input_objects(temporary_store);
828 let mut result = result.and_then(|()| {
829 run_inputs_checks(
830 protocol_config,
831 deny_cert,
832 contains_deleted_input,
833 cancelled_objects,
834 )?;
835
836 let mut execution_result = pre_execution_result_opt.unwrap_or(Ok(())).and_then(|_| {
839 execution_loop::<Mode>(
840 temporary_store,
841 transaction_kind,
842 tx_ctx,
843 move_vm,
844 gas_charger,
845 protocol_config,
846 metrics.clone(),
847 trace_builder_opt,
848 )
849 });
850
851 let meter_check = check_meter_limit(
852 temporary_store,
853 gas_charger,
854 protocol_config,
855 metrics.clone(),
856 );
857 if let Err(e) = meter_check {
858 execution_result = Err(e);
859 }
860
861 if execution_result.is_ok() {
862 let gas_check = check_written_objects_limit(
863 temporary_store,
864 gas_charger,
865 protocol_config,
866 metrics,
867 );
868 if let Err(e) = gas_check {
869 execution_result = Err(e);
870 }
871 }
872
873 execution_result
874 });
875
876 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
877 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
886
887 if let Err(e) = run_conservation_checks::<Mode>(
888 temporary_store,
889 gas_charger,
890 tx_digest,
891 move_vm,
892 enable_expensive_checks,
893 &cost_summary,
894 is_genesis_or_epoch_change_tx,
895 advance_epoch_gas_summary,
896 ) {
897 result = Err(e);
899 }
900
901 (cost_summary, result)
902 }
903
904 fn elaborate_error_logs(
907 execution_error: &ExecutionError,
908 transaction_digest: TransactionDigest,
909 ) -> ExecutionStatus {
910 use ExecutionErrorKind as K;
911 match execution_error.kind() {
912 K::InvariantViolation | K::VmInvariantViolation => {
913 #[skip_checked_arithmetic]
914 tracing::error!(
915 kind = ?execution_error.kind(),
916 tx_digest = ?transaction_digest,
917 "INVARIANT VIOLATION! Source: {:?}",
918 execution_error.source(),
919 );
920 }
921
922 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
923 #[skip_checked_arithmetic]
924 tracing::debug!(
925 kind = ?execution_error.kind(),
926 tx_digest = ?transaction_digest,
927 "Verification Error. Source: {:?}",
928 execution_error.source(),
929 );
930 }
931
932 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
933 #[skip_checked_arithmetic]
934 tracing::debug!(
935 kind = ?execution_error.kind(),
936 tx_digest = ?transaction_digest,
937 "Publish/Upgrade Error. Source: {:?}",
938 execution_error.source(),
939 )
940 }
941
942 _ => (),
943 };
944
945 let (status, command) = execution_error.to_execution_status();
946 ExecutionStatus::new_failure(status, command)
947 }
948
949 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
958 fn run_conservation_checks<Mode: ExecutionMode>(
959 temporary_store: &mut TemporaryStore<'_>,
960 gas_charger: &mut GasCharger,
961 tx_digest: TransactionDigest,
962 move_vm: &Arc<MoveVM>,
963 enable_expensive_checks: bool,
964 cost_summary: &GasCostSummary,
965 is_genesis_or_epoch_change_tx: bool,
966 advance_epoch_gas_summary: Option<(u64, u64)>,
967 ) -> Result<(), ExecutionError> {
968 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
969 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
970 let conservation_result = {
973 temporary_store
974 .check_iota_conserved(cost_summary)
975 .and_then(|()| {
976 if enable_expensive_checks {
977 let mut layout_resolver =
980 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
981 temporary_store.check_iota_conserved_expensive(
982 cost_summary,
983 advance_epoch_gas_summary,
984 &mut layout_resolver,
985 )
986 } else {
987 Ok(())
988 }
989 })
990 };
991 if let Err(conservation_err) = conservation_result {
992 result = Err(conservation_err);
996 gas_charger.reset(temporary_store);
997 gas_charger.charge_gas(temporary_store, &mut result);
998 if let Err(recovery_err) = {
1000 temporary_store
1001 .check_iota_conserved(cost_summary)
1002 .and_then(|()| {
1003 if enable_expensive_checks {
1004 let mut layout_resolver =
1007 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1008 temporary_store.check_iota_conserved_expensive(
1009 cost_summary,
1010 advance_epoch_gas_summary,
1011 &mut layout_resolver,
1012 )
1013 } else {
1014 Ok(())
1015 }
1016 })
1017 } {
1018 panic!(
1022 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1023 tx_digest,
1024 recovery_err,
1025 gas_charger.summary()
1026 )
1027 }
1028 }
1029 } result
1033 }
1034
1035 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1046 fn run_inputs_checks(
1047 protocol_config: &ProtocolConfig,
1048 deny_cert: bool,
1049 contains_deleted_input: bool,
1050 cancelled_objects: Option<(Vec<ObjectId>, Version)>,
1051 ) -> Result<(), ExecutionError> {
1052 if deny_cert {
1053 Err(ExecutionError::new(
1054 ExecutionErrorKind::CertificateDenied,
1055 None,
1056 ))
1057 } else if contains_deleted_input {
1058 Err(ExecutionError::new(
1059 ExecutionErrorKind::InputObjectDeleted,
1060 None,
1061 ))
1062 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1063 match reason {
1064 version if version.is_congested() => Err(ExecutionError::new(
1065 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1066 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestionV2 {
1067 congested_objects: cancelled_objects,
1068 suggested_gas_price: version
1069 .get_congested_version_suggested_gas_price()
1070 .unwrap(),
1071 }
1072 } else {
1073 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestion {
1078 congested_objects: cancelled_objects,
1079 }
1080 },
1081 None,
1082 )),
1083 Version::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1084 ExecutionErrorKind::ExecutionCancelledDueToRandomnessUnavailable,
1085 None,
1086 )),
1087 _ => panic!("invalid cancellation reason Version: {reason}"),
1088 }
1089 } else {
1090 Ok(())
1091 }
1092 }
1093
1094 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1099 fn check_meter_limit(
1100 temporary_store: &mut TemporaryStore<'_>,
1101 gas_charger: &mut GasCharger,
1102 protocol_config: &ProtocolConfig,
1103 metrics: Arc<LimitsMetrics>,
1104 ) -> Result<(), ExecutionError> {
1105 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1106
1107 match check_limit_by_meter!(
1112 !gas_charger.is_unmetered(),
1113 effects_estimated_size,
1114 protocol_config.max_serialized_tx_effects_size_bytes(),
1115 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1116 metrics.excessive_estimated_effects_size
1117 ) {
1118 LimitThresholdCrossed::None => Ok(()),
1119 LimitThresholdCrossed::Soft(_, limit) => {
1120 warn!(
1121 effects_estimated_size = effects_estimated_size,
1122 soft_limit = limit,
1123 "Estimated transaction effects size crossed soft limit",
1124 );
1125 Ok(())
1126 }
1127 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1128 ExecutionErrorKind::EffectsTooLarge {
1129 current_size: effects_estimated_size as u64,
1130 max_size: lim as u64,
1131 },
1132 "Transaction effects are too large",
1133 )),
1134 }
1135 }
1136
1137 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1142 fn check_written_objects_limit(
1143 temporary_store: &mut TemporaryStore<'_>,
1144 gas_charger: &mut GasCharger,
1145 protocol_config: &ProtocolConfig,
1146 metrics: Arc<LimitsMetrics>,
1147 ) -> Result<(), ExecutionError> {
1148 if let (Some(normal_lim), Some(system_lim)) = (
1149 protocol_config.max_size_written_objects_as_option(),
1150 protocol_config.max_size_written_objects_system_tx_as_option(),
1151 ) {
1152 let written_objects_size = temporary_store.written_objects_size();
1153
1154 match check_limit_by_meter!(
1155 !gas_charger.is_unmetered(),
1156 written_objects_size,
1157 normal_lim,
1158 system_lim,
1159 metrics.excessive_written_objects_size
1160 ) {
1161 LimitThresholdCrossed::None => (),
1162 LimitThresholdCrossed::Soft(_, limit) => {
1163 warn!(
1164 written_objects_size = written_objects_size,
1165 soft_limit = limit,
1166 "Written objects size crossed soft limit",
1167 )
1168 }
1169 LimitThresholdCrossed::Hard(_, lim) => {
1170 return Err(ExecutionError::new_with_source(
1171 ExecutionErrorKind::WrittenObjectsTooLarge {
1172 object_size: written_objects_size as u64,
1173 max_object_size: lim as u64,
1174 },
1175 "Written objects size crossed hard limit",
1176 ));
1177 }
1178 };
1179 }
1180
1181 Ok(())
1182 }
1183
1184 #[instrument(level = "debug", skip_all)]
1191 fn execution_loop<Mode: ExecutionMode>(
1192 temporary_store: &mut TemporaryStore<'_>,
1193 transaction_kind: TransactionKind,
1194 tx_ctx: Rc<RefCell<TxContext>>,
1195 move_vm: &Arc<MoveVM>,
1196 gas_charger: &mut GasCharger,
1197 protocol_config: &ProtocolConfig,
1198 metrics: Arc<LimitsMetrics>,
1199 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1200 ) -> Result<Mode::ExecutionResults, ExecutionError> {
1201 let result = match transaction_kind {
1202 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1203 if tx_ctx.borrow().epoch() != 0 {
1204 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1205 }
1206
1207 for genesis_object in objects {
1208 let object = ObjectInner {
1209 data: genesis_object.data,
1210 owner: genesis_object.owner,
1211 previous_transaction: tx_ctx.borrow().digest(),
1212 storage_rebate: 0,
1213 };
1214 temporary_store.create_object(object.into());
1215 }
1216
1217 temporary_store.record_execution_results(ExecutionResults::V1(
1218 ExecutionResultsV1 {
1219 user_events: events,
1220 ..Default::default()
1221 },
1222 ));
1223
1224 Ok(Mode::empty_results())
1225 }
1226 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1227 setup_consensus_commit(
1228 prologue.commit_timestamp_ms,
1229 temporary_store,
1230 tx_ctx,
1231 move_vm,
1232 gas_charger,
1233 protocol_config,
1234 metrics,
1235 trace_builder_opt,
1236 )
1237 .expect("ConsensusCommitPrologueV1 cannot fail");
1238 Ok(Mode::empty_results())
1239 }
1240 TransactionKind::Programmable(pt) => {
1241 programmable_transactions::execution::execute::<Mode>(
1242 protocol_config,
1243 metrics,
1244 move_vm,
1245 temporary_store,
1246 tx_ctx,
1247 gas_charger,
1248 pt,
1249 trace_builder_opt,
1250 )
1251 }
1252 TransactionKind::EndOfEpoch(txns) => {
1253 let builder = ProgrammableTransactionBuilder::new();
1254 let len = txns.len();
1255
1256 if let Some((i, tx)) = txns.into_iter().enumerate().next() {
1257 match tx {
1258 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1259 assert_eq!(i, len - 1);
1260 advance_epoch_v1(
1261 builder,
1262 change_epoch,
1263 temporary_store,
1264 tx_ctx,
1265 move_vm,
1266 gas_charger,
1267 protocol_config,
1268 metrics,
1269 trace_builder_opt,
1270 )?;
1271 return Ok(Mode::empty_results());
1272 }
1273 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1274 assert_eq!(i, len - 1);
1275 advance_epoch_v2(
1276 builder,
1277 change_epoch_v2,
1278 temporary_store,
1279 tx_ctx,
1280 move_vm,
1281 gas_charger,
1282 protocol_config,
1283 metrics,
1284 trace_builder_opt,
1285 )?;
1286 return Ok(Mode::empty_results());
1287 }
1288 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1289 assert_eq!(i, len - 1);
1290 advance_epoch_v3(
1291 builder,
1292 change_epoch_v3,
1293 temporary_store,
1294 tx_ctx,
1295 move_vm,
1296 gas_charger,
1297 protocol_config,
1298 metrics,
1299 trace_builder_opt,
1300 )?;
1301 return Ok(Mode::empty_results());
1302 }
1303 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1304 assert_eq!(i, len - 1);
1305 advance_epoch_v4(
1306 builder,
1307 change_epoch_v4,
1308 temporary_store,
1309 tx_ctx,
1310 move_vm,
1311 gas_charger,
1312 protocol_config,
1313 metrics,
1314 trace_builder_opt,
1315 )?;
1316 return Ok(Mode::empty_results());
1317 }
1318 _ => unimplemented!(
1319 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1320 ),
1321 }
1322 }
1323 unreachable!(
1324 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1325 )
1326 }
1327 #[allow(deprecated)]
1328 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1329 return Err(ExecutionError::new(
1333 ExecutionErrorKind::VmInvariantViolation,
1334 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1335 ));
1336 }
1337 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1338 setup_randomness_state_update(
1339 randomness_state_update,
1340 temporary_store,
1341 tx_ctx,
1342 move_vm,
1343 gas_charger,
1344 protocol_config,
1345 metrics,
1346 trace_builder_opt,
1347 )?;
1348 Ok(Mode::empty_results())
1349 }
1350 _ => unimplemented!(
1351 "a new TransactionKind enum variant was added and needs to be handled"
1352 ),
1353 }?;
1354 temporary_store.check_execution_results_consistency()?;
1355 Ok(result)
1356 }
1357
1358 fn mint_epoch_rewards_in_pt(
1367 builder: &mut ProgrammableTransactionBuilder,
1368 params: &AdvanceEpochParams,
1369 ) -> (Argument, Argument) {
1370 let storage_charge_arg = builder
1372 .input(CallArg::pure(¶ms.storage_charge))
1373 .unwrap();
1374 let storage_charges = builder.programmable_move_call(
1375 ObjectId::FRAMEWORK,
1376 Identifier::BALANCE_MODULE,
1377 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1378 vec![GAS::type_tag()],
1379 vec![storage_charge_arg],
1380 );
1381
1382 let computation_charge_arg = builder
1384 .input(CallArg::pure(¶ms.computation_charge))
1385 .unwrap();
1386 let computation_charges = builder.programmable_move_call(
1387 ObjectId::FRAMEWORK,
1388 Identifier::BALANCE_MODULE,
1389 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1390 vec![GAS::type_tag()],
1391 vec![computation_charge_arg],
1392 );
1393 (storage_charges, computation_charges)
1394 }
1395
1396 pub fn construct_advance_epoch_pt_impl(
1404 mut builder: ProgrammableTransactionBuilder,
1405 params: &AdvanceEpochParams,
1406 call_arg_vec: Vec<CallArg>,
1407 ) -> Result<ProgrammableTransaction, ExecutionError> {
1408 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1410 let mut arguments = vec![
1411 builder
1412 .pure(params.validator_subsidy)
1413 .expect("bcs encoding a u64 should not fail"),
1414 storage_charges,
1415 computation_charges,
1416 ];
1417
1418 let call_arg_arguments = call_arg_vec
1419 .into_iter()
1420 .map(|a| builder.input(a))
1421 .collect::<Result<_, _>>();
1422
1423 assert_invariant!(
1424 call_arg_arguments.is_ok(),
1425 "Unable to generate args for advance_epoch transaction!"
1426 );
1427
1428 arguments.append(&mut call_arg_arguments.unwrap());
1429
1430 info!("Call arguments to advance_epoch transaction: {:?}", params);
1431
1432 let storage_rebates = builder.programmable_move_call(
1433 ObjectId::SYSTEM,
1434 Identifier::IOTA_SYSTEM_MODULE,
1435 ADVANCE_EPOCH_FUNCTION_NAME,
1436 vec![],
1437 arguments,
1438 );
1439
1440 builder.programmable_move_call(
1442 ObjectId::FRAMEWORK,
1443 Identifier::BALANCE_MODULE,
1444 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1445 vec![GAS::type_tag()],
1446 vec![storage_rebates],
1447 );
1448 Ok(builder.finish())
1449 }
1450
1451 pub fn construct_advance_epoch_pt_v1(
1452 builder: ProgrammableTransactionBuilder,
1453 params: &AdvanceEpochParams,
1454 ) -> Result<ProgrammableTransaction, ExecutionError> {
1455 let call_arg_vec = vec![
1460 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), ];
1468 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1469 }
1470
1471 pub fn construct_advance_epoch_pt_v2(
1472 builder: ProgrammableTransactionBuilder,
1473 params: &AdvanceEpochParams,
1474 ) -> Result<ProgrammableTransaction, ExecutionError> {
1475 let call_arg_vec = vec![
1480 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), ];
1490 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1491 }
1492
1493 pub fn construct_advance_epoch_pt_v3(
1494 builder: ProgrammableTransactionBuilder,
1495 params: &AdvanceEpochParams,
1496 ) -> Result<ProgrammableTransaction, ExecutionError> {
1497 let call_arg_vec = vec![
1503 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), ];
1515 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1516 }
1517
1518 pub fn construct_advance_epoch_pt_v4(
1519 builder: ProgrammableTransactionBuilder,
1520 params: &AdvanceEpochParams,
1521 ) -> Result<ProgrammableTransaction, ExecutionError> {
1522 let call_arg_vec = vec![
1528 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), ];
1542 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1543 }
1544
1545 fn advance_epoch_impl(
1552 advance_epoch_pt: ProgrammableTransaction,
1553 params: AdvanceEpochParams,
1554 system_packages: Vec<SystemPackage>,
1555 temporary_store: &mut TemporaryStore<'_>,
1556 tx_ctx: Rc<RefCell<TxContext>>,
1557 move_vm: &Arc<MoveVM>,
1558 gas_charger: &mut GasCharger,
1559 protocol_config: &ProtocolConfig,
1560 metrics: Arc<LimitsMetrics>,
1561 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1562 ) -> Result<(), ExecutionError> {
1563 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1564 protocol_config,
1565 metrics.clone(),
1566 move_vm,
1567 temporary_store,
1568 tx_ctx.clone(),
1569 gas_charger,
1570 advance_epoch_pt,
1571 trace_builder_opt,
1572 );
1573
1574 #[cfg(msim)]
1575 let result = maybe_modify_result(result, params.epoch);
1576
1577 if result.is_err() {
1578 tracing::error!(
1579 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1580 result.as_ref().err(),
1581 temporary_store.objects(),
1582 params,
1583 );
1584 temporary_store.drop_writes();
1585 gas_charger.reset_storage_cost_and_rebate();
1587
1588 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1589 }
1590
1591 let new_vm = new_move_vm(
1592 all_natives(true, protocol_config),
1593 protocol_config,
1594 None,
1596 )
1597 .expect("Failed to create new MoveVM");
1598 process_system_packages(
1599 system_packages,
1600 temporary_store,
1601 tx_ctx,
1602 &new_vm,
1603 gas_charger,
1604 protocol_config,
1605 metrics,
1606 trace_builder_opt,
1607 );
1608
1609 Ok(())
1610 }
1611
1612 fn advance_epoch_v1(
1616 builder: ProgrammableTransactionBuilder,
1617 change_epoch: ChangeEpoch,
1618 temporary_store: &mut TemporaryStore<'_>,
1619 tx_ctx: Rc<RefCell<TxContext>>,
1620 move_vm: &Arc<MoveVM>,
1621 gas_charger: &mut GasCharger,
1622 protocol_config: &ProtocolConfig,
1623 metrics: Arc<LimitsMetrics>,
1624 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1625 ) -> Result<(), ExecutionError> {
1626 let params = AdvanceEpochParams {
1627 epoch: change_epoch.epoch,
1628 next_protocol_version: change_epoch.protocol_version.into(),
1629 validator_subsidy: protocol_config.validator_target_reward(),
1630 storage_charge: change_epoch.storage_charge,
1631 computation_charge: change_epoch.computation_charge,
1632 computation_charge_burned: change_epoch.computation_charge,
1634 storage_rebate: change_epoch.storage_rebate,
1635 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1636 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1637 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1638 max_committee_members_count: 0,
1641 eligible_active_validators: vec![],
1642 scores: vec![],
1643 adjust_rewards_by_score: false,
1644 };
1645 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1646 advance_epoch_impl(
1647 advance_epoch_pt,
1648 params,
1649 change_epoch.system_packages,
1650 temporary_store,
1651 tx_ctx,
1652 move_vm,
1653 gas_charger,
1654 protocol_config,
1655 metrics,
1656 trace_builder_opt,
1657 )
1658 }
1659
1660 fn advance_epoch_v2(
1664 builder: ProgrammableTransactionBuilder,
1665 change_epoch_v2: ChangeEpochV2,
1666 temporary_store: &mut TemporaryStore<'_>,
1667 tx_ctx: Rc<RefCell<TxContext>>,
1668 move_vm: &Arc<MoveVM>,
1669 gas_charger: &mut GasCharger,
1670 protocol_config: &ProtocolConfig,
1671 metrics: Arc<LimitsMetrics>,
1672 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1673 ) -> Result<(), ExecutionError> {
1674 let params = AdvanceEpochParams {
1675 epoch: change_epoch_v2.epoch,
1676 next_protocol_version: change_epoch_v2.protocol_version.into(),
1677 validator_subsidy: protocol_config.validator_target_reward(),
1678 storage_charge: change_epoch_v2.storage_charge,
1679 computation_charge: change_epoch_v2.computation_charge,
1680 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1681 storage_rebate: change_epoch_v2.storage_rebate,
1682 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1683 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1684 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1685 max_committee_members_count: protocol_config.max_committee_members_count(),
1686 eligible_active_validators: vec![],
1689 scores: vec![],
1690 adjust_rewards_by_score: false,
1691 };
1692 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1693 advance_epoch_impl(
1694 advance_epoch_pt,
1695 params,
1696 change_epoch_v2.system_packages,
1697 temporary_store,
1698 tx_ctx,
1699 move_vm,
1700 gas_charger,
1701 protocol_config,
1702 metrics,
1703 trace_builder_opt,
1704 )
1705 }
1706
1707 fn advance_epoch_v3(
1711 builder: ProgrammableTransactionBuilder,
1712 change_epoch_v3: ChangeEpochV3,
1713 temporary_store: &mut TemporaryStore<'_>,
1714 tx_ctx: Rc<RefCell<TxContext>>,
1715 move_vm: &Arc<MoveVM>,
1716 gas_charger: &mut GasCharger,
1717 protocol_config: &ProtocolConfig,
1718 metrics: Arc<LimitsMetrics>,
1719 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1720 ) -> Result<(), ExecutionError> {
1721 let params = AdvanceEpochParams {
1722 epoch: change_epoch_v3.epoch,
1723 next_protocol_version: change_epoch_v3.protocol_version.into(),
1724 validator_subsidy: protocol_config.validator_target_reward(),
1725 storage_charge: change_epoch_v3.storage_charge,
1726 computation_charge: change_epoch_v3.computation_charge,
1727 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1728 storage_rebate: change_epoch_v3.storage_rebate,
1729 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1730 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1731 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1732 max_committee_members_count: protocol_config.max_committee_members_count(),
1733 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1734 scores: vec![],
1737 adjust_rewards_by_score: false,
1738 };
1739 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1740 advance_epoch_impl(
1741 advance_epoch_pt,
1742 params,
1743 change_epoch_v3.system_packages,
1744 temporary_store,
1745 tx_ctx,
1746 move_vm,
1747 gas_charger,
1748 protocol_config,
1749 metrics,
1750 trace_builder_opt,
1751 )
1752 }
1753
1754 fn advance_epoch_v4(
1758 builder: ProgrammableTransactionBuilder,
1759 change_epoch_v4: ChangeEpochV4,
1760 temporary_store: &mut TemporaryStore<'_>,
1761 tx_ctx: Rc<RefCell<TxContext>>,
1762 move_vm: &Arc<MoveVM>,
1763 gas_charger: &mut GasCharger,
1764 protocol_config: &ProtocolConfig,
1765 metrics: Arc<LimitsMetrics>,
1766 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1767 ) -> Result<(), ExecutionError> {
1768 let params = AdvanceEpochParams {
1769 epoch: change_epoch_v4.epoch,
1770 next_protocol_version: change_epoch_v4.protocol_version.into(),
1771 validator_subsidy: protocol_config.validator_target_reward(),
1772 storage_charge: change_epoch_v4.storage_charge,
1773 computation_charge: change_epoch_v4.computation_charge,
1774 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1775 storage_rebate: change_epoch_v4.storage_rebate,
1776 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1777 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1778 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1779 max_committee_members_count: protocol_config.max_committee_members_count(),
1780 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1781 scores: change_epoch_v4.scores,
1782 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1783 };
1784 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1785 advance_epoch_impl(
1786 advance_epoch_pt,
1787 params,
1788 change_epoch_v4.system_packages,
1789 temporary_store,
1790 tx_ctx,
1791 move_vm,
1792 gas_charger,
1793 protocol_config,
1794 metrics,
1795 trace_builder_opt,
1796 )
1797 }
1798
1799 fn process_system_packages(
1800 system_packages: Vec<SystemPackage>,
1801 temporary_store: &mut TemporaryStore<'_>,
1802 tx_ctx: Rc<RefCell<TxContext>>,
1803 move_vm: &MoveVM,
1804 gas_charger: &mut GasCharger,
1805 protocol_config: &ProtocolConfig,
1806 metrics: Arc<LimitsMetrics>,
1807 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1808 ) {
1809 let binary_config = to_binary_config(protocol_config);
1810 for SystemPackage {
1811 version,
1812 modules,
1813 dependencies,
1814 } in system_packages.into_iter()
1815 {
1816 let deserialized_modules: Vec<_> = modules
1817 .iter()
1818 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1819 .collect();
1820
1821 if version == OBJECT_START_VERSION {
1822 let package_id = deserialized_modules.first().unwrap().address();
1823 info!("adding new system package {package_id}");
1824
1825 let publish_pt = {
1826 let mut b = ProgrammableTransactionBuilder::new();
1827 b.command(Command::new_publish(modules, dependencies));
1828 b.finish()
1829 };
1830
1831 programmable_transactions::execution::execute::<execution_mode::System>(
1832 protocol_config,
1833 metrics.clone(),
1834 move_vm,
1835 temporary_store,
1836 tx_ctx.clone(),
1837 gas_charger,
1838 publish_pt,
1839 trace_builder_opt,
1840 )
1841 .expect("System Package Publish must succeed");
1842 } else {
1843 let mut new_package = Object::new_system_package(
1844 &deserialized_modules,
1845 version,
1846 dependencies,
1847 tx_ctx.borrow().digest(),
1848 );
1849
1850 info!("upgraded system package {:?}", new_package.object_ref());
1851
1852 new_package
1855 .data
1856 .as_opt_mut_package()
1857 .unwrap()
1858 .decrement_version()
1859 .expect("package version should never underflow");
1860
1861 temporary_store.upgrade_system_package(new_package);
1863 }
1864 }
1865 }
1866
1867 fn setup_consensus_commit(
1873 consensus_commit_timestamp_ms: CheckpointTimestamp,
1874 temporary_store: &mut TemporaryStore<'_>,
1875 tx_ctx: Rc<RefCell<TxContext>>,
1876 move_vm: &Arc<MoveVM>,
1877 gas_charger: &mut GasCharger,
1878 protocol_config: &ProtocolConfig,
1879 metrics: Arc<LimitsMetrics>,
1880 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1881 ) -> Result<(), ExecutionError> {
1882 let pt = {
1883 let mut builder = ProgrammableTransactionBuilder::new();
1884 let res = builder.move_call(
1885 ObjectId::FRAMEWORK,
1886 Identifier::CLOCK_MODULE,
1887 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
1888 vec![],
1889 vec![
1890 CallArg::CLOCK_MUTABLE,
1891 CallArg::pure(&consensus_commit_timestamp_ms),
1892 ],
1893 );
1894 assert_invariant!(
1895 res.is_ok(),
1896 "Unable to generate consensus_commit_prologue transaction!"
1897 );
1898 builder.finish()
1899 };
1900 programmable_transactions::execution::execute::<execution_mode::System>(
1901 protocol_config,
1902 metrics,
1903 move_vm,
1904 temporary_store,
1905 tx_ctx,
1906 gas_charger,
1907 pt,
1908 trace_builder_opt,
1909 )
1910 }
1911
1912 fn setup_randomness_state_update(
1918 update: RandomnessStateUpdate,
1919 temporary_store: &mut TemporaryStore<'_>,
1920 tx_ctx: Rc<RefCell<TxContext>>,
1921 move_vm: &Arc<MoveVM>,
1922 gas_charger: &mut GasCharger,
1923 protocol_config: &ProtocolConfig,
1924 metrics: Arc<LimitsMetrics>,
1925 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1926 ) -> Result<(), ExecutionError> {
1927 let pt = {
1928 let mut builder = ProgrammableTransactionBuilder::new();
1929 let res = builder.move_call(
1930 ObjectId::FRAMEWORK,
1931 Identifier::RANDOM_MODULE,
1932 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
1933 vec![],
1934 vec![
1935 CallArg::Shared(SharedObjectRef::new(
1936 ObjectId::RANDOMNESS_STATE,
1937 update.randomness_obj_initial_shared_version,
1938 true,
1939 )),
1940 CallArg::pure(&update.randomness_round),
1941 CallArg::pure(&update.random_bytes),
1942 ],
1943 );
1944 assert_invariant!(
1945 res.is_ok(),
1946 "Unable to generate randomness_state_update transaction!"
1947 );
1948 builder.finish()
1949 };
1950 programmable_transactions::execution::execute::<execution_mode::System>(
1951 protocol_config,
1952 metrics,
1953 move_vm,
1954 temporary_store,
1955 tx_ctx,
1956 gas_charger,
1957 pt,
1958 trace_builder_opt,
1959 )
1960 }
1961
1962 fn setup_authenticator_move_call(
1969 authenticator: MoveAuthenticator,
1970 authenticator_function_ref: AuthenticatorFunctionRefV1,
1971 ) -> Result<ProgrammableTransaction, ExecutionError> {
1972 let mut builder = ProgrammableTransactionBuilder::new();
1973
1974 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
1975 args.extend(authenticator.call_args().to_owned());
1976
1977 let res = builder.move_call(
1978 authenticator_function_ref.package,
1979 Identifier::new(authenticator_function_ref.module.clone()).expect(
1980 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
1981 ),
1982 Identifier::new(authenticator_function_ref.function).expect(
1983 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
1984 ),
1985 authenticator.type_args().to_vec(),
1986 args,
1987 );
1988
1989 assert_invariant!(
1990 res.is_ok(),
1991 "Unable to generate an account authenticator call transaction!"
1992 );
1993
1994 Ok(builder.finish())
1995 }
1996
1997 fn resolve_sponsor(gas_data: &GasData, transaction_signer: &Address) -> Option<Address> {
1998 let gas_owner = gas_data.owner;
1999 if &gas_owner == transaction_signer {
2000 None
2001 } else {
2002 Some(gas_owner)
2003 }
2004 }
2005}