1pub use checked::*;
6
7#[iota_macros::with_checked_arithmetic]
8mod checked {
9
10 use std::{
11 collections::{BTreeMap, BTreeSet, HashSet},
12 sync::Arc,
13 };
14
15 use iota_move_natives::all_natives;
16 use iota_protocol_config::{LimitThresholdCrossed, ProtocolConfig, check_limit_by_meter};
17 #[cfg(msim)]
18 use iota_types::iota_system_state::advance_epoch_result_injection::maybe_modify_result;
19 use iota_types::{
20 IOTA_AUTHENTICATOR_STATE_OBJECT_ID, IOTA_FRAMEWORK_ADDRESS, IOTA_FRAMEWORK_PACKAGE_ID,
21 IOTA_RANDOMNESS_STATE_OBJECT_ID, IOTA_SYSTEM_PACKAGE_ID, Identifier,
22 account_abstraction::authenticator_function::{
23 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
24 AuthenticatorFunctionRefV1,
25 },
26 auth_context::AuthContext,
27 authenticator_state::{
28 AUTHENTICATOR_STATE_CREATE_FUNCTION_NAME,
29 AUTHENTICATOR_STATE_EXPIRE_JWKS_FUNCTION_NAME, AUTHENTICATOR_STATE_MODULE_NAME,
30 AUTHENTICATOR_STATE_UPDATE_FUNCTION_NAME,
31 },
32 balance::{
33 BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME,
34 BALANCE_MODULE_NAME,
35 },
36 base_types::{
37 IotaAddress, ObjectID, ObjectRef, SequenceNumber, TransactionDigest, TxContext,
38 },
39 clock::{CLOCK_MODULE_NAME, CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME},
40 committee::EpochId,
41 effects::TransactionEffects,
42 error::{ExecutionError, ExecutionErrorKind},
43 execution::{ExecutionResults, ExecutionResultsV1, SharedInput, is_certificate_denied},
44 execution_config_utils::to_binary_config,
45 execution_status::{CongestedObjects, ExecutionStatus},
46 gas::{GasCostSummary, IotaGasStatus},
47 gas_coin::GAS,
48 inner_temporary_store::InnerTemporaryStore,
49 iota_system_state::{
50 ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams, IOTA_SYSTEM_MODULE_NAME,
51 },
52 messages_checkpoint::CheckpointTimestamp,
53 metrics::LimitsMetrics,
54 move_authenticator::MoveAuthenticator,
55 object::{OBJECT_START_VERSION, Object, ObjectInner},
56 programmable_transaction_builder::ProgrammableTransactionBuilder,
57 randomness_state::{RANDOMNESS_MODULE_NAME, RANDOMNESS_STATE_UPDATE_FUNCTION_NAME},
58 storage::{BackingStore, Storage},
59 transaction::{
60 Argument, AuthenticatorStateExpire, AuthenticatorStateUpdateV1, CallArg, ChangeEpoch,
61 ChangeEpochV2, ChangeEpochV3, ChangeEpochV4, CheckedInputObjects, Command,
62 EndOfEpochTransactionKind, GenesisTransaction, InputObjects, ObjectArg,
63 ProgrammableTransaction, RandomnessStateUpdate, TransactionKind,
64 },
65 };
66 use move_binary_format::CompiledModule;
67 use move_trace_format::format::MoveTraceBuilder;
68 use move_vm_runtime::move_vm::MoveVM;
69 use tracing::{info, instrument, trace, warn};
70
71 use crate::{
72 adapter::new_move_vm,
73 execution_mode::{self, ExecutionMode},
74 gas_charger::GasCharger,
75 programmable_transactions,
76 temporary_store::TemporaryStore,
77 type_layout_resolver::TypeLayoutResolver,
78 };
79
80 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
92 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
93 store: &dyn BackingStore,
94 input_objects: CheckedInputObjects,
95 gas_coins: Vec<ObjectRef>,
96 gas_status: IotaGasStatus,
97 transaction_kind: TransactionKind,
98 transaction_signer: IotaAddress,
99 transaction_digest: TransactionDigest,
100 move_vm: &Arc<MoveVM>,
101 epoch_id: &EpochId,
102 epoch_timestamp_ms: u64,
103 protocol_config: &ProtocolConfig,
104 metrics: Arc<LimitsMetrics>,
105 enable_expensive_checks: bool,
106 certificate_deny_set: &HashSet<TransactionDigest>,
107 trace_builder_opt: &mut Option<MoveTraceBuilder>,
108 ) -> (
109 InnerTemporaryStore,
110 IotaGasStatus,
111 TransactionEffects,
112 Result<Mode::ExecutionResults, ExecutionError>,
113 ) {
114 let input_objects = input_objects.into_inner();
115 let mutable_inputs = if enable_expensive_checks {
116 input_objects.mutable_inputs().keys().copied().collect()
117 } else {
118 HashSet::new()
119 };
120 let shared_object_refs = input_objects.filter_shared_objects();
121 let receiving_objects = transaction_kind.receiving_objects();
122 let transaction_dependencies = input_objects.transaction_dependencies();
123 let contains_deleted_input = input_objects.contains_deleted_objects();
124 let cancelled_objects = input_objects.get_cancelled_objects();
125
126 let temporary_store = TemporaryStore::new(
127 store,
128 input_objects,
129 receiving_objects,
130 transaction_digest,
131 protocol_config,
132 *epoch_id,
133 );
134
135 let gas_charger =
136 GasCharger::new(transaction_digest, gas_coins, gas_status, protocol_config);
137
138 let mut tx_ctx = TxContext::new_from_components(
139 &transaction_signer,
140 &transaction_digest,
141 epoch_id,
142 epoch_timestamp_ms,
143 );
144
145 execute_transaction_to_effects_inner::<Mode>(
146 temporary_store,
147 gas_charger,
148 &mut tx_ctx,
149 &mutable_inputs,
150 shared_object_refs,
151 transaction_dependencies,
152 contains_deleted_input,
153 cancelled_objects,
154 transaction_kind,
155 transaction_signer,
156 transaction_digest,
157 move_vm,
158 epoch_id,
159 protocol_config,
160 metrics,
161 enable_expensive_checks,
162 certificate_deny_set,
163 trace_builder_opt,
164 None,
165 )
166 }
167
168 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
171 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
172 mut temporary_store: TemporaryStore,
173 mut gas_charger: GasCharger,
174 tx_ctx: &mut TxContext,
175 mutable_inputs: &HashSet<ObjectID>,
176 shared_object_refs: Vec<SharedInput>,
177 mut transaction_dependencies: BTreeSet<TransactionDigest>,
178 contains_deleted_input: bool,
179 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
180 transaction_kind: TransactionKind,
181 transaction_signer: IotaAddress,
182 transaction_digest: TransactionDigest,
183 move_vm: &Arc<MoveVM>,
184 epoch_id: &EpochId,
185 protocol_config: &ProtocolConfig,
186 metrics: Arc<LimitsMetrics>,
187 enable_expensive_checks: bool,
188 certificate_deny_set: &HashSet<TransactionDigest>,
189 trace_builder_opt: &mut Option<MoveTraceBuilder>,
190 pre_execution_result_opt: Option<
191 Result<
192 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
193 ExecutionError,
194 >,
195 >,
196 ) -> (
197 InnerTemporaryStore,
198 IotaGasStatus,
199 TransactionEffects,
200 Result<Mode::ExecutionResults, ExecutionError>,
201 ) {
202 let is_epoch_change = transaction_kind.is_end_of_epoch_tx();
203 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
204
205 let (gas_cost_summary, execution_result) = execute_transaction::<Mode>(
206 &mut temporary_store,
207 transaction_kind,
208 &mut gas_charger,
209 tx_ctx,
210 move_vm,
211 protocol_config,
212 metrics,
213 enable_expensive_checks,
214 deny_cert,
215 contains_deleted_input,
216 cancelled_objects,
217 trace_builder_opt,
218 pre_execution_result_opt,
219 );
220
221 let status = if let Err(error) = &execution_result {
222 elaborate_error_logs(error, transaction_digest)
223 } else {
224 ExecutionStatus::Success
225 };
226
227 #[skip_checked_arithmetic]
228 trace!(
229 tx_digest = ?transaction_digest,
230 computation_gas_cost = gas_cost_summary.computation_cost,
231 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
232 storage_gas_cost = gas_cost_summary.storage_cost,
233 storage_gas_rebate = gas_cost_summary.storage_rebate,
234 "Finished execution of transaction with status {:?}",
235 status
236 );
237
238 transaction_dependencies.remove(&TransactionDigest::genesis_marker());
242
243 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
244 temporary_store
245 .check_ownership_invariants(
246 &transaction_signer,
247 &mut gas_charger,
248 mutable_inputs,
249 is_epoch_change,
250 )
251 .unwrap()
252 } let (inner, effects) = temporary_store.into_effects(
255 shared_object_refs,
256 &transaction_digest,
257 transaction_dependencies,
258 gas_cost_summary,
259 status,
260 &mut gas_charger,
261 *epoch_id,
262 );
263
264 (
265 inner,
266 gas_charger.into_gas_status(),
267 effects,
268 execution_result,
269 )
270 }
271
272 #[instrument(
286 name = "tx_authenticate_then_execute_to_effects",
287 level = "debug",
288 skip_all
289 )]
290 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
291 store: &dyn BackingStore,
292 protocol_config: &ProtocolConfig,
294 metrics: Arc<LimitsMetrics>,
295 enable_expensive_checks: bool,
296 certificate_deny_set: &HashSet<TransactionDigest>,
297 epoch_id: &EpochId,
299 epoch_timestamp_ms: u64,
300 gas_status: IotaGasStatus,
302 gas_coins: Vec<ObjectRef>,
303 authenticator: MoveAuthenticator,
305 authenticator_function_ref_for_execution: AuthenticatorFunctionRefForExecution,
306 authenticator_input_objects: CheckedInputObjects,
307 authenticator_and_transaction_input_objects: CheckedInputObjects,
308 transaction_kind: TransactionKind,
310 transaction_signer: IotaAddress,
311 transaction_digest: TransactionDigest,
312 trace_builder_opt: &mut Option<MoveTraceBuilder>,
314 move_vm: &Arc<MoveVM>,
316 ) -> (
317 InnerTemporaryStore,
318 IotaGasStatus,
319 TransactionEffects,
320 Result<Mode::ExecutionResults, ExecutionError>,
321 ) {
322 let input_objects = authenticator_and_transaction_input_objects.into_inner();
328 let mutable_inputs = if enable_expensive_checks {
330 input_objects.mutable_inputs().keys().copied().collect()
331 } else {
332 HashSet::new()
333 };
334 let shared_object_refs = input_objects.filter_shared_objects();
336 let transaction_receiving_objects = transaction_kind.receiving_objects();
338 let transaction_dependencies = input_objects.transaction_dependencies();
340 let contains_deleted_input = input_objects.contains_deleted_objects();
343 let cancelled_objects = input_objects.get_cancelled_objects();
344
345 let mut temporary_store = TemporaryStore::new(
347 store,
348 input_objects,
349 transaction_receiving_objects,
350 transaction_digest,
351 protocol_config,
352 *epoch_id,
353 );
354
355 let mut gas_charger =
357 GasCharger::new(transaction_digest, gas_coins, gas_status, protocol_config);
358
359 let mut tx_ctx = TxContext::new_from_components(
361 &transaction_signer,
362 &transaction_digest,
363 epoch_id,
364 epoch_timestamp_ms,
365 );
366
367 let AuthenticatorFunctionRefForExecution {
372 authenticator_function_ref,
373 loaded_object_id,
374 loaded_object_metadata,
375 } = authenticator_function_ref_for_execution;
376
377 let authentication_execution_result = match authenticator_function_ref {
378 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
379 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
382 loaded_object_id,
383 loaded_object_metadata,
384 )]));
385
386 authenticate_transaction_inner(
388 &mut temporary_store,
389 protocol_config,
390 metrics.clone(),
391 &mut gas_charger,
392 authenticator,
393 authenticator_function_ref_v1,
394 &authenticator_input_objects.into_inner(),
395 transaction_kind.clone(),
396 transaction_digest,
397 &mut tx_ctx,
398 trace_builder_opt,
399 move_vm,
400 )
401 }
402 };
403
404 execute_transaction_to_effects_inner::<Mode>(
412 temporary_store,
413 gas_charger,
414 &mut tx_ctx,
415 &mutable_inputs,
416 shared_object_refs,
417 transaction_dependencies,
418 contains_deleted_input,
419 cancelled_objects,
420 transaction_kind,
421 transaction_signer,
422 transaction_digest,
423 move_vm,
424 epoch_id,
425 protocol_config,
426 metrics,
427 enable_expensive_checks,
428 certificate_deny_set,
429 trace_builder_opt,
430 Some(authentication_execution_result),
431 )
432 }
433
434 #[instrument(name = "tx_validate", level = "debug", skip_all)]
439 pub fn authenticate_transaction(
440 store: &dyn BackingStore,
441 protocol_config: &ProtocolConfig,
443 metrics: Arc<LimitsMetrics>,
444 epoch_id: &EpochId,
446 epoch_timestamp_ms: u64,
447 gas_status: IotaGasStatus,
449 authenticator: MoveAuthenticator,
451 authenticator_function_ref: AuthenticatorFunctionRef,
452 authenticator_input_objects: CheckedInputObjects,
453 transaction_kind: TransactionKind,
455 transaction_signer: IotaAddress,
456 transaction_digest: TransactionDigest,
457 trace_builder_opt: &mut Option<MoveTraceBuilder>,
459 move_vm: &Arc<MoveVM>,
461 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
462 {
463 let input_objects = authenticator_input_objects.into_inner();
464
465 let mut temporary_store = TemporaryStore::new(
467 store,
468 input_objects.clone(),
469 vec![],
470 transaction_digest,
471 protocol_config,
472 *epoch_id,
473 );
474
475 let mut gas_charger =
477 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
478
479 let mut tx_ctx = TxContext::new_from_components(
482 &transaction_signer,
483 &transaction_digest,
484 epoch_id,
485 epoch_timestamp_ms,
486 );
487
488 match authenticator_function_ref {
490 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
491 authenticate_transaction_inner(
492 &mut temporary_store,
493 protocol_config,
494 metrics.clone(),
495 &mut gas_charger,
496 authenticator,
497 authenticator_function_ref_v1,
498 &input_objects,
499 transaction_kind.clone(),
500 transaction_digest,
501 &mut tx_ctx,
502 trace_builder_opt,
503 move_vm,
504 )
505 }
506 }
507 }
508
509 #[instrument(name = "tx_validate", level = "debug", skip_all)]
519 pub fn authenticate_transaction_inner(
520 temporary_store: &mut TemporaryStore<'_>,
521 protocol_config: &ProtocolConfig,
523 metrics: Arc<LimitsMetrics>,
524 gas_charger: &mut GasCharger,
526 authenticator: MoveAuthenticator,
528 authenticator_function_ref: AuthenticatorFunctionRefV1,
529 authenticator_input_objects: &InputObjects,
530 transaction_kind: TransactionKind,
532 transaction_digest: TransactionDigest,
533 tx_ctx: &mut TxContext,
534 trace_builder_opt: &mut Option<MoveTraceBuilder>,
536 move_vm: &Arc<MoveVM>,
538 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
539 {
540 debug_assert!(
542 transaction_kind.is_programmable_transaction(),
543 "Only programmable transactions are allowed"
544 );
545 debug_assert!(
546 authenticator_input_objects
547 .mutable_inputs()
548 .keys()
549 .copied()
550 .collect::<HashSet<_>>()
551 .is_empty(),
552 "No mutable inputs are allowed"
553 );
554 debug_assert!(
555 authenticator.receiving_objects().is_empty(),
556 "No receiving inputs are allowed"
557 );
558
559 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
560 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
561
562 let auth_ctx = {
564 let TransactionKind::ProgrammableTransaction(ptb) = &transaction_kind else {
565 unreachable!("Only programmable transactions are allowed");
566 };
567 AuthContext::new_from_components(authenticator.digest(), ptb)
568 };
569
570 temporary_store.store_auth_context(auth_ctx);
574
575 let authentication_execution_result = execute_authenticator_move_call(
577 temporary_store,
578 authenticator,
579 authenticator_function_ref,
580 gas_charger,
581 tx_ctx,
582 move_vm,
583 protocol_config,
584 metrics.clone(),
585 false,
586 contains_deleted_input,
587 cancelled_objects,
588 trace_builder_opt,
589 );
590
591 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
593 elaborate_error_logs(error, transaction_digest)
594 } else {
595 ExecutionStatus::Success
596 };
597
598 #[skip_checked_arithmetic]
599 trace!(
600 tx_digest = ?transaction_digest,
601 computation_gas_cost = gas_charger.summary().gas_used(),
602 "Finished authenticator execution of transaction with status {:?}",
603 authentication_execution_status
604 );
605
606 authentication_execution_result
607 }
608
609 #[instrument(name = "auth_execute", level = "debug", skip_all)]
620 fn execute_authenticator_move_call(
621 temporary_store: &mut TemporaryStore<'_>,
622 authenticator: MoveAuthenticator,
623 authenticator_function_ref: AuthenticatorFunctionRefV1,
624 gas_charger: &mut GasCharger,
625 tx_ctx: &mut TxContext,
626 move_vm: &Arc<MoveVM>,
627 protocol_config: &ProtocolConfig,
628 metrics: Arc<LimitsMetrics>,
629 deny_cert: bool,
630 contains_deleted_input: bool,
631 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
632 trace_builder_opt: &mut Option<MoveTraceBuilder>,
633 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
634 {
635 debug_assert!(
636 gas_charger.no_charges(),
637 "At this point no gas charges must be applied yet"
638 );
639
640 run_inputs_checks(
644 protocol_config,
645 deny_cert,
646 contains_deleted_input,
647 cancelled_objects,
648 )
649 .and_then(|()| {
650 let authenticator_move_call =
651 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
652 programmable_transactions::execution::execute::<execution_mode::Authentication>(
653 protocol_config,
654 metrics.clone(),
655 move_vm,
656 temporary_store,
657 tx_ctx,
658 gas_charger,
659 authenticator_move_call,
660 trace_builder_opt,
661 )
662 .and_then(|ok_result| {
663 temporary_store.check_move_authenticator_results_consistency()?;
664 Ok(ok_result)
665 })
666 })
667 }
668
669 pub fn execute_genesis_state_update(
676 store: &dyn BackingStore,
677 protocol_config: &ProtocolConfig,
678 metrics: Arc<LimitsMetrics>,
679 move_vm: &Arc<MoveVM>,
680 tx_context: &mut TxContext,
681 input_objects: CheckedInputObjects,
682 pt: ProgrammableTransaction,
683 ) -> Result<InnerTemporaryStore, ExecutionError> {
684 let input_objects = input_objects.into_inner();
685 let mut temporary_store = TemporaryStore::new(
686 store,
687 input_objects,
688 vec![],
689 tx_context.digest(),
690 protocol_config,
691 0,
692 );
693 let mut gas_charger = GasCharger::new_unmetered(tx_context.digest());
694 programmable_transactions::execution::execute::<execution_mode::Genesis>(
695 protocol_config,
696 metrics,
697 move_vm,
698 &mut temporary_store,
699 tx_context,
700 &mut gas_charger,
701 pt,
702 &mut None,
703 )?;
704 temporary_store.update_object_version_and_prev_tx();
705 Ok(temporary_store.into_inner())
706 }
707
708 #[instrument(name = "tx_execute", level = "debug", skip_all)]
717 fn execute_transaction<Mode: ExecutionMode>(
718 temporary_store: &mut TemporaryStore<'_>,
719 transaction_kind: TransactionKind,
720 gas_charger: &mut GasCharger,
721 tx_ctx: &mut TxContext,
722 move_vm: &Arc<MoveVM>,
723 protocol_config: &ProtocolConfig,
724 metrics: Arc<LimitsMetrics>,
725 enable_expensive_checks: bool,
726 deny_cert: bool,
727 contains_deleted_input: bool,
728 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
729 trace_builder_opt: &mut Option<MoveTraceBuilder>,
730 pre_execution_result_opt: Option<
731 Result<
732 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
733 ExecutionError,
734 >,
735 >,
736 ) -> (
737 GasCostSummary,
738 Result<Mode::ExecutionResults, ExecutionError>,
739 ) {
740 gas_charger.smash_gas(temporary_store);
741
742 debug_assert!(
745 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
746 "No gas charges must be applied yet"
747 );
748
749 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
750 || transaction_kind.is_end_of_epoch_tx();
751
752 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
753
754 let result = gas_charger.charge_input_objects(temporary_store);
758 let mut result = result.and_then(|()| {
759 run_inputs_checks(
760 protocol_config,
761 deny_cert,
762 contains_deleted_input,
763 cancelled_objects,
764 )?;
765
766 let mut execution_result = pre_execution_result_opt.unwrap_or(Ok(())).and_then(|_| {
769 execution_loop::<Mode>(
770 temporary_store,
771 transaction_kind,
772 tx_ctx,
773 move_vm,
774 gas_charger,
775 protocol_config,
776 metrics.clone(),
777 trace_builder_opt,
778 )
779 });
780
781 let meter_check = check_meter_limit(
782 temporary_store,
783 gas_charger,
784 protocol_config,
785 metrics.clone(),
786 );
787 if let Err(e) = meter_check {
788 execution_result = Err(e);
789 }
790
791 if execution_result.is_ok() {
792 let gas_check = check_written_objects_limit(
793 temporary_store,
794 gas_charger,
795 protocol_config,
796 metrics,
797 );
798 if let Err(e) = gas_check {
799 execution_result = Err(e);
800 }
801 }
802
803 execution_result
804 });
805
806 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
807 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
816
817 if let Err(e) = run_conservation_checks::<Mode>(
818 temporary_store,
819 gas_charger,
820 tx_ctx,
821 move_vm,
822 enable_expensive_checks,
823 &cost_summary,
824 is_genesis_or_epoch_change_tx,
825 advance_epoch_gas_summary,
826 ) {
827 result = Err(e);
829 }
830
831 (cost_summary, result)
832 }
833
834 fn elaborate_error_logs(
837 execution_error: &ExecutionError,
838 transaction_digest: TransactionDigest,
839 ) -> ExecutionStatus {
840 use ExecutionErrorKind as K;
841 match execution_error.kind() {
842 K::InvariantViolation | K::VMInvariantViolation => {
843 #[skip_checked_arithmetic]
844 tracing::error!(
845 kind = ?execution_error.kind(),
846 tx_digest = ?transaction_digest,
847 "INVARIANT VIOLATION! Source: {:?}",
848 execution_error.source(),
849 );
850 }
851
852 K::IotaMoveVerificationError | K::VMVerificationOrDeserializationError => {
853 #[skip_checked_arithmetic]
854 tracing::debug!(
855 kind = ?execution_error.kind(),
856 tx_digest = ?transaction_digest,
857 "Verification Error. Source: {:?}",
858 execution_error.source(),
859 );
860 }
861
862 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
863 #[skip_checked_arithmetic]
864 tracing::debug!(
865 kind = ?execution_error.kind(),
866 tx_digest = ?transaction_digest,
867 "Publish/Upgrade Error. Source: {:?}",
868 execution_error.source(),
869 )
870 }
871
872 _ => (),
873 };
874
875 let (status, command) = execution_error.to_execution_status();
876 ExecutionStatus::new_failure(status, command)
877 }
878
879 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
888 fn run_conservation_checks<Mode: ExecutionMode>(
889 temporary_store: &mut TemporaryStore<'_>,
890 gas_charger: &mut GasCharger,
891 tx_ctx: &mut TxContext,
892 move_vm: &Arc<MoveVM>,
893 enable_expensive_checks: bool,
894 cost_summary: &GasCostSummary,
895 is_genesis_or_epoch_change_tx: bool,
896 advance_epoch_gas_summary: Option<(u64, u64)>,
897 ) -> Result<(), ExecutionError> {
898 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
899 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
900 let conservation_result = {
903 temporary_store
904 .check_iota_conserved(cost_summary)
905 .and_then(|()| {
906 if enable_expensive_checks {
907 let mut layout_resolver =
910 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
911 temporary_store.check_iota_conserved_expensive(
912 cost_summary,
913 advance_epoch_gas_summary,
914 &mut layout_resolver,
915 )
916 } else {
917 Ok(())
918 }
919 })
920 };
921 if let Err(conservation_err) = conservation_result {
922 result = Err(conservation_err);
926 gas_charger.reset(temporary_store);
927 gas_charger.charge_gas(temporary_store, &mut result);
928 if let Err(recovery_err) = {
930 temporary_store
931 .check_iota_conserved(cost_summary)
932 .and_then(|()| {
933 if enable_expensive_checks {
934 let mut layout_resolver =
937 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
938 temporary_store.check_iota_conserved_expensive(
939 cost_summary,
940 advance_epoch_gas_summary,
941 &mut layout_resolver,
942 )
943 } else {
944 Ok(())
945 }
946 })
947 } {
948 panic!(
952 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
953 tx_ctx.digest(),
954 recovery_err,
955 gas_charger.summary()
956 )
957 }
958 }
959 } result
963 }
964
965 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
976 fn run_inputs_checks(
977 protocol_config: &ProtocolConfig,
978 deny_cert: bool,
979 contains_deleted_input: bool,
980 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
981 ) -> Result<(), ExecutionError> {
982 if deny_cert {
983 Err(ExecutionError::new(
984 ExecutionErrorKind::CertificateDenied,
985 None,
986 ))
987 } else if contains_deleted_input {
988 Err(ExecutionError::new(
989 ExecutionErrorKind::InputObjectDeleted,
990 None,
991 ))
992 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
993 match reason {
994 version if version.is_congested() => Err(ExecutionError::new(
995 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
996 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestionV2 {
997 congested_objects: CongestedObjects(cancelled_objects),
998 suggested_gas_price: version
999 .get_congested_version_suggested_gas_price(),
1000 }
1001 } else {
1002 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestion {
1007 congested_objects: CongestedObjects(cancelled_objects),
1008 }
1009 },
1010 None,
1011 )),
1012 SequenceNumber::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1013 ExecutionErrorKind::ExecutionCancelledDueToRandomnessUnavailable,
1014 None,
1015 )),
1016 _ => panic!("invalid cancellation reason SequenceNumber: {reason}"),
1017 }
1018 } else {
1019 Ok(())
1020 }
1021 }
1022
1023 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1028 fn check_meter_limit(
1029 temporary_store: &mut TemporaryStore<'_>,
1030 gas_charger: &mut GasCharger,
1031 protocol_config: &ProtocolConfig,
1032 metrics: Arc<LimitsMetrics>,
1033 ) -> Result<(), ExecutionError> {
1034 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1035
1036 match check_limit_by_meter!(
1041 !gas_charger.is_unmetered(),
1042 effects_estimated_size,
1043 protocol_config.max_serialized_tx_effects_size_bytes(),
1044 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1045 metrics.excessive_estimated_effects_size
1046 ) {
1047 LimitThresholdCrossed::None => Ok(()),
1048 LimitThresholdCrossed::Soft(_, limit) => {
1049 warn!(
1050 effects_estimated_size = effects_estimated_size,
1051 soft_limit = limit,
1052 "Estimated transaction effects size crossed soft limit",
1053 );
1054 Ok(())
1055 }
1056 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1057 ExecutionErrorKind::EffectsTooLarge {
1058 current_size: effects_estimated_size as u64,
1059 max_size: lim as u64,
1060 },
1061 "Transaction effects are too large",
1062 )),
1063 }
1064 }
1065
1066 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1071 fn check_written_objects_limit(
1072 temporary_store: &mut TemporaryStore<'_>,
1073 gas_charger: &mut GasCharger,
1074 protocol_config: &ProtocolConfig,
1075 metrics: Arc<LimitsMetrics>,
1076 ) -> Result<(), ExecutionError> {
1077 if let (Some(normal_lim), Some(system_lim)) = (
1078 protocol_config.max_size_written_objects_as_option(),
1079 protocol_config.max_size_written_objects_system_tx_as_option(),
1080 ) {
1081 let written_objects_size = temporary_store.written_objects_size();
1082
1083 match check_limit_by_meter!(
1084 !gas_charger.is_unmetered(),
1085 written_objects_size,
1086 normal_lim,
1087 system_lim,
1088 metrics.excessive_written_objects_size
1089 ) {
1090 LimitThresholdCrossed::None => (),
1091 LimitThresholdCrossed::Soft(_, limit) => {
1092 warn!(
1093 written_objects_size = written_objects_size,
1094 soft_limit = limit,
1095 "Written objects size crossed soft limit",
1096 )
1097 }
1098 LimitThresholdCrossed::Hard(_, lim) => {
1099 return Err(ExecutionError::new_with_source(
1100 ExecutionErrorKind::WrittenObjectsTooLarge {
1101 current_size: written_objects_size as u64,
1102 max_size: lim as u64,
1103 },
1104 "Written objects size crossed hard limit",
1105 ));
1106 }
1107 };
1108 }
1109
1110 Ok(())
1111 }
1112
1113 #[instrument(level = "debug", skip_all)]
1120 fn execution_loop<Mode: ExecutionMode>(
1121 temporary_store: &mut TemporaryStore<'_>,
1122 transaction_kind: TransactionKind,
1123 tx_ctx: &mut TxContext,
1124 move_vm: &Arc<MoveVM>,
1125 gas_charger: &mut GasCharger,
1126 protocol_config: &ProtocolConfig,
1127 metrics: Arc<LimitsMetrics>,
1128 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1129 ) -> Result<Mode::ExecutionResults, ExecutionError> {
1130 let result = match transaction_kind {
1131 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1132 if tx_ctx.epoch() != 0 {
1133 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1134 }
1135
1136 for genesis_object in objects {
1137 match genesis_object {
1138 iota_types::transaction::GenesisObject::RawObject { data, owner } => {
1139 let object = ObjectInner {
1140 data,
1141 owner,
1142 previous_transaction: tx_ctx.digest(),
1143 storage_rebate: 0,
1144 };
1145 temporary_store.create_object(object.into());
1146 }
1147 }
1148 }
1149
1150 temporary_store.record_execution_results(ExecutionResults::V1(
1151 ExecutionResultsV1 {
1152 user_events: events,
1153 ..Default::default()
1154 },
1155 ));
1156
1157 Ok(Mode::empty_results())
1158 }
1159 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1160 setup_consensus_commit(
1161 prologue.commit_timestamp_ms,
1162 temporary_store,
1163 tx_ctx,
1164 move_vm,
1165 gas_charger,
1166 protocol_config,
1167 metrics,
1168 trace_builder_opt,
1169 )
1170 .expect("ConsensusCommitPrologueV1 cannot fail");
1171 Ok(Mode::empty_results())
1172 }
1173 TransactionKind::ProgrammableTransaction(pt) => {
1174 programmable_transactions::execution::execute::<Mode>(
1175 protocol_config,
1176 metrics,
1177 move_vm,
1178 temporary_store,
1179 tx_ctx,
1180 gas_charger,
1181 pt,
1182 trace_builder_opt,
1183 )
1184 }
1185 TransactionKind::EndOfEpochTransaction(txns) => {
1186 let mut builder = ProgrammableTransactionBuilder::new();
1187 let len = txns.len();
1188 for (i, tx) in txns.into_iter().enumerate() {
1189 match tx {
1190 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1191 assert_eq!(i, len - 1);
1192 advance_epoch_v1(
1193 builder,
1194 change_epoch,
1195 temporary_store,
1196 tx_ctx,
1197 move_vm,
1198 gas_charger,
1199 protocol_config,
1200 metrics,
1201 trace_builder_opt,
1202 )?;
1203 return Ok(Mode::empty_results());
1204 }
1205 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1206 assert_eq!(i, len - 1);
1207 advance_epoch_v2(
1208 builder,
1209 change_epoch_v2,
1210 temporary_store,
1211 tx_ctx,
1212 move_vm,
1213 gas_charger,
1214 protocol_config,
1215 metrics,
1216 trace_builder_opt,
1217 )?;
1218 return Ok(Mode::empty_results());
1219 }
1220 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1221 assert_eq!(i, len - 1);
1222 advance_epoch_v3(
1223 builder,
1224 change_epoch_v3,
1225 temporary_store,
1226 tx_ctx,
1227 move_vm,
1228 gas_charger,
1229 protocol_config,
1230 metrics,
1231 trace_builder_opt,
1232 )?;
1233 return Ok(Mode::empty_results());
1234 }
1235 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1236 assert_eq!(i, len - 1);
1237 advance_epoch_v4(
1238 builder,
1239 change_epoch_v4,
1240 temporary_store,
1241 tx_ctx,
1242 move_vm,
1243 gas_charger,
1244 protocol_config,
1245 metrics,
1246 trace_builder_opt,
1247 )?;
1248 return Ok(Mode::empty_results());
1249 }
1250 EndOfEpochTransactionKind::AuthenticatorStateCreate => {
1251 assert!(protocol_config.enable_jwk_consensus_updates());
1252 builder = setup_authenticator_state_create(builder);
1253 }
1254 EndOfEpochTransactionKind::AuthenticatorStateExpire(expire) => {
1255 assert!(protocol_config.enable_jwk_consensus_updates());
1256
1257 builder = setup_authenticator_state_expire(builder, expire);
1260 }
1261 }
1262 }
1263 unreachable!(
1264 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1265 )
1266 }
1267 TransactionKind::AuthenticatorStateUpdateV1(auth_state_update) => {
1268 setup_authenticator_state_update(
1269 auth_state_update,
1270 temporary_store,
1271 tx_ctx,
1272 move_vm,
1273 gas_charger,
1274 protocol_config,
1275 metrics,
1276 trace_builder_opt,
1277 )?;
1278 Ok(Mode::empty_results())
1279 }
1280 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1281 setup_randomness_state_update(
1282 randomness_state_update,
1283 temporary_store,
1284 tx_ctx,
1285 move_vm,
1286 gas_charger,
1287 protocol_config,
1288 metrics,
1289 trace_builder_opt,
1290 )?;
1291 Ok(Mode::empty_results())
1292 }
1293 }?;
1294 temporary_store.check_execution_results_consistency()?;
1295 Ok(result)
1296 }
1297
1298 fn mint_epoch_rewards_in_pt(
1307 builder: &mut ProgrammableTransactionBuilder,
1308 params: &AdvanceEpochParams,
1309 ) -> (Argument, Argument) {
1310 let storage_charge_arg = builder
1312 .input(CallArg::Pure(
1313 bcs::to_bytes(¶ms.storage_charge).unwrap(),
1314 ))
1315 .unwrap();
1316 let storage_charges = builder.programmable_move_call(
1317 IOTA_FRAMEWORK_PACKAGE_ID,
1318 BALANCE_MODULE_NAME.to_owned(),
1319 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
1320 vec![GAS::type_tag()],
1321 vec![storage_charge_arg],
1322 );
1323
1324 let computation_charge_arg = builder
1326 .input(CallArg::Pure(
1327 bcs::to_bytes(¶ms.computation_charge).unwrap(),
1328 ))
1329 .unwrap();
1330 let computation_charges = builder.programmable_move_call(
1331 IOTA_FRAMEWORK_PACKAGE_ID,
1332 BALANCE_MODULE_NAME.to_owned(),
1333 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
1334 vec![GAS::type_tag()],
1335 vec![computation_charge_arg],
1336 );
1337 (storage_charges, computation_charges)
1338 }
1339
1340 pub fn construct_advance_epoch_pt_impl(
1348 mut builder: ProgrammableTransactionBuilder,
1349 params: &AdvanceEpochParams,
1350 call_arg_vec: Vec<CallArg>,
1351 ) -> Result<ProgrammableTransaction, ExecutionError> {
1352 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1354 let mut arguments = vec![
1355 builder
1356 .pure(params.validator_subsidy)
1357 .expect("bcs encoding a u64 should not fail"),
1358 storage_charges,
1359 computation_charges,
1360 ];
1361
1362 let call_arg_arguments = call_arg_vec
1363 .into_iter()
1364 .map(|a| builder.input(a))
1365 .collect::<Result<_, _>>();
1366
1367 assert_invariant!(
1368 call_arg_arguments.is_ok(),
1369 "Unable to generate args for advance_epoch transaction!"
1370 );
1371
1372 arguments.append(&mut call_arg_arguments.unwrap());
1373
1374 info!("Call arguments to advance_epoch transaction: {:?}", params);
1375
1376 let storage_rebates = builder.programmable_move_call(
1377 IOTA_SYSTEM_PACKAGE_ID,
1378 IOTA_SYSTEM_MODULE_NAME.to_owned(),
1379 ADVANCE_EPOCH_FUNCTION_NAME.to_owned(),
1380 vec![],
1381 arguments,
1382 );
1383
1384 builder.programmable_move_call(
1386 IOTA_FRAMEWORK_PACKAGE_ID,
1387 BALANCE_MODULE_NAME.to_owned(),
1388 BALANCE_DESTROY_REBATES_FUNCTION_NAME.to_owned(),
1389 vec![GAS::type_tag()],
1390 vec![storage_rebates],
1391 );
1392 Ok(builder.finish())
1393 }
1394
1395 pub fn construct_advance_epoch_pt_v1(
1396 builder: ProgrammableTransactionBuilder,
1397 params: &AdvanceEpochParams,
1398 ) -> Result<ProgrammableTransaction, ExecutionError> {
1399 let call_arg_vec = vec![
1404 CallArg::IOTA_SYSTEM_MUT, CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.reward_slashing_rate).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap()), ];
1412 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1413 }
1414
1415 pub fn construct_advance_epoch_pt_v2(
1416 builder: ProgrammableTransactionBuilder,
1417 params: &AdvanceEpochParams,
1418 ) -> Result<ProgrammableTransaction, ExecutionError> {
1419 let call_arg_vec = vec![
1424 CallArg::Pure(bcs::to_bytes(¶ms.computation_charge_burned).unwrap()), CallArg::IOTA_SYSTEM_MUT, CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.reward_slashing_rate).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.max_committee_members_count).unwrap()), ];
1434 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1435 }
1436
1437 pub fn construct_advance_epoch_pt_v3(
1438 builder: ProgrammableTransactionBuilder,
1439 params: &AdvanceEpochParams,
1440 ) -> Result<ProgrammableTransaction, ExecutionError> {
1441 let call_arg_vec = vec![
1447 CallArg::Pure(bcs::to_bytes(¶ms.computation_charge_burned).unwrap()), CallArg::IOTA_SYSTEM_MUT, CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.reward_slashing_rate).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.max_committee_members_count).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.eligible_active_validators).unwrap()), ];
1458 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1459 }
1460
1461 pub fn construct_advance_epoch_pt_v4(
1462 builder: ProgrammableTransactionBuilder,
1463 params: &AdvanceEpochParams,
1464 ) -> Result<ProgrammableTransaction, ExecutionError> {
1465 let call_arg_vec = vec![
1471 CallArg::Pure(bcs::to_bytes(¶ms.computation_charge_burned).unwrap()), CallArg::IOTA_SYSTEM_MUT, CallArg::Pure(bcs::to_bytes(¶ms.epoch).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.next_protocol_version.as_u64()).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.storage_rebate).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.non_refundable_storage_fee).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.reward_slashing_rate).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.epoch_start_timestamp_ms).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.max_committee_members_count).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.eligible_active_validators).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.scores).unwrap()), CallArg::Pure(bcs::to_bytes(¶ms.adjust_rewards_by_score).unwrap()), ];
1484 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1485 }
1486
1487 fn advance_epoch_impl(
1494 advance_epoch_pt: ProgrammableTransaction,
1495 params: AdvanceEpochParams,
1496 system_packages: Vec<(SequenceNumber, Vec<Vec<u8>>, Vec<ObjectID>)>,
1497 temporary_store: &mut TemporaryStore<'_>,
1498 tx_ctx: &mut TxContext,
1499 move_vm: &Arc<MoveVM>,
1500 gas_charger: &mut GasCharger,
1501 protocol_config: &ProtocolConfig,
1502 metrics: Arc<LimitsMetrics>,
1503 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1504 ) -> Result<(), ExecutionError> {
1505 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1506 protocol_config,
1507 metrics.clone(),
1508 move_vm,
1509 temporary_store,
1510 tx_ctx,
1511 gas_charger,
1512 advance_epoch_pt,
1513 trace_builder_opt,
1514 );
1515
1516 #[cfg(msim)]
1517 let result = maybe_modify_result(result, params.epoch);
1518
1519 if result.is_err() {
1520 tracing::error!(
1521 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1522 result.as_ref().err(),
1523 temporary_store.objects(),
1524 params,
1525 );
1526 temporary_store.drop_writes();
1527 gas_charger.reset_storage_cost_and_rebate();
1529
1530 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1531 }
1532
1533 let new_vm = new_move_vm(
1534 all_natives(true, protocol_config),
1535 protocol_config,
1536 None,
1538 )
1539 .expect("Failed to create new MoveVM");
1540 process_system_packages(
1541 system_packages,
1542 temporary_store,
1543 tx_ctx,
1544 &new_vm,
1545 gas_charger,
1546 protocol_config,
1547 metrics,
1548 trace_builder_opt,
1549 );
1550
1551 Ok(())
1552 }
1553
1554 fn advance_epoch_v1(
1558 builder: ProgrammableTransactionBuilder,
1559 change_epoch: ChangeEpoch,
1560 temporary_store: &mut TemporaryStore<'_>,
1561 tx_ctx: &mut TxContext,
1562 move_vm: &Arc<MoveVM>,
1563 gas_charger: &mut GasCharger,
1564 protocol_config: &ProtocolConfig,
1565 metrics: Arc<LimitsMetrics>,
1566 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1567 ) -> Result<(), ExecutionError> {
1568 let params = AdvanceEpochParams {
1569 epoch: change_epoch.epoch,
1570 next_protocol_version: change_epoch.protocol_version,
1571 validator_subsidy: protocol_config.validator_target_reward(),
1572 storage_charge: change_epoch.storage_charge,
1573 computation_charge: change_epoch.computation_charge,
1574 computation_charge_burned: change_epoch.computation_charge,
1576 storage_rebate: change_epoch.storage_rebate,
1577 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1578 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1579 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1580 max_committee_members_count: 0,
1583 eligible_active_validators: vec![],
1584 scores: vec![],
1585 adjust_rewards_by_score: false,
1586 };
1587 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1588 advance_epoch_impl(
1589 advance_epoch_pt,
1590 params,
1591 change_epoch.system_packages,
1592 temporary_store,
1593 tx_ctx,
1594 move_vm,
1595 gas_charger,
1596 protocol_config,
1597 metrics,
1598 trace_builder_opt,
1599 )
1600 }
1601
1602 fn advance_epoch_v2(
1606 builder: ProgrammableTransactionBuilder,
1607 change_epoch_v2: ChangeEpochV2,
1608 temporary_store: &mut TemporaryStore<'_>,
1609 tx_ctx: &mut TxContext,
1610 move_vm: &Arc<MoveVM>,
1611 gas_charger: &mut GasCharger,
1612 protocol_config: &ProtocolConfig,
1613 metrics: Arc<LimitsMetrics>,
1614 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1615 ) -> Result<(), ExecutionError> {
1616 let params = AdvanceEpochParams {
1617 epoch: change_epoch_v2.epoch,
1618 next_protocol_version: change_epoch_v2.protocol_version,
1619 validator_subsidy: protocol_config.validator_target_reward(),
1620 storage_charge: change_epoch_v2.storage_charge,
1621 computation_charge: change_epoch_v2.computation_charge,
1622 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1623 storage_rebate: change_epoch_v2.storage_rebate,
1624 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1625 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1626 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1627 max_committee_members_count: protocol_config.max_committee_members_count(),
1628 eligible_active_validators: vec![],
1631 scores: vec![],
1632 adjust_rewards_by_score: false,
1633 };
1634 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1635 advance_epoch_impl(
1636 advance_epoch_pt,
1637 params,
1638 change_epoch_v2.system_packages,
1639 temporary_store,
1640 tx_ctx,
1641 move_vm,
1642 gas_charger,
1643 protocol_config,
1644 metrics,
1645 trace_builder_opt,
1646 )
1647 }
1648
1649 fn advance_epoch_v3(
1653 builder: ProgrammableTransactionBuilder,
1654 change_epoch_v3: ChangeEpochV3,
1655 temporary_store: &mut TemporaryStore<'_>,
1656 tx_ctx: &mut TxContext,
1657 move_vm: &Arc<MoveVM>,
1658 gas_charger: &mut GasCharger,
1659 protocol_config: &ProtocolConfig,
1660 metrics: Arc<LimitsMetrics>,
1661 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1662 ) -> Result<(), ExecutionError> {
1663 let params = AdvanceEpochParams {
1664 epoch: change_epoch_v3.epoch,
1665 next_protocol_version: change_epoch_v3.protocol_version,
1666 validator_subsidy: protocol_config.validator_target_reward(),
1667 storage_charge: change_epoch_v3.storage_charge,
1668 computation_charge: change_epoch_v3.computation_charge,
1669 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1670 storage_rebate: change_epoch_v3.storage_rebate,
1671 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1672 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1673 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1674 max_committee_members_count: protocol_config.max_committee_members_count(),
1675 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1676 scores: vec![],
1679 adjust_rewards_by_score: false,
1680 };
1681 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1682 advance_epoch_impl(
1683 advance_epoch_pt,
1684 params,
1685 change_epoch_v3.system_packages,
1686 temporary_store,
1687 tx_ctx,
1688 move_vm,
1689 gas_charger,
1690 protocol_config,
1691 metrics,
1692 trace_builder_opt,
1693 )
1694 }
1695
1696 fn advance_epoch_v4(
1700 builder: ProgrammableTransactionBuilder,
1701 change_epoch_v4: ChangeEpochV4,
1702 temporary_store: &mut TemporaryStore<'_>,
1703 tx_ctx: &mut TxContext,
1704 move_vm: &Arc<MoveVM>,
1705 gas_charger: &mut GasCharger,
1706 protocol_config: &ProtocolConfig,
1707 metrics: Arc<LimitsMetrics>,
1708 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1709 ) -> Result<(), ExecutionError> {
1710 let params = AdvanceEpochParams {
1711 epoch: change_epoch_v4.epoch,
1712 next_protocol_version: change_epoch_v4.protocol_version,
1713 validator_subsidy: protocol_config.validator_target_reward(),
1714 storage_charge: change_epoch_v4.storage_charge,
1715 computation_charge: change_epoch_v4.computation_charge,
1716 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1717 storage_rebate: change_epoch_v4.storage_rebate,
1718 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1719 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1720 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1721 max_committee_members_count: protocol_config.max_committee_members_count(),
1722 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1723 scores: change_epoch_v4.scores,
1724 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1725 };
1726 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1727 advance_epoch_impl(
1728 advance_epoch_pt,
1729 params,
1730 change_epoch_v4.system_packages,
1731 temporary_store,
1732 tx_ctx,
1733 move_vm,
1734 gas_charger,
1735 protocol_config,
1736 metrics,
1737 trace_builder_opt,
1738 )
1739 }
1740
1741 fn process_system_packages(
1742 system_packages: Vec<(SequenceNumber, Vec<Vec<u8>>, Vec<ObjectID>)>,
1743 temporary_store: &mut TemporaryStore<'_>,
1744 tx_ctx: &mut TxContext,
1745 move_vm: &MoveVM,
1746 gas_charger: &mut GasCharger,
1747 protocol_config: &ProtocolConfig,
1748 metrics: Arc<LimitsMetrics>,
1749 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1750 ) {
1751 let binary_config = to_binary_config(protocol_config);
1752 for (version, modules, dependencies) in system_packages.into_iter() {
1753 let deserialized_modules: Vec<_> = modules
1754 .iter()
1755 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1756 .collect();
1757
1758 if version == OBJECT_START_VERSION {
1759 let package_id = deserialized_modules.first().unwrap().address();
1760 info!("adding new system package {package_id}");
1761
1762 let publish_pt = {
1763 let mut b = ProgrammableTransactionBuilder::new();
1764 b.command(Command::Publish(modules, dependencies));
1765 b.finish()
1766 };
1767
1768 programmable_transactions::execution::execute::<execution_mode::System>(
1769 protocol_config,
1770 metrics.clone(),
1771 move_vm,
1772 temporary_store,
1773 tx_ctx,
1774 gas_charger,
1775 publish_pt,
1776 trace_builder_opt,
1777 )
1778 .expect("System Package Publish must succeed");
1779 } else {
1780 let mut new_package = Object::new_system_package(
1781 &deserialized_modules,
1782 version,
1783 dependencies,
1784 tx_ctx.digest(),
1785 );
1786
1787 info!(
1788 "upgraded system package {:?}",
1789 new_package.compute_object_reference()
1790 );
1791
1792 new_package
1795 .data
1796 .try_as_package_mut()
1797 .unwrap()
1798 .decrement_version();
1799
1800 temporary_store.upgrade_system_package(new_package);
1802 }
1803 }
1804 }
1805
1806 fn setup_consensus_commit(
1812 consensus_commit_timestamp_ms: CheckpointTimestamp,
1813 temporary_store: &mut TemporaryStore<'_>,
1814 tx_ctx: &mut TxContext,
1815 move_vm: &Arc<MoveVM>,
1816 gas_charger: &mut GasCharger,
1817 protocol_config: &ProtocolConfig,
1818 metrics: Arc<LimitsMetrics>,
1819 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1820 ) -> Result<(), ExecutionError> {
1821 let pt = {
1822 let mut builder = ProgrammableTransactionBuilder::new();
1823 let res = builder.move_call(
1824 IOTA_FRAMEWORK_ADDRESS.into(),
1825 CLOCK_MODULE_NAME.to_owned(),
1826 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME.to_owned(),
1827 vec![],
1828 vec![
1829 CallArg::CLOCK_MUT,
1830 CallArg::Pure(bcs::to_bytes(&consensus_commit_timestamp_ms).unwrap()),
1831 ],
1832 );
1833 assert_invariant!(
1834 res.is_ok(),
1835 "Unable to generate consensus_commit_prologue transaction!"
1836 );
1837 builder.finish()
1838 };
1839 programmable_transactions::execution::execute::<execution_mode::System>(
1840 protocol_config,
1841 metrics,
1842 move_vm,
1843 temporary_store,
1844 tx_ctx,
1845 gas_charger,
1846 pt,
1847 trace_builder_opt,
1848 )
1849 }
1850
1851 fn setup_authenticator_state_create(
1855 mut builder: ProgrammableTransactionBuilder,
1856 ) -> ProgrammableTransactionBuilder {
1857 builder
1858 .move_call(
1859 IOTA_FRAMEWORK_ADDRESS.into(),
1860 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1861 AUTHENTICATOR_STATE_CREATE_FUNCTION_NAME.to_owned(),
1862 vec![],
1863 vec![],
1864 )
1865 .expect("Unable to generate authenticator_state_create transaction!");
1866 builder
1867 }
1868
1869 fn setup_authenticator_state_update(
1876 update: AuthenticatorStateUpdateV1,
1877 temporary_store: &mut TemporaryStore<'_>,
1878 tx_ctx: &mut TxContext,
1879 move_vm: &Arc<MoveVM>,
1880 gas_charger: &mut GasCharger,
1881 protocol_config: &ProtocolConfig,
1882 metrics: Arc<LimitsMetrics>,
1883 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1884 ) -> Result<(), ExecutionError> {
1885 let pt = {
1886 let mut builder = ProgrammableTransactionBuilder::new();
1887 let res = builder.move_call(
1888 IOTA_FRAMEWORK_ADDRESS.into(),
1889 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1890 AUTHENTICATOR_STATE_UPDATE_FUNCTION_NAME.to_owned(),
1891 vec![],
1892 vec![
1893 CallArg::Object(ObjectArg::SharedObject {
1894 id: IOTA_AUTHENTICATOR_STATE_OBJECT_ID,
1895 initial_shared_version: update.authenticator_obj_initial_shared_version,
1896 mutable: true,
1897 }),
1898 CallArg::Pure(bcs::to_bytes(&update.new_active_jwks).unwrap()),
1899 ],
1900 );
1901 assert_invariant!(
1902 res.is_ok(),
1903 "Unable to generate authenticator_state_update transaction!"
1904 );
1905 builder.finish()
1906 };
1907 programmable_transactions::execution::execute::<execution_mode::System>(
1908 protocol_config,
1909 metrics,
1910 move_vm,
1911 temporary_store,
1912 tx_ctx,
1913 gas_charger,
1914 pt,
1915 trace_builder_opt,
1916 )
1917 }
1918
1919 fn setup_authenticator_state_expire(
1924 mut builder: ProgrammableTransactionBuilder,
1925 expire: AuthenticatorStateExpire,
1926 ) -> ProgrammableTransactionBuilder {
1927 builder
1928 .move_call(
1929 IOTA_FRAMEWORK_ADDRESS.into(),
1930 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1931 AUTHENTICATOR_STATE_EXPIRE_JWKS_FUNCTION_NAME.to_owned(),
1932 vec![],
1933 vec![
1934 CallArg::Object(ObjectArg::SharedObject {
1935 id: IOTA_AUTHENTICATOR_STATE_OBJECT_ID,
1936 initial_shared_version: expire.authenticator_obj_initial_shared_version,
1937 mutable: true,
1938 }),
1939 CallArg::Pure(bcs::to_bytes(&expire.min_epoch).unwrap()),
1940 ],
1941 )
1942 .expect("Unable to generate authenticator_state_expire transaction!");
1943 builder
1944 }
1945
1946 fn setup_randomness_state_update(
1952 update: RandomnessStateUpdate,
1953 temporary_store: &mut TemporaryStore<'_>,
1954 tx_ctx: &mut TxContext,
1955 move_vm: &Arc<MoveVM>,
1956 gas_charger: &mut GasCharger,
1957 protocol_config: &ProtocolConfig,
1958 metrics: Arc<LimitsMetrics>,
1959 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1960 ) -> Result<(), ExecutionError> {
1961 let pt = {
1962 let mut builder = ProgrammableTransactionBuilder::new();
1963 let res = builder.move_call(
1964 IOTA_FRAMEWORK_ADDRESS.into(),
1965 RANDOMNESS_MODULE_NAME.to_owned(),
1966 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME.to_owned(),
1967 vec![],
1968 vec![
1969 CallArg::Object(ObjectArg::SharedObject {
1970 id: IOTA_RANDOMNESS_STATE_OBJECT_ID,
1971 initial_shared_version: update.randomness_obj_initial_shared_version,
1972 mutable: true,
1973 }),
1974 CallArg::Pure(bcs::to_bytes(&update.randomness_round).unwrap()),
1975 CallArg::Pure(bcs::to_bytes(&update.random_bytes).unwrap()),
1976 ],
1977 );
1978 assert_invariant!(
1979 res.is_ok(),
1980 "Unable to generate randomness_state_update transaction!"
1981 );
1982 builder.finish()
1983 };
1984 programmable_transactions::execution::execute::<execution_mode::System>(
1985 protocol_config,
1986 metrics,
1987 move_vm,
1988 temporary_store,
1989 tx_ctx,
1990 gas_charger,
1991 pt,
1992 trace_builder_opt,
1993 )
1994 }
1995
1996 fn setup_authenticator_move_call(
2003 authenticator: MoveAuthenticator,
2004 authenticator_function_ref: AuthenticatorFunctionRefV1,
2005 ) -> Result<ProgrammableTransaction, ExecutionError> {
2006 let mut builder = ProgrammableTransactionBuilder::new();
2007
2008 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
2009 args.extend(authenticator.call_args().to_owned());
2010
2011 let type_arguments = authenticator
2012 .type_arguments()
2013 .iter()
2014 .map(|t| {
2015 t.as_type_tag().map_err(|err| {
2016 ExecutionError::new_with_source(
2017 ExecutionErrorKind::VMInvariantViolation,
2018 err.to_string(),
2019 )
2020 })
2021 })
2022 .collect::<Result<Vec<_>, _>>()?;
2023
2024 let res = builder.move_call(
2025 authenticator_function_ref.package,
2026 Identifier::new(authenticator_function_ref.module.clone()).expect(
2027 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2028 ),
2029 Identifier::new(authenticator_function_ref.function.clone()).expect(
2030 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2031 ),
2032 type_arguments,
2033 args,
2034 );
2035
2036 assert_invariant!(
2037 res.is_ok(),
2038 "Unable to generate an account authenticator call transaction!"
2039 );
2040
2041 Ok(builder.finish())
2042 }
2043}