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 digests::Digest,
34 effects::TransactionEffects,
35 error::{ExecutionError, ExecutionErrorKind},
36 execution::{ExecutionResults, ExecutionResultsV1, SharedInput, is_certificate_denied},
37 execution_config_utils::to_binary_config,
38 execution_status::ExecutionStatus,
39 gas::{GasCostSummary, IotaGasStatus, IotaGasStatusAPI},
40 gas_coin::GAS,
41 inner_temporary_store::InnerTemporaryStore,
42 iota_system_state::{ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams},
43 messages_checkpoint::CheckpointTimestamp,
44 metrics::LimitsMetrics,
45 move_authenticator::MoveAuthenticator,
46 object::{OBJECT_START_VERSION, Object, ObjectInner},
47 programmable_transaction_builder::ProgrammableTransactionBuilder,
48 randomness_state::RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
49 storage::{BackingStore, Storage},
50 transaction::{
51 Argument, CallArg, ChangeEpoch, ChangeEpochV2, ChangeEpochV3, ChangeEpochV4,
52 CheckedInputObjects, Command, EndOfEpochTransactionKind, GasData, GenesisTransaction,
53 InputObjects, ProgrammableTransaction, RandomnessStateUpdate, SharedObjectRef,
54 SystemPackage, TransactionKind, TransactionKindExt,
55 },
56 };
57 use move_binary_format::CompiledModule;
58 use move_trace_format::format::MoveTraceBuilder;
59 use move_vm_runtime::move_vm::MoveVM;
60 use tracing::{info, instrument, trace, warn};
61
62 use crate::{
63 adapter::new_move_vm,
64 execution_mode::{self, ExecutionMode},
65 gas_charger::GasCharger,
66 programmable_transactions,
67 temporary_store::TemporaryStore,
68 type_layout_resolver::TypeLayoutResolver,
69 };
70
71 #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)]
83 pub fn execute_transaction_to_effects<Mode: ExecutionMode>(
84 store: &dyn BackingStore,
85 input_objects: CheckedInputObjects,
86 gas_data: GasData,
87 gas_status: IotaGasStatus,
88 transaction_kind: TransactionKind,
89 transaction_signer: IotaAddress,
90 transaction_digest: TransactionDigest,
91 move_vm: &Arc<MoveVM>,
92 epoch_id: &EpochId,
93 epoch_timestamp_ms: u64,
94 protocol_config: &ProtocolConfig,
95 metrics: Arc<LimitsMetrics>,
96 enable_expensive_checks: bool,
97 certificate_deny_set: &HashSet<TransactionDigest>,
98 trace_builder_opt: &mut Option<MoveTraceBuilder>,
99 ) -> (
100 InnerTemporaryStore,
101 IotaGasStatus,
102 TransactionEffects,
103 Result<Mode::ExecutionResults, ExecutionError>,
104 ) {
105 let input_objects = input_objects.into_inner();
106 let mutable_inputs = if enable_expensive_checks {
107 input_objects.mutable_inputs().keys().copied().collect()
108 } else {
109 HashSet::new()
110 };
111 let shared_object_refs = input_objects.filter_shared_objects();
112 let receiving_objects = transaction_kind.receiving_objects();
113 let transaction_dependencies = input_objects.transaction_dependencies();
114 let contains_deleted_input = input_objects.contains_deleted_objects();
115 let cancelled_objects = input_objects.get_cancelled_objects();
116
117 let temporary_store = TemporaryStore::new(
118 store,
119 input_objects,
120 receiving_objects,
121 transaction_digest,
122 protocol_config,
123 *epoch_id,
124 );
125
126 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
127 let gas_price = gas_status.gas_price();
128 let rgp = gas_status.reference_gas_price();
129 let gas_charger = GasCharger::new(
130 transaction_digest,
131 gas_data.objects,
132 gas_status,
133 protocol_config,
134 );
135
136 let tx_ctx = TxContext::new_from_components(
137 &transaction_signer,
138 &transaction_digest,
139 epoch_id,
140 epoch_timestamp_ms,
141 rgp,
142 gas_price,
143 gas_data.budget,
144 sponsor,
145 protocol_config,
146 );
147 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
148
149 execute_transaction_to_effects_inner::<Mode>(
150 temporary_store,
151 gas_charger,
152 tx_ctx,
153 &mutable_inputs,
154 shared_object_refs,
155 transaction_dependencies,
156 contains_deleted_input,
157 cancelled_objects,
158 transaction_kind,
159 transaction_signer,
160 transaction_digest,
161 move_vm,
162 epoch_id,
163 protocol_config,
164 metrics,
165 enable_expensive_checks,
166 certificate_deny_set,
167 trace_builder_opt,
168 None,
169 )
170 }
171
172 #[instrument(name = "tx_execute_to_effects_inner", level = "debug", skip_all)]
175 fn execute_transaction_to_effects_inner<Mode: ExecutionMode>(
176 mut temporary_store: TemporaryStore,
177 mut gas_charger: GasCharger,
178 tx_ctx: Rc<RefCell<TxContext>>,
179 mutable_inputs: &HashSet<ObjectID>,
180 shared_object_refs: Vec<SharedInput>,
181 mut transaction_dependencies: BTreeSet<TransactionDigest>,
182 contains_deleted_input: bool,
183 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
184 transaction_kind: TransactionKind,
185 transaction_signer: IotaAddress,
186 transaction_digest: TransactionDigest,
187 move_vm: &Arc<MoveVM>,
188 epoch_id: &EpochId,
189 protocol_config: &ProtocolConfig,
190 metrics: Arc<LimitsMetrics>,
191 enable_expensive_checks: bool,
192 certificate_deny_set: &HashSet<TransactionDigest>,
193 trace_builder_opt: &mut Option<MoveTraceBuilder>,
194 pre_execution_result_opt: Option<
195 Result<
196 <execution_mode::Authentication as ExecutionMode>::ExecutionResults,
197 ExecutionError,
198 >,
199 >,
200 ) -> (
201 InnerTemporaryStore,
202 IotaGasStatus,
203 TransactionEffects,
204 Result<Mode::ExecutionResults, ExecutionError>,
205 ) {
206 let is_epoch_change = transaction_kind.is_end_of_epoch();
207 let deny_cert = is_certificate_denied(&transaction_digest, certificate_deny_set);
208
209 let (gas_cost_summary, execution_result) = execute_transaction::<Mode>(
210 &mut temporary_store,
211 transaction_kind,
212 &mut gas_charger,
213 tx_ctx,
214 move_vm,
215 protocol_config,
216 metrics,
217 enable_expensive_checks,
218 deny_cert,
219 contains_deleted_input,
220 cancelled_objects,
221 trace_builder_opt,
222 pre_execution_result_opt,
223 );
224
225 let status = if let Err(error) = &execution_result {
226 elaborate_error_logs(error, transaction_digest)
227 } else {
228 ExecutionStatus::Success
229 };
230
231 #[skip_checked_arithmetic]
232 trace!(
233 tx_digest = ?transaction_digest,
234 computation_gas_cost = gas_cost_summary.computation_cost,
235 computation_gas_cost_burned = gas_cost_summary.computation_cost_burned,
236 storage_gas_cost = gas_cost_summary.storage_cost,
237 storage_gas_rebate = gas_cost_summary.storage_rebate,
238 "Finished execution of transaction with status {:?}",
239 status
240 );
241
242 transaction_dependencies.remove(&TransactionDigest::GENESIS_MARKER);
246
247 if enable_expensive_checks && !Mode::allow_arbitrary_function_calls() {
248 temporary_store
249 .check_ownership_invariants(
250 &transaction_signer,
251 &mut gas_charger,
252 mutable_inputs,
253 is_epoch_change,
254 )
255 .unwrap()
256 } let (inner, effects) = temporary_store.into_effects(
259 shared_object_refs,
260 &transaction_digest,
261 transaction_dependencies,
262 gas_cost_summary,
263 status,
264 &mut gas_charger,
265 *epoch_id,
266 );
267
268 (
269 inner,
270 gas_charger.into_gas_status(),
271 effects,
272 execution_result,
273 )
274 }
275
276 #[instrument(
290 name = "tx_authenticate_then_execute_to_effects",
291 level = "debug",
292 skip_all
293 )]
294 pub fn authenticate_then_execute_transaction_to_effects<Mode: ExecutionMode>(
295 store: &dyn BackingStore,
296 protocol_config: &ProtocolConfig,
298 metrics: Arc<LimitsMetrics>,
299 enable_expensive_checks: bool,
300 certificate_deny_set: &HashSet<TransactionDigest>,
301 epoch_id: &EpochId,
303 epoch_timestamp_ms: u64,
304 gas_data: GasData,
306 gas_status: IotaGasStatus,
307 authenticators: Vec<(
309 MoveAuthenticator,
310 AuthenticatorFunctionRefForExecution,
311 CheckedInputObjects,
312 )>,
313 authenticator_and_transaction_input_objects: CheckedInputObjects,
314 transaction_kind: TransactionKind,
316 transaction_signer: IotaAddress,
317 transaction_digest: TransactionDigest,
318 transaction_data_bytes: Vec<u8>,
319 sender_auth_digest: Digest,
320 sponsor_auth_digest: Option<Digest>,
321 trace_builder_opt: &mut Option<MoveTraceBuilder>,
323 move_vm: &Arc<MoveVM>,
325 ) -> (
326 InnerTemporaryStore,
327 IotaGasStatus,
328 TransactionEffects,
329 Result<Mode::ExecutionResults, ExecutionError>,
330 ) {
331 let input_objects = authenticator_and_transaction_input_objects.into_inner();
337 let mutable_inputs = if enable_expensive_checks {
339 input_objects.mutable_inputs().keys().copied().collect()
340 } else {
341 HashSet::new()
342 };
343 let shared_object_refs = input_objects.filter_shared_objects();
345 let transaction_receiving_objects = transaction_kind.receiving_objects();
347 let transaction_dependencies = input_objects.transaction_dependencies();
349 let contains_deleted_input = input_objects.contains_deleted_objects();
352 let cancelled_objects = input_objects.get_cancelled_objects();
353
354 let mut temporary_store = TemporaryStore::new(
356 store,
357 input_objects,
358 transaction_receiving_objects,
359 transaction_digest,
360 protocol_config,
361 *epoch_id,
362 );
363
364 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
366 let gas_price = gas_status.gas_price();
367 let rgp = gas_status.reference_gas_price();
368 let mut gas_charger = GasCharger::new(
369 transaction_digest,
370 gas_data.objects,
371 gas_status,
372 protocol_config,
373 );
374
375 let tx_ctx = TxContext::new_from_components(
377 &transaction_signer,
378 &transaction_digest,
379 epoch_id,
380 epoch_timestamp_ms,
381 rgp,
382 gas_price,
383 gas_data.budget,
384 sponsor,
385 protocol_config,
386 );
387 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
388
389 let authenticators = authenticators
395 .into_iter()
396 .map(
397 |(
398 authenticator,
399 authenticator_function_ref_for_execution,
400 authenticator_input_objects,
401 )| {
402 let AuthenticatorFunctionRefForExecution {
403 authenticator_function_ref,
404 loaded_object_id,
405 loaded_object_metadata,
406 } = authenticator_function_ref_for_execution;
407
408 temporary_store.save_loaded_runtime_objects(BTreeMap::from([(
411 loaded_object_id,
412 loaded_object_metadata,
413 )]));
414
415 (
416 authenticator,
417 authenticator_function_ref,
418 authenticator_input_objects,
419 )
420 },
421 )
422 .collect::<Vec<_>>();
423
424 let authentication_execution_result = authenticators.into_iter().try_for_each(
430 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
431 match authenticator_function_ref {
432 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
433 authenticate_transaction_inner(
434 &mut temporary_store,
435 protocol_config,
436 metrics.clone(),
437 &mut gas_charger,
438 authenticator,
439 authenticator_function_ref_v1,
440 &authenticator_input_objects.into_inner(),
441 transaction_kind.clone(),
442 transaction_digest,
443 transaction_data_bytes.clone(),
444 sender_auth_digest,
445 sponsor_auth_digest,
446 tx_ctx.clone(),
447 trace_builder_opt,
448 move_vm,
449 )
450 }
451 }
452 },
453 );
454
455 execute_transaction_to_effects_inner::<Mode>(
463 temporary_store,
464 gas_charger,
465 tx_ctx,
466 &mutable_inputs,
467 shared_object_refs,
468 transaction_dependencies,
469 contains_deleted_input,
470 cancelled_objects,
471 transaction_kind,
472 transaction_signer,
473 transaction_digest,
474 move_vm,
475 epoch_id,
476 protocol_config,
477 metrics,
478 enable_expensive_checks,
479 certificate_deny_set,
480 trace_builder_opt,
481 Some(authentication_execution_result),
482 )
483 }
484
485 #[instrument(name = "tx_validate", level = "debug", skip_all)]
490 pub fn authenticate_transaction(
491 store: &dyn BackingStore,
492 protocol_config: &ProtocolConfig,
494 metrics: Arc<LimitsMetrics>,
495 epoch_id: &EpochId,
497 epoch_timestamp_ms: u64,
498 gas_data: GasData,
500 gas_status: IotaGasStatus,
501 authenticators: Vec<(
503 MoveAuthenticator,
504 AuthenticatorFunctionRef,
505 CheckedInputObjects,
506 )>,
507 aggregated_authenticator_input_objects: CheckedInputObjects,
508 transaction_kind: TransactionKind,
510 transaction_signer: IotaAddress,
511 transaction_digest: TransactionDigest,
512 transaction_data_bytes: Vec<u8>,
513 sender_auth_digest: Digest,
514 sponsor_auth_digest: Option<Digest>,
515 trace_builder_opt: &mut Option<MoveTraceBuilder>,
517 move_vm: &Arc<MoveVM>,
519 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
520 {
521 let sponsor = resolve_sponsor(&gas_data, &transaction_signer);
523 let gas_price = gas_status.gas_price();
524 let rgp = gas_status.reference_gas_price();
525 let mut gas_charger =
526 GasCharger::new(transaction_digest, vec![], gas_status, protocol_config);
527
528 let tx_ctx = TxContext::new_from_components(
531 &transaction_signer,
532 &transaction_digest,
533 epoch_id,
534 epoch_timestamp_ms,
535 rgp,
536 gas_price,
537 gas_data.budget,
538 sponsor,
539 protocol_config,
540 );
541 let tx_ctx = Rc::new(RefCell::new(tx_ctx));
542
543 let mut temporary_store = TemporaryStore::new(
544 store,
545 aggregated_authenticator_input_objects.into_inner(),
546 vec![],
547 transaction_digest,
548 protocol_config,
549 *epoch_id,
550 );
551
552 authenticators.into_iter().try_for_each(
554 |(authenticator, authenticator_function_ref, authenticator_input_objects)| {
555 match authenticator_function_ref {
556 AuthenticatorFunctionRef::V1(authenticator_function_ref_v1) => {
557 authenticate_transaction_inner(
558 &mut temporary_store,
559 protocol_config,
560 metrics.clone(),
561 &mut gas_charger,
562 authenticator,
563 authenticator_function_ref_v1,
564 &authenticator_input_objects.into_inner(),
565 transaction_kind.clone(),
566 transaction_digest,
567 transaction_data_bytes.clone(),
568 sender_auth_digest,
569 sponsor_auth_digest,
570 tx_ctx.clone(),
571 trace_builder_opt,
572 move_vm,
573 )
574 }
575 }
576 },
577 )
578 }
579
580 #[instrument(name = "tx_validate", level = "debug", skip_all)]
590 pub fn authenticate_transaction_inner(
591 temporary_store: &mut TemporaryStore<'_>,
592 protocol_config: &ProtocolConfig,
594 metrics: Arc<LimitsMetrics>,
595 gas_charger: &mut GasCharger,
597 authenticator: MoveAuthenticator,
599 authenticator_function_ref: AuthenticatorFunctionRefV1,
600 authenticator_input_objects: &InputObjects,
601 transaction_kind: TransactionKind,
603 transaction_digest: TransactionDigest,
604 tx_data_bytes: Vec<u8>,
605 sender_auth_digest: Digest,
606 sponsor_auth_digest: Option<Digest>,
607 tx_ctx: Rc<RefCell<TxContext>>,
608 trace_builder_opt: &mut Option<MoveTraceBuilder>,
610 move_vm: &Arc<MoveVM>,
612 ) -> Result<<execution_mode::Authentication as ExecutionMode>::ExecutionResults, ExecutionError>
613 {
614 debug_assert!(
616 transaction_kind.is_programmable(),
617 "Only programmable transactions are allowed"
618 );
619 debug_assert!(
620 authenticator_input_objects
621 .mutable_inputs()
622 .keys()
623 .copied()
624 .collect::<HashSet<_>>()
625 .is_empty(),
626 "No mutable inputs are allowed"
627 );
628 debug_assert!(
629 authenticator.receiving_objects().is_empty(),
630 "No receiving inputs are allowed"
631 );
632
633 let contains_deleted_input = authenticator_input_objects.contains_deleted_objects();
634 let cancelled_objects = authenticator_input_objects.get_cancelled_objects();
635
636 let auth_ctx = {
638 let TransactionKind::Programmable(ptb) = &transaction_kind else {
639 unreachable!("Only programmable transactions are allowed");
640 };
641 AuthContext::new_from_components(
642 authenticator.digest(),
643 sender_auth_digest,
644 sponsor_auth_digest,
645 ptb,
646 tx_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<(Vec<ObjectID>, SequenceNumber)>,
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<(Vec<ObjectID>, SequenceNumber)>,
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 elaborate_error_logs(
911 execution_error: &ExecutionError,
912 transaction_digest: TransactionDigest,
913 ) -> ExecutionStatus {
914 use ExecutionErrorKind as K;
915 match execution_error.kind() {
916 K::InvariantViolation | K::VmInvariantViolation => {
917 #[skip_checked_arithmetic]
918 tracing::error!(
919 kind = ?execution_error.kind(),
920 tx_digest = ?transaction_digest,
921 "INVARIANT VIOLATION! Source: {:?}",
922 execution_error.source(),
923 );
924 }
925
926 K::IotaMoveVerificationError | K::VmVerificationOrDeserializationError => {
927 #[skip_checked_arithmetic]
928 tracing::debug!(
929 kind = ?execution_error.kind(),
930 tx_digest = ?transaction_digest,
931 "Verification Error. Source: {:?}",
932 execution_error.source(),
933 );
934 }
935
936 K::PublishUpgradeMissingDependency | K::PublishUpgradeDependencyDowngrade => {
937 #[skip_checked_arithmetic]
938 tracing::debug!(
939 kind = ?execution_error.kind(),
940 tx_digest = ?transaction_digest,
941 "Publish/Upgrade Error. Source: {:?}",
942 execution_error.source(),
943 )
944 }
945
946 _ => (),
947 };
948
949 let (status, command) = execution_error.to_execution_status();
950 ExecutionStatus::new_failure(status, command)
951 }
952
953 #[instrument(name = "run_conservation_checks", level = "debug", skip_all)]
962 fn run_conservation_checks<Mode: ExecutionMode>(
963 temporary_store: &mut TemporaryStore<'_>,
964 gas_charger: &mut GasCharger,
965 tx_digest: TransactionDigest,
966 move_vm: &Arc<MoveVM>,
967 enable_expensive_checks: bool,
968 cost_summary: &GasCostSummary,
969 is_genesis_or_epoch_change_tx: bool,
970 advance_epoch_gas_summary: Option<(u64, u64)>,
971 ) -> Result<(), ExecutionError> {
972 let mut result: std::result::Result<(), iota_types::error::ExecutionError> = Ok(());
973 if !is_genesis_or_epoch_change_tx && !Mode::skip_conservation_checks() {
974 let conservation_result = {
977 temporary_store
978 .check_iota_conserved(cost_summary)
979 .and_then(|()| {
980 if enable_expensive_checks {
981 let mut layout_resolver =
984 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
985 temporary_store.check_iota_conserved_expensive(
986 cost_summary,
987 advance_epoch_gas_summary,
988 &mut layout_resolver,
989 )
990 } else {
991 Ok(())
992 }
993 })
994 };
995 if let Err(conservation_err) = conservation_result {
996 result = Err(conservation_err);
1000 gas_charger.reset(temporary_store);
1001 gas_charger.charge_gas(temporary_store, &mut result);
1002 if let Err(recovery_err) = {
1004 temporary_store
1005 .check_iota_conserved(cost_summary)
1006 .and_then(|()| {
1007 if enable_expensive_checks {
1008 let mut layout_resolver =
1011 TypeLayoutResolver::new(move_vm, Box::new(&*temporary_store));
1012 temporary_store.check_iota_conserved_expensive(
1013 cost_summary,
1014 advance_epoch_gas_summary,
1015 &mut layout_resolver,
1016 )
1017 } else {
1018 Ok(())
1019 }
1020 })
1021 } {
1022 panic!(
1026 "IOTA conservation fail in tx block {}: {}\nGas status is {}\nTx was ",
1027 tx_digest,
1028 recovery_err,
1029 gas_charger.summary()
1030 )
1031 }
1032 }
1033 } result
1037 }
1038
1039 #[instrument(name = "run_inputs_checks", level = "debug", skip_all)]
1050 fn run_inputs_checks(
1051 protocol_config: &ProtocolConfig,
1052 deny_cert: bool,
1053 contains_deleted_input: bool,
1054 cancelled_objects: Option<(Vec<ObjectID>, SequenceNumber)>,
1055 ) -> Result<(), ExecutionError> {
1056 if deny_cert {
1057 Err(ExecutionError::new(
1058 ExecutionErrorKind::CertificateDenied,
1059 None,
1060 ))
1061 } else if contains_deleted_input {
1062 Err(ExecutionError::new(
1063 ExecutionErrorKind::InputObjectDeleted,
1064 None,
1065 ))
1066 } else if let Some((cancelled_objects, reason)) = cancelled_objects {
1067 match reason {
1068 version if version.is_congested() => Err(ExecutionError::new(
1069 if protocol_config.congestion_control_gas_price_feedback_mechanism() {
1070 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestionV2 {
1071 congested_objects: cancelled_objects,
1072 suggested_gas_price: version
1073 .get_congested_version_suggested_gas_price()
1074 .unwrap(),
1075 }
1076 } else {
1077 ExecutionErrorKind::ExecutionCancelledDueToSharedObjectCongestion {
1082 congested_objects: cancelled_objects,
1083 }
1084 },
1085 None,
1086 )),
1087 SequenceNumber::RANDOMNESS_UNAVAILABLE => Err(ExecutionError::new(
1088 ExecutionErrorKind::ExecutionCancelledDueToRandomnessUnavailable,
1089 None,
1090 )),
1091 _ => panic!("invalid cancellation reason SequenceNumber: {reason}"),
1092 }
1093 } else {
1094 Ok(())
1095 }
1096 }
1097
1098 #[instrument(name = "check_meter_limit", level = "debug", skip_all)]
1103 fn check_meter_limit(
1104 temporary_store: &mut TemporaryStore<'_>,
1105 gas_charger: &mut GasCharger,
1106 protocol_config: &ProtocolConfig,
1107 metrics: Arc<LimitsMetrics>,
1108 ) -> Result<(), ExecutionError> {
1109 let effects_estimated_size = temporary_store.estimate_effects_size_upperbound();
1110
1111 match check_limit_by_meter!(
1116 !gas_charger.is_unmetered(),
1117 effects_estimated_size,
1118 protocol_config.max_serialized_tx_effects_size_bytes(),
1119 protocol_config.max_serialized_tx_effects_size_bytes_system_tx(),
1120 metrics.excessive_estimated_effects_size
1121 ) {
1122 LimitThresholdCrossed::None => Ok(()),
1123 LimitThresholdCrossed::Soft(_, limit) => {
1124 warn!(
1125 effects_estimated_size = effects_estimated_size,
1126 soft_limit = limit,
1127 "Estimated transaction effects size crossed soft limit",
1128 );
1129 Ok(())
1130 }
1131 LimitThresholdCrossed::Hard(_, lim) => Err(ExecutionError::new_with_source(
1132 ExecutionErrorKind::EffectsTooLarge {
1133 current_size: effects_estimated_size as u64,
1134 max_size: lim as u64,
1135 },
1136 "Transaction effects are too large",
1137 )),
1138 }
1139 }
1140
1141 #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)]
1146 fn check_written_objects_limit(
1147 temporary_store: &mut TemporaryStore<'_>,
1148 gas_charger: &mut GasCharger,
1149 protocol_config: &ProtocolConfig,
1150 metrics: Arc<LimitsMetrics>,
1151 ) -> Result<(), ExecutionError> {
1152 if let (Some(normal_lim), Some(system_lim)) = (
1153 protocol_config.max_size_written_objects_as_option(),
1154 protocol_config.max_size_written_objects_system_tx_as_option(),
1155 ) {
1156 let written_objects_size = temporary_store.written_objects_size();
1157
1158 match check_limit_by_meter!(
1159 !gas_charger.is_unmetered(),
1160 written_objects_size,
1161 normal_lim,
1162 system_lim,
1163 metrics.excessive_written_objects_size
1164 ) {
1165 LimitThresholdCrossed::None => (),
1166 LimitThresholdCrossed::Soft(_, limit) => {
1167 warn!(
1168 written_objects_size = written_objects_size,
1169 soft_limit = limit,
1170 "Written objects size crossed soft limit",
1171 )
1172 }
1173 LimitThresholdCrossed::Hard(_, lim) => {
1174 return Err(ExecutionError::new_with_source(
1175 ExecutionErrorKind::WrittenObjectsTooLarge {
1176 object_size: written_objects_size as u64,
1177 max_object_size: lim as u64,
1178 },
1179 "Written objects size crossed hard limit",
1180 ));
1181 }
1182 };
1183 }
1184
1185 Ok(())
1186 }
1187
1188 #[instrument(level = "debug", skip_all)]
1195 fn execution_loop<Mode: ExecutionMode>(
1196 temporary_store: &mut TemporaryStore<'_>,
1197 transaction_kind: TransactionKind,
1198 tx_ctx: Rc<RefCell<TxContext>>,
1199 move_vm: &Arc<MoveVM>,
1200 gas_charger: &mut GasCharger,
1201 protocol_config: &ProtocolConfig,
1202 metrics: Arc<LimitsMetrics>,
1203 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1204 ) -> Result<Mode::ExecutionResults, ExecutionError> {
1205 let result = match transaction_kind {
1206 TransactionKind::Genesis(GenesisTransaction { objects, events }) => {
1207 if tx_ctx.borrow().epoch() != 0 {
1208 panic!("BUG: Genesis Transactions can only be executed in epoch 0");
1209 }
1210
1211 for genesis_object in objects {
1212 let object = ObjectInner {
1213 data: genesis_object.data,
1214 owner: genesis_object.owner,
1215 previous_transaction: tx_ctx.borrow().digest(),
1216 storage_rebate: 0,
1217 };
1218 temporary_store.create_object(object.into());
1219 }
1220
1221 temporary_store.record_execution_results(ExecutionResults::V1(
1222 ExecutionResultsV1 {
1223 user_events: events,
1224 ..Default::default()
1225 },
1226 ));
1227
1228 Ok(Mode::empty_results())
1229 }
1230 TransactionKind::ConsensusCommitPrologueV1(prologue) => {
1231 setup_consensus_commit(
1232 prologue.commit_timestamp_ms,
1233 temporary_store,
1234 tx_ctx,
1235 move_vm,
1236 gas_charger,
1237 protocol_config,
1238 metrics,
1239 trace_builder_opt,
1240 )
1241 .expect("ConsensusCommitPrologueV1 cannot fail");
1242 Ok(Mode::empty_results())
1243 }
1244 TransactionKind::Programmable(pt) => {
1245 programmable_transactions::execution::execute::<Mode>(
1246 protocol_config,
1247 metrics,
1248 move_vm,
1249 temporary_store,
1250 tx_ctx,
1251 gas_charger,
1252 pt,
1253 trace_builder_opt,
1254 )
1255 }
1256 TransactionKind::EndOfEpoch(txns) => {
1257 let builder = ProgrammableTransactionBuilder::new();
1258 let len = txns.len();
1259
1260 if let Some((i, tx)) = txns.into_iter().enumerate().next() {
1261 match tx {
1262 EndOfEpochTransactionKind::ChangeEpoch(change_epoch) => {
1263 assert_eq!(i, len - 1);
1264 advance_epoch_v1(
1265 builder,
1266 change_epoch,
1267 temporary_store,
1268 tx_ctx,
1269 move_vm,
1270 gas_charger,
1271 protocol_config,
1272 metrics,
1273 trace_builder_opt,
1274 )?;
1275 return Ok(Mode::empty_results());
1276 }
1277 EndOfEpochTransactionKind::ChangeEpochV2(change_epoch_v2) => {
1278 assert_eq!(i, len - 1);
1279 advance_epoch_v2(
1280 builder,
1281 change_epoch_v2,
1282 temporary_store,
1283 tx_ctx,
1284 move_vm,
1285 gas_charger,
1286 protocol_config,
1287 metrics,
1288 trace_builder_opt,
1289 )?;
1290 return Ok(Mode::empty_results());
1291 }
1292 EndOfEpochTransactionKind::ChangeEpochV3(change_epoch_v3) => {
1293 assert_eq!(i, len - 1);
1294 advance_epoch_v3(
1295 builder,
1296 change_epoch_v3,
1297 temporary_store,
1298 tx_ctx,
1299 move_vm,
1300 gas_charger,
1301 protocol_config,
1302 metrics,
1303 trace_builder_opt,
1304 )?;
1305 return Ok(Mode::empty_results());
1306 }
1307 EndOfEpochTransactionKind::ChangeEpochV4(change_epoch_v4) => {
1308 assert_eq!(i, len - 1);
1309 advance_epoch_v4(
1310 builder,
1311 change_epoch_v4,
1312 temporary_store,
1313 tx_ctx,
1314 move_vm,
1315 gas_charger,
1316 protocol_config,
1317 metrics,
1318 trace_builder_opt,
1319 )?;
1320 return Ok(Mode::empty_results());
1321 }
1322 _ => unimplemented!(
1323 "a new EndOfEpochTransactionKind enum variant was added and needs to be handled"
1324 ),
1325 }
1326 }
1327 unreachable!(
1328 "EndOfEpochTransactionKind::ChangeEpoch should be the last transaction in the list"
1329 )
1330 }
1331 #[allow(deprecated)]
1332 TransactionKind::AuthenticatorStateUpdateV1Deprecated => {
1333 return Err(ExecutionError::new(
1337 ExecutionErrorKind::VmInvariantViolation,
1338 Some("AuthenticatorState transactions are deprecated and were never created on IOTA".into()),
1339 ));
1340 }
1341 TransactionKind::RandomnessStateUpdate(randomness_state_update) => {
1342 setup_randomness_state_update(
1343 randomness_state_update,
1344 temporary_store,
1345 tx_ctx,
1346 move_vm,
1347 gas_charger,
1348 protocol_config,
1349 metrics,
1350 trace_builder_opt,
1351 )?;
1352 Ok(Mode::empty_results())
1353 }
1354 _ => unimplemented!(
1355 "a new TransactionKind enum variant was added and needs to be handled"
1356 ),
1357 }?;
1358 temporary_store.check_execution_results_consistency()?;
1359 Ok(result)
1360 }
1361
1362 fn mint_epoch_rewards_in_pt(
1371 builder: &mut ProgrammableTransactionBuilder,
1372 params: &AdvanceEpochParams,
1373 ) -> (Argument, Argument) {
1374 let storage_charge_arg = builder
1376 .input(CallArg::pure(¶ms.storage_charge))
1377 .unwrap();
1378 let storage_charges = builder.programmable_move_call(
1379 ObjectID::FRAMEWORK,
1380 Identifier::BALANCE_MODULE,
1381 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1382 vec![GAS::type_tag()],
1383 vec![storage_charge_arg],
1384 );
1385
1386 let computation_charge_arg = builder
1388 .input(CallArg::pure(¶ms.computation_charge))
1389 .unwrap();
1390 let computation_charges = builder.programmable_move_call(
1391 ObjectID::FRAMEWORK,
1392 Identifier::BALANCE_MODULE,
1393 BALANCE_CREATE_REWARDS_FUNCTION_NAME,
1394 vec![GAS::type_tag()],
1395 vec![computation_charge_arg],
1396 );
1397 (storage_charges, computation_charges)
1398 }
1399
1400 pub fn construct_advance_epoch_pt_impl(
1408 mut builder: ProgrammableTransactionBuilder,
1409 params: &AdvanceEpochParams,
1410 call_arg_vec: Vec<CallArg>,
1411 ) -> Result<ProgrammableTransaction, ExecutionError> {
1412 let (storage_charges, computation_charges) = mint_epoch_rewards_in_pt(&mut builder, params);
1414 let mut arguments = vec![
1415 builder
1416 .pure(params.validator_subsidy)
1417 .expect("bcs encoding a u64 should not fail"),
1418 storage_charges,
1419 computation_charges,
1420 ];
1421
1422 let call_arg_arguments = call_arg_vec
1423 .into_iter()
1424 .map(|a| builder.input(a))
1425 .collect::<Result<_, _>>();
1426
1427 assert_invariant!(
1428 call_arg_arguments.is_ok(),
1429 "Unable to generate args for advance_epoch transaction!"
1430 );
1431
1432 arguments.append(&mut call_arg_arguments.unwrap());
1433
1434 info!("Call arguments to advance_epoch transaction: {:?}", params);
1435
1436 let storage_rebates = builder.programmable_move_call(
1437 ObjectID::SYSTEM,
1438 Identifier::IOTA_SYSTEM_MODULE,
1439 ADVANCE_EPOCH_FUNCTION_NAME,
1440 vec![],
1441 arguments,
1442 );
1443
1444 builder.programmable_move_call(
1446 ObjectID::FRAMEWORK,
1447 Identifier::BALANCE_MODULE,
1448 BALANCE_DESTROY_REBATES_FUNCTION_NAME,
1449 vec![GAS::type_tag()],
1450 vec![storage_rebates],
1451 );
1452 Ok(builder.finish())
1453 }
1454
1455 pub fn construct_advance_epoch_pt_v1(
1456 builder: ProgrammableTransactionBuilder,
1457 params: &AdvanceEpochParams,
1458 ) -> Result<ProgrammableTransaction, ExecutionError> {
1459 let call_arg_vec = vec![
1464 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), ];
1472 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1473 }
1474
1475 pub fn construct_advance_epoch_pt_v2(
1476 builder: ProgrammableTransactionBuilder,
1477 params: &AdvanceEpochParams,
1478 ) -> Result<ProgrammableTransaction, ExecutionError> {
1479 let call_arg_vec = vec![
1484 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), ];
1494 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1495 }
1496
1497 pub fn construct_advance_epoch_pt_v3(
1498 builder: ProgrammableTransactionBuilder,
1499 params: &AdvanceEpochParams,
1500 ) -> Result<ProgrammableTransaction, ExecutionError> {
1501 let call_arg_vec = vec![
1507 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), ];
1519 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1520 }
1521
1522 pub fn construct_advance_epoch_pt_v4(
1523 builder: ProgrammableTransactionBuilder,
1524 params: &AdvanceEpochParams,
1525 ) -> Result<ProgrammableTransaction, ExecutionError> {
1526 let call_arg_vec = vec![
1532 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), ];
1546 construct_advance_epoch_pt_impl(builder, params, call_arg_vec)
1547 }
1548
1549 fn advance_epoch_impl(
1556 advance_epoch_pt: ProgrammableTransaction,
1557 params: AdvanceEpochParams,
1558 system_packages: Vec<SystemPackage>,
1559 temporary_store: &mut TemporaryStore<'_>,
1560 tx_ctx: Rc<RefCell<TxContext>>,
1561 move_vm: &Arc<MoveVM>,
1562 gas_charger: &mut GasCharger,
1563 protocol_config: &ProtocolConfig,
1564 metrics: Arc<LimitsMetrics>,
1565 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1566 ) -> Result<(), ExecutionError> {
1567 let result = programmable_transactions::execution::execute::<execution_mode::System>(
1568 protocol_config,
1569 metrics.clone(),
1570 move_vm,
1571 temporary_store,
1572 tx_ctx.clone(),
1573 gas_charger,
1574 advance_epoch_pt,
1575 trace_builder_opt,
1576 );
1577
1578 #[cfg(msim)]
1579 let result = maybe_modify_result(result, params.epoch);
1580
1581 if result.is_err() {
1582 tracing::error!(
1583 "Failed to execute advance epoch transaction. Switching to safe mode. Error: {:?}. Input objects: {:?}. Tx params: {:?}",
1584 result.as_ref().err(),
1585 temporary_store.objects(),
1586 params,
1587 );
1588 temporary_store.drop_writes();
1589 gas_charger.reset_storage_cost_and_rebate();
1591
1592 temporary_store.advance_epoch_safe_mode(¶ms, protocol_config);
1593 }
1594
1595 let new_vm = new_move_vm(
1596 all_natives(true, protocol_config),
1597 protocol_config,
1598 None,
1600 )
1601 .expect("Failed to create new MoveVM");
1602 process_system_packages(
1603 system_packages,
1604 temporary_store,
1605 tx_ctx,
1606 &new_vm,
1607 gas_charger,
1608 protocol_config,
1609 metrics,
1610 trace_builder_opt,
1611 );
1612
1613 Ok(())
1614 }
1615
1616 fn advance_epoch_v1(
1620 builder: ProgrammableTransactionBuilder,
1621 change_epoch: ChangeEpoch,
1622 temporary_store: &mut TemporaryStore<'_>,
1623 tx_ctx: Rc<RefCell<TxContext>>,
1624 move_vm: &Arc<MoveVM>,
1625 gas_charger: &mut GasCharger,
1626 protocol_config: &ProtocolConfig,
1627 metrics: Arc<LimitsMetrics>,
1628 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1629 ) -> Result<(), ExecutionError> {
1630 let params = AdvanceEpochParams {
1631 epoch: change_epoch.epoch,
1632 next_protocol_version: change_epoch.protocol_version.into(),
1633 validator_subsidy: protocol_config.validator_target_reward(),
1634 storage_charge: change_epoch.storage_charge,
1635 computation_charge: change_epoch.computation_charge,
1636 computation_charge_burned: change_epoch.computation_charge,
1638 storage_rebate: change_epoch.storage_rebate,
1639 non_refundable_storage_fee: change_epoch.non_refundable_storage_fee,
1640 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1641 epoch_start_timestamp_ms: change_epoch.epoch_start_timestamp_ms,
1642 max_committee_members_count: 0,
1645 eligible_active_validators: vec![],
1646 scores: vec![],
1647 adjust_rewards_by_score: false,
1648 };
1649 let advance_epoch_pt = construct_advance_epoch_pt_v1(builder, ¶ms)?;
1650 advance_epoch_impl(
1651 advance_epoch_pt,
1652 params,
1653 change_epoch.system_packages,
1654 temporary_store,
1655 tx_ctx,
1656 move_vm,
1657 gas_charger,
1658 protocol_config,
1659 metrics,
1660 trace_builder_opt,
1661 )
1662 }
1663
1664 fn advance_epoch_v2(
1668 builder: ProgrammableTransactionBuilder,
1669 change_epoch_v2: ChangeEpochV2,
1670 temporary_store: &mut TemporaryStore<'_>,
1671 tx_ctx: Rc<RefCell<TxContext>>,
1672 move_vm: &Arc<MoveVM>,
1673 gas_charger: &mut GasCharger,
1674 protocol_config: &ProtocolConfig,
1675 metrics: Arc<LimitsMetrics>,
1676 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1677 ) -> Result<(), ExecutionError> {
1678 let params = AdvanceEpochParams {
1679 epoch: change_epoch_v2.epoch,
1680 next_protocol_version: change_epoch_v2.protocol_version.into(),
1681 validator_subsidy: protocol_config.validator_target_reward(),
1682 storage_charge: change_epoch_v2.storage_charge,
1683 computation_charge: change_epoch_v2.computation_charge,
1684 computation_charge_burned: change_epoch_v2.computation_charge_burned,
1685 storage_rebate: change_epoch_v2.storage_rebate,
1686 non_refundable_storage_fee: change_epoch_v2.non_refundable_storage_fee,
1687 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1688 epoch_start_timestamp_ms: change_epoch_v2.epoch_start_timestamp_ms,
1689 max_committee_members_count: protocol_config.max_committee_members_count(),
1690 eligible_active_validators: vec![],
1693 scores: vec![],
1694 adjust_rewards_by_score: false,
1695 };
1696 let advance_epoch_pt = construct_advance_epoch_pt_v2(builder, ¶ms)?;
1697 advance_epoch_impl(
1698 advance_epoch_pt,
1699 params,
1700 change_epoch_v2.system_packages,
1701 temporary_store,
1702 tx_ctx,
1703 move_vm,
1704 gas_charger,
1705 protocol_config,
1706 metrics,
1707 trace_builder_opt,
1708 )
1709 }
1710
1711 fn advance_epoch_v3(
1715 builder: ProgrammableTransactionBuilder,
1716 change_epoch_v3: ChangeEpochV3,
1717 temporary_store: &mut TemporaryStore<'_>,
1718 tx_ctx: Rc<RefCell<TxContext>>,
1719 move_vm: &Arc<MoveVM>,
1720 gas_charger: &mut GasCharger,
1721 protocol_config: &ProtocolConfig,
1722 metrics: Arc<LimitsMetrics>,
1723 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1724 ) -> Result<(), ExecutionError> {
1725 let params = AdvanceEpochParams {
1726 epoch: change_epoch_v3.epoch,
1727 next_protocol_version: change_epoch_v3.protocol_version.into(),
1728 validator_subsidy: protocol_config.validator_target_reward(),
1729 storage_charge: change_epoch_v3.storage_charge,
1730 computation_charge: change_epoch_v3.computation_charge,
1731 computation_charge_burned: change_epoch_v3.computation_charge_burned,
1732 storage_rebate: change_epoch_v3.storage_rebate,
1733 non_refundable_storage_fee: change_epoch_v3.non_refundable_storage_fee,
1734 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1735 epoch_start_timestamp_ms: change_epoch_v3.epoch_start_timestamp_ms,
1736 max_committee_members_count: protocol_config.max_committee_members_count(),
1737 eligible_active_validators: change_epoch_v3.eligible_active_validators,
1738 scores: vec![],
1741 adjust_rewards_by_score: false,
1742 };
1743 let advance_epoch_pt = construct_advance_epoch_pt_v3(builder, ¶ms)?;
1744 advance_epoch_impl(
1745 advance_epoch_pt,
1746 params,
1747 change_epoch_v3.system_packages,
1748 temporary_store,
1749 tx_ctx,
1750 move_vm,
1751 gas_charger,
1752 protocol_config,
1753 metrics,
1754 trace_builder_opt,
1755 )
1756 }
1757
1758 fn advance_epoch_v4(
1762 builder: ProgrammableTransactionBuilder,
1763 change_epoch_v4: ChangeEpochV4,
1764 temporary_store: &mut TemporaryStore<'_>,
1765 tx_ctx: Rc<RefCell<TxContext>>,
1766 move_vm: &Arc<MoveVM>,
1767 gas_charger: &mut GasCharger,
1768 protocol_config: &ProtocolConfig,
1769 metrics: Arc<LimitsMetrics>,
1770 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1771 ) -> Result<(), ExecutionError> {
1772 let params = AdvanceEpochParams {
1773 epoch: change_epoch_v4.epoch,
1774 next_protocol_version: change_epoch_v4.protocol_version.into(),
1775 validator_subsidy: protocol_config.validator_target_reward(),
1776 storage_charge: change_epoch_v4.storage_charge,
1777 computation_charge: change_epoch_v4.computation_charge,
1778 computation_charge_burned: change_epoch_v4.computation_charge_burned,
1779 storage_rebate: change_epoch_v4.storage_rebate,
1780 non_refundable_storage_fee: change_epoch_v4.non_refundable_storage_fee,
1781 reward_slashing_rate: protocol_config.reward_slashing_rate(),
1782 epoch_start_timestamp_ms: change_epoch_v4.epoch_start_timestamp_ms,
1783 max_committee_members_count: protocol_config.max_committee_members_count(),
1784 eligible_active_validators: change_epoch_v4.eligible_active_validators,
1785 scores: change_epoch_v4.scores,
1786 adjust_rewards_by_score: change_epoch_v4.adjust_rewards_by_score,
1787 };
1788 let advance_epoch_pt = construct_advance_epoch_pt_v4(builder, ¶ms)?;
1789 advance_epoch_impl(
1790 advance_epoch_pt,
1791 params,
1792 change_epoch_v4.system_packages,
1793 temporary_store,
1794 tx_ctx,
1795 move_vm,
1796 gas_charger,
1797 protocol_config,
1798 metrics,
1799 trace_builder_opt,
1800 )
1801 }
1802
1803 fn process_system_packages(
1804 system_packages: Vec<SystemPackage>,
1805 temporary_store: &mut TemporaryStore<'_>,
1806 tx_ctx: Rc<RefCell<TxContext>>,
1807 move_vm: &MoveVM,
1808 gas_charger: &mut GasCharger,
1809 protocol_config: &ProtocolConfig,
1810 metrics: Arc<LimitsMetrics>,
1811 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1812 ) {
1813 let binary_config = to_binary_config(protocol_config);
1814 for SystemPackage {
1815 version,
1816 modules,
1817 dependencies,
1818 } in system_packages.into_iter()
1819 {
1820 let deserialized_modules: Vec<_> = modules
1821 .iter()
1822 .map(|m| CompiledModule::deserialize_with_config(m, &binary_config).unwrap())
1823 .collect();
1824
1825 if version == OBJECT_START_VERSION {
1826 let package_id = deserialized_modules.first().unwrap().address();
1827 info!("adding new system package {package_id}");
1828
1829 let publish_pt = {
1830 let mut b = ProgrammableTransactionBuilder::new();
1831 b.command(Command::new_publish(modules, dependencies));
1832 b.finish()
1833 };
1834
1835 programmable_transactions::execution::execute::<execution_mode::System>(
1836 protocol_config,
1837 metrics.clone(),
1838 move_vm,
1839 temporary_store,
1840 tx_ctx.clone(),
1841 gas_charger,
1842 publish_pt,
1843 trace_builder_opt,
1844 )
1845 .expect("System Package Publish must succeed");
1846 } else {
1847 let mut new_package = Object::new_system_package(
1848 &deserialized_modules,
1849 version,
1850 dependencies,
1851 tx_ctx.borrow().digest(),
1852 );
1853
1854 info!(
1855 "upgraded system package {:?}",
1856 new_package.compute_object_reference()
1857 );
1858
1859 new_package
1862 .data
1863 .as_package_mut_opt()
1864 .unwrap()
1865 .decrement_version()
1866 .expect("package version should never underflow");
1867
1868 temporary_store.upgrade_system_package(new_package);
1870 }
1871 }
1872 }
1873
1874 fn setup_consensus_commit(
1880 consensus_commit_timestamp_ms: CheckpointTimestamp,
1881 temporary_store: &mut TemporaryStore<'_>,
1882 tx_ctx: Rc<RefCell<TxContext>>,
1883 move_vm: &Arc<MoveVM>,
1884 gas_charger: &mut GasCharger,
1885 protocol_config: &ProtocolConfig,
1886 metrics: Arc<LimitsMetrics>,
1887 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1888 ) -> Result<(), ExecutionError> {
1889 let pt = {
1890 let mut builder = ProgrammableTransactionBuilder::new();
1891 let res = builder.move_call(
1892 ObjectID::FRAMEWORK,
1893 Identifier::CLOCK_MODULE,
1894 CONSENSUS_COMMIT_PROLOGUE_FUNCTION_NAME,
1895 vec![],
1896 vec![
1897 CallArg::CLOCK_MUTABLE,
1898 CallArg::pure(&consensus_commit_timestamp_ms),
1899 ],
1900 );
1901 assert_invariant!(
1902 res.is_ok(),
1903 "Unable to generate consensus_commit_prologue transaction!"
1904 );
1905 builder.finish()
1906 };
1907 programmable_transactions::execution::execute::<execution_mode::System>(
1908 protocol_config,
1909 metrics,
1910 move_vm,
1911 temporary_store,
1912 tx_ctx,
1913 gas_charger,
1914 pt,
1915 trace_builder_opt,
1916 )
1917 }
1918
1919 fn setup_randomness_state_update(
1925 update: RandomnessStateUpdate,
1926 temporary_store: &mut TemporaryStore<'_>,
1927 tx_ctx: Rc<RefCell<TxContext>>,
1928 move_vm: &Arc<MoveVM>,
1929 gas_charger: &mut GasCharger,
1930 protocol_config: &ProtocolConfig,
1931 metrics: Arc<LimitsMetrics>,
1932 trace_builder_opt: &mut Option<MoveTraceBuilder>,
1933 ) -> Result<(), ExecutionError> {
1934 let pt = {
1935 let mut builder = ProgrammableTransactionBuilder::new();
1936 let res = builder.move_call(
1937 ObjectID::FRAMEWORK,
1938 Identifier::RANDOM_MODULE,
1939 RANDOMNESS_STATE_UPDATE_FUNCTION_NAME,
1940 vec![],
1941 vec![
1942 CallArg::Shared(SharedObjectRef::new(
1943 ObjectID::RANDOMNESS_STATE,
1944 update.randomness_obj_initial_shared_version,
1945 true,
1946 )),
1947 CallArg::pure(&update.randomness_round),
1948 CallArg::pure(&update.random_bytes),
1949 ],
1950 );
1951 assert_invariant!(
1952 res.is_ok(),
1953 "Unable to generate randomness_state_update transaction!"
1954 );
1955 builder.finish()
1956 };
1957 programmable_transactions::execution::execute::<execution_mode::System>(
1958 protocol_config,
1959 metrics,
1960 move_vm,
1961 temporary_store,
1962 tx_ctx,
1963 gas_charger,
1964 pt,
1965 trace_builder_opt,
1966 )
1967 }
1968
1969 fn setup_authenticator_move_call(
1976 authenticator: MoveAuthenticator,
1977 authenticator_function_ref: AuthenticatorFunctionRefV1,
1978 ) -> Result<ProgrammableTransaction, ExecutionError> {
1979 let mut builder = ProgrammableTransactionBuilder::new();
1980
1981 let mut args = vec![authenticator.object_to_authenticate().to_owned()];
1982 args.extend(authenticator.call_args().to_owned());
1983
1984 let res = builder.move_call(
1985 authenticator_function_ref.package,
1986 Identifier::new(authenticator_function_ref.module.clone()).expect(
1987 "`AuthenticatorFunctionRefV1::module` is expected to be a valid `Identifier`",
1988 ),
1989 Identifier::new(authenticator_function_ref.function).expect(
1990 "`AuthenticatorFunctionRefV1::function` is expected to be a valid `Identifier`",
1991 ),
1992 authenticator.type_arguments().clone(),
1993 args,
1994 );
1995
1996 assert_invariant!(
1997 res.is_ok(),
1998 "Unable to generate an account authenticator call transaction!"
1999 );
2000
2001 Ok(builder.finish())
2002 }
2003
2004 fn resolve_sponsor(
2005 gas_data: &GasData,
2006 transaction_signer: &IotaAddress,
2007 ) -> Option<IotaAddress> {
2008 let gas_owner = gas_data.owner;
2009 if &gas_owner == transaction_signer {
2010 None
2011 } else {
2012 Some(gas_owner)
2013 }
2014 }
2015}