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