1pub use checked::*;
6
7#[iota_macros::with_checked_arithmetic]
8mod checked {
9
10 use std::{
11 cell::RefCell,
12 collections::{BTreeMap, BTreeSet, HashSet},
13 rc::Rc,
14 sync::Arc,
15 };
16
17 use iota_move_natives::all_natives;
18 use iota_protocol_config::{LimitThresholdCrossed, ProtocolConfig, check_limit_by_meter};
19 use iota_sdk_types::{
20 Address, Argument, ChangeEpoch, ChangeEpochV2, ChangeEpochV3, ChangeEpochV4, Command,
21 EndOfEpochTransactionKind, ExecutionStatus, GasPayment, GenesisTransaction, Identifier,
22 MoveAuthenticator, ObjectId, ProgrammableTransaction, RandomnessStateUpdate,
23 SharedObjectReference, SystemPackage, TransactionDigest, TransactionEffects,
24 TransactionKind, Version, gas::GasCostSummary,
25 };
26 #[cfg(msim)]
27 use iota_types::iota_system_state::advance_epoch_result_injection::maybe_modify_result;
28 use iota_types::{
29 account_abstraction::authenticator_function::{
30 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
31 AuthenticatorFunctionRefV1,
32 },
33 auth_context::{AuthContext, AuthContextData},
34 balance::{BALANCE_CREATE_REWARDS_FUNCTION_NAME, BALANCE_DESTROY_REBATES_FUNCTION_NAME},
35 base_types::TxContext,
36 clock::CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
37 committee::EpochId,
38 error::{ExecutionError, ExecutionErrorKind},
39 execution::{ExecutionResults, ExecutionResultsV1, SharedInput, is_certificate_denied},
40 execution_config_utils::to_binary_config,
41 gas::{IotaGasStatus, IotaGasStatusAPI},
42 gas_coin::GAS,
43 inner_temporary_store::InnerTemporaryStore,
44 iota_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams},
45 messages_checkpoint::CheckpointTimestamp,
46 metrics::LimitsMetrics,
47 move_authenticator::MoveAuthenticatorExt,
48 object::{OBJECT_START_VERSION, Object, ObjectInner},
49 programmable_transaction_builder::ProgrammableTransactionBuilder,
50 randomness_state::RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
51 storage::{BackingStore, Storage},
52 transaction::{
53 CallArg, CancelledObjects, CheckedInputObjects, InputObjects, 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: GasPayment,
86 gas_status: IotaGasStatus,
87 transaction_kind: TransactionKind,
88 transaction_signer: Address,
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<(CancelledObjects, Version)>,
183 transaction_kind: TransactionKind,
184 transaction_signer: Address,
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: GasPayment,
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: Address,
316 transaction_digest: TransactionDigest,
317 auth_context_data: AuthContextData,
318 trace_builder_opt: &mut Option<MoveTraceBuilder>,
320 move_vm: &Arc<MoveVM>,
322 ) -> (
323 InnerTemporaryStore,
324 IotaGasStatus,
325 TransactionEffects,
326 Result<Mode::ExecutionResults, ExecutionError>,
327 ) {
328 let input_objects = authenticator_and_transaction_input_objects.into_inner();
334 let mutable_inputs = if enable_expensive_checks {
336 input_objects.mutable_inputs().keys().copied().collect()
337 } else {
338 HashSet::new()
339 };
340 let shared_object_refs = input_objects.filter_shared_objects();
342 let transaction_receiving_objects = transaction_kind.receiving_objects();
344 let transaction_dependencies = input_objects.transaction_dependencies();
346 let contains_deleted_input = input_objects.contains_deleted_objects();
349 let cancelled_objects = input_objects.get_cancelled_objects();
350
351 let mut temporary_store = TemporaryStore::new(
353 store,
354 input_objects,
355 transaction_receiving_objects,
356 transaction_digest,
357 protocol_config,
358 *epoch_id,
359 );
360
361 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
363 let gas_price = gas_status.gas_price();
364 let rgp = gas_status.reference_gas_price();
365 let mut gas_charger = GasCharger::new(
366 transaction_digest,
367 gas_data.objects,
368 gas_status,
369 protocol_config,
370 );
371
372 let tx_ctx = TxContext::new_from_components(
374 &transaction_signer,
375 &transaction_digest,
376 epoch_id,
377 epoch_timestamp_ms,
378 rgp,
379 gas_price,
380 gas_data.budget,
381 sponsor,
382 protocol_config,
383 );
384 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
385
386 let authenticators = authenticators
392 .into_iter()
393 .map(
394 |(
395 authenticator,
396 authenticator_function_ref_for_execution,
397 authenticator_input_objects,
398 )| {
399 let AuthenticatorFunctionRefForExecution {
400 authenticator_function_ref,
401 loaded_object_id,
402 loaded_object_metadata,
403 } = authenticator_function_ref_for_execution;
404
405 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
408 loaded_object_id,
409 loaded_object_metadata,
410 )]));
411
412 (
413 authenticator,
414 authenticator_function_ref,
415 authenticator_input_objects,
416 )
417 },
418 )
419 .collect::<Vec<_>>();
420
421 let authentication_execution_result = authenticators.into_iter().try_for_each(
427 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
428 match authenticator_function_ref {
429 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
430 authenticate_transaction_inner(
431 &mut temporary_store,
432 protocol_config,
433 metrics.clone(),
434 &mut gas_charger,
435 authenticator,
436 authenticator_function_ref_v1,
437 &authenticator_input_objects.into_inner(),
438 transaction_kind.clone(),
439 transaction_digest,
440 auth_context_data.clone(),
441 tx_ctx.clone(),
442 trace_builder_opt,
443 move_vm,
444 )
445 }
446 }
447 },
448 );
449
450 let authentication_execution_result =
451 report_authentication_error(authentication_execution_result, protocol_config);
452
453 execute_transaction_to_effects_inner::<Mode>(
461 temporary_store,
462 gas_charger,
463 tx_ctx,
464 &mutable_inputs,
465 shared_object_refs,
466 transaction_dependencies,
467 contains_deleted_input,
468 cancelled_objects,
469 transaction_kind,
470 transaction_signer,
471 transaction_digest,
472 move_vm,
473 epoch_id,
474 protocol_config,
475 metrics,
476 enable_expensive_checks,
477 certificate_deny_set,
478 trace_builder_opt,
479 Some(authentication_execution_result),
480 )
481 }
482
483 #[instrument(name = "tx_validate", level = "debug", skip_all)]
488 pub fn authenticate_transaction(
489 store: &dyn BackingStore,
490 protocol_config: &ProtocolConfig,
492 metrics: Arc<LimitsMetrics>,
493 epoch_id: &EpochId,
495 epoch_timestamp_ms: u64,
496 gas_data: GasPayment,
498 gas_status: IotaGasStatus,
499 authenticators: Vec<(
501 MoveAuthenticator,
502 AuthenticatorFunctionRef,
503 CheckedInputObjects,
504 )>,
505 aggregated_authenticator_input_objects: CheckedInputObjects,
506 transaction_kind: TransactionKind,
508 transaction_signer: Address,
509 transaction_digest: TransactionDigest,
510 auth_context_data: AuthContextData,
511 trace_builder_opt: &mut Option<MoveTraceBuilder>,
513 move_vm: &Arc<MoveVM>,
515 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
516 {
517 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
519 let gas_price = gas_status.gas_price();
520 let rgp = gas_status.reference_gas_price();
521 let mut gas_charger =
522 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
523
524 let tx_ctx = TxContext::new_from_components(
527 &transaction_signer,
528 &transaction_digest,
529 epoch_id,
530 epoch_timestamp_ms,
531 rgp,
532 gas_price,
533 gas_data.budget,
534 sponsor,
535 protocol_config,
536 );
537 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
538
539 let mut temporary_store = TemporaryStore::new(
540 store,
541 aggregated_authenticator_input_objects.into_inner(),
542 vec![],
543 transaction_digest,
544 protocol_config,
545 *epoch_id,
546 );
547
548 let authentication_execution_result = authenticators.into_iter().try_for_each(
550 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
551 match authenticator_function_ref {
552 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
553 authenticate_transaction_inner(
554 &mut temporary_store,
555 protocol_config,
556 metrics.clone(),
557 &mut gas_charger,
558 authenticator,
559 authenticator_function_ref_v1,
560 &authenticator_input_objects.into_inner(),
561 transaction_kind.clone(),
562 transaction_digest,
563 auth_context_data.clone(),
564 tx_ctx.clone(),
565 trace_builder_opt,
566 move_vm,
567 )
568 }
569 }
570 },
571 );
572
573 report_authentication_error(authentication_execution_result, protocol_config)
574 }
575
576 #[instrument(name = "tx_validate", level = "debug", skip_all)]
586 pub fn authenticate_transaction_inner(
587 temporary_store: &mut TemporaryStore<'_>,
588 protocol_config: &ProtocolConfig,
590 metrics: Arc<LimitsMetrics>,
591 gas_charger: &mut GasCharger,
593 authenticator: MoveAuthenticator,
595 authenticator_function_ref: AuthenticatorFunctionRefV1,
596 authenticator_input_objects: &InputObjects,
597 transaction_kind: TransactionKind,
599 transaction_digest: TransactionDigest,
600 auth_context_data: AuthContextData,
601 tx_ctx: Rc<RefCell<TxContext>>,
602 trace_builder_opt: &mut Option<MoveTraceBuilder>,
604 move_vm: &Arc<MoveVM>,
606 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
607 {
608 debug_assert!(
610 transaction_kind.is_programmable(),
611 "Only programmable transactions are allowed"
612 );
613 debug_assert!(
614 authenticator_input_objects
615 .mutable_inputs()
616 .keys()
617 .copied()
618 .collect::<HashSet<_>>()
619 .is_empty(),
620 "No mutable inputs are allowed"
621 );
622 debug_assert!(
623 authenticator.receiving_objects().is_empty(),
624 "No receiving inputs are allowed"
625 );
626
627 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
628 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
629
630 let auth_ctx = {
632 let TransactionKind::Programmable(ptb) = &transaction_kind else {
633 unreachable!("Only programmable transactions are allowed");
634 };
635 AuthContext::new_from_components(
636 authenticator.digest().into(),
637 auth_context_data.sender_auth_digest,
638 auth_context_data.sponsor_auth_digest,
639 auth_context_data
640 .sender_authenticator_function_ref
641 .and_then(Into::into),
642 auth_context_data
643 .sponsor_authenticator_function_ref
644 .and_then(Into::into),
645 ptb,
646 auth_context_data.transaction_data_bytes,
647 )
648 };
649 let auth_ctx = Rc::new(RefCell::new(auth_ctx));
650
651 temporary_store.store_auth_context(auth_ctx);
655
656 let authentication_execution_result = execute_authenticator_move_call(
658 temporary_store,
659 authenticator,
660 authenticator_function_ref,
661 gas_charger,
662 tx_ctx,
663 move_vm,
664 protocol_config,
665 metrics,
666 false,
667 contains_deleted_input,
668 cancelled_objects,
669 trace_builder_opt,
670 );
671
672 let authentication_execution_status = if let Err(error) = &authentication_execution_result {
674 elaborate_error_logs(error, transaction_digest)
675 } else {
676 ExecutionStatus::Success
677 };
678
679 #[skip_checked_arithmetic]
680 trace!(
681 tx_digest = ?transaction_digest,
682 computation_gas_cost = gas_charger.summary().gas_used(),
683 "Finished authenticator execution of transaction with status {:?}",
684 authentication_execution_status
685 );
686
687 authentication_execution_result
688 }
689
690 #[instrument(name = "auth_execute", level = "debug", skip_all)]
701 fn execute_authenticator_move_call(
702 temporary_store: &mut TemporaryStore<'_>,
703 authenticator: MoveAuthenticator,
704 authenticator_function_ref: AuthenticatorFunctionRefV1,
705 gas_charger: &mut GasCharger,
706 tx_ctx: Rc<RefCell<TxContext>>,
707 move_vm: &Arc<MoveVM>,
708 protocol_config: &ProtocolConfig,
709 metrics: Arc<LimitsMetrics>,
710 deny_cert: bool,
711 contains_deleted_input: bool,
712 cancelled_objects: Option<(CancelledObjects, Version)>,
713 trace_builder_opt: &mut Option<MoveTraceBuilder>,
714 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
715 {
716 run_inputs_checks(
720 protocol_config,
721 deny_cert,
722 contains_deleted_input,
723 cancelled_objects,
724 )
725 .and_then(|()| {
726 let authenticator_move_call =
727 setup_authenticator_move_call(authenticator, authenticator_function_ref)?;
728 programmable_transactions::execution::execute::<execution_mode::Authentication>(
729 protocol_config,
730 metrics.clone(),
731 move_vm,
732 temporary_store,
733 tx_ctx,
734 gas_charger,
735 authenticator_move_call,
736 trace_builder_opt,
737 )
738 .and_then(|ok_result| {
739 temporary_store.check_move_authenticator_results_consistency()?;
740 Ok(ok_result)
741 })
742 })
743 }
744
745 pub fn execute_genesis_state_update(
752 store: &dyn BackingStore,
753 protocol_config: &ProtocolConfig,
754 metrics: Arc<LimitsMetrics>,
755 move_vm: &Arc<MoveVM>,
756 tx_context: Rc<RefCell<TxContext>>,
757 input_objects: CheckedInputObjects,
758 pt: ProgrammableTransaction,
759 ) -> Result<InnerTemporaryStore, ExecutionError> {
760 let input_objects = input_objects.into_inner();
761 let tx_digest = tx_context.borrow().digest();
762
763 let mut temporary_store =
764 TemporaryStore::new(store, input_objects, vec![], tx_digest, protocol_config, 0);
765 let mut gas_charger = GasCharger::new_unmetered(tx_digest);
766 programmable_transactions::execution::execute::<execution_mode::Genesis>(
767 protocol_config,
768 metrics,
769 move_vm,
770 &mut temporary_store,
771 tx_context,
772 &mut gas_charger,
773 pt,
774 &mut None,
775 )?;
776 temporary_store.update_object_version_and_prev_tx();
777 Ok(temporary_store.into_inner())
778 }
779
780 #[instrument(name = "tx_execute", level = "debug", skip_all)]
789 fn execute_transaction<Mode: ExecutionMode>(
790 temporary_store: &mut TemporaryStore<'_>,
791 transaction_kind: TransactionKind,
792 gas_charger: &mut GasCharger,
793 tx_ctx: Rc<RefCell<TxContext>>,
794 move_vm: &Arc<MoveVM>,
795 protocol_config: &ProtocolConfig,
796 metrics: Arc<LimitsMetrics>,
797 enable_expensive_checks: bool,
798 deny_cert: bool,
799 contains_deleted_input: bool,
800 cancelled_objects: Option<(CancelledObjects, Version)>,
801 trace_builder_opt: &mut Option<MoveTraceBuilder>,
802 pre_execution_result_opt: Option<
803 Result<
804 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
805 ExecutionError,
806 >,
807 >,
808 ) -> (
809 GasCostSummary,
810 Result<Mode::ExecutionResults, ExecutionError>,
811 ) {
812 gas_charger.smash_gas(temporary_store);
813
814 debug_assert!(
817 pre_execution_result_opt.is_some() || gas_charger.no_charges(),
818 "No gas charges must be applied yet"
819 );
820
821 let is_genesis_or_epoch_change_tx = matches!(transaction_kind, TransactionKind::Genesis(_))
822 || transaction_kind.is_end_of_epoch();
823
824 let advance_epoch_gas_summary = transaction_kind.get_advance_epoch_tx_gas_summary();
825
826 let tx_digest = tx_ctx.borrow().digest();
827
828 let result = gas_charger.charge_input_objects(temporary_store);
832 let mut result = result.and_then(|()| {
833 run_inputs_checks(
834 protocol_config,
835 deny_cert,
836 contains_deleted_input,
837 cancelled_objects,
838 )?;
839
840 let mut execution_result = pre_execution_result_opt.unwrap_or(Ok(())).and_then(|_| {
843 execution_loop::<Mode>(
844 temporary_store,
845 transaction_kind,
846 tx_ctx,
847 move_vm,
848 gas_charger,
849 protocol_config,
850 metrics.clone(),
851 trace_builder_opt,
852 )
853 });
854
855 let meter_check = check_meter_limit(
856 temporary_store,
857 gas_charger,
858 protocol_config,
859 metrics.clone(),
860 );
861 if let Err(e) = meter_check {
862 execution_result = Err(e);
863 }
864
865 if execution_result.is_ok() {
866 let gas_check = check_written_objects_limit(
867 temporary_store,
868 gas_charger,
869 protocol_config,
870 metrics,
871 );
872 if let Err(e) = gas_check {
873 execution_result = Err(e);
874 }
875 }
876
877 execution_result
878 });
879
880 let cost_summary = gas_charger.charge_gas(temporary_store, &mut result);
881 temporary_store.conserve_unmetered_storage_rebate(gas_charger.unmetered_storage_rebate());
890
891 if let Err(e) = run_conservation_checks::<Mode>(
892 temporary_store,
893 gas_charger,
894 tx_digest,
895 move_vm,
896 enable_expensive_checks,
897 &cost_summary,
898 is_genesis_or_epoch_change_tx,
899 advance_epoch_gas_summary,
900 ) {
901 result = Err(e);
903 }
904
905 (cost_summary, result)
906 }
907
908 fn report_authentication_error<T>(
914 authentication_execution_result: Result<T, ExecutionError>,
915 protocol_config: &ProtocolConfig,
916 ) -> Result<T, ExecutionError> {
917 if protocol_config.report_move_authentication_error() {
918 authentication_execution_result.map_err(ExecutionError::into_move_authentication_error)
919 } else {
920 authentication_execution_result
921 }
922 }
923
924 fn elaborate_error_logs(
927 execution_error: &ExecutionError,
928 transaction_digest: TransactionDigest,
929 ) -> ExecutionStatus {
930 use ExecutionErrorKind as K;
931 match execution_error.kind() {
932 K::InvariantViolation | K::VmInvariantViolation => {
933 #[skip_checked_arithmetic]
934 tracing::error!(
935 kind = ?execution_error.kind(),
936 tx_digest = ?transaction_digest,
937 "INVARIANT VIOLATION! Source: {:?}",
938 execution_error.source(),
939 );
940 }
941
942 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
943 #[skip_checked_arithmetic]
944 tracing::debug!(
945 kind = ?execution_error.kind(),
946 tx_digest = ?transaction_digest,
947 "Verification Error. Source: {:?}",
948 execution_error.source(),
949 );
950 }
951
952 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
953 #[skip_checked_arithmetic]
954 tracing::debug!(
955 kind = ?execution_error.kind(),
956 tx_digest = ?transaction_digest,
957 "Publish/Upgrade Error. Source: {:?}",
958 execution_error.source(),
959 )
960 }
961
962 _ => (),
963 };
964
965 let (status, command) = execution_error.to_execution_status();
966 ExecutionStatus::new_failure(status, command)
967 }
968
969 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
978 fn run_conservation_checks<Mode: ExecutionMode>(
979 temporary_store: &mut TemporaryStore<'_>,
980 gas_charger: &mut GasCharger,
981 tx_digest: TransactionDigest,
982 move_vm: &Arc<MoveVM>,
983 enable_expensive_checks: bool,
984 cost_summary: &GasCostSummary,
985 is_genesis_or_epoch_change_tx: bool,
986 advance_epoch_gas_summary: Option<(u64, u64)>,
987 ) -> Result<(), ExecutionError> {
988 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
989 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
990 let conservation_result = {
993 temporary_store
994 .check_iota_conserved(cost_summary)
995 .and_then(|()| {
996 if enable_expensive_checks {
997 let mut layout_resolver =
1000 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1001 temporary_store.check_iota_conserved_expensive(
1002 cost_summary,
1003 advance_epoch_gas_summary,
1004 &mut layout_resolver,
1005 )
1006 } else {
1007 Ok(())
1008 }
1009 })
1010 };
1011 if let Err(conservation_err) = conservation_result {
1012 result = Err(conservation_err);
1016 gas_charger.reset(temporary_store);
1017 gas_charger.charge_gas(temporary_store, &mut result);
1018 if let Err(recovery_err) = {
1020 temporary_store
1021 .check_iota_conserved(cost_summary)
1022 .and_then(|()| {
1023 if enable_expensive_checks {
1024 let mut layout_resolver =
1027 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1028 temporary_store.check_iota_conserved_expensive(
1029 cost_summary,
1030 advance_epoch_gas_summary,
1031 &mut layout_resolver,
1032 )
1033 } else {
1034 Ok(())
1035 }
1036 })
1037 } {
1038 panic!(
1042 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1043 tx_digest,
1044 recovery_err,
1045 gas_charger.summary()
1046 )
1047 }
1048 }
1049 } result
1053 }
1054
1055 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1066 fn run_inputs_checks(
1067 protocol_config: &ProtocolConfig,
1068 deny_cert: bool,
1069 contains_deleted_input: bool,
1070 cancelled_objects: Option<(CancelledObjects, Version)>,
1071 ) -> Result<(), ExecutionError> {
1072 if deny_cert {
1073 Err(ExecutionError::new(
1074 ExecutionErrorKind::CertificateDenied,
1075 None,
1076 ))
1077 } else if contains_deleted_input {
1078 Err(ExecutionError::new(
1079 ExecutionErrorKind::InputObjectDeleted,
1080 None,
1081 ))
1082 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1083 match reason {
1084 version if version.is_congested() => Err(ExecutionError::new(
1085 match cancelled_objects {
1086 CancelledObjects::GasObject => {
1090 ExecutionErrorKind::ExecutionCanceledDueToExecutionWorkerCongestion {
1091 suggested_gas_price: version
1092 .get_congested_version_suggested_gas_price()
1093 .expect(
1094 "execution-worker congestion control requires the gas \
1095 price feedback mechanism",
1096 ),
1097 }
1098 }
1099 CancelledObjects::SharedObjects(congested_objects) => {
1100 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1101 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestionV2 {
1102 congested_objects,
1103 suggested_gas_price: version
1104 .get_congested_version_suggested_gas_price()
1105 .unwrap(),
1106 }
1107 } else {
1108 ExecutionErrorKind::ExecutionCanceledDueToSharedObjectCongestion {
1113 congested_objects,
1114 }
1115 }
1116 }
1117 },
1118 None,
1119 )),
1120 Version::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1121 ExecutionErrorKind::ExecutionCanceledDueToRandomnessUnavailable,
1122 None,
1123 )),
1124 _ => panic!("invalid cancellation reason Version: {reason}"),
1125 }
1126 } else {
1127 Ok(())
1128 }
1129 }
1130
1131 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1136 fn check_meter_limit(
1137 temporary_store: &mut TemporaryStore<'_>,
1138 gas_charger: &mut GasCharger,
1139 protocol_config: &ProtocolConfig,
1140 metrics: Arc<LimitsMetrics>,
1141 ) -> Result<(), ExecutionError> {
1142 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1143
1144 match check_limit_by_meter!(
1149 !gas_charger.is_unmetered(),
1150 effects_estimated_size,
1151 protocol_config.max_serialized_tx_effects_size_bytes(),
1152 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1153 metrics.excessive_estimated_effects_size
1154 ) {
1155 LimitThresholdCrossed::None => Ok(()),
1156 LimitThresholdCrossed::Soft(_, limit) => {
1157 warn!(
1158 effects_estimated_size = effects_estimated_size,
1159 soft_limit = limit,
1160 "Estimated transaction effects size crossed soft limit",
1161 );
1162 Ok(())
1163 }
1164 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1165 ExecutionErrorKind::EffectsTooLarge {
1166 current_size: effects_estimated_size as u64,
1167 max_size: lim as u64,
1168 },
1169 "Transaction effects are too large",
1170 )),
1171 }
1172 }
1173
1174 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1179 fn check_written_objects_limit(
1180 temporary_store: &mut TemporaryStore<'_>,
1181 gas_charger: &mut GasCharger,
1182 protocol_config: &ProtocolConfig,
1183 metrics: Arc<LimitsMetrics>,
1184 ) -> Result<(), ExecutionError> {
1185 if let (Some(normal_lim), Some(system_lim)) = (
1186 protocol_config.max_size_written_objects_as_option(),
1187 protocol_config.max_size_written_objects_system_tx_as_option(),
1188 ) {
1189 let written_objects_size = temporary_store.written_objects_size();
1190
1191 match check_limit_by_meter!(
1192 !gas_charger.is_unmetered(),
1193 written_objects_size,
1194 normal_lim,
1195 system_lim,
1196 metrics.excessive_written_objects_size
1197 ) {
1198 LimitThresholdCrossed::None => (),
1199 LimitThresholdCrossed::Soft(_, limit) => {
1200 warn!(
1201 written_objects_size = written_objects_size,
1202 soft_limit = limit,
1203 "Written objects size crossed soft limit",
1204 )
1205 }
1206 LimitThresholdCrossed::Hard(_, lim) => {
1207 return Err(ExecutionError::new_with_source(
1208 ExecutionErrorKind::WrittenObjectsTooLarge {
1209 object_size: written_objects_size as u64,
1210 max_object_size: lim as u64,
1211 },
1212 "Written objects size crossed hard limit",
1213 ));
1214 }
1215 };
1216 }
1217
1218 Ok(())
1219 }
1220
1221 #[instrument(level = "debug", skip_all)]
1228 fn execution_loop<Mode: ExecutionMode>(
1229 temporary_store: &mut TemporaryStore<'_>,
1230 transaction_kind: TransactionKind,
1231 tx_ctx: Rc<RefCell<TxContext>>,
1232 move_vm: &Arc<MoveVM>,
1233 gas_charger: &mut GasCharger,
1234 protocol_config: &ProtocolConfig,
1235 metrics: Arc<LimitsMetrics>,
1236 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1237 ) -> Result<Mode::ExecutionResults, ExecutionError> {
1238 let result = match transaction_kind {
1239 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1240 if tx_ctx.borrow().epoch() != 0 {
1241 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1242 }
1243
1244 for genesis_object in objects {
1245 let object = ObjectInner {
1246 data: genesis_object.data,
1247 owner: genesis_object.owner,
1248 previous_transaction: tx_ctx.borrow().digest(),
1249 storage_rebate: 0,
1250 };
1251 temporary_store.create_object(object.into());
1252 }
1253
1254 temporary_store.record_execution_results(ExecutionResults::V1(
1255 ExecutionResultsV1 {
1256 user_events: events,
1257 ..Default::default()
1258 },
1259 ));
1260
1261 Ok(Mode::empty_results())
1262 }
1263 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1264 setup_consensus_commit(
1265 prologue.commit_timestamp_ms,
1266 temporary_store,
1267 tx_ctx,
1268 move_vm,
1269 gas_charger,
1270 protocol_config,
1271 metrics,
1272 trace_builder_opt,
1273 )
1274 .expect("ConsensusCommitPrologueV1 cannot fail");
1275 Ok(Mode::empty_results())
1276 }
1277 TransactionKind::Programmable(pt) => {
1278 programmable_transactions::execution::execute::<Mode>(
1279 protocol_config,
1280 metrics,
1281 move_vm,
1282 temporary_store,
1283 tx_ctx,
1284 gas_charger,
1285 pt,
1286 trace_builder_opt,
1287 )
1288 }
1289 TransactionKind::EndOfEpoch(txns) => {
1290 let builder = ProgrammableTransactionBuilder::new();
1291 let len = txns.len();
1292
1293 if let Some((i, tx)) = txns.into_iter().enumerate().next() {
1294 match tx {
1295 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1296 assert_eq!(i, len - 1);
1297 advance_epoch_v1(
1298 builder,
1299 change_epoch,
1300 temporary_store,
1301 tx_ctx,
1302 move_vm,
1303 gas_charger,
1304 protocol_config,
1305 metrics,
1306 trace_builder_opt,
1307 )?;
1308 return Ok(Mode::empty_results());
1309 }
1310 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1311 assert_eq!(i, len - 1);
1312 advance_epoch_v2(
1313 builder,
1314 change_epoch_v2,
1315 temporary_store,
1316 tx_ctx,
1317 move_vm,
1318 gas_charger,
1319 protocol_config,
1320 metrics,
1321 trace_builder_opt,
1322 )?;
1323 return Ok(Mode::empty_results());
1324 }
1325 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1326 assert_eq!(i, len - 1);
1327 advance_epoch_v3(
1328 builder,
1329 change_epoch_v3,
1330 temporary_store,
1331 tx_ctx,
1332 move_vm,
1333 gas_charger,
1334 protocol_config,
1335 metrics,
1336 trace_builder_opt,
1337 )?;
1338 return Ok(Mode::empty_results());
1339 }
1340 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1341 assert_eq!(i, len - 1);
1342 advance_epoch_v4(
1343 builder,
1344 change_epoch_v4,
1345 temporary_store,
1346 tx_ctx,
1347 move_vm,
1348 gas_charger,
1349 protocol_config,
1350 metrics,
1351 trace_builder_opt,
1352 )?;
1353 return Ok(Mode::empty_results());
1354 }
1355 EndOfEpochTransactionKind::TransactionDenyRulesCreate => {
1356 return Err(ExecutionError::new(
1360 ExecutionErrorKind::VmInvariantViolation,
1361 Some(
1362 "TransactionDenyRulesCreate cannot be executed at this protocol version"
1363 .into(),
1364 ),
1365 ));
1366 }
1367 _ => unimplemented!(
1368 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1369 ),
1370 }
1371 }
1372 unreachable!(
1373 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1374 )
1375 }
1376 #[allow(deprecated)]
1377 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1378 return Err(ExecutionError::new(
1382 ExecutionErrorKind::VmInvariantViolation,
1383 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1384 ));
1385 }
1386 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1387 setup_randomness_state_update(
1388 randomness_state_update,
1389 temporary_store,
1390 tx_ctx,
1391 move_vm,
1392 gas_charger,
1393 protocol_config,
1394 metrics,
1395 trace_builder_opt,
1396 )?;
1397 Ok(Mode::empty_results())
1398 }
1399 TransactionKind::TransactionDenyRulesUpdate(_) => {
1400 Err(ExecutionError::new(
1403 ExecutionErrorKind::VmInvariantViolation,
1404 Some(
1405 "TransactionDenyRulesUpdate cannot be executed at this protocol version"
1406 .into(),
1407 ),
1408 ))
1409 }
1410 _ => unimplemented!(
1411 "a new TransactionKind enum variant was added and needs to be handled"
1412 ),
1413 }?;
1414 temporary_store.check_execution_results_consistency()?;
1415 Ok(result)
1416 }
1417
1418 fn mint_epoch_rewards_in_pt(
1427 builder: &mut ProgrammableTransactionBuilder,
1428 params: &AdvanceEpochParams,
1429 ) -> (Argument, Argument) {
1430 let storage_charge_arg = builder
1432 .input(CallArg::pure(¶ms.storage_charge))
1433 .unwrap();
1434 let storage_charges = builder.programmable_move_call(
1435 ObjectId::FRAMEWORK,
1436 Identifier::BALANCE_MODULE,
1437 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1438 vec![GAS::type_tag()],
1439 vec![storage_charge_arg],
1440 );
1441
1442 let computation_charge_arg = builder
1444 .input(CallArg::pure(¶ms.computation_charge))
1445 .unwrap();
1446 let computation_charges = builder.programmable_move_call(
1447 ObjectId::FRAMEWORK,
1448 Identifier::BALANCE_MODULE,
1449 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1450 vec![GAS::type_tag()],
1451 vec![computation_charge_arg],
1452 );
1453 (storage_charges, computation_charges)
1454 }
1455
1456 pub fn construct_advance_epoch_pt_impl(
1464 mut builder: ProgrammableTransactionBuilder,
1465 params: &AdvanceEpochParams,
1466 call_arg_vec: Vec<CallArg>,
1467 ) -> Result<ProgrammableTransaction, ExecutionError> {
1468 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1470 let mut arguments = vec![
1471 builder
1472 .pure(params.validator_subsidy)
1473 .expect("bcs encoding a u64 should not fail"),
1474 storage_charges,
1475 computation_charges,
1476 ];
1477
1478 let call_arg_arguments = call_arg_vec
1479 .into_iter()
1480 .map(|a| builder.input(a))
1481 .collect::<Result<_, _>>();
1482
1483 assert_invariant!(
1484 call_arg_arguments.is_ok(),
1485 "Unable to generate args for advance_epoch transaction!"
1486 );
1487
1488 arguments.append(&mut call_arg_arguments.unwrap());
1489
1490 info!("Call arguments to advance_epoch transaction: {:?}", params);
1491
1492 let storage_rebates = builder.programmable_move_call(
1493 ObjectId::SYSTEM,
1494 Identifier::IOTA_SYSTEM_MODULE,
1495 ADVANCE_EPOCH_FUNCTION_NAME,
1496 vec![],
1497 arguments,
1498 );
1499
1500 builder.programmable_move_call(
1502 ObjectId::FRAMEWORK,
1503 Identifier::BALANCE_MODULE,
1504 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1505 vec![GAS::type_tag()],
1506 vec![storage_rebates],
1507 );
1508 Ok(builder.finish())
1509 }
1510
1511 pub fn construct_advance_epoch_pt_v1(
1512 builder: ProgrammableTransactionBuilder,
1513 params: &AdvanceEpochParams,
1514 ) -> Result<ProgrammableTransaction, ExecutionError> {
1515 let call_arg_vec = vec![
1520 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), ];
1528 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1529 }
1530
1531 pub fn construct_advance_epoch_pt_v2(
1532 builder: ProgrammableTransactionBuilder,
1533 params: &AdvanceEpochParams,
1534 ) -> Result<ProgrammableTransaction, ExecutionError> {
1535 let call_arg_vec = vec![
1540 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), ];
1550 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1551 }
1552
1553 pub fn construct_advance_epoch_pt_v3(
1554 builder: ProgrammableTransactionBuilder,
1555 params: &AdvanceEpochParams,
1556 ) -> Result<ProgrammableTransaction, ExecutionError> {
1557 let call_arg_vec = vec![
1563 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), ];
1575 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1576 }
1577
1578 pub fn construct_advance_epoch_pt_v4(
1579 builder: ProgrammableTransactionBuilder,
1580 params: &AdvanceEpochParams,
1581 ) -> Result<ProgrammableTransaction, ExecutionError> {
1582 let call_arg_vec = vec![
1588 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), ];
1602 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1603 }
1604
1605 fn advance_epoch_impl(
1612 advance_epoch_pt: ProgrammableTransaction,
1613 params: AdvanceEpochParams,
1614 system_packages: Vec<SystemPackage>,
1615 temporary_store: &mut TemporaryStore<'_>,
1616 tx_ctx: Rc<RefCell<TxContext>>,
1617 move_vm: &Arc<MoveVM>,
1618 gas_charger: &mut GasCharger,
1619 protocol_config: &ProtocolConfig,
1620 metrics: Arc<LimitsMetrics>,
1621 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1622 ) -> Result<(), ExecutionError> {
1623 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1624 protocol_config,
1625 metrics.clone(),
1626 move_vm,
1627 temporary_store,
1628 tx_ctx.clone(),
1629 gas_charger,
1630 advance_epoch_pt,
1631 trace_builder_opt,
1632 );
1633
1634 #[cfg(msim)]
1635 let result = maybe_modify_result(result, params.epoch);
1636
1637 if result.is_err() {
1638 tracing::error!(
1639 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1640 result.as_ref().err(),
1641 temporary_store.objects(),
1642 params,
1643 );
1644 temporary_store.drop_writes();
1645 gas_charger.reset_storage_cost_and_rebate();
1647
1648 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1649 }
1650
1651 let new_vm = new_move_vm(
1652 all_natives(true, protocol_config),
1653 protocol_config,
1654 None,
1656 )
1657 .expect("Failed to create new MoveVM");
1658 process_system_packages(
1659 system_packages,
1660 temporary_store,
1661 tx_ctx,
1662 &new_vm,
1663 gas_charger,
1664 protocol_config,
1665 metrics,
1666 trace_builder_opt,
1667 );
1668
1669 Ok(())
1670 }
1671
1672 fn advance_epoch_v1(
1676 builder: ProgrammableTransactionBuilder,
1677 change_epoch: ChangeEpoch,
1678 temporary_store: &mut TemporaryStore<'_>,
1679 tx_ctx: Rc<RefCell<TxContext>>,
1680 move_vm: &Arc<MoveVM>,
1681 gas_charger: &mut GasCharger,
1682 protocol_config: &ProtocolConfig,
1683 metrics: Arc<LimitsMetrics>,
1684 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1685 ) -> Result<(), ExecutionError> {
1686 let params = AdvanceEpochParams {
1687 epoch: change_epoch.epoch,
1688 next_protocol_version: change_epoch.protocol_version.into(),
1689 validator_subsidy: protocol_config.validator_target_reward(),
1690 storage_charge: change_epoch.storage_charge,
1691 computation_charge: change_epoch.computation_charge,
1692 computation_charge_burned: change_epoch.computation_charge,
1694 storage_rebate: change_epoch.storage_rebate,
1695 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1696 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1697 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1698 max_committee_members_count: 0,
1701 eligible_active_validators: vec![],
1702 scores: vec![],
1703 adjust_rewards_by_score: false,
1704 };
1705 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1706 advance_epoch_impl(
1707 advance_epoch_pt,
1708 params,
1709 change_epoch.system_packages,
1710 temporary_store,
1711 tx_ctx,
1712 move_vm,
1713 gas_charger,
1714 protocol_config,
1715 metrics,
1716 trace_builder_opt,
1717 )
1718 }
1719
1720 fn advance_epoch_v2(
1724 builder: ProgrammableTransactionBuilder,
1725 change_epoch_v2: ChangeEpochV2,
1726 temporary_store: &mut TemporaryStore<'_>,
1727 tx_ctx: Rc<RefCell<TxContext>>,
1728 move_vm: &Arc<MoveVM>,
1729 gas_charger: &mut GasCharger,
1730 protocol_config: &ProtocolConfig,
1731 metrics: Arc<LimitsMetrics>,
1732 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1733 ) -> Result<(), ExecutionError> {
1734 let params = AdvanceEpochParams {
1735 epoch: change_epoch_v2.epoch,
1736 next_protocol_version: change_epoch_v2.protocol_version.into(),
1737 validator_subsidy: protocol_config.validator_target_reward(),
1738 storage_charge: change_epoch_v2.storage_charge,
1739 computation_charge: change_epoch_v2.computation_charge,
1740 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1741 storage_rebate: change_epoch_v2.storage_rebate,
1742 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1743 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1744 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1745 max_committee_members_count: protocol_config.max_committee_members_count(),
1746 eligible_active_validators: vec![],
1749 scores: vec![],
1750 adjust_rewards_by_score: false,
1751 };
1752 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1753 advance_epoch_impl(
1754 advance_epoch_pt,
1755 params,
1756 change_epoch_v2.system_packages,
1757 temporary_store,
1758 tx_ctx,
1759 move_vm,
1760 gas_charger,
1761 protocol_config,
1762 metrics,
1763 trace_builder_opt,
1764 )
1765 }
1766
1767 fn advance_epoch_v3(
1771 builder: ProgrammableTransactionBuilder,
1772 change_epoch_v3: ChangeEpochV3,
1773 temporary_store: &mut TemporaryStore<'_>,
1774 tx_ctx: Rc<RefCell<TxContext>>,
1775 move_vm: &Arc<MoveVM>,
1776 gas_charger: &mut GasCharger,
1777 protocol_config: &ProtocolConfig,
1778 metrics: Arc<LimitsMetrics>,
1779 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1780 ) -> Result<(), ExecutionError> {
1781 let params = AdvanceEpochParams {
1782 epoch: change_epoch_v3.epoch,
1783 next_protocol_version: change_epoch_v3.protocol_version.into(),
1784 validator_subsidy: protocol_config.validator_target_reward(),
1785 storage_charge: change_epoch_v3.storage_charge,
1786 computation_charge: change_epoch_v3.computation_charge,
1787 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1788 storage_rebate: change_epoch_v3.storage_rebate,
1789 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1790 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1791 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1792 max_committee_members_count: protocol_config.max_committee_members_count(),
1793 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1794 scores: vec![],
1797 adjust_rewards_by_score: false,
1798 };
1799 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1800 advance_epoch_impl(
1801 advance_epoch_pt,
1802 params,
1803 change_epoch_v3.system_packages,
1804 temporary_store,
1805 tx_ctx,
1806 move_vm,
1807 gas_charger,
1808 protocol_config,
1809 metrics,
1810 trace_builder_opt,
1811 )
1812 }
1813
1814 fn advance_epoch_v4(
1818 builder: ProgrammableTransactionBuilder,
1819 change_epoch_v4: ChangeEpochV4,
1820 temporary_store: &mut TemporaryStore<'_>,
1821 tx_ctx: Rc<RefCell<TxContext>>,
1822 move_vm: &Arc<MoveVM>,
1823 gas_charger: &mut GasCharger,
1824 protocol_config: &ProtocolConfig,
1825 metrics: Arc<LimitsMetrics>,
1826 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1827 ) -> Result<(), ExecutionError> {
1828 let params = AdvanceEpochParams {
1829 epoch: change_epoch_v4.epoch,
1830 next_protocol_version: change_epoch_v4.protocol_version.into(),
1831 validator_subsidy: protocol_config.validator_target_reward(),
1832 storage_charge: change_epoch_v4.storage_charge,
1833 computation_charge: change_epoch_v4.computation_charge,
1834 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1835 storage_rebate: change_epoch_v4.storage_rebate,
1836 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1837 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1838 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1839 max_committee_members_count: protocol_config.max_committee_members_count(),
1840 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1841 scores: change_epoch_v4.scores,
1842 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1843 };
1844 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1845 advance_epoch_impl(
1846 advance_epoch_pt,
1847 params,
1848 change_epoch_v4.system_packages,
1849 temporary_store,
1850 tx_ctx,
1851 move_vm,
1852 gas_charger,
1853 protocol_config,
1854 metrics,
1855 trace_builder_opt,
1856 )
1857 }
1858
1859 fn process_system_packages(
1860 system_packages: Vec<SystemPackage>,
1861 temporary_store: &mut TemporaryStore<'_>,
1862 tx_ctx: Rc<RefCell<TxContext>>,
1863 move_vm: &MoveVM,
1864 gas_charger: &mut GasCharger,
1865 protocol_config: &ProtocolConfig,
1866 metrics: Arc<LimitsMetrics>,
1867 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1868 ) {
1869 let binary_config = to_binary_config(protocol_config);
1870 for SystemPackage {
1871 version,
1872 modules,
1873 dependencies,
1874 } in system_packages.into_iter()
1875 {
1876 let deserialized_modules: Vec<_> = modules
1877 .iter()
1878 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1879 .collect();
1880
1881 if version == OBJECT_START_VERSION {
1882 let package_id = deserialized_modules.first().unwrap().address();
1883 info!("adding new system package {package_id}");
1884
1885 let publish_pt = {
1886 let mut b = ProgrammableTransactionBuilder::new();
1887 b.command(Command::new_publish(modules, dependencies));
1888 b.finish()
1889 };
1890
1891 programmable_transactions::execution::execute::<execution_mode::System>(
1892 protocol_config,
1893 metrics.clone(),
1894 move_vm,
1895 temporary_store,
1896 tx_ctx.clone(),
1897 gas_charger,
1898 publish_pt,
1899 trace_builder_opt,
1900 )
1901 .expect("System Package Publish must succeed");
1902 } else {
1903 let mut new_package = Object::new_system_package(
1904 &deserialized_modules,
1905 version,
1906 dependencies,
1907 tx_ctx.borrow().digest(),
1908 );
1909
1910 info!("upgraded system package {:?}", new_package.object_ref());
1911
1912 new_package
1915 .data
1916 .as_opt_mut_package()
1917 .unwrap()
1918 .decrement_version()
1919 .expect("package version should never underflow");
1920
1921 temporary_store.upgrade_system_package(new_package);
1923 }
1924 }
1925 }
1926
1927 fn setup_consensus_commit(
1933 consensus_commit_timestamp_ms: CheckpointTimestamp,
1934 temporary_store: &mut TemporaryStore<'_>,
1935 tx_ctx: Rc<RefCell<TxContext>>,
1936 move_vm: &Arc<MoveVM>,
1937 gas_charger: &mut GasCharger,
1938 protocol_config: &ProtocolConfig,
1939 metrics: Arc<LimitsMetrics>,
1940 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1941 ) -> Result<(), ExecutionError> {
1942 let pt = {
1943 let mut builder = ProgrammableTransactionBuilder::new();
1944 let res = builder.move_call(
1945 ObjectId::FRAMEWORK,
1946 Identifier::CLOCK_MODULE,
1947 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
1948 vec![],
1949 vec![
1950 CallArg::CLOCK_MUTABLE,
1951 CallArg::pure(&consensus_commit_timestamp_ms),
1952 ],
1953 );
1954 assert_invariant!(
1955 res.is_ok(),
1956 "Unable to generate consensus_commit_prologue transaction!"
1957 );
1958 builder.finish()
1959 };
1960 programmable_transactions::execution::execute::<execution_mode::System>(
1961 protocol_config,
1962 metrics,
1963 move_vm,
1964 temporary_store,
1965 tx_ctx,
1966 gas_charger,
1967 pt,
1968 trace_builder_opt,
1969 )
1970 }
1971
1972 fn setup_randomness_state_update(
1978 update: RandomnessStateUpdate,
1979 temporary_store: &mut TemporaryStore<'_>,
1980 tx_ctx: Rc<RefCell<TxContext>>,
1981 move_vm: &Arc<MoveVM>,
1982 gas_charger: &mut GasCharger,
1983 protocol_config: &ProtocolConfig,
1984 metrics: Arc<LimitsMetrics>,
1985 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1986 ) -> Result<(), ExecutionError> {
1987 let pt = {
1988 let mut builder = ProgrammableTransactionBuilder::new();
1989 let res = builder.move_call(
1990 ObjectId::FRAMEWORK,
1991 Identifier::RANDOM_MODULE,
1992 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
1993 vec![],
1994 vec![
1995 CallArg::Shared(SharedObjectReference::new(
1996 ObjectId::RANDOMNESS_STATE,
1997 update.randomness_obj_initial_shared_version,
1998 true,
1999 )),
2000 CallArg::pure(&update.randomness_round),
2001 CallArg::pure(&update.random_bytes),
2002 ],
2003 );
2004 assert_invariant!(
2005 res.is_ok(),
2006 "Unable to generate randomness_state_update transaction!"
2007 );
2008 builder.finish()
2009 };
2010 programmable_transactions::execution::execute::<execution_mode::System>(
2011 protocol_config,
2012 metrics,
2013 move_vm,
2014 temporary_store,
2015 tx_ctx,
2016 gas_charger,
2017 pt,
2018 trace_builder_opt,
2019 )
2020 }
2021
2022 fn setup_authenticator_move_call(
2029 authenticator: MoveAuthenticator,
2030 authenticator_function_ref: AuthenticatorFunctionRefV1,
2031 ) -> Result<ProgrammableTransaction, ExecutionError> {
2032 let mut builder = ProgrammableTransactionBuilder::new();
2033
2034 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
2035 args.extend(authenticator.call_args().to_owned());
2036
2037 let res = builder.move_call(
2038 authenticator_function_ref.package,
2039 Identifier::new(authenticator_function_ref.module.clone()).expect(
2040 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
2041 ),
2042 Identifier::new(authenticator_function_ref.function).expect(
2043 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
2044 ),
2045 authenticator.type_args().to_vec(),
2046 args,
2047 );
2048
2049 assert_invariant!(
2050 res.is_ok(),
2051 "Unable to generate an account authenticator call transaction!"
2052 );
2053
2054 Ok(builder.finish())
2055 }
2056
2057 fn resolve_sponsor(gas_data: &GasPayment, transaction_signer: &Address) -> Option<Address> {
2058 let gas_owner = gas_data.owner;
2059 if &gas_owner == transaction_signer {
2060 None
2061 } else {
2062 Some(gas_owner)
2063 }
2064 }
2065}