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