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 #[cfg(msim)]
20 use iota_types::iota_system_state::advance_epoch_result_injection::maybe_modify_result;
21 use iota_types::{
22 IOTA_AUTHENTICATOR_STATE_OBJECT_ID, IOTA_FRAMEWORK_ADDRESS, IOTA_FRAMEWORK_PACKAGE_ID,
23 IOTA_RANDOMNESS_STATE_OBJECT_ID, IOTA_SYSTEM_PACKAGE_ID, Identifier,
24 account_abstraction::authenticator_function::{
25 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
26 AuthenticatorFunctionRefV1,
27 },
28 auth_context::AuthContext,
29 authenticator_state::{
30 AUTHENTICATOR_STATE_CREATE_FUNCTION_NAME,
31 AUTHENTICATOR_STATE_EXPIRE_JWKS_FUNCTION_NAME, AUTHENTICATOR_STATE_MODULE_NAME,
32 AUTHENTICATOR_STATE_UPDATE_FUNCTION_NAME,
33 },
34 balance::{
35 BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME,
36 BALANCE_MODULE_NAME,
37 },
38 base_types::{IotaAddress, ObjectID, SequenceNumber, TransactionDigest, TxContext},
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, IotaGasStatusAPI},
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, GasData, 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_data: GasData,
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 sponsor = resolve_sponsor(&gas_data, &transaction_signer);
136 let gas_price = gas_status.gas_price();
137 let rgp = gas_status.reference_gas_price();
138 let gas_charger = GasCharger::new(
139 transaction_digest,
140 gas_data.payment,
141 gas_status,
142 protocol_config,
143 );
144
145 let tx_ctx = TxContext::new_from_components(
146 &transaction_signer,
147 &transaction_digest,
148 epoch_id,
149 epoch_timestamp_ms,
150 rgp,
151 gas_price,
152 gas_data.budget,
153 sponsor,
154 protocol_config,
155 );
156 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
157
158 execute_transaction_to_effects_inner::<Mode>(
159 temporary_store,
160 gas_charger,
161 tx_ctx,
162 &mutable_inputs,
163 shared_object_refs,
164 transaction_dependencies,
165 contains_deleted_input,
166 cancelled_objects,
167 transaction_kind,
168 transaction_signer,
169 transaction_digest,
170 move_vm,
171 epoch_id,
172 protocol_config,
173 metrics,
174 enable_expensive_checks,
175 certificate_deny_set,
176 trace_builder_opt,
177 None,
178 )
179 }
180
181 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
184 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
185 mut temporary_store: TemporaryStore,
186 mut gas_charger: GasCharger,
187 tx_ctx: Rc<RefCell<TxContext>>,
188 mutable_inputs: &HashSet<ObjectID>,
189 shared_object_refs: Vec<SharedInput>,
190 mut transaction_dependencies: BTreeSet<TransactionDigest>,
191 contains_deleted_input: bool,
192 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
193 transaction_kind: TransactionKind,
194 transaction_signer: IotaAddress,
195 transaction_digest: TransactionDigest,
196 move_vm: &Arc<MoveVM>,
197 epoch_id: &EpochId,
198 protocol_config: &ProtocolConfig,
199 metrics: Arc<LimitsMetrics>,
200 enable_expensive_checks: bool,
201 certificate_deny_set: &HashSet<TransactionDigest>,
202 trace_builder_opt: &mut Option<MoveTraceBuilder>,
203 pre_execution_result_opt: Option<
204 Result<
205 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
206 ExecutionError,
207 >,
208 >,
209 ) -> (
210 InnerTemporaryStore,
211 IotaGasStatus,
212 TransactionEffects,
213 Result<Mode::ExecutionResults, ExecutionError>,
214 ) {
215 let is_epoch_change = transaction_kind.is_end_of_epoch_tx();
216 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
217
218 let (gas_cost_summary, execution_result) = execute_transaction::<Mode>(
219 &mut temporary_store,
220 transaction_kind,
221 &mut gas_charger,
222 tx_ctx,
223 move_vm,
224 protocol_config,
225 metrics,
226 enable_expensive_checks,
227 deny_cert,
228 contains_deleted_input,
229 cancelled_objects,
230 trace_builder_opt,
231 pre_execution_result_opt,
232 );
233
234 let status = if let Err(error) = &execution_result {
235 elaborate_error_logs(error, transaction_digest)
236 } else {
237 ExecutionStatus::Success
238 };
239
240 #[skip_checked_arithmetic]
241 trace!(
242 tx_digest = ?transaction_digest,
243 computation_gas_cost = gas_cost_summary.computation_cost,
244 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
245 storage_gas_cost = gas_cost_summary.storage_cost,
246 storage_gas_rebate = gas_cost_summary.storage_rebate,
247 "Finished execution of transaction with status {:?}",
248 status
249 );
250
251 transaction_dependencies.remove(&TransactionDigest::genesis_marker());
255
256 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
257 temporary_store
258 .check_ownership_invariants(
259 &transaction_signer,
260 &mut gas_charger,
261 mutable_inputs,
262 is_epoch_change,
263 )
264 .unwrap()
265 } let (inner, effects) = temporary_store.into_effects(
268 shared_object_refs,
269 &transaction_digest,
270 transaction_dependencies,
271 gas_cost_summary,
272 status,
273 &mut gas_charger,
274 *epoch_id,
275 );
276
277 (
278 inner,
279 gas_charger.into_gas_status(),
280 effects,
281 execution_result,
282 )
283 }
284
285 #[instrument(
299 name = "tx_authenticate_then_execute_to_effects",
300 level = "debug",
301 skip_all
302 )]
303 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
304 store: &dyn BackingStore,
305 protocol_config: &ProtocolConfig,
307 metrics: Arc<LimitsMetrics>,
308 enable_expensive_checks: bool,
309 certificate_deny_set: &HashSet<TransactionDigest>,
310 epoch_id: &EpochId,
312 epoch_timestamp_ms: u64,
313 gas_data: GasData,
315 gas_status: IotaGasStatus,
316 authenticators: Vec<(
318 MoveAuthenticator,
319 AuthenticatorFunctionRefForExecution,
320 CheckedInputObjects,
321 )>,
322 authenticator_and_transaction_input_objects: CheckedInputObjects,
323 transaction_kind: TransactionKind,
325 transaction_signer: IotaAddress,
326 transaction_digest: TransactionDigest,
327 transaction_data_bytes: Vec<u8>,
328 trace_builder_opt: &mut Option<MoveTraceBuilder>,
330 move_vm: &Arc<MoveVM>,
332 ) -> (
333 InnerTemporaryStore,
334 IotaGasStatus,
335 TransactionEffects,
336 Result<Mode::ExecutionResults, ExecutionError>,
337 ) {
338 let input_objects = authenticator_and_transaction_input_objects.into_inner();
344 let mutable_inputs = if enable_expensive_checks {
346 input_objects.mutable_inputs().keys().copied().collect()
347 } else {
348 HashSet::new()
349 };
350 let shared_object_refs = input_objects.filter_shared_objects();
352 let transaction_receiving_objects = transaction_kind.receiving_objects();
354 let transaction_dependencies = input_objects.transaction_dependencies();
356 let contains_deleted_input = input_objects.contains_deleted_objects();
359 let cancelled_objects = input_objects.get_cancelled_objects();
360
361 let mut temporary_store = TemporaryStore::new(
363 store,
364 input_objects,
365 transaction_receiving_objects,
366 transaction_digest,
367 protocol_config,
368 *epoch_id,
369 );
370
371 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
373 let gas_price = gas_status.gas_price();
374 let rgp = gas_status.reference_gas_price();
375 let mut gas_charger = GasCharger::new(
376 transaction_digest,
377 gas_data.payment,
378 gas_status,
379 protocol_config,
380 );
381
382 let tx_ctx = TxContext::new_from_components(
384 &transaction_signer,
385 &transaction_digest,
386 epoch_id,
387 epoch_timestamp_ms,
388 rgp,
389 gas_price,
390 gas_data.budget,
391 sponsor,
392 protocol_config,
393 );
394 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
395
396 let authenticators = authenticators
402 .into_iter()
403 .map(
404 |(
405 authenticator,
406 authenticator_function_ref_for_execution,
407 authenticator_input_objects,
408 )| {
409 let AuthenticatorFunctionRefForExecution {
410 authenticator_function_ref,
411 loaded_object_id,
412 loaded_object_metadata,
413 } = authenticator_function_ref_for_execution;
414
415 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
418 loaded_object_id,
419 loaded_object_metadata,
420 )]));
421
422 (
423 authenticator,
424 authenticator_function_ref,
425 authenticator_input_objects,
426 )
427 },
428 )
429 .collect::<Vec<_>>();
430
431 let authentication_execution_result = authenticators.into_iter().try_for_each(
437 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
438 match authenticator_function_ref {
439 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
440 authenticate_transaction_inner(
441 &mut temporary_store,
442 protocol_config,
443 metrics.clone(),
444 &mut gas_charger,
445 authenticator,
446 authenticator_function_ref_v1,
447 &authenticator_input_objects.into_inner(),
448 transaction_kind.clone(),
449 transaction_digest,
450 transaction_data_bytes.clone(),
451 tx_ctx.clone(),
452 trace_builder_opt,
453 move_vm,
454 )
455 }
456 }
457 },
458 );
459
460 execute_transaction_to_effects_inner::<Mode>(
468 temporary_store,
469 gas_charger,
470 tx_ctx,
471 &mutable_inputs,
472 shared_object_refs,
473 transaction_dependencies,
474 contains_deleted_input,
475 cancelled_objects,
476 transaction_kind,
477 transaction_signer,
478 transaction_digest,
479 move_vm,
480 epoch_id,
481 protocol_config,
482 metrics,
483 enable_expensive_checks,
484 certificate_deny_set,
485 trace_builder_opt,
486 Some(authentication_execution_result),
487 )
488 }
489
490 #[instrument(name = "tx_validate", level = "debug", skip_all)]
495 pub fn authenticate_transaction(
496 store: &dyn BackingStore,
497 protocol_config: &ProtocolConfig,
499 metrics: Arc<LimitsMetrics>,
500 epoch_id: &EpochId,
502 epoch_timestamp_ms: u64,
503 gas_data: GasData,
505 gas_status: IotaGasStatus,
506 authenticators: Vec<(
508 MoveAuthenticator,
509 AuthenticatorFunctionRef,
510 CheckedInputObjects,
511 )>,
512 aggregated_authenticator_input_objects: CheckedInputObjects,
513 transaction_kind: TransactionKind,
515 transaction_signer: IotaAddress,
516 transaction_digest: TransactionDigest,
517 transaction_data_bytes: Vec<u8>,
518 trace_builder_opt: &mut Option<MoveTraceBuilder>,
520 move_vm: &Arc<MoveVM>,
522 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
523 {
524 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
526 let gas_price = gas_status.gas_price();
527 let rgp = gas_status.reference_gas_price();
528 let mut gas_charger =
529 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
530
531 let tx_ctx = TxContext::new_from_components(
534 &transaction_signer,
535 &transaction_digest,
536 epoch_id,
537 epoch_timestamp_ms,
538 rgp,
539 gas_price,
540 gas_data.budget,
541 sponsor,
542 protocol_config,
543 );
544 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
545
546 let mut temporary_store = TemporaryStore::new(
547 store,
548 aggregated_authenticator_input_objects.into_inner(),
549 vec![],
550 transaction_digest,
551 protocol_config,
552 *epoch_id,
553 );
554
555 authenticators.into_iter().try_for_each(
557 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
558 match authenticator_function_ref {
559 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
560 authenticate_transaction_inner(
561 &mut temporary_store,
562 protocol_config,
563 metrics.clone(),
564 &mut gas_charger,
565 authenticator,
566 authenticator_function_ref_v1,
567 &authenticator_input_objects.into_inner(),
568 transaction_kind.clone(),
569 transaction_digest,
570 transaction_data_bytes.clone(),
571 tx_ctx.clone(),
572 trace_builder_opt,
573 move_vm,
574 )
575 }
576 }
577 },
578 )
579 }
580
581 #[instrument(name = "tx_validate", level = "debug", skip_all)]
591 pub fn authenticate_transaction_inner(
592 temporary_store: &mut TemporaryStore<'_>,
593 protocol_config: &ProtocolConfig,
595 metrics: Arc<LimitsMetrics>,
596 gas_charger: &mut GasCharger,
598 authenticator: MoveAuthenticator,
600 authenticator_function_ref: AuthenticatorFunctionRefV1,
601 authenticator_input_objects: &InputObjects,
602 transaction_kind: TransactionKind,
604 transaction_digest: TransactionDigest,
605 tx_data_bytes: Vec<u8>,
606 tx_ctx: Rc<RefCell<TxContext>>,
607 trace_builder_opt: &mut Option<MoveTraceBuilder>,
609 move_vm: &Arc<MoveVM>,
611 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
612 {
613 debug_assert!(
615 transaction_kind.is_programmable_transaction(),
616 "Only programmable transactions are allowed"
617 );
618 debug_assert!(
619 authenticator_input_objects
620 .mutable_inputs()
621 .keys()
622 .copied()
623 .collect::<HashSet<_>>()
624 .is_empty(),
625 "No mutable inputs are allowed"
626 );
627 debug_assert!(
628 authenticator.receiving_objects().is_empty(),
629 "No receiving inputs are allowed"
630 );
631
632 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
633 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
634
635 let auth_ctx = {
637 let TransactionKind::ProgrammableTransaction(ptb) = &transaction_kind else {
638 unreachable!("Only programmable transactions are allowed");
639 };
640 AuthContext::new_from_components(authenticator.digest(), ptb, tx_data_bytes)
641 };
642 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
643
644 temporary_store.store_auth_context(auth_ctx);
648
649 let authentication_execution_result = execute_authenticator_move_call(
651 temporary_store,
652 authenticator,
653 authenticator_function_ref,
654 gas_charger,
655 tx_ctx,
656 move_vm,
657 protocol_config,
658 metrics,
659 false,
660 contains_deleted_input,
661 cancelled_objects,
662 trace_builder_opt,
663 );
664
665 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
667 elaborate_error_logs(error, transaction_digest)
668 } else {
669 ExecutionStatus::Success
670 };
671
672 #[skip_checked_arithmetic]
673 trace!(
674 tx_digest = ?transaction_digest,
675 computation_gas_cost = gas_charger.summary().gas_used(),
676 "Finished authenticator execution of transaction with status {:?}",
677 authentication_execution_status
678 );
679
680 authentication_execution_result
681 }
682
683 #[instrument(name = "auth_execute", level = "debug", skip_all)]
694 fn execute_authenticator_move_call(
695 temporary_store: &mut TemporaryStore<'_>,
696 authenticator: MoveAuthenticator,
697 authenticator_function_ref: AuthenticatorFunctionRefV1,
698 gas_charger: &mut GasCharger,
699 tx_ctx: Rc<RefCell<TxContext>>,
700 move_vm: &Arc<MoveVM>,
701 protocol_config: &ProtocolConfig,
702 metrics: Arc<LimitsMetrics>,
703 deny_cert: bool,
704 contains_deleted_input: bool,
705 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
706 trace_builder_opt: &mut Option<MoveTraceBuilder>,
707 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
708 {
709 run_inputs_checks(
713 protocol_config,
714 deny_cert,
715 contains_deleted_input,
716 cancelled_objects,
717 )
718 .and_then(|()| {
719 let authenticator_move_call =
720 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
721 programmable_transactions::execution::execute::<execution_mode::Authentication>(
722 protocol_config,
723 metrics.clone(),
724 move_vm,
725 temporary_store,
726 tx_ctx,
727 gas_charger,
728 authenticator_move_call,
729 trace_builder_opt,
730 )
731 .and_then(|ok_result| {
732 temporary_store.check_move_authenticator_results_consistency()?;
733 Ok(ok_result)
734 })
735 })
736 }
737
738 pub fn execute_genesis_state_update(
745 store: &dyn BackingStore,
746 protocol_config: &ProtocolConfig,
747 metrics: Arc<LimitsMetrics>,
748 move_vm: &Arc<MoveVM>,
749 tx_context: Rc<RefCell<TxContext>>,
750 input_objects: CheckedInputObjects,
751 pt: ProgrammableTransaction,
752 ) -> Result<InnerTemporaryStore, ExecutionError> {
753 let input_objects = input_objects.into_inner();
754 let tx_digest = tx_context.borrow().digest();
755
756 let mut temporary_store =
757 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
758 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
759 programmable_transactions::execution::execute::<execution_mode::Genesis>(
760 protocol_config,
761 metrics,
762 move_vm,
763 &mut temporary_store,
764 tx_context,
765 &mut gas_charger,
766 pt,
767 &mut None,
768 )?;
769 temporary_store.update_object_version_and_prev_tx();
770 Ok(temporary_store.into_inner())
771 }
772
773 #[instrument(name = "tx_execute", level = "debug", skip_all)]
782 fn execute_transaction<Mode: ExecutionMode>(
783 temporary_store: &mut TemporaryStore<'_>,
784 transaction_kind: TransactionKind,
785 gas_charger: &mut GasCharger,
786 tx_ctx: Rc<RefCell<TxContext>>,
787 move_vm: &Arc<MoveVM>,
788 protocol_config: &ProtocolConfig,
789 metrics: Arc<LimitsMetrics>,
790 enable_expensive_checks: bool,
791 deny_cert: bool,
792 contains_deleted_input: bool,
793 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
794 trace_builder_opt: &mut Option<MoveTraceBuilder>,
795 pre_execution_result_opt: Option<
796 Result<
797 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
798 ExecutionError,
799 >,
800 >,
801 ) -> (
802 GasCostSummary,
803 Result<Mode::ExecutionResults, ExecutionError>,
804 ) {
805 gas_charger.smash_gas(temporary_store);
806
807 debug_assert!(
810 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
811 "No gas charges must be applied yet"
812 );
813
814 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
815 || transaction_kind.is_end_of_epoch_tx();
816
817 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
818
819 let tx_digest = tx_ctx.borrow().digest();
820
821 let result = gas_charger.charge_input_objects(temporary_store);
825 let mut result = result.and_then(|()| {
826 run_inputs_checks(
827 protocol_config,
828 deny_cert,
829 contains_deleted_input,
830 cancelled_objects,
831 )?;
832
833 let mut execution_result = pre_execution_result_opt.unwrap_or(Ok(())).and_then(|_| {
836 execution_loop::<Mode>(
837 temporary_store,
838 transaction_kind,
839 tx_ctx,
840 move_vm,
841 gas_charger,
842 protocol_config,
843 metrics.clone(),
844 trace_builder_opt,
845 )
846 });
847
848 let meter_check = check_meter_limit(
849 temporary_store,
850 gas_charger,
851 protocol_config,
852 metrics.clone(),
853 );
854 if let Err(e) = meter_check {
855 execution_result = Err(e);
856 }
857
858 if execution_result.is_ok() {
859 let gas_check = check_written_objects_limit(
860 temporary_store,
861 gas_charger,
862 protocol_config,
863 metrics,
864 );
865 if let Err(e) = gas_check {
866 execution_result = Err(e);
867 }
868 }
869
870 execution_result
871 });
872
873 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
874 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
883
884 if let Err(e) = run_conservation_checks::<Mode>(
885 temporary_store,
886 gas_charger,
887 tx_digest,
888 move_vm,
889 enable_expensive_checks,
890 &cost_summary,
891 is_genesis_or_epoch_change_tx,
892 advance_epoch_gas_summary,
893 ) {
894 result = Err(e);
896 }
897
898 (cost_summary, result)
899 }
900
901 fn elaborate_error_logs(
904 execution_error: &ExecutionError,
905 transaction_digest: TransactionDigest,
906 ) -> ExecutionStatus {
907 use ExecutionErrorKind as K;
908 match execution_error.kind() {
909 K::InvariantViolation | K::VMInvariantViolation => {
910 #[skip_checked_arithmetic]
911 tracing::error!(
912 kind = ?execution_error.kind(),
913 tx_digest = ?transaction_digest,
914 "INVARIANT VIOLATION! Source: {:?}",
915 execution_error.source(),
916 );
917 }
918
919 K::IotaMoveVerificationError | K::VMVerificationOrDeserializationError => {
920 #[skip_checked_arithmetic]
921 tracing::debug!(
922 kind = ?execution_error.kind(),
923 tx_digest = ?transaction_digest,
924 "Verification Error. Source: {:?}",
925 execution_error.source(),
926 );
927 }
928
929 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
930 #[skip_checked_arithmetic]
931 tracing::debug!(
932 kind = ?execution_error.kind(),
933 tx_digest = ?transaction_digest,
934 "Publish/Upgrade Error. Source: {:?}",
935 execution_error.source(),
936 )
937 }
938
939 _ => (),
940 };
941
942 let (status, command) = execution_error.to_execution_status();
943 ExecutionStatus::new_failure(status, command)
944 }
945
946 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
955 fn run_conservation_checks<Mode: ExecutionMode>(
956 temporary_store: &mut TemporaryStore<'_>,
957 gas_charger: &mut GasCharger,
958 tx_digest: TransactionDigest,
959 move_vm: &Arc<MoveVM>,
960 enable_expensive_checks: bool,
961 cost_summary: &GasCostSummary,
962 is_genesis_or_epoch_change_tx: bool,
963 advance_epoch_gas_summary: Option<(u64, u64)>,
964 ) -> Result<(), ExecutionError> {
965 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
966 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
967 let conservation_result = {
970 temporary_store
971 .check_iota_conserved(cost_summary)
972 .and_then(|()| {
973 if enable_expensive_checks {
974 let mut layout_resolver =
977 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
978 temporary_store.check_iota_conserved_expensive(
979 cost_summary,
980 advance_epoch_gas_summary,
981 &mut layout_resolver,
982 )
983 } else {
984 Ok(())
985 }
986 })
987 };
988 if let Err(conservation_err) = conservation_result {
989 result = Err(conservation_err);
993 gas_charger.reset(temporary_store);
994 gas_charger.charge_gas(temporary_store, &mut result);
995 if let Err(recovery_err) = {
997 temporary_store
998 .check_iota_conserved(cost_summary)
999 .and_then(|()| {
1000 if enable_expensive_checks {
1001 let mut layout_resolver =
1004 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1005 temporary_store.check_iota_conserved_expensive(
1006 cost_summary,
1007 advance_epoch_gas_summary,
1008 &mut layout_resolver,
1009 )
1010 } else {
1011 Ok(())
1012 }
1013 })
1014 } {
1015 panic!(
1019 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1020 tx_digest,
1021 recovery_err,
1022 gas_charger.summary()
1023 )
1024 }
1025 }
1026 } result
1030 }
1031
1032 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1043 fn run_inputs_checks(
1044 protocol_config: &ProtocolConfig,
1045 deny_cert: bool,
1046 contains_deleted_input: bool,
1047 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
1048 ) -> Result<(), ExecutionError> {
1049 if deny_cert {
1050 Err(ExecutionError::new(
1051 ExecutionErrorKind::CertificateDenied,
1052 None,
1053 ))
1054 } else if contains_deleted_input {
1055 Err(ExecutionError::new(
1056 ExecutionErrorKind::InputObjectDeleted,
1057 None,
1058 ))
1059 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1060 match reason {
1061 version if version.is_congested() => Err(ExecutionError::new(
1062 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1063 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestionV2 {
1064 congested_objects: CongestedObjects(cancelled_objects),
1065 suggested_gas_price: version
1066 .get_congested_version_suggested_gas_price(),
1067 }
1068 } else {
1069 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestion {
1074 congested_objects: CongestedObjects(cancelled_objects),
1075 }
1076 },
1077 None,
1078 )),
1079 SequenceNumber::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1080 ExecutionErrorKind::ExecutionCancelledDueToRandomnessUnavailable,
1081 None,
1082 )),
1083 _ => panic!("invalid cancellation reason SequenceNumber: {reason}"),
1084 }
1085 } else {
1086 Ok(())
1087 }
1088 }
1089
1090 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1095 fn check_meter_limit(
1096 temporary_store: &mut TemporaryStore<'_>,
1097 gas_charger: &mut GasCharger,
1098 protocol_config: &ProtocolConfig,
1099 metrics: Arc<LimitsMetrics>,
1100 ) -> Result<(), ExecutionError> {
1101 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1102
1103 match check_limit_by_meter!(
1108 !gas_charger.is_unmetered(),
1109 effects_estimated_size,
1110 protocol_config.max_serialized_tx_effects_size_bytes(),
1111 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1112 metrics.excessive_estimated_effects_size
1113 ) {
1114 LimitThresholdCrossed::None => Ok(()),
1115 LimitThresholdCrossed::Soft(_, limit) => {
1116 warn!(
1117 effects_estimated_size = effects_estimated_size,
1118 soft_limit = limit,
1119 "Estimated transaction effects size crossed soft limit",
1120 );
1121 Ok(())
1122 }
1123 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1124 ExecutionErrorKind::EffectsTooLarge {
1125 current_size: effects_estimated_size as u64,
1126 max_size: lim as u64,
1127 },
1128 "Transaction effects are too large",
1129 )),
1130 }
1131 }
1132
1133 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1138 fn check_written_objects_limit(
1139 temporary_store: &mut TemporaryStore<'_>,
1140 gas_charger: &mut GasCharger,
1141 protocol_config: &ProtocolConfig,
1142 metrics: Arc<LimitsMetrics>,
1143 ) -> Result<(), ExecutionError> {
1144 if let (Some(normal_lim), Some(system_lim)) = (
1145 protocol_config.max_size_written_objects_as_option(),
1146 protocol_config.max_size_written_objects_system_tx_as_option(),
1147 ) {
1148 let written_objects_size = temporary_store.written_objects_size();
1149
1150 match check_limit_by_meter!(
1151 !gas_charger.is_unmetered(),
1152 written_objects_size,
1153 normal_lim,
1154 system_lim,
1155 metrics.excessive_written_objects_size
1156 ) {
1157 LimitThresholdCrossed::None => (),
1158 LimitThresholdCrossed::Soft(_, limit) => {
1159 warn!(
1160 written_objects_size = written_objects_size,
1161 soft_limit = limit,
1162 "Written objects size crossed soft limit",
1163 )
1164 }
1165 LimitThresholdCrossed::Hard(_, lim) => {
1166 return Err(ExecutionError::new_with_source(
1167 ExecutionErrorKind::WrittenObjectsTooLarge {
1168 current_size: written_objects_size as u64,
1169 max_size: lim as u64,
1170 },
1171 "Written objects size crossed hard limit",
1172 ));
1173 }
1174 };
1175 }
1176
1177 Ok(())
1178 }
1179
1180 #[instrument(level = "debug", skip_all)]
1187 fn execution_loop<Mode: ExecutionMode>(
1188 temporary_store: &mut TemporaryStore<'_>,
1189 transaction_kind: TransactionKind,
1190 tx_ctx: Rc<RefCell<TxContext>>,
1191 move_vm: &Arc<MoveVM>,
1192 gas_charger: &mut GasCharger,
1193 protocol_config: &ProtocolConfig,
1194 metrics: Arc<LimitsMetrics>,
1195 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1196 ) -> Result<Mode::ExecutionResults, ExecutionError> {
1197 let result = match transaction_kind {
1198 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1199 if tx_ctx.borrow().epoch() != 0 {
1200 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1201 }
1202
1203 for genesis_object in objects {
1204 match genesis_object {
1205 iota_types::transaction::GenesisObject::RawObject { data, owner } => {
1206 let object = ObjectInner {
1207 data,
1208 owner,
1209 previous_transaction: tx_ctx.borrow().digest(),
1210 storage_rebate: 0,
1211 };
1212 temporary_store.create_object(object.into());
1213 }
1214 }
1215 }
1216
1217 temporary_store.record_execution_results(ExecutionResults::V1(
1218 ExecutionResultsV1 {
1219 user_events: events,
1220 ..Default::default()
1221 },
1222 ));
1223
1224 Ok(Mode::empty_results())
1225 }
1226 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1227 setup_consensus_commit(
1228 prologue.commit_timestamp_ms,
1229 temporary_store,
1230 tx_ctx,
1231 move_vm,
1232 gas_charger,
1233 protocol_config,
1234 metrics,
1235 trace_builder_opt,
1236 )
1237 .expect("ConsensusCommitPrologueV1 cannot fail");
1238 Ok(Mode::empty_results())
1239 }
1240 TransactionKind::ProgrammableTransaction(pt) => {
1241 programmable_transactions::execution::execute::<Mode>(
1242 protocol_config,
1243 metrics,
1244 move_vm,
1245 temporary_store,
1246 tx_ctx,
1247 gas_charger,
1248 pt,
1249 trace_builder_opt,
1250 )
1251 }
1252 TransactionKind::EndOfEpochTransaction(txns) => {
1253 let mut builder = ProgrammableTransactionBuilder::new();
1254 let len = txns.len();
1255 for (i, tx) in txns.into_iter().enumerate() {
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 EndOfEpochTransactionKind::AuthenticatorStateCreate => {
1318 assert!(protocol_config.enable_jwk_consensus_updates());
1319 builder = setup_authenticator_state_create(builder);
1320 }
1321 EndOfEpochTransactionKind::AuthenticatorStateExpire(expire) => {
1322 assert!(protocol_config.enable_jwk_consensus_updates());
1323
1324 builder = setup_authenticator_state_expire(builder, expire);
1327 }
1328 }
1329 }
1330 unreachable!(
1331 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1332 )
1333 }
1334 TransactionKind::AuthenticatorStateUpdateV1(auth_state_update) => {
1335 setup_authenticator_state_update(
1336 auth_state_update,
1337 temporary_store,
1338 tx_ctx,
1339 move_vm,
1340 gas_charger,
1341 protocol_config,
1342 metrics,
1343 trace_builder_opt,
1344 )?;
1345 Ok(Mode::empty_results())
1346 }
1347 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1348 setup_randomness_state_update(
1349 randomness_state_update,
1350 temporary_store,
1351 tx_ctx,
1352 move_vm,
1353 gas_charger,
1354 protocol_config,
1355 metrics,
1356 trace_builder_opt,
1357 )?;
1358 Ok(Mode::empty_results())
1359 }
1360 }?;
1361 temporary_store.check_execution_results_consistency()?;
1362 Ok(result)
1363 }
1364
1365 fn mint_epoch_rewards_in_pt(
1374 builder: &mut ProgrammableTransactionBuilder,
1375 params: &AdvanceEpochParams,
1376 ) -> (Argument, Argument) {
1377 let storage_charge_arg = builder
1379 .input(CallArg::Pure(
1380 bcs::to_bytes(¶ms.storage_charge).unwrap(),
1381 ))
1382 .unwrap();
1383 let storage_charges = builder.programmable_move_call(
1384 IOTA_FRAMEWORK_PACKAGE_ID,
1385 BALANCE_MODULE_NAME.to_owned(),
1386 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
1387 vec![GAS::type_tag()],
1388 vec![storage_charge_arg],
1389 );
1390
1391 let computation_charge_arg = builder
1393 .input(CallArg::Pure(
1394 bcs::to_bytes(¶ms.computation_charge).unwrap(),
1395 ))
1396 .unwrap();
1397 let computation_charges = builder.programmable_move_call(
1398 IOTA_FRAMEWORK_PACKAGE_ID,
1399 BALANCE_MODULE_NAME.to_owned(),
1400 BALANCE_CREATE_REWARDS_FUNCTION_NAME.to_owned(),
1401 vec![GAS::type_tag()],
1402 vec![computation_charge_arg],
1403 );
1404 (storage_charges, computation_charges)
1405 }
1406
1407 pub fn construct_advance_epoch_pt_impl(
1415 mut builder: ProgrammableTransactionBuilder,
1416 params: &AdvanceEpochParams,
1417 call_arg_vec: Vec<CallArg>,
1418 ) -> Result<ProgrammableTransaction, ExecutionError> {
1419 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1421 let mut arguments = vec![
1422 builder
1423 .pure(params.validator_subsidy)
1424 .expect("bcs encoding a u64 should not fail"),
1425 storage_charges,
1426 computation_charges,
1427 ];
1428
1429 let call_arg_arguments = call_arg_vec
1430 .into_iter()
1431 .map(|a| builder.input(a))
1432 .collect::<Result<_, _>>();
1433
1434 assert_invariant!(
1435 call_arg_arguments.is_ok(),
1436 "Unable to generate args for advance_epoch transaction!"
1437 );
1438
1439 arguments.append(&mut call_arg_arguments.unwrap());
1440
1441 info!("Call arguments to advance_epoch transaction: {:?}", params);
1442
1443 let storage_rebates = builder.programmable_move_call(
1444 IOTA_SYSTEM_PACKAGE_ID,
1445 IOTA_SYSTEM_MODULE_NAME.to_owned(),
1446 ADVANCE_EPOCH_FUNCTION_NAME.to_owned(),
1447 vec![],
1448 arguments,
1449 );
1450
1451 builder.programmable_move_call(
1453 IOTA_FRAMEWORK_PACKAGE_ID,
1454 BALANCE_MODULE_NAME.to_owned(),
1455 BALANCE_DESTROY_REBATES_FUNCTION_NAME.to_owned(),
1456 vec![GAS::type_tag()],
1457 vec![storage_rebates],
1458 );
1459 Ok(builder.finish())
1460 }
1461
1462 pub fn construct_advance_epoch_pt_v1(
1463 builder: ProgrammableTransactionBuilder,
1464 params: &AdvanceEpochParams,
1465 ) -> Result<ProgrammableTransaction, ExecutionError> {
1466 let call_arg_vec = vec![
1471 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()), ];
1479 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1480 }
1481
1482 pub fn construct_advance_epoch_pt_v2(
1483 builder: ProgrammableTransactionBuilder,
1484 params: &AdvanceEpochParams,
1485 ) -> Result<ProgrammableTransaction, ExecutionError> {
1486 let call_arg_vec = vec![
1491 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()), ];
1501 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1502 }
1503
1504 pub fn construct_advance_epoch_pt_v3(
1505 builder: ProgrammableTransactionBuilder,
1506 params: &AdvanceEpochParams,
1507 ) -> Result<ProgrammableTransaction, ExecutionError> {
1508 let call_arg_vec = vec![
1514 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()), ];
1525 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1526 }
1527
1528 pub fn construct_advance_epoch_pt_v4(
1529 builder: ProgrammableTransactionBuilder,
1530 params: &AdvanceEpochParams,
1531 ) -> Result<ProgrammableTransaction, ExecutionError> {
1532 let call_arg_vec = vec![
1538 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()), ];
1551 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1552 }
1553
1554 fn advance_epoch_impl(
1561 advance_epoch_pt: ProgrammableTransaction,
1562 params: AdvanceEpochParams,
1563 system_packages: Vec<(SequenceNumber, Vec<Vec<u8>>, Vec<ObjectID>)>,
1564 temporary_store: &mut TemporaryStore<'_>,
1565 tx_ctx: Rc<RefCell<TxContext>>,
1566 move_vm: &Arc<MoveVM>,
1567 gas_charger: &mut GasCharger,
1568 protocol_config: &ProtocolConfig,
1569 metrics: Arc<LimitsMetrics>,
1570 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1571 ) -> Result<(), ExecutionError> {
1572 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1573 protocol_config,
1574 metrics.clone(),
1575 move_vm,
1576 temporary_store,
1577 tx_ctx.clone(),
1578 gas_charger,
1579 advance_epoch_pt,
1580 trace_builder_opt,
1581 );
1582
1583 #[cfg(msim)]
1584 let result = maybe_modify_result(result, params.epoch);
1585
1586 if result.is_err() {
1587 tracing::error!(
1588 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1589 result.as_ref().err(),
1590 temporary_store.objects(),
1591 params,
1592 );
1593 temporary_store.drop_writes();
1594 gas_charger.reset_storage_cost_and_rebate();
1596
1597 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1598 }
1599
1600 let new_vm = new_move_vm(
1601 all_natives(true, protocol_config),
1602 protocol_config,
1603 None,
1605 )
1606 .expect("Failed to create new MoveVM");
1607 process_system_packages(
1608 system_packages,
1609 temporary_store,
1610 tx_ctx,
1611 &new_vm,
1612 gas_charger,
1613 protocol_config,
1614 metrics,
1615 trace_builder_opt,
1616 );
1617
1618 Ok(())
1619 }
1620
1621 fn advance_epoch_v1(
1625 builder: ProgrammableTransactionBuilder,
1626 change_epoch: ChangeEpoch,
1627 temporary_store: &mut TemporaryStore<'_>,
1628 tx_ctx: Rc<RefCell<TxContext>>,
1629 move_vm: &Arc<MoveVM>,
1630 gas_charger: &mut GasCharger,
1631 protocol_config: &ProtocolConfig,
1632 metrics: Arc<LimitsMetrics>,
1633 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1634 ) -> Result<(), ExecutionError> {
1635 let params = AdvanceEpochParams {
1636 epoch: change_epoch.epoch,
1637 next_protocol_version: change_epoch.protocol_version,
1638 validator_subsidy: protocol_config.validator_target_reward(),
1639 storage_charge: change_epoch.storage_charge,
1640 computation_charge: change_epoch.computation_charge,
1641 computation_charge_burned: change_epoch.computation_charge,
1643 storage_rebate: change_epoch.storage_rebate,
1644 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1645 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1646 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1647 max_committee_members_count: 0,
1650 eligible_active_validators: vec![],
1651 scores: vec![],
1652 adjust_rewards_by_score: false,
1653 };
1654 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1655 advance_epoch_impl(
1656 advance_epoch_pt,
1657 params,
1658 change_epoch.system_packages,
1659 temporary_store,
1660 tx_ctx,
1661 move_vm,
1662 gas_charger,
1663 protocol_config,
1664 metrics,
1665 trace_builder_opt,
1666 )
1667 }
1668
1669 fn advance_epoch_v2(
1673 builder: ProgrammableTransactionBuilder,
1674 change_epoch_v2: ChangeEpochV2,
1675 temporary_store: &mut TemporaryStore<'_>,
1676 tx_ctx: Rc<RefCell<TxContext>>,
1677 move_vm: &Arc<MoveVM>,
1678 gas_charger: &mut GasCharger,
1679 protocol_config: &ProtocolConfig,
1680 metrics: Arc<LimitsMetrics>,
1681 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1682 ) -> Result<(), ExecutionError> {
1683 let params = AdvanceEpochParams {
1684 epoch: change_epoch_v2.epoch,
1685 next_protocol_version: change_epoch_v2.protocol_version,
1686 validator_subsidy: protocol_config.validator_target_reward(),
1687 storage_charge: change_epoch_v2.storage_charge,
1688 computation_charge: change_epoch_v2.computation_charge,
1689 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1690 storage_rebate: change_epoch_v2.storage_rebate,
1691 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1692 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1693 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1694 max_committee_members_count: protocol_config.max_committee_members_count(),
1695 eligible_active_validators: vec![],
1698 scores: vec![],
1699 adjust_rewards_by_score: false,
1700 };
1701 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1702 advance_epoch_impl(
1703 advance_epoch_pt,
1704 params,
1705 change_epoch_v2.system_packages,
1706 temporary_store,
1707 tx_ctx,
1708 move_vm,
1709 gas_charger,
1710 protocol_config,
1711 metrics,
1712 trace_builder_opt,
1713 )
1714 }
1715
1716 fn advance_epoch_v3(
1720 builder: ProgrammableTransactionBuilder,
1721 change_epoch_v3: ChangeEpochV3,
1722 temporary_store: &mut TemporaryStore<'_>,
1723 tx_ctx: Rc<RefCell<TxContext>>,
1724 move_vm: &Arc<MoveVM>,
1725 gas_charger: &mut GasCharger,
1726 protocol_config: &ProtocolConfig,
1727 metrics: Arc<LimitsMetrics>,
1728 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1729 ) -> Result<(), ExecutionError> {
1730 let params = AdvanceEpochParams {
1731 epoch: change_epoch_v3.epoch,
1732 next_protocol_version: change_epoch_v3.protocol_version,
1733 validator_subsidy: protocol_config.validator_target_reward(),
1734 storage_charge: change_epoch_v3.storage_charge,
1735 computation_charge: change_epoch_v3.computation_charge,
1736 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1737 storage_rebate: change_epoch_v3.storage_rebate,
1738 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1739 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1740 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1741 max_committee_members_count: protocol_config.max_committee_members_count(),
1742 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1743 scores: vec![],
1746 adjust_rewards_by_score: false,
1747 };
1748 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1749 advance_epoch_impl(
1750 advance_epoch_pt,
1751 params,
1752 change_epoch_v3.system_packages,
1753 temporary_store,
1754 tx_ctx,
1755 move_vm,
1756 gas_charger,
1757 protocol_config,
1758 metrics,
1759 trace_builder_opt,
1760 )
1761 }
1762
1763 fn advance_epoch_v4(
1767 builder: ProgrammableTransactionBuilder,
1768 change_epoch_v4: ChangeEpochV4,
1769 temporary_store: &mut TemporaryStore<'_>,
1770 tx_ctx: Rc<RefCell<TxContext>>,
1771 move_vm: &Arc<MoveVM>,
1772 gas_charger: &mut GasCharger,
1773 protocol_config: &ProtocolConfig,
1774 metrics: Arc<LimitsMetrics>,
1775 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1776 ) -> Result<(), ExecutionError> {
1777 let params = AdvanceEpochParams {
1778 epoch: change_epoch_v4.epoch,
1779 next_protocol_version: change_epoch_v4.protocol_version,
1780 validator_subsidy: protocol_config.validator_target_reward(),
1781 storage_charge: change_epoch_v4.storage_charge,
1782 computation_charge: change_epoch_v4.computation_charge,
1783 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1784 storage_rebate: change_epoch_v4.storage_rebate,
1785 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1786 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1787 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1788 max_committee_members_count: protocol_config.max_committee_members_count(),
1789 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1790 scores: change_epoch_v4.scores,
1791 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1792 };
1793 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1794 advance_epoch_impl(
1795 advance_epoch_pt,
1796 params,
1797 change_epoch_v4.system_packages,
1798 temporary_store,
1799 tx_ctx,
1800 move_vm,
1801 gas_charger,
1802 protocol_config,
1803 metrics,
1804 trace_builder_opt,
1805 )
1806 }
1807
1808 fn process_system_packages(
1809 system_packages: Vec<(SequenceNumber, Vec<Vec<u8>>, Vec<ObjectID>)>,
1810 temporary_store: &mut TemporaryStore<'_>,
1811 tx_ctx: Rc<RefCell<TxContext>>,
1812 move_vm: &MoveVM,
1813 gas_charger: &mut GasCharger,
1814 protocol_config: &ProtocolConfig,
1815 metrics: Arc<LimitsMetrics>,
1816 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1817 ) {
1818 let binary_config = to_binary_config(protocol_config);
1819 for (version, modules, dependencies) in system_packages.into_iter() {
1820 let deserialized_modules: Vec<_> = modules
1821 .iter()
1822 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1823 .collect();
1824
1825 if version == OBJECT_START_VERSION {
1826 let package_id = deserialized_modules.first().unwrap().address();
1827 info!("adding new system package {package_id}");
1828
1829 let publish_pt = {
1830 let mut b = ProgrammableTransactionBuilder::new();
1831 b.command(Command::Publish(modules, dependencies));
1832 b.finish()
1833 };
1834
1835 programmable_transactions::execution::execute::<execution_mode::System>(
1836 protocol_config,
1837 metrics.clone(),
1838 move_vm,
1839 temporary_store,
1840 tx_ctx.clone(),
1841 gas_charger,
1842 publish_pt,
1843 trace_builder_opt,
1844 )
1845 .expect("System Package Publish must succeed");
1846 } else {
1847 let mut new_package = Object::new_system_package(
1848 &deserialized_modules,
1849 version,
1850 dependencies,
1851 tx_ctx.borrow().digest(),
1852 );
1853
1854 info!(
1855 "upgraded system package {:?}",
1856 new_package.compute_object_reference()
1857 );
1858
1859 new_package
1862 .data
1863 .try_as_package_mut()
1864 .unwrap()
1865 .decrement_version();
1866
1867 temporary_store.upgrade_system_package(new_package);
1869 }
1870 }
1871 }
1872
1873 fn setup_consensus_commit(
1879 consensus_commit_timestamp_ms: CheckpointTimestamp,
1880 temporary_store: &mut TemporaryStore<'_>,
1881 tx_ctx: Rc<RefCell<TxContext>>,
1882 move_vm: &Arc<MoveVM>,
1883 gas_charger: &mut GasCharger,
1884 protocol_config: &ProtocolConfig,
1885 metrics: Arc<LimitsMetrics>,
1886 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1887 ) -> Result<(), ExecutionError> {
1888 let pt = {
1889 let mut builder = ProgrammableTransactionBuilder::new();
1890 let res = builder.move_call(
1891 IOTA_FRAMEWORK_ADDRESS.into(),
1892 CLOCK_MODULE_NAME.to_owned(),
1893 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME.to_owned(),
1894 vec![],
1895 vec![
1896 CallArg::CLOCK_MUT,
1897 CallArg::Pure(bcs::to_bytes(&consensus_commit_timestamp_ms).unwrap()),
1898 ],
1899 );
1900 assert_invariant!(
1901 res.is_ok(),
1902 "Unable to generate consensus_commit_prologue transaction!"
1903 );
1904 builder.finish()
1905 };
1906 programmable_transactions::execution::execute::<execution_mode::System>(
1907 protocol_config,
1908 metrics,
1909 move_vm,
1910 temporary_store,
1911 tx_ctx,
1912 gas_charger,
1913 pt,
1914 trace_builder_opt,
1915 )
1916 }
1917
1918 fn setup_authenticator_state_create(
1922 mut builder: ProgrammableTransactionBuilder,
1923 ) -> ProgrammableTransactionBuilder {
1924 builder
1925 .move_call(
1926 IOTA_FRAMEWORK_ADDRESS.into(),
1927 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1928 AUTHENTICATOR_STATE_CREATE_FUNCTION_NAME.to_owned(),
1929 vec![],
1930 vec![],
1931 )
1932 .expect("Unable to generate authenticator_state_create transaction!");
1933 builder
1934 }
1935
1936 fn setup_authenticator_state_update(
1943 update: AuthenticatorStateUpdateV1,
1944 temporary_store: &mut TemporaryStore<'_>,
1945 tx_ctx: Rc<RefCell<TxContext>>,
1946 move_vm: &Arc<MoveVM>,
1947 gas_charger: &mut GasCharger,
1948 protocol_config: &ProtocolConfig,
1949 metrics: Arc<LimitsMetrics>,
1950 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1951 ) -> Result<(), ExecutionError> {
1952 let pt = {
1953 let mut builder = ProgrammableTransactionBuilder::new();
1954 let res = builder.move_call(
1955 IOTA_FRAMEWORK_ADDRESS.into(),
1956 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1957 AUTHENTICATOR_STATE_UPDATE_FUNCTION_NAME.to_owned(),
1958 vec![],
1959 vec![
1960 CallArg::Object(ObjectArg::SharedObject {
1961 id: IOTA_AUTHENTICATOR_STATE_OBJECT_ID,
1962 initial_shared_version: update.authenticator_obj_initial_shared_version,
1963 mutable: true,
1964 }),
1965 CallArg::Pure(bcs::to_bytes(&update.new_active_jwks).unwrap()),
1966 ],
1967 );
1968 assert_invariant!(
1969 res.is_ok(),
1970 "Unable to generate authenticator_state_update transaction!"
1971 );
1972 builder.finish()
1973 };
1974 programmable_transactions::execution::execute::<execution_mode::System>(
1975 protocol_config,
1976 metrics,
1977 move_vm,
1978 temporary_store,
1979 tx_ctx,
1980 gas_charger,
1981 pt,
1982 trace_builder_opt,
1983 )
1984 }
1985
1986 fn setup_authenticator_state_expire(
1991 mut builder: ProgrammableTransactionBuilder,
1992 expire: AuthenticatorStateExpire,
1993 ) -> ProgrammableTransactionBuilder {
1994 builder
1995 .move_call(
1996 IOTA_FRAMEWORK_ADDRESS.into(),
1997 AUTHENTICATOR_STATE_MODULE_NAME.to_owned(),
1998 AUTHENTICATOR_STATE_EXPIRE_JWKS_FUNCTION_NAME.to_owned(),
1999 vec![],
2000 vec![
2001 CallArg::Object(ObjectArg::SharedObject {
2002 id: IOTA_AUTHENTICATOR_STATE_OBJECT_ID,
2003 initial_shared_version: expire.authenticator_obj_initial_shared_version,
2004 mutable: true,
2005 }),
2006 CallArg::Pure(bcs::to_bytes(&expire.min_epoch).unwrap()),
2007 ],
2008 )
2009 .expect("Unable to generate authenticator_state_expire transaction!");
2010 builder
2011 }
2012
2013 fn setup_randomness_state_update(
2019 update: RandomnessStateUpdate,
2020 temporary_store: &mut TemporaryStore<'_>,
2021 tx_ctx: Rc<RefCell<TxContext>>,
2022 move_vm: &Arc<MoveVM>,
2023 gas_charger: &mut GasCharger,
2024 protocol_config: &ProtocolConfig,
2025 metrics: Arc<LimitsMetrics>,
2026 trace_builder_opt: &mut Option<MoveTraceBuilder>,
2027 ) -> Result<(), ExecutionError> {
2028 let pt = {
2029 let mut builder = ProgrammableTransactionBuilder::new();
2030 let res = builder.move_call(
2031 IOTA_FRAMEWORK_ADDRESS.into(),
2032 RANDOMNESS_MODULE_NAME.to_owned(),
2033 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME.to_owned(),
2034 vec![],
2035 vec![
2036 CallArg::Object(ObjectArg::SharedObject {
2037 id: IOTA_RANDOMNESS_STATE_OBJECT_ID,
2038 initial_shared_version: update.randomness_obj_initial_shared_version,
2039 mutable: true,
2040 }),
2041 CallArg::Pure(bcs::to_bytes(&update.randomness_round).unwrap()),
2042 CallArg::Pure(bcs::to_bytes(&update.random_bytes).unwrap()),
2043 ],
2044 );
2045 assert_invariant!(
2046 res.is_ok(),
2047 "Unable to generate randomness_state_update transaction!"
2048 );
2049 builder.finish()
2050 };
2051 programmable_transactions::execution::execute::<execution_mode::System>(
2052 protocol_config,
2053 metrics,
2054 move_vm,
2055 temporary_store,
2056 tx_ctx,
2057 gas_charger,
2058 pt,
2059 trace_builder_opt,
2060 )
2061 }
2062
2063 fn setup_authenticator_move_call(
2070 authenticator: MoveAuthenticator,
2071 authenticator_function_ref: AuthenticatorFunctionRefV1,
2072 ) -> Result<ProgrammableTransaction, ExecutionError> {
2073 let mut builder = ProgrammableTransactionBuilder::new();
2074
2075 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
2076 args.extend(authenticator.call_args().to_owned());
2077
2078 let type_arguments = authenticator
2079 .type_arguments()
2080 .iter()
2081 .map(|t| {
2082 t.as_type_tag().map_err(|err| {
2083 ExecutionError::new_with_source(
2084 ExecutionErrorKind::VMInvariantViolation,
2085 err.to_string(),
2086 )
2087 })
2088 })
2089 .collect::<Result<Vec<_>, _>>()?;
2090
2091 let res = builder.move_call(
2092 authenticator_function_ref.package,
2093 Identifier::new(authenticator_function_ref.module.clone()).expect(
2094 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2095 ),
2096 Identifier::new(authenticator_function_ref.function).expect(
2097 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2098 ),
2099 type_arguments,
2100 args,
2101 );
2102
2103 assert_invariant!(
2104 res.is_ok(),
2105 "Unable to generate an account authenticator call transaction!"
2106 );
2107
2108 Ok(builder.finish())
2109 }
2110
2111 fn resolve_sponsor(
2112 gas_data: &GasData,
2113 transaction_signer: &IotaAddress,
2114 ) -> Option<IotaAddress> {
2115 let gas_owner = gas_data.owner;
2116 if &gas_owner == transaction_signer {
2117 None
2118 } else {
2119 Some(gas_owner)
2120 }
2121 }
2122}