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