Skip to main content

iota_core/
authority.rs

1// Copyright (c) 2021, Facebook, Inc. and its affiliates
2// Copyright (c) Mysten Labs, Inc.
3// Modifications Copyright (c) 2024 IOTA Stiftung
4// SPDX-License-Identifier: Apache-2.0
5
6use std::{
7    collections::{BTreeMap, HashMap, HashSet},
8    fs::File,
9    io::Write,
10    path::{Path, PathBuf},
11    pin::Pin,
12    sync::{Arc, atomic::Ordering},
13    time::{Duration, SystemTime, UNIX_EPOCH},
14    vec,
15};
16
17use arc_swap::{ArcSwap, Guard};
18use async_trait::async_trait;
19use authority_per_epoch_store::TxLockGuard;
20pub use authority_store::{AuthorityStore, ResolverWrapper, UpdateType};
21use fastcrypto::{
22    encoding::{Base58, Encoding},
23    hash::MultisetHash,
24};
25use iota_common::{debug_fatal, fatal};
26use iota_config::{
27    NodeConfig,
28    genesis::Genesis,
29    node::{AuthorityOverloadConfig, ExpensiveSafetyCheckConfig, StateDebugDumpConfig},
30};
31use iota_framework::{BuiltInFramework, SystemPackage as FrameworkSystemPackage};
32use iota_json_rpc_types::{
33    EventFilter, IotaEvent, IotaMoveValue, IotaObjectDataFilter, IotaTransactionBlockEffects,
34    IotaTransactionBlockEvents, TransactionFilter,
35};
36use iota_macros::{fail_point, fail_point_async, fail_point_if};
37use iota_metrics::{
38    TX_TYPE_SHARED_OBJ_TX, TX_TYPE_SINGLE_WRITER_TX, monitored_scope, spawn_monitored_task,
39};
40use iota_sdk_types::{
41    Address, CheckpointCommitment, CheckpointContents, CheckpointContentsDigest, CheckpointDigest,
42    CheckpointSummary, Digest, EndOfEpochTransactionKind, ExecutionStatus, GasCostSummary,
43    InputSharedObject, MoveAuthenticator, ObjectDigest, ObjectId, ObjectReference, Owner,
44    RandomnessRound, SenderSignedTransaction, StructTag, SystemPackage, Transaction,
45    TransactionDigest, TransactionEffects, TransactionEffectsDigest, TransactionEvents,
46    TransactionKind, TypeTag, Version, WriteKind,
47    crypto::{Intent, IntentScope},
48};
49use iota_storage::{
50    key_value_store::{
51        KVStoreTransactionData, TransactionKeyValueStore, TransactionKeyValueStoreTrait,
52    },
53    key_value_store_metrics::KeyValueStoreMetrics,
54};
55use iota_traffic_controller::{TrafficController, metrics::TrafficControllerMetrics};
56use iota_transaction_checks::VerifierLimitsSource;
57#[cfg(msim)]
58use iota_types::committee::CommitteeTrait;
59use iota_types::{
60    account_abstraction::authenticator_function::{
61        AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
62        MoveAuthenticatorForExecution, MoveAuthenticatorsForExecution,
63        authenticator_function_ref_v1_from_dynamic_field_object,
64        derive_authenticator_function_ref_v1_dynamic_field_id, extract_auth_fun_refs,
65    },
66    auth_context::AuthContextData,
67    base_types::{AuthorityName, ConciseableName, ObjectInfo, ObjectType, VersionNumber},
68    committee::{Committee, EpochId, ProtocolVersion},
69    crypto::{AggregateAuthorityPublicKey, AuthoritySignInfo, AuthoritySignature, Signer},
70    deny_list_v1::{check_coin_deny_list_v1, coin_types_for_denylist_check},
71    deny_rule_governance::DenyRuleConfig,
72    digests::ChainIdentifier,
73    dynamic_field::{DynamicFieldInfo, DynamicFieldName, visitor as DFV},
74    effects::{
75        SignedTransactionEffects, TransactionEffectsAPI, TransactionEffectsExt,
76        VerifiedSignedTransactionEffects,
77    },
78    error::{ExecutionError, ExecutionErrorKind, IotaError, IotaResult, UserInputError},
79    event::{EventID, SystemEpochInfoEvent},
80    executable_transaction::VerifiedExecutableTransaction,
81    execution_config_utils::to_binary_config,
82    fp_ensure,
83    gas::IotaGasStatus,
84    gas_coin::mock_simulation_gas_coin,
85    inner_temporary_store::{
86        InnerTemporaryStore, ObjectMap, PackageStoreWithFallback, TxCoins, WrittenObjects,
87    },
88    iota_sdk_types_conversions::type_tag_core_to_sdk,
89    iota_system_state::{
90        IotaSystemState, IotaSystemStateTrait,
91        epoch_start_iota_system_state::EpochStartSystemStateTrait, get_iota_system_state,
92    },
93    layout_resolver::{LayoutResolver, into_struct_layout},
94    message_envelope::Message,
95    messages_checkpoint::{
96        CertifiedCheckpointSummary, CheckpointContentsExt, CheckpointRequest, CheckpointResponse,
97        CheckpointSequenceNumber, CheckpointSummaryResponse, CheckpointTimestamp,
98        ECMHLiveObjectSetDigest, VerifiedCheckpoint,
99    },
100    messages_consensus::AuthorityCapabilitiesV1,
101    messages_grpc::{
102        HandleTransactionResponse, LayoutGenerationOption, ObjectInfoRequest,
103        ObjectInfoRequestKind, ObjectInfoResponse, TransactionInfoRequest, TransactionInfoResponse,
104        TransactionStatus,
105    },
106    metrics::{BytecodeVerifierMetrics, LimitsMetrics},
107    move_authenticator::MoveAuthenticatorExt,
108    object::{Object, ObjectRead, PastObjectRead, bounded_visitor::BoundedVisitor},
109    storage::{BackingPackageStore, BackingStore, ObjectKey, ObjectOrTombstone, ObjectStore},
110    supported_protocol_versions::{
111        ProtocolConfig, SupportedProtocolVersions, SupportedProtocolVersionsWithHashes,
112    },
113    traffic_control::{PolicyConfig, TrafficControlReconfigParams},
114    transaction::*,
115    transaction_executor::{SimulateTransactionResult, VmChecks},
116};
117use itertools::Itertools;
118use move_binary_format::{CompiledModule, binary_config::BinaryConfig};
119use move_core_types::{
120    account_address::AccountAddress, annotated_value::MoveStructLayout, language_storage::ModuleId,
121};
122use parking_lot::Mutex;
123use prometheus_filtered::{
124    Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, MetricLevel,
125    Registry, register_histogram_vec_with_registry, register_histogram_with_registry,
126    register_int_counter_vec_with_registry, register_int_counter_with_registry,
127    register_int_gauge_vec_with_registry, register_int_gauge_with_registry,
128};
129use serde::{Deserialize, Serialize, de::DeserializeOwned};
130use tap::TapFallible;
131use tokio::{
132    sync::{RwLock, mpsc, mpsc::unbounded_channel, oneshot},
133    task::JoinHandle,
134};
135use tracing::{debug, error, info, instrument, trace, warn};
136use typed_store::TypedStoreError;
137
138use self::{
139    authority_store::ExecutionLockWriteGuard, authority_store_pruner::AuthorityStorePruningMetrics,
140};
141#[cfg(msim)]
142pub use crate::checkpoints::checkpoint_executor::utils::{
143    CheckpointTimeoutConfig, init_checkpoint_timeout_config,
144};
145use crate::{
146    authority::{
147        authority_per_epoch_store::{AuthorityPerEpochStore, TxGuard},
148        authority_per_epoch_store_pruner::AuthorityPerEpochStorePruner,
149        authority_store::{ExecutionLockReadGuard, ObjectLockStatus},
150        authority_store_pruner::{
151            AuthorityStorePruner, EPOCH_DURATION_MS_FOR_TESTING, ObjectRetentionGuard,
152        },
153        epoch_start_configuration::{EpochStartConfigTrait, EpochStartConfiguration},
154        shared_object_version_manager::{AssignedVersions, Schedulable},
155    },
156    authority_client::NetworkAuthorityClient,
157    checkpoint_progress_tracker::CheckpointProgressTracker,
158    checkpoints::{CheckpointBuilderError, CheckpointBuilderResult, CheckpointStore},
159    congestion_tracker::CongestionTracker,
160    consensus_adapter::ConsensusAdapter,
161    epoch::committee_store::CommitteeStore,
162    epoch_end_db_snapshot::{EpochEndDbSnapshotHandle, HandOver},
163    execution_cache::{
164        CheckpointCache, ExecutionCacheCommit, ExecutionCacheReconfigAPI,
165        ExecutionCacheTraitPointers, ExecutionCacheWrite, ObjectCacheRead, StateSyncAPI,
166        TransactionCacheRead,
167    },
168    execution_driver::execution_process,
169    execution_scheduler::{ExecutionSchedulerAPI, ExecutionSchedulerWrapper},
170    global_state_hasher::{GlobalStateHashStore, GlobalStateHasher},
171    grpc_indexes::GrpcIndexesStore,
172    jsonrpc_index::{CoinInfo, IndexStore, ObjectIndexChanges},
173    metrics::{LatencyObserver, RateTracker},
174    module_cache_metrics::ResolverMetrics,
175    overload_monitor::{
176        AuthorityOverloadInfo, compute_graduated_load_shedding_percentage,
177        overload_monitor_accept_tx,
178    },
179    post_consensus_input_reader::{
180        AccountVerdict, InputResolution, ReceivingObjectsResolution, ValidationAtCommit,
181        ValidationInputsAtCommit,
182        reader::{CommitIndexedReader, DenyListAtCommit},
183    },
184    stake_aggregator::StakeAggregator,
185    subscription_handler::SubscriptionHandler,
186    transaction_input_loader::TransactionInputLoader,
187    transaction_outputs::TransactionOutputs,
188    validator_tx_finalizer::ValidatorTxFinalizer,
189    verify_indexes::verify_indexes,
190};
191
192#[cfg(test)]
193#[path = "unit_tests/authority_tests.rs"]
194pub mod authority_tests;
195
196#[cfg(test)]
197#[path = "unit_tests/transaction_tests.rs"]
198pub mod transaction_tests;
199
200#[cfg(test)]
201#[path = "unit_tests/batch_transaction_tests.rs"]
202mod batch_transaction_tests;
203
204#[cfg(test)]
205#[path = "unit_tests/move_integration_tests.rs"]
206pub mod move_integration_tests;
207
208#[cfg(test)]
209#[path = "unit_tests/gas_tests.rs"]
210mod gas_tests;
211
212#[cfg(test)]
213#[path = "unit_tests/batch_verification_tests.rs"]
214mod batch_verification_tests;
215
216#[cfg(test)]
217#[path = "unit_tests/coin_deny_list_tests.rs"]
218mod coin_deny_list_tests;
219
220#[cfg(test)]
221#[path = "unit_tests/pre_execution_failure_tests.rs"]
222mod pre_execution_failure_tests;
223
224#[cfg(test)]
225#[path = "unit_tests/cancelled_move_authenticator_tests.rs"]
226mod cancelled_move_authenticator_tests;
227
228#[cfg(test)]
229#[path = "unit_tests/auth_unit_test_utils.rs"]
230pub mod auth_unit_test_utils;
231
232#[cfg(any(test, feature = "test-utils"))]
233pub mod authority_test_utils;
234
235pub mod authority_per_epoch_store;
236pub mod authority_per_epoch_store_pruner;
237
238pub mod authority_store_pruner;
239pub mod authority_store_tables;
240pub mod authority_store_types;
241pub mod epoch_start_configuration;
242pub mod shared_object_congestion_tracker;
243pub mod shared_object_version_manager;
244pub mod suggested_gas_price_calculator;
245#[cfg(any(test, feature = "test-utils"))]
246pub mod test_authority_builder;
247pub mod transaction_deferral;
248
249pub(crate) mod authority_store;
250pub mod backpressure;
251pub(crate) mod dropped_tx_status_cache;
252
253/// Prometheus metrics which can be displayed in Grafana, queried and alerted on
254pub struct AuthorityMetrics {
255    tx_orders: IntCounter,
256    total_certs: IntCounter,
257    total_cert_attempts: IntCounter,
258    total_effects: IntCounter,
259    pub shared_obj_tx: IntCounter,
260    sponsored_tx: IntCounter,
261    tx_already_processed: IntCounter,
262    num_input_objs: Histogram,
263    num_shared_objects: Histogram,
264    batch_size: Histogram,
265
266    authority_state_handle_transaction_latency: Histogram,
267
268    execute_certificate_latency_single_writer: Histogram,
269    execute_certificate_latency_shared_object: Histogram,
270
271    internal_execution_latency: Histogram,
272    /// Number of times the validator refused to report effects (signed or
273    /// unsigned, labeled by RPC surface) because it had previously signed
274    /// different effects for the same transaction.
275    signed_effects_equivocation_prevented: IntCounterVec,
276    execution_load_input_objects_latency: Histogram,
277    prepare_certificate_latency: Histogram,
278    commit_certificate_latency: Histogram,
279    epoch_end_db_snapshot_handover_latency: Histogram,
280    epoch_end_db_snapshots_skipped: IntCounter,
281
282    pub(crate) transaction_manager_num_enqueued_certificates: IntCounterVec,
283    pub(crate) transaction_manager_num_missing_objects: IntGauge,
284    pub(crate) transaction_manager_num_pending_certificates: IntGauge,
285    pub(crate) transaction_manager_num_executing_certificates: IntGauge,
286    pub(crate) transaction_manager_num_ready: IntGauge,
287    pub(crate) transaction_manager_object_cache_size: IntGauge,
288    pub(crate) transaction_manager_object_cache_hits: IntCounter,
289    pub(crate) transaction_manager_object_cache_misses: IntCounter,
290    pub(crate) transaction_manager_object_cache_evictions: IntCounter,
291    pub(crate) transaction_manager_package_cache_size: IntGauge,
292    pub(crate) transaction_manager_package_cache_hits: IntCounter,
293    pub(crate) transaction_manager_package_cache_misses: IntCounter,
294    pub(crate) transaction_manager_package_cache_evictions: IntCounter,
295    pub(crate) transaction_manager_transaction_queue_age_s: Histogram,
296
297    pub(crate) execution_driver_executed_transactions: IntCounter,
298    pub(crate) execution_driver_dispatch_queue: IntGauge,
299    pub(crate) execution_queueing_delay_s: Histogram,
300    pub(crate) prepare_cert_gas_latency_ratio: Histogram,
301    pub(crate) execution_gas_latency_ratio: Histogram,
302
303    pub(crate) skipped_consensus_txns: IntCounter,
304    pub(crate) skipped_consensus_txns_cache_hit: IntCounter,
305
306    pub(crate) authority_overload_status: IntGauge,
307    /// Percentage of transactions shed due to consensus queue length.
308    pub(crate) consensus_queue_load_shedding_percentage: IntGauge,
309    /// This authority's locally computed load shedding percentage, taken as the
310    /// max of its latency/rate-based, transaction-manager-queue-based, and
311    /// writeback-cache-backpressure signals.
312    pub(crate) local_post_consensus_load_shedding_percentage: IntGauge,
313
314    pub(crate) transaction_overload_sources: IntCounterVec,
315
316    // Post processing metrics
317    post_processing_total_events_emitted: IntCounter,
318    post_processing_total_tx_indexed: IntCounter,
319    post_processing_total_tx_had_event_processed: IntCounter,
320    post_processing_total_failures: IntCounter,
321
322    // Consensus handler metrics
323    pub consensus_handler_processed: IntCounterVec,
324    pub consensus_handler_transaction_sizes: HistogramVec,
325    pub consensus_handler_num_low_scoring_authorities: IntGauge,
326    pub consensus_handler_scores: IntGaugeVec,
327    pub consensus_handler_deferred_transactions: IntCounter,
328    pub consensus_handler_congested_transactions: IntCounter,
329    pub consensus_handler_cancelled_transactions: IntCounter,
330    /// Number of user transactions dropped during a consensus commit because
331    /// post-consensus conflict/lock validation rejected them. Distinct from
332    /// `consensus_handler_load_shedding_dropped_transactions`.
333    pub consensus_handler_validation_dropped_transactions: IntCounter,
334    /// Results of the commit-indexed reader in post-consensus validation, by
335    /// result (keep, drop or missing) and the reason that decided it. Only
336    /// with deterministic validation on.
337    pub consensus_handler_validation_reader_verdicts: IntCounterVec,
338    /// The commit being validated minus the highest fully executed commit, set
339    /// once per commit. Only with deterministic validation on.
340    pub consensus_handler_commit_execution_lag: IntGauge,
341    /// Number of user transactions dropped during a consensus commit by
342    /// post-consensus load shedding, i.e. probabilistically rejected at the
343    /// quorum `consensus_handler_load_shedding_percentage` rate.
344    pub consensus_handler_load_shedding_dropped_transactions: IntCounter,
345    /// Stake-weighted quorum (2f+1) load shedding percentage enforced on user
346    /// transactions in the most recent consensus commit. This is the cluster
347    /// value actually applied post-consensus, as opposed to this authority's
348    /// own `authority_load_shedding_percentage`. 0 when the P-COOL flow is
349    /// disabled.
350    pub consensus_handler_load_shedding_percentage: IntGauge,
351    pub consensus_handler_max_object_costs: IntGaugeVec,
352    pub consensus_committed_subdags: IntCounterVec,
353    pub consensus_committed_messages: IntGaugeVec,
354    pub consensus_committed_user_transactions: IntGaugeVec,
355    pub consensus_handler_leader_round: IntGauge,
356    pub consensus_calculated_throughput: IntGauge,
357    pub consensus_calculated_throughput_profile: IntGauge,
358
359    pub validator_scoreboard_scores: IntGaugeVec,
360    pub invalid_misbehavior_reports_by_authority: IntGaugeVec,
361
362    pub limits_metrics: Arc<LimitsMetrics>,
363
364    /// bytecode verifier metrics for tracking timeouts
365    pub bytecode_verifier_metrics: Arc<BytecodeVerifierMetrics>,
366
367    /// Count of multisig signatures
368    pub multisig_sig_count: IntCounter,
369
370    // Tracks recent average txn queueing delay between when it is ready for execution
371    // until it starts executing.
372    pub execution_queueing_latency: LatencyObserver,
373
374    // Tracks the rate at which transactions become ready for execution in the
375    // scheduler. The need for the Mutex is that the tracker is updated in the
376    // scheduler and read in the overload_monitor. There should be low mutex
377    // contention because the update side is effectively single threaded and the
378    // read rate in overload_monitor is low. If the update side becomes
379    // multi-threaded, we can create one rate tracker per thread.
380    pub txn_ready_rate_tracker: Arc<Mutex<RateTracker>>,
381
382    // Tracks the rate of transactions starts execution in execution driver.
383    // Similar reason for using a Mutex here as to `txn_ready_rate_tracker`.
384    pub execution_rate_tracker: Arc<Mutex<RateTracker>>,
385}
386
387// Override default Prom buckets for positive numbers in 0-10M range
388const POSITIVE_INT_BUCKETS: &[f64] = &[
389    1., 2., 5., 7., 10., 20., 50., 70., 100., 200., 500., 700., 1000., 2000., 5000., 7000., 10000.,
390    20000., 50000., 70000., 100000., 200000., 500000., 700000., 1000000., 2000000., 5000000.,
391    7000000., 10000000.,
392];
393
394const LATENCY_SEC_BUCKETS: &[f64] = &[
395    0.0005, 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1., 2., 3., 4., 5., 6., 7., 8., 9.,
396    10., 20., 30., 60., 90.,
397];
398
399// Buckets for low latency samples. Starts from 10us.
400const LOW_LATENCY_SEC_BUCKETS: &[f64] = &[
401    0.00001, 0.00002, 0.00005, 0.0001, 0.0002, 0.0005, 0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1,
402    0.2, 0.5, 1., 2., 5., 10., 20., 50., 100.,
403];
404
405const GAS_LATENCY_RATIO_BUCKETS: &[f64] = &[
406    10.0, 50.0, 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0, 2000.0,
407    3000.0, 4000.0, 5000.0, 6000.0, 7000.0, 8000.0, 9000.0, 10000.0, 50000.0, 100000.0, 1000000.0,
408];
409
410impl AuthorityMetrics {
411    pub fn new(registry: &prometheus_filtered::Registry) -> AuthorityMetrics {
412        let execute_certificate_latency = register_histogram_vec_with_registry!(
413            "authority_state_execute_certificate_latency",
414            "Latency of executing certificates, including waiting for inputs",
415            &["tx_type"],
416            LATENCY_SEC_BUCKETS.to_vec(),
417            registry;
418            MetricLevel::Info,
419        )
420        .unwrap();
421
422        let execute_certificate_latency_single_writer =
423            execute_certificate_latency.with_label_values(&[TX_TYPE_SINGLE_WRITER_TX]);
424        let execute_certificate_latency_shared_object =
425            execute_certificate_latency.with_label_values(&[TX_TYPE_SHARED_OBJ_TX]);
426
427        Self {
428            tx_orders: register_int_counter_with_registry!(
429                "total_transaction_orders",
430                "Total number of transaction orders",
431                registry;
432                MetricLevel::Warn,
433            )
434                .unwrap(),
435            total_certs: register_int_counter_with_registry!(
436                "total_transaction_certificates",
437                "Total number of transaction certificates handled",
438                registry;
439                MetricLevel::Warn,
440            )
441                .unwrap(),
442            total_cert_attempts: register_int_counter_with_registry!(
443                "total_handle_certificate_attempts",
444                "Number of calls to handle_certificate",
445                registry,
446            )
447                .unwrap(),
448            // total_effects == total transactions finished
449            total_effects: register_int_counter_with_registry!(
450                "total_transaction_effects",
451                "Total number of transaction effects produced",
452                registry;
453                MetricLevel::Warn,
454            )
455                .unwrap(),
456
457            shared_obj_tx: register_int_counter_with_registry!(
458                "num_shared_obj_tx",
459                "Number of transactions involving shared objects",
460                registry;
461                MetricLevel::Warn,
462            )
463                .unwrap(),
464
465            sponsored_tx: register_int_counter_with_registry!(
466                "num_sponsored_tx",
467                "Number of sponsored transactions",
468                registry,
469            )
470                .unwrap(),
471
472            tx_already_processed: register_int_counter_with_registry!(
473                "num_tx_already_processed",
474                "Number of transaction orders already processed previously",
475                registry,
476            )
477                .unwrap(),
478            num_input_objs: register_histogram_with_registry!(
479                "num_input_objects",
480                "Distribution of number of input TX objects per TX",
481                POSITIVE_INT_BUCKETS.to_vec(),
482                registry;
483                MetricLevel::Warn,
484            )
485                .unwrap(),
486            num_shared_objects: register_histogram_with_registry!(
487                "num_shared_objects",
488                "Number of shared input objects per TX",
489                POSITIVE_INT_BUCKETS.to_vec(),
490                registry,
491            )
492                .unwrap(),
493            batch_size: register_histogram_with_registry!(
494                "batch_size",
495                "Distribution of size of transaction batch",
496                POSITIVE_INT_BUCKETS.to_vec(),
497                registry,
498            )
499                .unwrap(),
500            authority_state_handle_transaction_latency: register_histogram_with_registry!(
501                "authority_state_handle_transaction_latency",
502                "Latency of handling transactions",
503                LATENCY_SEC_BUCKETS.to_vec(),
504                registry,
505            )
506                .unwrap(),
507            execute_certificate_latency_single_writer,
508            execute_certificate_latency_shared_object,
509            internal_execution_latency: register_histogram_with_registry!(
510                "authority_state_internal_execution_latency",
511                "Latency of actual certificate executions",
512                LATENCY_SEC_BUCKETS.to_vec(),
513                registry,
514            )
515                .unwrap(),
516            signed_effects_equivocation_prevented: register_int_counter_vec_with_registry!(
517                "authority_state_signed_effects_equivocation_prevented",
518                "Number of times the validator refused to report effects that differ from previously signed effects for the same transaction, by RPC surface",
519                &["surface"],
520                registry,
521            )
522            .unwrap(),
523            execution_load_input_objects_latency: register_histogram_with_registry!(
524                "authority_state_execution_load_input_objects_latency",
525                "Latency of loading input objects for execution",
526                LOW_LATENCY_SEC_BUCKETS.to_vec(),
527                registry,
528            )
529                .unwrap(),
530            prepare_certificate_latency: register_histogram_with_registry!(
531                "authority_state_prepare_certificate_latency",
532                "Latency of executing certificates, before committing the results",
533                LATENCY_SEC_BUCKETS.to_vec(),
534                registry,
535            )
536                .unwrap(),
537            commit_certificate_latency: register_histogram_with_registry!(
538                "authority_state_commit_certificate_latency",
539                "Latency of committing certificate execution results",
540                LATENCY_SEC_BUCKETS.to_vec(),
541                registry,
542            )
543                .unwrap(),
544            epoch_end_db_snapshot_handover_latency: register_histogram_with_registry!(
545                "epoch_end_db_snapshot_handover_latency",
546                "Time the epoch boundary waits for the consumer to take its database \
547                 snapshot of the perpetual store",
548                LATENCY_SEC_BUCKETS.to_vec(),
549                registry,
550            ).unwrap(),
551            epoch_end_db_snapshots_skipped: register_int_counter_with_registry!(
552                "epoch_end_db_snapshots_skipped",
553                "Epoch boundaries whose database snapshot was not taken, because the \
554                 consumer was busy or did not take it in time",
555                registry,
556            ).unwrap(),
557            transaction_manager_num_enqueued_certificates: register_int_counter_vec_with_registry!(
558                "transaction_manager_num_enqueued_certificates",
559                "Current number of certificates enqueued to TransactionManager",
560                &["result"],
561                registry,
562            )
563                .unwrap(),
564            transaction_manager_num_missing_objects: register_int_gauge_with_registry!(
565                "transaction_manager_num_missing_objects",
566                "Current number of missing objects in TransactionManager",
567                registry,
568            )
569                .unwrap(),
570            transaction_manager_num_pending_certificates: register_int_gauge_with_registry!(
571                "transaction_manager_num_pending_certificates",
572                "Number of certificates pending in TransactionManager, with at least 1 missing input object",
573                registry;
574                MetricLevel::Warn,
575            )
576                .unwrap(),
577            transaction_manager_num_executing_certificates: register_int_gauge_with_registry!(
578                "transaction_manager_num_executing_certificates",
579                "Number of executing certificates, including queued and actually running certificates",
580                registry;
581                MetricLevel::Warn,
582            )
583                .unwrap(),
584            transaction_manager_num_ready: register_int_gauge_with_registry!(
585                "transaction_manager_num_ready",
586                "Number of ready transactions in TransactionManager",
587                registry,
588            )
589                .unwrap(),
590            transaction_manager_object_cache_size: register_int_gauge_with_registry!(
591                "transaction_manager_object_cache_size",
592                "Current size of object-availability cache in TransactionManager",
593                registry,
594            )
595                .unwrap(),
596            transaction_manager_object_cache_hits: register_int_counter_with_registry!(
597                "transaction_manager_object_cache_hits",
598                "Number of object-availability cache hits in TransactionManager",
599                registry,
600            )
601                .unwrap(),
602            authority_overload_status: register_int_gauge_with_registry!(
603                "authority_overload_status",
604                "Whether authority is current experiencing overload and enters load shedding mode.",
605                registry;
606                MetricLevel::Warn,)
607                .unwrap(),
608            local_post_consensus_load_shedding_percentage: register_int_gauge_with_registry!(
609                "authority_load_shedding_percentage",
610                "This authority's locally computed load shedding percentage. In the P-COOL flow this is the value broadcast to peers, not necessarily the rate enforced (see consensus_handler_load_shedding_percentage).",
611                registry;
612                MetricLevel::Info,)
613                .unwrap(),
614            consensus_queue_load_shedding_percentage: register_int_gauge_with_registry!(
615                "consensus_queue_load_shedding_percentage",
616                "Percentage of transactions shed due to consensus queue length. Separate admission-control signal, not an input to authority_load_shedding_percentage.",
617                registry)
618                .unwrap(),
619            transaction_manager_object_cache_misses: register_int_counter_with_registry!(
620                "transaction_manager_object_cache_misses",
621                "Number of object-availability cache misses in TransactionManager",
622                registry,
623            )
624                .unwrap(),
625            transaction_manager_object_cache_evictions: register_int_counter_with_registry!(
626                "transaction_manager_object_cache_evictions",
627                "Number of object-availability cache evictions in TransactionManager",
628                registry,
629            )
630                .unwrap(),
631            transaction_manager_package_cache_size: register_int_gauge_with_registry!(
632                "transaction_manager_package_cache_size",
633                "Current size of package-availability cache in TransactionManager",
634                registry,
635            )
636                .unwrap(),
637            transaction_manager_package_cache_hits: register_int_counter_with_registry!(
638                "transaction_manager_package_cache_hits",
639                "Number of package-availability cache hits in TransactionManager",
640                registry,
641            )
642                .unwrap(),
643            transaction_manager_package_cache_misses: register_int_counter_with_registry!(
644                "transaction_manager_package_cache_misses",
645                "Number of package-availability cache misses in TransactionManager",
646                registry,
647            )
648                .unwrap(),
649            transaction_manager_package_cache_evictions: register_int_counter_with_registry!(
650                "transaction_manager_package_cache_evictions",
651                "Number of package-availability cache evictions in TransactionManager",
652                registry,
653            )
654                .unwrap(),
655            transaction_manager_transaction_queue_age_s: register_histogram_with_registry!(
656                "transaction_manager_transaction_queue_age_s",
657                "Time spent in waiting for transaction in the queue",
658                LATENCY_SEC_BUCKETS.to_vec(),
659                registry;
660                MetricLevel::Warn,
661            )
662                .unwrap(),
663            transaction_overload_sources: register_int_counter_vec_with_registry!(
664                "transaction_overload_sources",
665                "Number of times each source indicates transaction overload.",
666                &["source"],
667                registry)
668                .unwrap(),
669            execution_driver_executed_transactions: register_int_counter_with_registry!(
670                "execution_driver_executed_transactions",
671                "Cumulative number of transaction executed by execution driver",
672                registry;
673                MetricLevel::Warn,
674            )
675                .unwrap(),
676            execution_driver_dispatch_queue: register_int_gauge_with_registry!(
677                "execution_driver_dispatch_queue",
678                "Number of transaction pending in execution driver dispatch queue",
679                registry,
680            )
681                .unwrap(),
682            execution_queueing_delay_s: register_histogram_with_registry!(
683                "execution_queueing_delay_s",
684                "Queueing delay between a transaction is ready for execution until it starts executing.",
685                LATENCY_SEC_BUCKETS.to_vec(),
686                registry
687            )
688                .unwrap(),
689            prepare_cert_gas_latency_ratio: register_histogram_with_registry!(
690                "prepare_cert_gas_latency_ratio",
691                "The ratio of computation gas divided by VM execution latency.",
692                GAS_LATENCY_RATIO_BUCKETS.to_vec(),
693                registry
694            )
695                .unwrap(),
696            execution_gas_latency_ratio: register_histogram_with_registry!(
697                "execution_gas_latency_ratio",
698                "The ratio of computation gas divided by certificate execution latency, include committing certificate.",
699                GAS_LATENCY_RATIO_BUCKETS.to_vec(),
700                registry
701            )
702                .unwrap(),
703            skipped_consensus_txns: register_int_counter_with_registry!(
704                "skipped_consensus_txns",
705                "Total number of consensus transactions skipped",
706                registry,
707            )
708                .unwrap(),
709            skipped_consensus_txns_cache_hit: register_int_counter_with_registry!(
710                "skipped_consensus_txns_cache_hit",
711                "Total number of consensus transactions skipped because of local cache hit",
712                registry,
713            )
714                .unwrap(),
715            post_processing_total_events_emitted: register_int_counter_with_registry!(
716                "post_processing_total_events_emitted",
717                "Total number of events emitted in post processing",
718                registry,
719            )
720                .unwrap(),
721            post_processing_total_tx_indexed: register_int_counter_with_registry!(
722                "post_processing_total_tx_indexed",
723                "Total number of txes indexed in post processing",
724                registry,
725            )
726                .unwrap(),
727            post_processing_total_tx_had_event_processed: register_int_counter_with_registry!(
728                "post_processing_total_tx_had_event_processed",
729                "Total number of txes finished event processing in post processing",
730                registry,
731            )
732                .unwrap(),
733            post_processing_total_failures: register_int_counter_with_registry!(
734                "post_processing_total_failures",
735                "Total number of failure in post processing",
736                registry,
737            )
738                .unwrap(),
739            consensus_handler_processed: register_int_counter_vec_with_registry!(
740                "consensus_handler_processed",
741                "Number of transactions processed by consensus handler",
742                &["class"],
743                registry
744            ).unwrap(),
745            consensus_handler_transaction_sizes: register_histogram_vec_with_registry!(
746                "consensus_handler_transaction_sizes",
747                "Sizes of each type of transactions processed by consensus handler",
748                &["class"],
749                POSITIVE_INT_BUCKETS.to_vec(),
750                registry;
751                MetricLevel::Warn,
752            ).unwrap(),
753            consensus_handler_num_low_scoring_authorities: register_int_gauge_with_registry!(
754                "consensus_handler_num_low_scoring_authorities",
755                "Number of low scoring authorities based on reputation scores from consensus",
756                registry
757            ).unwrap(),
758            consensus_handler_scores: register_int_gauge_vec_with_registry!(
759                "consensus_handler_scores",
760                "scores from consensus for each authority",
761                &["authority"],
762                registry,
763            ).unwrap(),
764            validator_scoreboard_scores: register_int_gauge_vec_with_registry!(
765                "validator_scoreboard_scores",
766                "Per-authority validator scores published by the local Scoreboard after each consensus commit. Range [0, MAX_SCORE].",
767                &["authority"],
768                registry;
769                MetricLevel::Warn,
770            ).unwrap(),
771            invalid_misbehavior_reports_by_authority: register_int_gauge_vec_with_registry!(
772                "invalid_misbehavior_reports_by_authority",
773                "Cumulative count of invalid misbehavior reports received from each reporting authority in the current epoch. Bumped when a `MisbehaviorReport` consensus transaction fails sender/authority match or payload validation. Snapshot republished after each consensus commit.",
774                &["authority"],
775                registry;
776                MetricLevel::Warn,
777            ).unwrap(),
778            consensus_handler_deferred_transactions: register_int_counter_with_registry!(
779                "consensus_handler_deferred_transactions",
780                "Number of transactions deferred by consensus handler",
781                registry,
782            ).unwrap(),
783            consensus_handler_congested_transactions: register_int_counter_with_registry!(
784                "consensus_handler_congested_transactions",
785                "Number of transactions deferred by consensus handler due to congestion",
786                registry,
787            ).unwrap(),
788            consensus_handler_cancelled_transactions: register_int_counter_with_registry!(
789                "consensus_handler_cancelled_transactions",
790                "Number of transactions cancelled by consensus handler",
791                registry,
792            ).unwrap(),
793            consensus_handler_validation_dropped_transactions: register_int_counter_with_registry!(
794                "consensus_handler_validation_dropped_transactions",
795                "Number of UserTransactionV1 transactions dropped by post-consensus validation",
796                registry,
797            ).unwrap(),
798            consensus_handler_validation_reader_verdicts: register_int_counter_vec_with_registry!(
799                "consensus_handler_validation_reader_verdicts",
800                "Verdicts of the commit-indexed reader in post-consensus validation, by verdict and deciding reason",
801                &["verdict", "reason"],
802                registry,
803            ).unwrap(),
804            consensus_handler_commit_execution_lag: register_int_gauge_with_registry!(
805                "consensus_handler_commit_execution_lag",
806                "The consensus commit being validated minus the highest fully executed commit",
807                registry,
808            ).unwrap(),
809            consensus_handler_load_shedding_dropped_transactions: register_int_counter_with_registry!(
810                "consensus_handler_load_shedding_dropped_transactions",
811                "Number of user transactions dropped by post-consensus load shedding, based on the quorum load shedding percentage",
812                registry,
813            ).unwrap(),
814            consensus_handler_load_shedding_percentage: register_int_gauge_with_registry!(
815                "consensus_handler_load_shedding_percentage",
816                "Stake-weighted quorum (2f+1) load shedding percentage enforced on user transactions in the most recent consensus commit. 0 when the P-COOL flow is disabled.",
817                registry,
818            ).unwrap(),
819            consensus_handler_max_object_costs: register_int_gauge_vec_with_registry!(
820                "consensus_handler_max_congestion_control_object_costs",
821                "Max object costs for congestion control in the current consensus commit",
822                &["commit_type"],
823                registry,
824            ).unwrap(),
825            consensus_committed_subdags: register_int_counter_vec_with_registry!(
826                "consensus_committed_subdags",
827                "Number of committed subdags, sliced by leader",
828                &["authority"],
829                registry,
830            ).unwrap(),
831            consensus_committed_messages: register_int_gauge_vec_with_registry!(
832                "consensus_committed_messages",
833                "Total number of committed consensus messages, sliced by author",
834                &["authority"],
835                registry;
836                MetricLevel::Warn,
837            ).unwrap(),
838            consensus_committed_user_transactions: register_int_gauge_vec_with_registry!(
839                "consensus_committed_user_transactions",
840                "Number of committed user transactions, sliced by submitter",
841                &["authority"],
842                registry,
843            ).unwrap(),
844            consensus_handler_leader_round: register_int_gauge_with_registry!(
845                "consensus_handler_leader_round",
846                "The leader round of the current consensus output being processed in the consensus handler",
847                registry;
848                MetricLevel::Warn,
849            ).unwrap(),
850            limits_metrics: Arc::new(LimitsMetrics::new(registry)),
851            bytecode_verifier_metrics: Arc::new(BytecodeVerifierMetrics::new(registry)),
852            multisig_sig_count: register_int_counter_with_registry!(
853                "multisig_sig_count",
854                "Count of multisig signatures",
855                registry,
856            )
857                .unwrap(),
858            consensus_calculated_throughput: register_int_gauge_with_registry!(
859                "consensus_calculated_throughput",
860                "The calculated throughput from consensus output. Result is calculated based on unique transactions.",
861                registry,
862            ).unwrap(),
863            consensus_calculated_throughput_profile: register_int_gauge_with_registry!(
864                "consensus_calculated_throughput_profile",
865                "The current active calculated throughput profile",
866                registry
867            ).unwrap(),
868            execution_queueing_latency: LatencyObserver::new(),
869            txn_ready_rate_tracker: Arc::new(Mutex::new(RateTracker::new(Duration::from_secs(10)))),
870            execution_rate_tracker: Arc::new(Mutex::new(RateTracker::new(Duration::from_secs(10)))),
871        }
872    }
873
874    /// Reset metrics that contain `hostname` as one of the labels. This is
875    /// needed to avoid retaining metrics for long-gone committee members and
876    /// only exposing metrics for the committee in the current epoch.
877    pub fn reset_on_reconfigure(&self) {
878        self.consensus_committed_messages.reset();
879        self.consensus_handler_scores.reset();
880        self.validator_scoreboard_scores.reset();
881        self.invalid_misbehavior_reports_by_authority.reset();
882        self.consensus_committed_user_transactions.reset();
883    }
884}
885
886/// a Trait object for `Signer` that is:
887/// - Pin, i.e. confined to one place in memory (we don't want to copy private keys).
888/// - Sync, i.e. can be safely shared between threads.
889///
890/// Typically instantiated with Box::pin(keypair) where keypair is a `KeyPair`
891pub type StableSyncAuthoritySigner = Pin<Arc<dyn Signer<AuthoritySignature> + Send + Sync>>;
892
893/// The checked transaction inputs and, per Move authenticator, its checked inputs.
894type CheckedValidationInputs = (CheckedInputObjects, Vec<CheckedInputObjects>);
895
896/// Execution env contains the "environment" for the transaction to be executed
897/// in, that is, all the information necessary for execution that is not
898/// specified by the transaction itself.
899#[derive(Debug, Clone, Default)]
900pub struct ExecutionEnv {
901    /// The assigned version of each shared object for the transaction.
902    pub assigned_versions: AssignedVersions,
903    /// The expected digest of the effects of the transaction, if executing from
904    /// checkpoint or other sources where the effects are known in advance.
905    pub expected_effects_digest: Option<TransactionEffectsDigest>,
906}
907
908impl ExecutionEnv {
909    pub fn new() -> Self {
910        Default::default()
911    }
912
913    pub fn with_expected_effects_digest(
914        mut self,
915        expected_effects_digest: TransactionEffectsDigest,
916    ) -> Self {
917        self.expected_effects_digest = Some(expected_effects_digest);
918        self
919    }
920
921    pub fn with_assigned_versions(mut self, assigned_versions: AssignedVersions) -> Self {
922        if !assigned_versions.is_empty() {
923            self.assigned_versions = assigned_versions;
924        }
925        self
926    }
927}
928
929pub struct AuthorityState {
930    // Fixed size, static, identity of the authority
931    /// The name of this authority.
932    pub name: AuthorityName,
933    /// The signature key of the authority.
934    pub secret: StableSyncAuthoritySigner,
935
936    /// The database
937    input_loader: TransactionInputLoader,
938    execution_cache_trait_pointers: ExecutionCacheTraitPointers,
939
940    epoch_store: ArcSwap<AuthorityPerEpochStore>,
941
942    /// This lock denotes current 'execution epoch'.
943    /// Execution acquires read lock, checks transaction epoch and holds it
944    /// until all writes are complete. Reconfiguration acquires write lock,
945    /// changes the epoch and revert all transactions from previous epoch
946    /// that are executed but did not make into checkpoint.
947    execution_lock: RwLock<EpochId>,
948
949    pub indexes: Option<Arc<IndexStore>>,
950    pub grpc_indexes_store: Option<Arc<GrpcIndexesStore>>,
951
952    pub subscription_handler: Arc<SubscriptionHandler>,
953    pub checkpoint_store: Arc<CheckpointStore>,
954
955    committee_store: Arc<CommitteeStore>,
956
957    /// Schedules transaction execution.
958    execution_scheduler: Arc<ExecutionSchedulerWrapper>,
959
960    /// Shuts down the execution task. Used only in testing.
961    #[cfg_attr(not(test), expect(unused))]
962    tx_execution_shutdown: Mutex<Option<oneshot::Sender<()>>>,
963
964    pub metrics: Arc<AuthorityMetrics>,
965    /// The store pruner. The checkpoint executor uses it to nudge the pruner
966    /// after each checkpoint.
967    pruner: AuthorityStorePruner,
968    authority_per_epoch_pruner: AuthorityPerEpochStorePruner,
969    checkpoint_progress_tracker: Option<Arc<CheckpointProgressTracker>>,
970
971    pub config: NodeConfig,
972
973    /// Current overload status in this authority. Updated periodically.
974    pub overload_info: AuthorityOverloadInfo,
975
976    pub validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
977
978    /// The chain identifier is derived from the digest of the genesis
979    /// checkpoint.
980    chain_identifier: ChainIdentifier,
981
982    pub(crate) congestion_tracker: Arc<CongestionTracker>,
983
984    /// Traffic controller for IOTA core servers (json-rpc, validator service)
985    pub traffic_controller: Option<Arc<TrafficController>>,
986    /// Set when a consumer wants a database snapshot of the perpetual store at
987    /// each epoch boundary. See [`Self::hand_over_epoch_end_db_snapshot`].
988    epoch_end_db_snapshots: Option<EpochEndDbSnapshotHandle>,
989}
990
991/// The authority state encapsulates all state, drives execution, and ensures
992/// safety.
993///
994/// Note the authority operations can be accessed through a read ref (&) and do
995/// not require &mut. Internally a database is synchronized through a mutex
996/// lock.
997///
998/// Repeating valid commands should produce no changes and return no error.
999impl AuthorityState {
1000    pub fn is_committee_validator(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1001        epoch_store.committee().authority_exists(&self.name)
1002    }
1003
1004    pub fn is_active_validator(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1005        epoch_store
1006            .active_validators()
1007            .iter()
1008            .any(|a| AuthorityName::from(a) == self.name)
1009    }
1010
1011    pub fn is_fullnode(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1012        !self.is_committee_validator(epoch_store)
1013    }
1014
1015    pub fn committee_store(&self) -> &Arc<CommitteeStore> {
1016        &self.committee_store
1017    }
1018
1019    pub fn clone_committee_store(&self) -> Arc<CommitteeStore> {
1020        self.committee_store.clone()
1021    }
1022
1023    pub fn overload_config(&self) -> &AuthorityOverloadConfig {
1024        &self.config.authority_overload_config
1025    }
1026
1027    pub fn get_epoch_state_commitments(
1028        &self,
1029        epoch: EpochId,
1030    ) -> IotaResult<Option<Vec<CheckpointCommitment>>> {
1031        self.checkpoint_store.get_epoch_state_commitments(epoch)
1032    }
1033
1034    /// Runs deny list, input object validation, gas checks, coin deny list, and
1035    /// MoveAuthenticator checks. Returns the owned object refs for optional
1036    /// version validation. Does NOT acquire locks or sign the transaction.
1037    ///
1038    /// [`Self::handle_transaction_validation_checks_at_commit`] repeats the
1039    /// checks after loading the inputs for post-consensus validation at a
1040    /// commit, so a check added here belongs there too.
1041    ///
1042    /// `deny_config` is the deny rule source to enforce, chosen per caller:
1043    /// the local config alone, the local config combined with the governance
1044    /// rules (admission), or the governance-derived active set alone
1045    /// (post-consensus) — the latter two with `enable_pcool_flow`.
1046    ///
1047    /// `epoch_gated_coin_deny_list` selects how the coin deny list is read:
1048    /// `false` reads the latest value, so denials apply immediately - for
1049    /// validator-local admission (signing); `true` reads the value settled
1050    /// before the current epoch, which is deterministic across validators
1051    /// regardless of each validator's execution progress - required
1052    /// post-consensus, where the verdict decides whether the transaction
1053    /// stays in the committed set. The two read modes intentionally disagree
1054    /// about deny-list changes made in the current epoch, in both directions:
1055    /// - An entry added this epoch is enforced at admission right away, while the epoch-gated
1056    ///   layers enforce it only from the next epoch. Since execution and post-consensus must read
1057    ///   epoch-gated to stay deterministic, admission is the only layer that can react to a new
1058    ///   denial or global pause before the epoch boundary.
1059    /// - An entry removed this epoch is admitted right away but still denied by the epoch-gated
1060    ///   post-consensus read, so such transactions are sequenced by consensus and then
1061    ///   deterministically dropped (no execution, no gas charged) until the removal settles at the
1062    ///   next epoch boundary. The wasted consensus slot is accepted: post-consensus must handle
1063    ///   deterministic drops regardless (owned-object double-spend losers, for example), and
1064    ///   validators that skip admission can put such transactions into their blocks anyway, so no
1065    ///   admission policy can limit how many deterministically-dropped transactions reach
1066    ///   consensus.
1067    ///
1068    /// With `enable_pcool_flow`, post-consensus validation does
1069    /// not call this function: [`Self::handle_transaction_validation_checks_at_commit`]
1070    /// reads the deny list as of the commit's horizon, where a change made
1071    /// this epoch counts from the horizon distance after the commit that
1072    /// made it.
1073    ///
1074    /// `verifier_limits_source` says where the metered bytecode verifier takes
1075    /// its limits for the packages the transaction publishes. Validator-local
1076    /// admission passes this validator's own `VerifierSigningConfig`;
1077    /// post-consensus validation passes the protocol config, because every
1078    /// validator must reach the same verdict there.
1079    #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1080    pub(crate) async fn handle_transaction_validation_checks(
1081        &self,
1082        transaction: &VerifiedTransaction,
1083        epoch_store: &Arc<AuthorityPerEpochStore>,
1084        deny_config: &dyn DenyRuleConfig,
1085        epoch_gated_coin_deny_list: bool,
1086        verifier_limits_source: VerifierLimitsSource<'_>,
1087    ) -> IotaResult<Vec<ObjectReference>> {
1088        let protocol_config = epoch_store.protocol_config();
1089        let reference_gas_price = epoch_store.reference_gas_price();
1090
1091        let epoch = epoch_store.epoch();
1092
1093        let tx = transaction.data().transaction();
1094
1095        // Note: the deny checks may do redundant package loads but:
1096        // - they only load packages when there is an active package deny map
1097        // - the loads are cached anyway
1098        iota_transaction_checks::deny::check_transaction_for_validation(
1099            tx,
1100            transaction.signatures(),
1101            &transaction.input_objects()?,
1102            &tx.receiving_objects(),
1103            deny_config,
1104            self.get_backing_package_store().as_ref(),
1105        )?;
1106
1107        // Load all transaction-related input objects including ones for every
1108        // `MoveAuthenticator`. Loading all objects eagerly means that any invalid
1109        // reference — missing object, wrong version, inaccessible object — causes a
1110        // pre-consensus rejection.
1111        let (tx_input_objects, tx_receiving_objects, per_authenticator_inputs) =
1112            self.read_objects_for_validation(transaction, epoch)?;
1113
1114        let move_authenticators = transaction.move_authenticators();
1115
1116        // Check the inputs for signing.
1117        // If there are `MoveAuthenticator` signatures, their input objects and the
1118        // account objects are also checked and must be provided.
1119        // It is also checked if there is enough gas to execute the transaction and its
1120        // authenticators.
1121        let (gas_status, tx_checked_input_objects, per_authenticator_checked_inputs) = self
1122            .check_transaction_inputs_for_validation(
1123                protocol_config,
1124                reference_gas_price,
1125                tx,
1126                tx_input_objects,
1127                &tx_receiving_objects,
1128                &move_authenticators,
1129                per_authenticator_inputs,
1130                verifier_limits_source,
1131            )?;
1132
1133        // Get the input objects for the authenticators, if there are
1134        // `MoveAuthenticator`s.
1135        let per_authenticator_checked_input_objects: Vec<_> = per_authenticator_checked_inputs
1136            .iter()
1137            .map(|i| &i.0)
1138            .collect();
1139
1140        // Move authenticators cannot use owned objects, so their inputs never
1141        // acquire owned-object locks.
1142        debug_assert!(
1143            per_authenticator_checked_input_objects
1144                .iter()
1145                .all(|objects| objects.inner().filter_owned_objects().is_empty()),
1146            "Move authenticator input objects must not contain owned objects"
1147        );
1148
1149        // The package holding each authenticate function is known only now that the
1150        // `AuthenticatorFunctionRef`s are loaded, so the deny-list check for it
1151        // stands apart from the one above. It must stay ahead of two things: the
1152        // filtering below, which drops authenticators that do not run
1153        // pre-consensus, so that every authenticator is covered; and the
1154        // authenticator execution itself, so that a denied package is never run.
1155        if protocol_config.deny_authenticator_packages() {
1156            iota_transaction_checks::deny::check_authenticator_packages(
1157                deny_config,
1158                per_authenticator_checked_inputs
1159                    .iter()
1160                    .map(|(_, authenticator_function_ref)| authenticator_function_ref),
1161                self.get_backing_package_store().as_ref(),
1162            )?;
1163        }
1164
1165        // Check if any of the sender, the transaction input objects, the receiving
1166        // objects and the authenticator input objects are in the coin deny
1167        // list, which would prevent the transaction from being signed.
1168        check_coin_deny_list_v1(
1169            tx.sender(),
1170            &tx_checked_input_objects,
1171            &tx_receiving_objects,
1172            &per_authenticator_checked_input_objects,
1173            &self.get_object_store(),
1174            epoch_gated_coin_deny_list.then_some(epoch),
1175        )?;
1176
1177        let (kind, signer, gas_data) = tx.execution_parts();
1178
1179        let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) =
1180            extract_auth_fun_refs(signer, gas_data.owner, |address| {
1181                move_authenticators
1182                    .iter()
1183                    .zip(per_authenticator_checked_inputs.iter())
1184                    .find(|(move_authenticator, _)| move_authenticator.address() == address)
1185                    .map(|(_, (_, auth_fun_ref))| auth_fun_ref.clone())
1186            });
1187
1188        // Filter the authenticators and their checked inputs down to those that must
1189        // be executed pre-consensus. This is done *after* the deny-list check so
1190        // that all MoveAuthenticator input objects are covered by that check regardless
1191        // of deferral.
1192        let pre_consensus_move_authenticators =
1193            pre_consensus_move_authenticators(transaction, protocol_config);
1194        // Asserted before the zip below pairs them positionally; the two lists
1195        // come from independent computations.
1196        debug_assert_eq!(
1197            move_authenticators.len(),
1198            per_authenticator_checked_inputs.len(),
1199            "Move authenticators amount must match the number of checked authenticator inputs"
1200        );
1201        let (move_authenticators, per_authenticator_checked_inputs): (Vec<_>, Vec<_>) =
1202            move_authenticators
1203                .into_iter()
1204                .zip(per_authenticator_checked_inputs)
1205                .filter(|(a, _)| pre_consensus_move_authenticators.contains(a))
1206                .unzip();
1207        let per_authenticator_checked_input_objects: Vec<_> = per_authenticator_checked_inputs
1208            .iter()
1209            .map(|i| &i.0)
1210            .collect();
1211
1212        // If there are `MoveAuthenticator` signatures, execute them and check if they
1213        // all succeed.
1214        if !move_authenticators.is_empty() {
1215            let aggregated_authenticator_input_objects =
1216                iota_transaction_checks::aggregate_authenticator_input_objects(
1217                    &per_authenticator_checked_input_objects,
1218                )?;
1219
1220            let move_authenticators = move_authenticators
1221                .into_iter()
1222                .zip(per_authenticator_checked_inputs)
1223                .map(
1224                    |(
1225                        move_authenticator,
1226                        (authenticator_checked_input_objects, authenticator_function_ref),
1227                    )| {
1228                        (
1229                            move_authenticator.to_owned(),
1230                            authenticator_function_ref,
1231                            authenticator_checked_input_objects,
1232                        )
1233                    },
1234                )
1235                .collect();
1236
1237            // It is supposed that `MoveAuthenticator` availability is checked in
1238            // `SenderSignedTransaction::validity_check`.
1239
1240            // Serialize the Transaction for the auth context before decomposing.
1241            let tx_bytes = bcs::to_bytes(tx).expect("Transaction serialization cannot fail");
1242
1243            let (sender_auth_digest, sponsor_auth_digest) =
1244                transaction.data().compute_auth_digests()?;
1245
1246            let auth_context_data = AuthContextData {
1247                transaction_data_bytes: tx_bytes,
1248                sender_auth_digest,
1249                sponsor_auth_digest,
1250                sender_authenticator_function_ref,
1251                sponsor_authenticator_function_ref,
1252            };
1253
1254            // Execute the Move authenticators.
1255            let validation_result = epoch_store.executor().authenticate_transaction(
1256                self.get_backing_store().as_ref(),
1257                protocol_config,
1258                self.metrics.limits_metrics.clone(),
1259                &epoch_store.epoch_start_config().epoch_data().epoch_id(),
1260                epoch_store
1261                    .epoch_start_config()
1262                    .epoch_data()
1263                    .epoch_start_timestamp(),
1264                gas_data,
1265                gas_status,
1266                move_authenticators,
1267                aggregated_authenticator_input_objects,
1268                kind,
1269                signer,
1270                transaction.digest().to_owned(),
1271                auth_context_data,
1272                &mut None,
1273            );
1274
1275            if let Err(validation_error) = validation_result {
1276                return Err(IotaError::MoveAuthenticatorExecutionFailure {
1277                    error: validation_error.to_string(),
1278                });
1279            }
1280        }
1281
1282        Ok(tx_checked_input_objects.inner().filter_owned_objects())
1283    }
1284
1285    /// Like [`Self::handle_transaction_validation_checks`], but for
1286    /// post-consensus validation at the commit `reader` was built for: the
1287    /// inputs and receiving objects are read as of that commit through the
1288    /// commit-indexed reader. Returns `Drop` or `Missing` when one of them is
1289    /// dropped or not visible yet. Any other failed check returns the same
1290    /// `Err` as at admission, except that the coin deny list is read as of the
1291    /// reader's horizon, with changes counting from there rather than from the
1292    /// next epoch. The Move authenticator's account is not resolved and the
1293    /// authenticators are not run here: both happen at execution. Instead,
1294    /// each account must have had its authenticator function field at the
1295    /// horizon, or the transaction is reported missing. The package that
1296    /// field names, and its dependencies, read as of the horizon, are checked
1297    /// against the deny rules of the commit, and a denial is returned as
1298    /// [`ValidationAtCommit::AuthenticatorPackageDenied`], since it holds for
1299    /// every copy of the transaction. So an account whose function is changed
1300    /// to a denied package above the horizon is not caught here.
1301    #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1302    pub(crate) fn handle_transaction_validation_checks_at_commit(
1303        &self,
1304        reader: &CommitIndexedReader,
1305        transaction: &VerifiedTransaction,
1306        epoch_store: &Arc<AuthorityPerEpochStore>,
1307        deny_config: &dyn DenyRuleConfig,
1308        verifier_limits_source: VerifierLimitsSource<'_>,
1309    ) -> IotaResult<ValidationAtCommit> {
1310        let protocol_config = epoch_store.protocol_config();
1311        let reference_gas_price = epoch_store.reference_gas_price();
1312
1313        let tx = transaction.data().transaction();
1314
1315        let (tx_input_objects, tx_receiving_objects, per_authenticator_inputs) =
1316            match self.read_objects_for_validation_at_commit(reader, transaction)? {
1317                ValidationInputsAtCommit::Loaded {
1318                    tx_input_objects,
1319                    tx_receiving_objects,
1320                    per_authenticator_inputs,
1321                } => (
1322                    tx_input_objects,
1323                    tx_receiving_objects,
1324                    per_authenticator_inputs,
1325                ),
1326                ValidationInputsAtCommit::Drop(kind, reason) => {
1327                    return Ok(ValidationAtCommit::Drop(kind, reason));
1328                }
1329                ValidationInputsAtCommit::Missing(kind, reason) => {
1330                    return Ok(ValidationAtCommit::Missing(kind, reason));
1331                }
1332            };
1333
1334        // The deny rules load packages through the reader. They run after the
1335        // inputs are loaded, so a call into a package not visible at this
1336        // commit has already answered missing instead of failing here as not
1337        // found.
1338        iota_transaction_checks::deny::check_transaction_for_validation(
1339            tx,
1340            transaction.signatures(),
1341            &transaction.input_objects()?,
1342            &tx.receiving_objects(),
1343            deny_config,
1344            reader,
1345        )?;
1346
1347        let move_authenticators = transaction.move_authenticators();
1348
1349        // The account is not resolved and the authenticators are not run
1350        // here. Both read a shared object's contents, and a shared input names
1351        // no version, so this would read whatever version this validator
1352        // holds, which differs between validators. Execution reads every
1353        // shared input at the version consensus assigned, so both happen
1354        // there, and a failure there produces failure effects. What is left
1355        // here asks only what the rows can answer: whether each authenticator
1356        // input exists and is what the transaction declares, and whether each
1357        // account had its authenticator function field at the horizon. That
1358        // field also names the package checked against the deny rules below,
1359        // and an account without it is reported missing last.
1360        let (tx_checked_input_objects, per_authenticator_checked_inputs) = self
1361            .check_transaction_inputs_at_commit(
1362                protocol_config,
1363                reference_gas_price,
1364                tx,
1365                tx_input_objects,
1366                &tx_receiving_objects,
1367                &move_authenticators,
1368                per_authenticator_inputs,
1369                verifier_limits_source,
1370            )?;
1371
1372        let per_authenticator_checked_input_objects =
1373            per_authenticator_checked_inputs.iter().collect::<Vec<_>>();
1374
1375        debug_assert!(
1376            per_authenticator_checked_input_objects
1377                .iter()
1378                .all(|objects| objects.inner().filter_owned_objects().is_empty()),
1379            "Move authenticator input objects must not contain owned objects"
1380        );
1381
1382        // Each account's authenticator function field as of the horizon, read
1383        // once: the deny check below reads the package it names, and an
1384        // account without it is reported missing last.
1385        let accounts = move_authenticators
1386            .iter()
1387            .map(|move_authenticator| {
1388                let account_kind = move_authenticator
1389                    .object_to_authenticate()
1390                    .input_object_kind()
1391                    .expect("the object to authenticate is validated before consensus");
1392                Ok((account_kind, reader.read_account(account_kind.object_id())?))
1393            })
1394            .collect::<IotaResult<Vec<_>>>()?;
1395
1396        // The package holding each authenticate function, as at admission,
1397        // but named by the account's field as of the horizon, the same on
1398        // every validator.
1399        if protocol_config.deny_authenticator_packages() && deny_config.has_denied_packages() {
1400            let mut function_refs = Vec::new();
1401            for (account_kind, verdict) in &accounts {
1402                if let AccountVerdict::Account(field) = verdict {
1403                    function_refs.extend(
1404                        reader
1405                            .visible_authenticator_function_ref(account_kind.object_id(), field)?,
1406                    );
1407                }
1408            }
1409            if let Err(error) = iota_transaction_checks::deny::check_authenticator_packages(
1410                deny_config,
1411                &function_refs,
1412                reader,
1413            ) {
1414                if error.is_storage_or_epoch_error() {
1415                    return Err(error);
1416                }
1417                return Ok(ValidationAtCommit::AuthenticatorPackageDenied(error));
1418            }
1419        }
1420
1421        // The sender against the coin types of its inputs and receiving
1422        // objects, as at admission, but with the deny list as of the horizon,
1423        // the same on every validator. A kept receiving object was loaded at
1424        // the version the transaction names. A shared input's object is not
1425        // loaded, so its type is read on its own. Execution also checks the
1426        // coins Move code receives, and the coins it writes, against the deny
1427        // list as the epoch started.
1428        let mut shared_objects = Vec::new();
1429        for input in tx_checked_input_objects.inner().iter().chain(
1430            per_authenticator_checked_input_objects
1431                .iter()
1432                .flat_map(|objects| objects.inner().iter()),
1433        ) {
1434            if let (
1435                InputObjectKind::SharedMoveObject {
1436                    id,
1437                    initial_shared_version,
1438                    ..
1439                },
1440                None,
1441            ) = (input.input_object_kind, input.as_object())
1442            {
1443                shared_objects
1444                    .push(reader.read_shared_object_for_type(id, initial_shared_version)?);
1445            }
1446        }
1447        let coin_types = coin_types_for_denylist_check(
1448            tx_checked_input_objects
1449                .inner()
1450                .iter_objects()
1451                .chain(
1452                    per_authenticator_checked_input_objects
1453                        .iter()
1454                        .flat_map(|objects| objects.inner().iter_objects()),
1455                )
1456                .chain(&shared_objects)
1457                .chain(tx_receiving_objects.iter_objects()),
1458        );
1459        if let Some(denial) = DenyListAtCommit::new(reader).denial(tx.sender(), coin_types)? {
1460            return Err(denial.into());
1461        }
1462
1463        // Last, so a check that rejects the transaction outright is reported
1464        // rather than a missing verdict that invites a resubmission.
1465        for (account_kind, verdict) in accounts {
1466            if let AccountVerdict::Missing(reason) = verdict {
1467                return Ok(ValidationAtCommit::Missing(account_kind, reason));
1468            }
1469        }
1470
1471        Ok(ValidationAtCommit::Keep(
1472            tx_checked_input_objects.inner().filter_owned_objects(),
1473        ))
1474    }
1475
1476    /// This is a private method and should be kept that way. It doesn't check
1477    /// whether the provided transaction is a system transaction, and hence
1478    /// can only be called internally.
1479    async fn handle_transaction_impl(
1480        &self,
1481        transaction: VerifiedTransaction,
1482        epoch_store: &Arc<AuthorityPerEpochStore>,
1483    ) -> IotaResult<VerifiedSignedTransaction> {
1484        // Ensure that validator cannot reconfigure while we are signing the tx
1485        let _execution_lock = self.execution_lock_for_signing()?;
1486
1487        let owned_objects = self
1488            .handle_transaction_validation_checks(
1489                &transaction,
1490                epoch_store,
1491                &self.config.transaction_deny_config,
1492                // Latest-value coin deny-list read: admission is validator-local,
1493                // and denials should take effect immediately. Unlike the P-COOL
1494                // submission path, no post-consensus re-check follows - this is
1495                // the only sender-side coin deny check in the certificate flow.
1496                false,
1497                VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
1498            )
1499            .await?;
1500
1501        let epoch = epoch_store.epoch();
1502        let signed_transaction =
1503            VerifiedSignedTransaction::new(epoch, transaction, self.name, &*self.secret);
1504
1505        // Check and write locks, to signed transaction, into the database
1506        // The call to self.set_transaction_lock checks the lock is not conflicting,
1507        // and returns ConflictingTransaction error in case there is a lock on a
1508        // different existing transaction.
1509        self.get_cache_writer().try_acquire_transaction_locks(
1510            epoch_store,
1511            &owned_objects,
1512            signed_transaction.clone(),
1513        )?;
1514
1515        Ok(signed_transaction)
1516    }
1517
1518    /// Initiate a new transaction.
1519    #[instrument(name = "handle_transaction", level = "trace", skip_all, fields(tx_digest = ?transaction.digest(), sender = transaction.data().transaction().gas_owner().to_string()
1520    ))]
1521    pub async fn handle_transaction(
1522        &self,
1523        epoch_store: &Arc<AuthorityPerEpochStore>,
1524        transaction: VerifiedTransaction,
1525    ) -> IotaResult<HandleTransactionResponse> {
1526        let tx_digest = *transaction.digest();
1527        debug!("handle_transaction");
1528
1529        // Ensure an idempotent answer.
1530        if let Some((_, status)) = self.get_transaction_status(&tx_digest, epoch_store)? {
1531            return Ok(HandleTransactionResponse { status });
1532        }
1533
1534        let _metrics_guard = self
1535            .metrics
1536            .authority_state_handle_transaction_latency
1537            .start_timer();
1538        self.metrics.tx_orders.inc();
1539
1540        let signed = self.handle_transaction_impl(transaction, epoch_store).await;
1541        match signed {
1542            Ok(s) => {
1543                if self.is_committee_validator(epoch_store) {
1544                    if let Some(validator_tx_finalizer) = &self.validator_tx_finalizer {
1545                        let tx = s.clone();
1546                        let validator_tx_finalizer = validator_tx_finalizer.clone();
1547                        let cache_reader = self.get_transaction_cache_reader().clone();
1548                        let epoch_store = epoch_store.clone();
1549                        spawn_monitored_task!(epoch_store.within_alive_epoch(
1550                            validator_tx_finalizer.track_signed_tx(cache_reader, &epoch_store, tx)
1551                        ));
1552                    }
1553                }
1554                Ok(HandleTransactionResponse {
1555                    status: TransactionStatus::Signed(s.into_inner().into_sig()),
1556                })
1557            }
1558            // It happens frequently that while we are checking the validity of the transaction, it
1559            // has just been executed.
1560            // In that case, we could still return Ok to avoid showing confusing errors.
1561            Err(err) => Ok(HandleTransactionResponse {
1562                status: self
1563                    .get_transaction_status(&tx_digest, epoch_store)?
1564                    .ok_or(err)?
1565                    .1,
1566            }),
1567        }
1568    }
1569
1570    pub fn check_system_overload_at_signing(&self) -> bool {
1571        self.config
1572            .authority_overload_config
1573            .check_system_overload_at_signing
1574    }
1575
1576    pub fn check_system_overload_at_execution(&self) -> bool {
1577        self.config
1578            .authority_overload_config
1579            .check_system_overload_at_execution
1580    }
1581
1582    /// Checks system overload conditions before accepting a transaction.
1583    ///
1584    /// In certificate-less (P-COOL) mode: only checks consensus
1585    /// queue overload, since execution-based overload will be handled
1586    /// post-consensus.
1587    ///
1588    /// In certificate mode: runs all checks — authority overload
1589    /// (execution latency), the execution scheduler (execution queue),
1590    /// consensus adapter (queue limit), and writeback cache backpressure.
1591    pub(crate) fn check_system_overload(
1592        &self,
1593        consensus_adapter: &Arc<ConsensusAdapter>,
1594        tx: &SenderSignedTransaction,
1595        do_authority_overload_check: bool,
1596        pcool_flow_enabled: bool,
1597    ) -> IotaResult {
1598        if pcool_flow_enabled {
1599            // Graduated shedding: 0% to 100% as consensus queue fills from soft
1600            // to hard limit.
1601            self.check_consensus_queue_graduated_limits(consensus_adapter, tx)
1602                .tap_err(|_| {
1603                    self.update_overload_metrics("consensus");
1604                })?;
1605
1606            // NOTE: graduated shedding at 100% already rejects everything at or above
1607            // `max_pending_transactions`, so the queue-length part of the check below
1608            // is redundant but harmless. But `check_consensus_overload()` should be
1609            // kept here because it also verifies that `submit_semaphore` has permits
1610            // (see `check_consensus_hard_limits` in consensus_adapter.rs), which is a
1611            // separate concurrency limit not covered by the graduated shedding.
1612            consensus_adapter.check_consensus_overload().tap_err(|_| {
1613                self.update_overload_metrics("consensus");
1614            })?;
1615        } else {
1616            if do_authority_overload_check {
1617                self.check_authority_overload(tx).tap_err(|_| {
1618                    self.update_overload_metrics("execution_queue");
1619                })?;
1620            }
1621            self.execution_scheduler
1622                .check_execution_overload(self.overload_config(), tx)
1623                .tap_err(|_| {
1624                    self.update_overload_metrics("execution_pending");
1625                })?;
1626            consensus_adapter.check_consensus_overload().tap_err(|_| {
1627                self.update_overload_metrics("consensus");
1628            })?;
1629
1630            let pending_tx_count = self
1631                .get_cache_commit()
1632                .approximate_pending_transaction_count();
1633            if pending_tx_count
1634                > self
1635                    .config
1636                    .execution_cache_config
1637                    .writeback_cache
1638                    .backpressure_threshold_for_rpc()
1639            {
1640                return Err(IotaError::ValidatorOverloadedRetryAfter {
1641                    retry_after_secs: 10,
1642                });
1643            }
1644        }
1645
1646        Ok(())
1647    }
1648
1649    /// Rejects `tx_data` via graduated shedding based on consensus queue
1650    /// length. Scales from 0% at the soft limit to 100% at
1651    /// `max_pending_transactions`. Returns `ValidatorOverloadedRetryAfter`
1652    /// for probabilistic rejection (shedding percentage < 100%, via
1653    /// `overload_monitor_accept_tx`) or `TooManyTransactionsPendingConsensus`
1654    /// for unconditional rejection (shedding percentage >= 100%). Updates
1655    /// `consensus_queue_load_shedding_percentage` metric.
1656    fn check_consensus_queue_graduated_limits(
1657        &self,
1658        consensus_adapter: &Arc<ConsensusAdapter>,
1659        tx: &SenderSignedTransaction,
1660    ) -> IotaResult {
1661        let num_inflight_txs = consensus_adapter.num_inflight_transactions() as usize;
1662
1663        let shedding_pct = compute_graduated_load_shedding_percentage(
1664            num_inflight_txs,
1665            consensus_adapter.max_pending_transactions(),
1666            consensus_adapter.graduated_load_shedding_soft_limit_pct(),
1667        );
1668
1669        self.metrics
1670            .consensus_queue_load_shedding_percentage
1671            .set(shedding_pct as i64);
1672
1673        if shedding_pct == 0 {
1674            return Ok(());
1675        }
1676
1677        // At/above the hard limit, rejection is unconditional (not
1678        // probabilistic), so the seed-rotation retry hint of
1679        // `ValidatorOverloadedRetryAfter` doesn't apply - return the
1680        // capacity-bound error instead.
1681        if shedding_pct >= 100 {
1682            return Err(IotaError::TooManyTransactionsPendingConsensus);
1683        }
1684
1685        overload_monitor_accept_tx(shedding_pct, tx.digest())
1686    }
1687
1688    fn check_authority_overload(&self, tx: &SenderSignedTransaction) -> IotaResult {
1689        if !self.overload_info.is_overload.load(Ordering::Relaxed) {
1690            return Ok(());
1691        }
1692
1693        let load_shedding_percentage = self
1694            .overload_info
1695            .local_load_shedding_percentage
1696            .load(Ordering::Relaxed);
1697        overload_monitor_accept_tx(load_shedding_percentage, tx.digest())
1698    }
1699
1700    fn update_overload_metrics(&self, source: &str) {
1701        self.metrics
1702            .transaction_overload_sources
1703            .with_label_values(&[source])
1704            .inc();
1705    }
1706
1707    /// Wait for a certificate to be executed.
1708    /// For consensus transactions, it needs to be sequenced by the consensus.
1709    /// For owned object transactions, this function will enqueue the
1710    /// transaction for execution.
1711    #[instrument(level = "trace", skip_all)]
1712    pub async fn wait_for_certificate_execution(
1713        &self,
1714        certificate: &VerifiedCertificate,
1715        epoch_store: &Arc<AuthorityPerEpochStore>,
1716    ) -> IotaResult<TransactionEffects> {
1717        let _metrics_guard = if certificate.contains_shared_object() {
1718            self.metrics
1719                .execute_certificate_latency_shared_object
1720                .start_timer()
1721        } else {
1722            self.metrics
1723                .execute_certificate_latency_single_writer
1724                .start_timer()
1725        };
1726        trace!("wait_for_certificate_execution");
1727
1728        self.metrics.total_cert_attempts.inc();
1729
1730        if !certificate.contains_shared_object() {
1731            // Shared object transactions need to be sequenced by the consensus before
1732            // enqueueing for execution, done in
1733            // AuthorityPerEpochStore::handle_consensus_transaction(). For owned
1734            // object transactions, they can be enqueued for execution immediately.
1735            self.execution_scheduler.enqueue(
1736                vec![(
1737                    Schedulable::Transaction(VerifiedExecutableTransaction::new_from_certificate(
1738                        certificate.clone(),
1739                    )),
1740                    ExecutionEnv::new(),
1741                )],
1742                epoch_store,
1743            );
1744        }
1745
1746        // tx could be reverted when epoch ends, so we must be careful not to return a
1747        // result here after the epoch ends.
1748        epoch_store
1749            .within_alive_epoch(self.notify_read_effects(
1750                "AuthorityState::wait_for_certificate_execution",
1751                certificate,
1752            ))
1753            .await
1754            .and_then(|r| r)
1755    }
1756
1757    /// Internal logic to execute a transaction.
1758    ///
1759    /// Guarantees that
1760    /// - If input objects are available, return no permanent failure.
1761    /// - Execution and output commit are atomic. i.e. outputs are only written to storage,
1762    /// on successful execution; crashed execution has no observable effect and
1763    /// can be retried.
1764    ///
1765    /// It is caller's responsibility to ensure input objects are available and
1766    /// locks are set. If this cannot be satisfied by the caller,
1767    /// `wait_for_certificate_execution()` should be called instead.
1768    ///
1769    /// Should only be called within iota-core.
1770    #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1771    pub fn try_execute_immediately(
1772        &self,
1773        transaction: &VerifiedExecutableTransaction,
1774        execution_env: ExecutionEnv,
1775        epoch_store: &Arc<AuthorityPerEpochStore>,
1776    ) -> IotaResult<(TransactionEffects, Option<ExecutionError>)> {
1777        let _scope = monitored_scope("Execution::try_execute_immediately");
1778        let _metrics_guard = self.metrics.internal_execution_latency.start_timer();
1779
1780        let tx_digest = transaction.digest();
1781
1782        // Acquire a lock to prevent concurrent executions of the same transaction.
1783        let tx_guard = epoch_store.acquire_tx_guard(transaction)?;
1784
1785        // The transaction could have been processed by a concurrent attempt of the
1786        // same transaction, so check if the effects have already been written.
1787        if let Some(effects) = self
1788            .get_transaction_cache_reader()
1789            .try_get_executed_effects(tx_digest)?
1790        {
1791            if let Some(expected_effects_digest_inner) = execution_env.expected_effects_digest {
1792                assert_eq!(
1793                    effects.digest(),
1794                    expected_effects_digest_inner,
1795                    "Unexpected effects digest for transaction {tx_digest}"
1796                );
1797            }
1798            tx_guard.release();
1799            return Ok((effects, None));
1800        }
1801
1802        let (tx_input_objects, per_authenticator_inputs) = self.read_objects_for_execution(
1803            tx_guard.as_lock_guard(),
1804            transaction,
1805            execution_env.assigned_versions,
1806            epoch_store,
1807        )?;
1808
1809        self.process_transaction(
1810            tx_guard,
1811            transaction,
1812            tx_input_objects,
1813            per_authenticator_inputs,
1814            execution_env.expected_effects_digest,
1815            epoch_store,
1816        )
1817        .tap_err(|e| info!(?tx_digest, "process_transaction failed: {e}"))
1818        .tap_ok(
1819            |(fx, _)| debug!(?tx_digest, fx_digest=?fx.digest(), "process_transaction succeeded"),
1820        )
1821    }
1822
1823    pub fn read_objects_for_execution(
1824        &self,
1825        tx_lock: &TxLockGuard,
1826        transaction: &VerifiedExecutableTransaction,
1827        assigned_shared_object_versions: AssignedVersions,
1828        epoch_store: &Arc<AuthorityPerEpochStore>,
1829    ) -> IotaResult<(InputObjects, Vec<(InputObjects, ObjectReadResult)>)> {
1830        let _scope = monitored_scope("Execution::load_input_objects");
1831        let _metrics_guard = self
1832            .metrics
1833            .execution_load_input_objects_latency
1834            .start_timer();
1835
1836        let input_objects = transaction.collect_all_input_object_kind_for_reading()?;
1837
1838        let input_objects = self.input_loader.read_objects_for_execution(
1839            &transaction.key(),
1840            tx_lock,
1841            &input_objects,
1842            &assigned_shared_object_versions,
1843            epoch_store.epoch(),
1844        )?;
1845
1846        transaction.split_input_objects_into_groups_for_reading(input_objects)
1847    }
1848
1849    /// Test only wrapper for `try_execute_immediately()` above, useful for
1850    /// checking errors if the pre-conditions are not satisfied, and
1851    /// executing change epoch transactions. With the P-COOL flow, a committee
1852    /// validator executes only transactions of commits its consensus handler
1853    /// assigned, so a transaction the handler has not assigned is assigned to
1854    /// a new commit first.
1855    pub fn try_execute_for_test(
1856        &self,
1857        certificate: &VerifiedCertificate,
1858        execution_env: ExecutionEnv,
1859    ) -> IotaResult<(VerifiedSignedTransactionEffects, Option<ExecutionError>)> {
1860        let epoch_store = self.epoch_store_for_testing();
1861        epoch_store.assign_to_a_new_commit_for_testing(&[certificate.key()]);
1862        let (effects, execution_error_opt) = self.try_execute_immediately(
1863            &VerifiedExecutableTransaction::new_from_certificate(certificate.clone()),
1864            execution_env,
1865            &epoch_store,
1866        )?;
1867        let signed_effects = self.sign_effects(effects, &epoch_store)?;
1868        Ok((signed_effects, execution_error_opt))
1869    }
1870
1871    /// Non-fallible version of `try_execute_for_test()`.
1872    pub fn execute_for_test(
1873        &self,
1874        certificate: &VerifiedCertificate,
1875        execution_env: ExecutionEnv,
1876    ) -> (VerifiedSignedTransactionEffects, Option<ExecutionError>) {
1877        self.try_execute_for_test(certificate, execution_env)
1878            .expect("try_execute_for_test should not fail")
1879    }
1880
1881    pub async fn notify_read_effects(
1882        &self,
1883        task_name: &'static str,
1884        certificate: &VerifiedCertificate,
1885    ) -> IotaResult<TransactionEffects> {
1886        self.get_transaction_cache_reader()
1887            .try_notify_read_executed_effects(task_name, &[*certificate.digest()])
1888            .await
1889            .map(|mut r| r.pop().expect("must return correct number of effects"))
1890    }
1891
1892    fn check_owned_locks(&self, owned_object_refs: &[ObjectReference]) -> IotaResult {
1893        self.get_object_cache_reader()
1894            .try_check_owned_objects_are_live(owned_object_refs)
1895    }
1896
1897    /// This function captures the required state to debug a forked transaction.
1898    /// The dump is written to a file in dir `path`, with name prefixed by the
1899    /// transaction digest. NOTE: Since this info escapes the validator
1900    /// context, make sure not to leak any private info here
1901    pub(crate) fn debug_dump_transaction_state(
1902        &self,
1903        tx_digest: &TransactionDigest,
1904        effects: &TransactionEffects,
1905        expected_effects_digest: TransactionEffectsDigest,
1906        inner_temporary_store: &InnerTemporaryStore,
1907        transaction: &VerifiedExecutableTransaction,
1908        debug_dump_config: &StateDebugDumpConfig,
1909    ) -> IotaResult<PathBuf> {
1910        // Fall back to the OS temp directory if no dump directory is configured.
1911        // This is safe: dump files are named by transaction digest, so no collisions.
1912        let dump_dir = debug_dump_config
1913            .dump_file_directory
1914            .as_ref()
1915            .cloned()
1916            .unwrap_or(std::env::temp_dir());
1917        let epoch_store = self.load_epoch_store_one_call_per_task();
1918
1919        NodeStateDump::new(
1920            tx_digest,
1921            effects,
1922            expected_effects_digest,
1923            self.get_object_store().as_ref(),
1924            &epoch_store,
1925            inner_temporary_store,
1926            transaction,
1927        )?
1928        .write_to_file(&dump_dir)
1929        .map_err(|e| IotaError::FileIO(e.to_string()))
1930    }
1931
1932    #[instrument(name = "process_certificate", level = "trace", skip_all, fields(tx_digest = ?transaction.digest(), sender = ?transaction.data().transaction().gas_owner().to_string()))]
1933    pub(crate) fn process_transaction(
1934        &self,
1935        tx_guard: TxGuard,
1936        transaction: &VerifiedExecutableTransaction,
1937        tx_input_objects: InputObjects,
1938        per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
1939        expected_effects_digest: Option<TransactionEffectsDigest>,
1940        epoch_store: &Arc<AuthorityPerEpochStore>,
1941    ) -> IotaResult<(TransactionEffects, Option<ExecutionError>)> {
1942        let process_transaction_start_time = tokio::time::Instant::now();
1943        let digest = *transaction.digest();
1944
1945        let _scope = monitored_scope("Execution::process_certificate");
1946
1947        fail_point_if!("correlated-crash-process-transaction", || {
1948            if iota_simulator::random::deterministic_probability_once(digest, 0.01) {
1949                iota_simulator::task::kill_current_node(None);
1950            }
1951        });
1952
1953        let execution_guard = self.execution_lock_for_executable_transaction(transaction);
1954        // Any caller that verifies the signatures on the transaction will have already
1955        // checked the epoch. But paths that don't verify sigs (e.g. execution
1956        // from checkpoint, reading from db) present the possibility of an epoch
1957        // mismatch. If this transaction is not finalized in previous epoch, then it's
1958        // invalid.
1959        let execution_guard = match execution_guard {
1960            Ok(execution_guard) => execution_guard,
1961            Err(err) => {
1962                tx_guard.release();
1963                return Err(err);
1964            }
1965        };
1966        // Since we obtain a reference to the epoch store before taking the execution
1967        // lock, it's possible that reconfiguration has happened and they no
1968        // longer match.
1969        if *execution_guard != epoch_store.epoch() {
1970            tx_guard.release();
1971            info!("The epoch of the execution_guard doesn't match the epoch store");
1972            return Err(IotaError::WrongEpoch {
1973                expected_epoch: epoch_store.epoch(),
1974                actual_epoch: *execution_guard,
1975            });
1976        }
1977
1978        // Errors originating from `execute_transaction` may be transient (failure to
1979        // read locks) or non-transient (transaction input is invalid, move vm
1980        // errors). However, all errors from this function occur before we have
1981        // written anything to the db, so we commit the tx guard and rely on the
1982        // client to retry the tx (if it was transient).
1983        let (inner_temporary_store, effects, execution_error_opt) = match self.execute_transaction(
1984            &execution_guard,
1985            transaction,
1986            tx_input_objects,
1987            per_authenticator_inputs,
1988            epoch_store,
1989        ) {
1990            Err(e) => {
1991                info!(name = ?self.name, ?digest, "Error preparing transaction: {e}");
1992                tx_guard.release();
1993                return Err(e);
1994            }
1995            Ok(res) => res,
1996        };
1997
1998        if let Some(expected_effects_digest) = expected_effects_digest {
1999            if effects.digest() != expected_effects_digest {
2000                // We dont want to mask the original error, so we log it and continue.
2001                match self.debug_dump_transaction_state(
2002                    &digest,
2003                    &effects,
2004                    expected_effects_digest,
2005                    &inner_temporary_store,
2006                    transaction,
2007                    &self.config.state_debug_dump_config,
2008                ) {
2009                    Ok(out_path) => {
2010                        info!(
2011                            "Dumped node state for transaction {} to {}",
2012                            digest,
2013                            out_path.as_path().display().to_string()
2014                        );
2015                    }
2016                    Err(e) => {
2017                        error!("Error dumping state for transaction {}: {e}", digest);
2018                    }
2019                }
2020                error!(
2021                    tx_digest = ?digest,
2022                    ?expected_effects_digest,
2023                    actual_effects = ?effects,
2024                    "fork detected!"
2025                );
2026                panic!(
2027                    "Transaction {} is expected to have effects digest {}, but got {}!",
2028                    digest,
2029                    expected_effects_digest,
2030                    effects.digest(),
2031                );
2032            }
2033        }
2034
2035        fail_point!("crash");
2036
2037        self.commit_transaction(
2038            transaction,
2039            inner_temporary_store,
2040            &effects,
2041            tx_guard,
2042            execution_guard,
2043            expected_effects_digest,
2044            epoch_store,
2045        )?;
2046
2047        let elapsed = process_transaction_start_time.elapsed().as_micros() as f64;
2048        if elapsed > 0.0 {
2049            self.metrics
2050                .execution_gas_latency_ratio
2051                .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed);
2052        };
2053        Ok((effects, execution_error_opt))
2054    }
2055
2056    pub async fn reconfigure_traffic_control(
2057        &self,
2058        params: TrafficControlReconfigParams,
2059    ) -> Result<TrafficControlReconfigParams, IotaError> {
2060        if let Some(traffic_controller) = self.traffic_controller.as_ref() {
2061            traffic_controller.admin_reconfigure(params)
2062        } else {
2063            Err(IotaError::InvalidAdminRequest(
2064                "Traffic controller is not configured on this node".to_string(),
2065            ))
2066        }
2067    }
2068
2069    #[instrument(level = "trace", skip_all)]
2070    fn commit_transaction(
2071        &self,
2072        transaction: &VerifiedExecutableTransaction,
2073        inner_temporary_store: InnerTemporaryStore,
2074        effects: &TransactionEffects,
2075        tx_guard: TxGuard,
2076        _execution_guard: ExecutionLockReadGuard<'_>,
2077        expected_effects_digest: Option<TransactionEffectsDigest>,
2078        epoch_store: &Arc<AuthorityPerEpochStore>,
2079    ) -> IotaResult {
2080        let _scope: Option<iota_metrics::MonitoredScopeGuard> =
2081            monitored_scope("Execution::commit_certificate");
2082        let _metrics_guard = self.metrics.commit_certificate_latency.start_timer();
2083
2084        let tx_digest = transaction.digest();
2085        let input_object_count = inner_temporary_store.input_objects.len();
2086        let shared_object_count = effects.input_shared_objects().len();
2087
2088        let output_keys = inner_temporary_store.get_output_keys(effects);
2089
2090        // index transaction
2091        let _ = self
2092            .post_process_one_tx(transaction, effects, &inner_temporary_store, epoch_store)
2093            .tap_err(|e| {
2094                self.metrics.post_processing_total_failures.inc();
2095                error!(?tx_digest, "tx post processing failed: {e}");
2096            });
2097
2098        // The insertion to epoch_store is not atomic with the insertion to the
2099        // perpetual store. This is OK because we insert to the epoch store
2100        // first. And during lookups we always look up in the perpetual store first.
2101        epoch_store.insert_executed_in_epoch(tx_digest);
2102
2103        let key = transaction.key();
2104        if !matches!(key, TransactionKey::Digest(_)) {
2105            epoch_store.insert_tx_key(key, *tx_digest)?;
2106        }
2107
2108        // Genesis and the change-epoch transaction are roots of no consensus
2109        // commit, so the handler never assigns them one and recording them
2110        // would stop the node. Without rows, the reader takes what they wrote
2111        // as epoch-start state: genesis writes the first epoch's, the
2112        // change-epoch transaction the next epoch's. The migration transactions
2113        // executed at epoch 0 are genesis transactions too: node startup first
2114        // re-executes each one through `execute_genesis_transaction`, which
2115        // asserts its kind, to collect the genesis objects.
2116        if epoch_store.pcool_bookkeeping_enabled()
2117            && !transaction.transaction().is_genesis_tx()
2118            && !transaction.transaction().is_end_of_epoch_tx()
2119        {
2120            epoch_store.record_executed_transaction(&key, effects);
2121        }
2122
2123        // Allow testing what happens if we crash here.
2124        fail_point!("crash");
2125
2126        let transaction_outputs = TransactionOutputs::build_transaction_outputs(
2127            transaction.clone().into_unsigned(),
2128            effects.clone(),
2129            inner_temporary_store,
2130        );
2131        self.get_cache_writer()
2132            .try_write_transaction_outputs(epoch_store.epoch(), transaction_outputs.into())?;
2133
2134        self.report_failed_deny_rule_update_execution(
2135            transaction,
2136            effects,
2137            expected_effects_digest,
2138            epoch_store,
2139        );
2140
2141        if transaction.transaction().is_end_of_epoch_tx() {
2142            // At the end of epoch, since system packages may have been upgraded, force
2143            // reload them in the cache.
2144            self.get_object_cache_reader()
2145                .force_reload_system_packages(&BuiltInFramework::all_package_ids());
2146        }
2147
2148        // `commit_transaction()` finished, the tx is fully committed to the store.
2149        tx_guard.commit_tx();
2150
2151        match self.execution_scheduler.as_ref() {
2152            ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
2153            ExecutionSchedulerWrapper::TransactionManager(tm) => {
2154                // Notifies transaction manager about transaction and output objects committed.
2155                // This provides necessary information to transaction manager to start executing
2156                // additional ready transactions.
2157                tm.notify_commit(tx_digest, output_keys, epoch_store);
2158                // A transaction with a non-digest key can execute from a synced
2159                // checkpoint, in which case local randomness generation — the only
2160                // other caller of `notify_transaction_key` — never runs for that
2161                // round and would leave the env parked under its key forever. The
2162                // enqueue this triggers is filtered out as already executed.
2163                if let Some(key) = transaction.non_digest_key() {
2164                    tm.notify_transaction_key(epoch_store, key, *tx_digest);
2165                }
2166            }
2167        }
2168
2169        self.update_metrics(transaction, input_object_count, shared_object_count);
2170
2171        Ok(())
2172    }
2173
2174    fn update_metrics(
2175        &self,
2176        transaction: &VerifiedExecutableTransaction,
2177        input_object_count: usize,
2178        shared_object_count: usize,
2179    ) {
2180        // count signature by scheme, for multisig
2181        if transaction.has_multisig() {
2182            self.metrics.multisig_sig_count.inc();
2183        }
2184
2185        self.metrics.total_effects.inc();
2186        self.metrics.total_certs.inc();
2187
2188        if shared_object_count > 0 {
2189            self.metrics.shared_obj_tx.inc();
2190        }
2191
2192        if transaction.is_sponsored_tx() {
2193            self.metrics.sponsored_tx.inc();
2194        }
2195
2196        self.metrics
2197            .num_input_objs
2198            .observe(input_object_count as f64);
2199        self.metrics
2200            .num_shared_objects
2201            .observe(shared_object_count as f64);
2202        self.metrics
2203            .batch_size
2204            .observe(transaction.data().transaction().kind().num_commands() as f64);
2205    }
2206
2207    /// `execute_transaction()` validates the transaction input, and executes
2208    /// the transaction, returning effects, output objects, events, etc.
2209    ///
2210    /// It reads state from the db (both owned and shared locks), but it has no
2211    /// side effects.
2212    ///
2213    /// It can be generally understood that a failure of `execute_transaction`
2214    /// indicates a non-transient error, e.g. the transaction input is
2215    /// somehow invalid, the correct locks are not held, etc. However, this
2216    /// is not entirely true, as a transient db read error may also cause
2217    /// this function to fail.
2218    #[instrument(level = "trace", skip_all)]
2219    fn execute_transaction(
2220        &self,
2221        _execution_guard: &ExecutionLockReadGuard<'_>,
2222        transaction: &VerifiedExecutableTransaction,
2223        tx_input_objects: InputObjects,
2224        per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
2225        epoch_store: &Arc<AuthorityPerEpochStore>,
2226    ) -> IotaResult<(
2227        InnerTemporaryStore,
2228        TransactionEffects,
2229        Option<ExecutionError>,
2230    )> {
2231        let _scope = monitored_scope("Execution::execute_certificate");
2232        let _metrics_guard = self.metrics.prepare_certificate_latency.start_timer();
2233        let prepare_transaction_start_time = tokio::time::Instant::now();
2234
2235        let protocol_config = epoch_store.protocol_config();
2236
2237        let reference_gas_price = epoch_store.reference_gas_price();
2238
2239        let epoch_id = epoch_store.epoch_start_config().epoch_data().epoch_id();
2240        let epoch_start_timestamp = epoch_store
2241            .epoch_start_config()
2242            .epoch_data()
2243            .epoch_start_timestamp();
2244
2245        let backing_store = self.get_backing_store().as_ref();
2246
2247        let tx_digest = *transaction.digest();
2248
2249        // TODO: We need to move this to a more appropriate place to avoid redundant
2250        // checks.
2251        let tx = transaction.data().transaction();
2252        tx.validity_check(protocol_config)?;
2253
2254        let (kind, signer, gas_data) = tx.execution_parts();
2255
2256        let move_authenticators = transaction.move_authenticators();
2257
2258        #[cfg_attr(not(any(msim, fail_points)), expect(unused_mut))]
2259        let (inner_temp_store, _, mut effects, _, execution_error_opt) = if move_authenticators
2260            .is_empty()
2261        {
2262            // No Move authentication required, proceed to execute the transaction directly.
2263
2264            // The cost of partially re-auditing a transaction before execution is
2265            // tolerated.
2266            let (tx_gas_status, tx_checked_input_objects) =
2267                iota_transaction_checks::check_certificate_input(
2268                    transaction,
2269                    tx_input_objects,
2270                    protocol_config,
2271                    reference_gas_price,
2272                )?;
2273
2274            let owned_object_refs = tx_checked_input_objects.inner().filter_owned_objects();
2275            self.check_owned_locks(&owned_object_refs)?;
2276            epoch_store.executor().execute_transaction_to_effects(
2277                backing_store,
2278                protocol_config,
2279                self.metrics.limits_metrics.clone(),
2280                // TODO: would be nice to pass the whole NodeConfig here, but it creates a
2281                // cyclic dependency w/ iota-adapter
2282                self.config
2283                    .expensive_safety_check_config
2284                    .enable_deep_per_tx_iota_conservation_check(),
2285                self.config.certificate_deny_config.certificate_deny_set(),
2286                &epoch_id,
2287                epoch_start_timestamp,
2288                tx_checked_input_objects,
2289                gas_data,
2290                tx_gas_status,
2291                kind,
2292                signer,
2293                tx_digest,
2294                &mut None,
2295            )
2296        } else {
2297            // One or more `MoveAuthenticator` signatures present — authenticate each and
2298            // then execute the transaction.
2299            // It is supposed that `MoveAuthenticator` availability is checked in
2300            // `SenderSignedTransaction::validity_check`.
2301
2302            debug_assert_eq!(
2303                move_authenticators.len(),
2304                per_authenticator_inputs.len(),
2305                "Move authenticators amount must match the number of authenticator inputs"
2306            );
2307
2308            // The first account that cannot be resolved fails the transaction. The
2309            // remaining inputs are still collected, since the failure effects need
2310            // them whether or not anyone is charged gas.
2311            let mut per_authenticator_input_objects = Vec::with_capacity(move_authenticators.len());
2312            let mut resolutions = Vec::with_capacity(move_authenticators.len());
2313            for (move_authenticator, (authenticator_input_objects, account_object)) in
2314                move_authenticators.iter().zip(per_authenticator_inputs)
2315            {
2316                // The shape of the object to authenticate is decided by the
2317                // transaction bytes, and `validity_check` settles it in the
2318                // consensus handler, so it cannot be wrong here.
2319                let (account_object_id, account_object_version, account_object_digest) =
2320                    move_authenticator
2321                        .object_to_authenticate_components()
2322                        .expect(
2323                            "the object to authenticate is validated before consensus and cannot \
2324                                be invalid during execution",
2325                        );
2326
2327                // Unlike the shape above, resolving the account depends on state,
2328                // so post-consensus validation cannot keep this check. Here, an
2329                // account that fails it produces failure effects instead of a
2330                // panic.
2331                resolutions.push(self.check_move_account_for_execution(
2332                    account_object_id,
2333                    account_object_version,
2334                    account_object_digest,
2335                    account_object,
2336                    &move_authenticator.address(),
2337                    protocol_config,
2338                ));
2339
2340                per_authenticator_input_objects.push(authenticator_input_objects);
2341            }
2342
2343            // Serialize the Transaction for the auth context.
2344            let tx_bytes = bcs::to_bytes(tx).expect("Transaction serialization cannot fail");
2345
2346            let (sender_auth_digest, sponsor_auth_digest) =
2347                transaction.data().compute_auth_digests()?;
2348
2349            // Check the `MoveAuthenticator` input objects.
2350            // The `MoveAuthenticator` receiving objects are checked on the signing step.
2351            // `max_auth_gas` is used here as a Move authenticator gas budget until it is
2352            // not a part of the transaction data.
2353            let authenticator_gas_budget = protocol_config.max_auth_gas();
2354            let (
2355                gas_status,
2356                per_authenticator_checked_input_objects,
2357                authenticator_and_tx_checked_input_objects,
2358            ) = iota_transaction_checks::check_certificate_and_move_authenticator_input(
2359                transaction,
2360                tx_input_objects,
2361                per_authenticator_input_objects,
2362                authenticator_gas_budget,
2363                protocol_config,
2364                reference_gas_price,
2365            )?;
2366
2367            let owned_object_refs = authenticator_and_tx_checked_input_objects
2368                .inner()
2369                .filter_owned_objects();
2370            self.check_owned_locks(&owned_object_refs)?;
2371
2372            // The function refs of the accounts that resolved, so an
2373            // authenticator that runs after another account failed to resolve
2374            // still finds its own.
2375            let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) =
2376                extract_auth_fun_refs(signer, gas_data.owner, |address| {
2377                    move_authenticators
2378                        .iter()
2379                        .zip(&resolutions)
2380                        .find(|(move_authenticator, _)| move_authenticator.address() == address)
2381                        .and_then(|(_, resolution)| resolution.as_ref().ok())
2382                        .map(|function_ref| function_ref.authenticator_function_ref.clone())
2383                });
2384
2385            let accounts = move_authenticators
2386                .iter()
2387                .map(|move_authenticator| move_authenticator.address())
2388                .collect::<Vec<_>>();
2389            debug_assert_eq!(
2390                move_authenticators.len(),
2391                per_authenticator_checked_input_objects.len(),
2392                "Move authenticators amount must match the number of checked authenticator inputs"
2393            );
2394            // Under deterministic validation, a gas owner that cannot be resolved
2395            // did not authorize the transaction, so nobody pays; its own failure is
2396            // then the one reported.
2397            let deterministic_validation = protocol_config.enable_pcool_flow();
2398            let mut first_resolution_error = None;
2399            let mut gas_owner_resolution_error = None;
2400            let mut resolved_authenticators = Vec::with_capacity(move_authenticators.len());
2401            for ((move_authenticator, resolution), authenticator_checked_input_objects) in
2402                move_authenticators
2403                    .into_iter()
2404                    .zip(resolutions)
2405                    .zip(per_authenticator_checked_input_objects)
2406            {
2407                match resolution {
2408                    Ok(function_ref) => {
2409                        resolved_authenticators.push(MoveAuthenticatorForExecution {
2410                            authenticator: move_authenticator.to_owned(),
2411                            function_ref,
2412                            input_objects: authenticator_checked_input_objects,
2413                        })
2414                    }
2415                    Err(error)
2416                        if deterministic_validation
2417                            && move_authenticator.address() == gas_data.owner =>
2418                    {
2419                        gas_owner_resolution_error = Some(error);
2420                    }
2421                    Err(error) => {
2422                        first_resolution_error.get_or_insert(error);
2423                    }
2424                }
2425            }
2426
2427            let auth_context_data = AuthContextData {
2428                transaction_data_bytes: tx_bytes,
2429                sender_auth_digest,
2430                sponsor_auth_digest,
2431                sender_authenticator_function_ref,
2432                sponsor_authenticator_function_ref,
2433            };
2434
2435            // With a resolution failure, the executor gets the failure in place of
2436            // the list, with the accounts the authenticators would have
2437            // authenticated and, under deterministic validation, the gas owner's
2438            // authenticator if its account resolved, so it can decide who pays.
2439            let authenticators = match gas_owner_resolution_error.or(first_resolution_error) {
2440                Some(error) => MoveAuthenticatorsForExecution::ResolutionFailed {
2441                    error,
2442                    accounts,
2443                    gas_owner: if deterministic_validation {
2444                        resolved_authenticators
2445                            .into_iter()
2446                            .find(|resolved| resolved.authenticator.address() == gas_data.owner)
2447                            .map(Box::new)
2448                    } else {
2449                        None
2450                    },
2451                },
2452                None => MoveAuthenticatorsForExecution::Resolved(resolved_authenticators),
2453            };
2454
2455            epoch_store
2456                .executor()
2457                .authenticate_then_execute_transaction_to_effects(
2458                    backing_store,
2459                    protocol_config,
2460                    self.metrics.limits_metrics.clone(),
2461                    self.config
2462                        .expensive_safety_check_config
2463                        .enable_deep_per_tx_iota_conservation_check(),
2464                    self.config.certificate_deny_config.certificate_deny_set(),
2465                    &epoch_id,
2466                    epoch_start_timestamp,
2467                    gas_data,
2468                    gas_status,
2469                    authenticators,
2470                    authenticator_and_tx_checked_input_objects,
2471                    kind,
2472                    signer,
2473                    tx_digest,
2474                    auth_context_data,
2475                    &mut None,
2476                )
2477        };
2478
2479        fail_point_if!("cp_execution_nondeterminism", || {
2480            #[cfg(msim)]
2481            self.create_fail_state(transaction, epoch_store, &mut effects);
2482        });
2483
2484        let elapsed = prepare_transaction_start_time.elapsed().as_micros() as f64;
2485        if elapsed > 0.0 {
2486            self.metrics
2487                .prepare_cert_gas_latency_ratio
2488                .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed);
2489        }
2490
2491        Ok((inner_temp_store, effects, execution_error_opt.err()))
2492    }
2493
2494    pub fn prepare_transaction_for_benchmark(
2495        &self,
2496        transaction: &VerifiedExecutableTransaction,
2497        input_objects: InputObjects,
2498        epoch_store: &Arc<AuthorityPerEpochStore>,
2499    ) -> IotaResult<(
2500        InnerTemporaryStore,
2501        TransactionEffects,
2502        Option<ExecutionError>,
2503    )> {
2504        let lock = RwLock::new(epoch_store.epoch());
2505        let execution_guard = lock.try_read().unwrap();
2506
2507        self.execute_transaction(
2508            &execution_guard,
2509            transaction,
2510            input_objects,
2511            vec![],
2512            epoch_store,
2513        )
2514    }
2515
2516    /// Simulate a transaction without committing it.
2517    ///
2518    /// `checks` selects the Move VM semantics: `VmChecks::Enabled` runs the
2519    /// transaction as it would run on chain (a dry run), while
2520    /// `VmChecks::Disabled` relaxes the checks around entry functions and
2521    /// argument values (a dev inspect). Both report the per-command return
2522    /// values in [`SimulateTransactionResult::execution_result`].
2523    ///
2524    /// Under either `checks`, the simulation fills in whatever gas the
2525    /// transaction leaves unset, so that a caller with no gas to declare can
2526    /// leave all of it out: no gas payment mints a mock gas coin, whose ID is
2527    /// reported back in [`SimulateTransactionResult::mock_gas_id`]; a zero gas
2528    /// price becomes the epoch's reference gas price; and a zero gas budget
2529    /// becomes as much as the gas coins can back, up to
2530    /// [`max_tx_gas`](iota_protocol_config::ProtocolConfig::max_tx_gas).
2531    /// Anything the transaction does declare is metered as given, so a dry run
2532    /// still rejects the gas a validator would.
2533    ///
2534    /// Under either `checks`, the packages the transaction publishes are run
2535    /// through the bytecode verifier with this node's signing-time limits, so a
2536    /// package that signing would reject with
2537    /// [`UserInputError::PackageVerificationTimedout`] is rejected here too.
2538    ///
2539    /// Whatever the budget resolves to, the gas coins have to cover it, since
2540    /// execution reserves the whole budget from them before running any command
2541    /// and refunds it afterwards. A caller leaving the budget at zero to have
2542    /// the cost estimated therefore gets an estimate whatever its coins hold,
2543    /// but the reserved budget is off limits for the duration of the
2544    /// programmable transaction: a transaction that also pays out of its gas
2545    /// coin has to declare a budget leaving room for that, exactly as it would
2546    /// on chain. A balance too small to declare the minimum budget at all is
2547    /// rejected with [`UserInputError::GasBalanceTooLow`].
2548    pub fn simulate_transaction(
2549        &self,
2550        transaction: Transaction,
2551        checks: VmChecks,
2552    ) -> IotaResult<SimulateTransactionResult> {
2553        let epoch_store = self.load_epoch_store_one_call_per_task();
2554        self.simulate_transaction_in_epoch(&epoch_store, transaction, checks)
2555    }
2556
2557    /// Same as [`AuthorityState::simulate_transaction`], for callers that
2558    /// already hold an epoch store.
2559    ///
2560    /// Callers that derive gas parameters from an epoch, or resolve types
2561    /// against its executor once the simulation returns, should pass that same
2562    /// epoch store here so the whole operation observes one epoch.
2563    ///
2564    /// Nothing here checks that `epoch_store` is the current one — pinning a
2565    /// superseded epoch is the point, and is what
2566    /// [`AuthorityState::simulate_transaction`] does for the span of its own
2567    /// call. Keeping one across an unbounded period is the caller's problem:
2568    /// the simulation would run against that epoch's protocol config,
2569    /// executor, and reference gas price.
2570    #[instrument("simulate_tx", level = "trace", skip_all)]
2571    pub fn simulate_transaction_in_epoch(
2572        &self,
2573        epoch_store: &AuthorityPerEpochStore,
2574        transaction: Transaction,
2575        checks: VmChecks,
2576    ) -> IotaResult<SimulateTransactionResult> {
2577        if !self.is_fullnode(epoch_store) {
2578            return Err(IotaError::UnsupportedFeature {
2579                error: "simulate is only supported on fullnodes".to_string(),
2580            });
2581        }
2582
2583        self.simulate_transaction_inner(epoch_store, transaction, checks)
2584    }
2585
2586    /// Same as [`AuthorityState::simulate_transaction`], but runs on a
2587    /// validator too. Only the single-node benchmark, which has no fullnode
2588    /// to run against, needs this.
2589    pub fn simulate_transaction_for_benchmark(
2590        &self,
2591        transaction: Transaction,
2592        checks: VmChecks,
2593    ) -> IotaResult<SimulateTransactionResult> {
2594        let epoch_store = self.load_epoch_store_one_call_per_task();
2595        self.simulate_transaction_inner(&epoch_store, transaction, checks)
2596    }
2597
2598    #[instrument(level = "trace", skip_all)]
2599    fn simulate_transaction_inner(
2600        &self,
2601        epoch_store: &AuthorityPerEpochStore,
2602        mut transaction: Transaction,
2603        checks: VmChecks,
2604    ) -> IotaResult<SimulateTransactionResult> {
2605        if transaction.kind().is_system() {
2606            return Err(IotaError::UnsupportedFeature {
2607                error: "simulate does not support system transactions".to_string(),
2608            });
2609        }
2610
2611        transaction.check_serialized_size(epoch_store.protocol_config())?;
2612
2613        // Cheap validity checks for a transaction, including input size limits.
2614        // This does not check if gas objects are missing since we may create a
2615        // mock gas object. It checks for other transaction input validity.
2616        transaction.validity_check_no_gas_check(epoch_store.protocol_config())?;
2617
2618        // The full validity check caps the gas payment size alongside requiring a
2619        // gas payment at all, which a simulation relaxes so it can mock one. The cap
2620        // still applies, and is cheapest before any object is loaded.
2621        transaction.check_gas_payment_size(epoch_store.protocol_config())?;
2622
2623        let input_object_kinds = transaction.input_objects()?;
2624        let receiving_object_refs = transaction.receiving_objects();
2625
2626        // Since we need to simulate a validator signing the transaction, the first step
2627        // is to check if some transaction elements are denied.
2628        iota_transaction_checks::deny::check_transaction_for_validation(
2629            &transaction,
2630            &[],
2631            &input_object_kinds,
2632            &receiving_object_refs,
2633            &self.config.transaction_deny_config,
2634            self.get_backing_package_store().as_ref(),
2635        )?;
2636
2637        // Load input and receiving objects
2638        let (mut input_objects, receiving_objects) = self.input_loader.read_objects_for_signing(
2639            // We don't want to cache this transaction since it's a simulation.
2640            None,
2641            &input_object_kinds,
2642            &receiving_object_refs,
2643            epoch_store.epoch(),
2644        )?;
2645
2646        // Create a mock gas object if one was not provided
2647        let mock_gas_id = if transaction.gas().is_empty() {
2648            let mock_gas_object = mock_simulation_gas_coin(transaction.gas_data().owner);
2649            let mock_gas_object_ref = mock_gas_object.object_ref();
2650            transaction.gas_data_mut().objects = vec![mock_gas_object_ref];
2651            input_objects.push(ObjectReadResult::new_from_gas_object(&mock_gas_object));
2652            Some(mock_gas_object.id())
2653        } else {
2654            None
2655        };
2656
2657        let protocol_config = epoch_store.protocol_config();
2658
2659        iota_types::gas::fill_in_unset_simulation_gas(
2660            &mut transaction,
2661            &input_objects,
2662            epoch_store.reference_gas_price(),
2663            protocol_config,
2664        );
2665
2666        // `MoveAuthenticator`s are not supported in simulation, so we set the
2667        // `authenticator_gas_budget` to 0.
2668        let authenticator_gas_budget = 0;
2669
2670        // Checks enabled -> DRY-RUN, it means we are simulating a real TX
2671        // Checks disabled -> DEV-INSPECT, more relaxed Move VM checks
2672        let (gas_status, checked_input_objects) = if checks.enabled() {
2673            iota_transaction_checks::check_transaction_input(
2674                protocol_config,
2675                epoch_store.reference_gas_price(),
2676                &transaction,
2677                input_objects,
2678                &receiving_objects,
2679                &self.metrics.bytecode_verifier_metrics,
2680                VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2681                authenticator_gas_budget,
2682            )?
2683        } else {
2684            // Execution smashes the gas coins and reserves the whole budget from them
2685            // before running any command, treating the input checks as having verified
2686            // that they are gas coins at all — so with those checks skipped here, this
2687            // has to stand in for them. With the checks enabled,
2688            // `check_transaction_input` covers it.
2689            iota_types::gas::check_gas_coins_cover_budget_in_simulation(
2690                &input_objects,
2691                transaction.gas(),
2692                transaction.gas_budget(),
2693            )?;
2694
2695            let checked_input_objects = iota_transaction_checks::check_simulation_input(
2696                protocol_config,
2697                transaction.kind(),
2698                input_objects,
2699                receiving_objects,
2700            )?;
2701
2702            // Execution verifies the packages a transaction publishes with neither a
2703            // limit nor a meter, trusting signing to have bounded them — so with the
2704            // signing-time checks skipped here, this has to bound them. The node's
2705            // own limits reject nothing that signing would accept. With the checks
2706            // enabled, `check_transaction_input` covers it.
2707            iota_transaction_checks::check_non_system_packages_to_be_published(
2708                &transaction,
2709                protocol_config,
2710                &self.metrics.bytecode_verifier_metrics,
2711                VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2712            )?;
2713
2714            let gas_status = IotaGasStatus::new(
2715                transaction.gas_budget(),
2716                transaction.gas_price(),
2717                epoch_store.reference_gas_price(),
2718                protocol_config,
2719            )?;
2720
2721            (gas_status, checked_input_objects)
2722        };
2723
2724        // Create a new executor for the simulation
2725        let executor = iota_execution::executor(
2726            protocol_config,
2727            true, // silent
2728            None,
2729        )
2730        .expect("Creating an executor should not fail here");
2731
2732        // Execute the simulation
2733        let (kind, signer, gas_data) = transaction.execution_parts();
2734        let (inner_temp_store, _, effects, execution_result) = executor.dev_inspect_transaction(
2735            self.get_backing_store().as_ref(),
2736            protocol_config,
2737            self.metrics.limits_metrics.clone(),
2738            false, // expensive_checks
2739            self.config.certificate_deny_config.certificate_deny_set(),
2740            &epoch_store.epoch_start_config().epoch_data().epoch_id(),
2741            epoch_store
2742                .epoch_start_config()
2743                .epoch_data()
2744                .epoch_start_timestamp(),
2745            checked_input_objects,
2746            gas_data,
2747            gas_status,
2748            kind,
2749            signer,
2750            transaction.digest(),
2751            checks.disabled(),
2752        );
2753
2754        let mut input_objects = inner_temp_store.input_objects;
2755        iota_types::storage::extend_input_objects_with_loaded_runtime_objects(
2756            &mut input_objects,
2757            &effects,
2758            &inner_temp_store.loaded_runtime_objects,
2759            self.get_backing_store().as_object_store(),
2760        );
2761
2762        Ok(SimulateTransactionResult {
2763            input_objects,
2764            output_objects: inner_temp_store.written,
2765            events: effects.events_digest().map(|_| inner_temp_store.events),
2766            effects,
2767            execution_result,
2768            suggested_gas_price: self
2769                .congestion_tracker
2770                .get_prediction_suggested_gas_price(&transaction),
2771            mock_gas_id,
2772            gas_data: transaction.gas_data().clone(),
2773        })
2774    }
2775
2776    // Only used for testing because of how epoch store is loaded.
2777    pub fn reference_gas_price_for_testing(&self) -> Result<u64, anyhow::Error> {
2778        let epoch_store = self.epoch_store_for_testing();
2779        Ok(epoch_store.reference_gas_price())
2780    }
2781
2782    #[instrument(level = "trace", skip_all)]
2783    pub fn try_is_tx_already_executed(&self, digest: &TransactionDigest) -> IotaResult<bool> {
2784        self.get_transaction_cache_reader()
2785            .try_is_tx_already_executed(digest)
2786    }
2787
2788    /// Non-fallible version of `try_is_tx_already_executed`.
2789    pub fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
2790        self.try_is_tx_already_executed(digest)
2791            .expect("storage access failed")
2792    }
2793
2794    /// Indexes a transaction by updating various indexes in the `IndexStore`.
2795    #[instrument(level = "debug", skip_all, err)]
2796    fn index_tx(
2797        &self,
2798        indexes: &IndexStore,
2799        digest: &TransactionDigest,
2800        // TODO: index_tx really just need the transaction data here.
2801        transaction: &VerifiedExecutableTransaction,
2802        effects: &TransactionEffects,
2803        events: &TransactionEvents,
2804        timestamp_ms: u64,
2805        tx_coins: Option<TxCoins>,
2806        written: &WrittenObjects,
2807        inner_temporary_store: &InnerTemporaryStore,
2808        epoch_store: &Arc<AuthorityPerEpochStore>,
2809    ) -> IotaResult<u64> {
2810        let changes = self
2811            .process_object_index(effects, written, inner_temporary_store, epoch_store)
2812            .tap_err(|e| warn!(tx_digest=?digest, "Failed to process object index, index_tx is skipped: {e}"))?;
2813
2814        indexes.index_tx(
2815            transaction.data().transaction().sender(),
2816            transaction
2817                .data()
2818                .transaction()
2819                .input_objects()?
2820                .iter()
2821                .map(|o| o.object_id()),
2822            effects
2823                .all_changed_objects()
2824                .into_iter()
2825                .map(|(changed, _kind)| (*changed.reference(), *changed.owner())),
2826            transaction
2827                .data()
2828                .transaction()
2829                .move_calls()
2830                .into_iter()
2831                .map(|(package, module, function)| {
2832                    (*package, module.to_owned(), function.to_owned())
2833                }),
2834            events,
2835            changes,
2836            digest,
2837            timestamp_ms,
2838            tx_coins,
2839        )
2840    }
2841
2842    #[cfg(msim)]
2843    fn create_fail_state(
2844        &self,
2845        transaction: &VerifiedExecutableTransaction,
2846        epoch_store: &Arc<AuthorityPerEpochStore>,
2847        effects: &mut TransactionEffects,
2848    ) {
2849        use std::cell::RefCell;
2850
2851        use iota_types::effects::TransactionEffectsAPIForTesting;
2852        thread_local! {
2853            static FAIL_STATE: RefCell<(u64, HashSet<AuthorityName>)> = RefCell::new((0, HashSet::new()));
2854        }
2855        if !transaction.data().transaction().is_system_tx() {
2856            let committee = epoch_store.committee();
2857            let cur_stake = (**committee).weight(&self.name);
2858            if cur_stake > 0 {
2859                FAIL_STATE.with_borrow_mut(|fail_state| {
2860                    // let (&mut failing_stake, &mut failing_validators) = fail_state;
2861                    if fail_state.0 < committee.validity_threshold() {
2862                        fail_state.0 += cur_stake;
2863                        fail_state.1.insert(self.name);
2864                    }
2865
2866                    if fail_state.1.contains(&self.name) {
2867                        info!("cp_exec failing tx");
2868                        effects.gas_cost_summary_mut_for_testing().computation_cost += 1;
2869                    }
2870                });
2871            }
2872        }
2873    }
2874
2875    fn process_object_index(
2876        &self,
2877        effects: &TransactionEffects,
2878        written: &WrittenObjects,
2879        inner_temporary_store: &InnerTemporaryStore,
2880        epoch_store: &Arc<AuthorityPerEpochStore>,
2881    ) -> IotaResult<ObjectIndexChanges> {
2882        let mut layout_resolver =
2883            epoch_store
2884                .executor()
2885                .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
2886                    inner_temporary_store,
2887                    self.get_backing_package_store(),
2888                )));
2889
2890        let modified_at_version = effects
2891            .modified_at_versions()
2892            .into_iter()
2893            .map(|modified| (*modified.object_id(), modified.version()))
2894            .collect::<HashMap<_, _>>();
2895
2896        let tx_digest = effects.transaction_digest();
2897        let mut deleted_owners = vec![];
2898        let mut deleted_dynamic_fields = vec![];
2899        for object_ref in effects.deleted().into_iter().chain(effects.wrapped()) {
2900            let old_version = modified_at_version.get(&object_ref.object_id).unwrap();
2901            // When we process the index, the latest object hasn't been written yet so
2902            // the old object must be present.
2903            match self.get_owner_at_version(&object_ref.object_id, *old_version).unwrap_or_else(
2904                |e| panic!("tx_digest={tx_digest}, error processing object owner index, cannot find owner for object {} at version {old_version:?}. Err: {e:?}", object_ref.object_id)
2905            ) {
2906                Owner::Address(addr) => deleted_owners.push((addr, object_ref.object_id)),
2907                Owner::Object(object_id) => {
2908                    deleted_dynamic_fields.push((object_id, object_ref.object_id))
2909                }
2910                _ => {}
2911            }
2912        }
2913
2914        let mut new_owners = vec![];
2915        let mut new_dynamic_fields = vec![];
2916
2917        for (changed, kind) in effects.all_changed_objects() {
2918            let (oref, owner) = (*changed.reference(), *changed.owner());
2919            let id = &oref.object_id;
2920            // For mutated objects, retrieve old owner and delete old index if there is a
2921            // owner change.
2922            if let WriteKind::Mutate = kind {
2923                let Some(old_version) = modified_at_version.get(id) else {
2924                    panic!(
2925                        "tx_digest={tx_digest}, error processing object owner index, cannot find modified at version for mutated object [{id}]."
2926                    );
2927                };
2928                // When we process the index, the latest object hasn't been written yet so
2929                // the old object must be present.
2930                let Some(old_object) = self
2931                    .get_object_store()
2932                    .try_get_object_by_key(id, *old_version)?
2933                else {
2934                    panic!(
2935                        "tx_digest={tx_digest}, error processing object owner index, cannot find owner for object {id} at version {old_version:?}"
2936                    );
2937                };
2938                if old_object.owner != owner {
2939                    match old_object.owner {
2940                        Owner::Address(addr) => {
2941                            deleted_owners.push((addr, *id));
2942                        }
2943                        Owner::Object(object_id) => deleted_dynamic_fields.push((object_id, *id)),
2944                        _ => {}
2945                    }
2946                }
2947            }
2948
2949            match owner {
2950                Owner::Address(addr) => {
2951                    // TODO: We can remove the object fetching after we added ObjectType to
2952                    // TransactionEffects
2953                    let new_object = written.get(id).unwrap_or_else(
2954                        || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2955                    );
2956                    assert_eq!(
2957                        new_object.version(),
2958                        oref.version,
2959                        "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2960                        tx_digest,
2961                        id,
2962                        new_object.version(),
2963                        oref.version
2964                    );
2965
2966                    let object_type = new_object
2967                        .data
2968                        .opt_object_type()
2969                        .map(|ty| ObjectType::Struct(ty.clone()))
2970                        .unwrap_or(ObjectType::Package);
2971
2972                    new_owners.push((
2973                        (addr, *id),
2974                        ObjectInfo {
2975                            object_id: *id,
2976                            version: oref.version,
2977                            digest: oref.digest,
2978                            object_type,
2979                            owner,
2980                            previous_transaction: *effects.transaction_digest(),
2981                        },
2982                    ));
2983                }
2984                Owner::Object(owner) => {
2985                    let new_object = written.get(id).unwrap_or_else(
2986                        || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2987                    );
2988                    assert_eq!(
2989                        new_object.version(),
2990                        oref.version,
2991                        "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2992                        tx_digest,
2993                        id,
2994                        new_object.version(),
2995                        oref.version
2996                    );
2997
2998                    let Some(df_info) = self
2999                        .try_create_dynamic_field_info(new_object, written, layout_resolver.as_mut())
3000                        .unwrap_or_else(|e| {
3001                            error!(
3002                                "try_create_dynamic_field_info should not fail, {}, new_object={}, new_object_type={}",
3003                                e,
3004                                new_object.id(),
3005                                ObjectType::from(new_object)
3006                            );
3007                            None
3008                        }
3009                        )
3010                    else {
3011                        // Skip indexing for non dynamic field objects.
3012                        continue;
3013                    };
3014                    new_dynamic_fields.push(((owner, *id), df_info))
3015                }
3016                _ => {}
3017            }
3018        }
3019
3020        Ok(ObjectIndexChanges {
3021            deleted_owners,
3022            deleted_dynamic_fields,
3023            new_owners,
3024            new_dynamic_fields,
3025        })
3026    }
3027
3028    fn try_create_dynamic_field_info(
3029        &self,
3030        o: &Object,
3031        written: &WrittenObjects,
3032        resolver: &mut dyn LayoutResolver,
3033    ) -> IotaResult<Option<DynamicFieldInfo>> {
3034        // Skip if not a move object
3035        let Some(move_object) = o.data.as_opt_struct().cloned() else {
3036            return Ok(None);
3037        };
3038
3039        // We only index dynamic field objects
3040        if !move_object.struct_tag().is_dynamic_field() {
3041            return Ok(None);
3042        }
3043
3044        let layout = match resolver.get_annotated_layout(move_object.struct_tag()) {
3045            Ok(annotated_layout) => annotated_layout.into_layout(),
3046            Err(e) => {
3047                error!(
3048                    "unable to load layout for type `{:?}`: {e}",
3049                    move_object.struct_tag()
3050                );
3051                return Ok(None);
3052            }
3053        };
3054
3055        let field =
3056            DFV::FieldVisitor::deserialize(move_object.contents(), &layout).map_err(|e| {
3057                IotaError::ObjectDeserialization {
3058                    error: e.to_string(),
3059                }
3060            })?;
3061
3062        let type_ = field.kind;
3063        let name_type: TypeTag = type_tag_core_to_sdk(&field.name_layout.into());
3064        let bcs_name = field.name_bytes.to_owned();
3065
3066        let name_value = BoundedVisitor::deserialize_value(field.name_bytes, field.name_layout)
3067            .map_err(|e| {
3068                warn!("{e}");
3069                IotaError::ObjectDeserialization {
3070                    error: e.to_string(),
3071                }
3072            })?;
3073
3074        let name = DynamicFieldName {
3075            type_tag: name_type,
3076            value: IotaMoveValue::from(name_value).to_json_value(),
3077        };
3078
3079        let value_metadata = field.value_metadata().map_err(|e| {
3080            warn!("{e}");
3081            IotaError::ObjectDeserialization {
3082                error: e.to_string(),
3083            }
3084        })?;
3085
3086        Ok(Some(match value_metadata {
3087            DFV::ValueMetadata::DynamicField(object_type) => DynamicFieldInfo {
3088                name,
3089                bcs_name,
3090                type_,
3091                object_type: object_type.to_canonical_string(/* with_prefix */ true),
3092                object_id: o.id(),
3093                version: o.version(),
3094                digest: o.digest(),
3095            },
3096
3097            DFV::ValueMetadata::DynamicObjectField(object_id) => {
3098                // Find the actual object from storage using the object id obtained from the
3099                // wrapper.
3100
3101                // Try to find the object in the written objects first.
3102                let (version, digest, object_type) = if let Some(object) = written.get(&object_id) {
3103                    (
3104                        object.version(),
3105                        object.digest(),
3106                        object.data.opt_object_type().unwrap().clone(),
3107                    )
3108                } else {
3109                    // If not found, try to find it in the database.
3110                    let object = self
3111                        .get_object_store()
3112                        .try_get_object_by_key(&object_id, o.version())?
3113                        .ok_or_else(|| UserInputError::ObjectNotFound {
3114                            object_id,
3115                            version: Some(o.version()),
3116                        })?;
3117                    let version = object.version();
3118                    let digest = object.digest();
3119                    let object_type = object.data.opt_object_type().unwrap().clone();
3120                    (version, digest, object_type)
3121                };
3122
3123                DynamicFieldInfo {
3124                    name,
3125                    bcs_name,
3126                    type_,
3127                    object_type: object_type.to_string(),
3128                    object_id,
3129                    version,
3130                    digest,
3131                }
3132            }
3133        }))
3134    }
3135
3136    #[instrument(level = "trace", skip_all, err)]
3137    fn post_process_one_tx(
3138        &self,
3139        transaction: &VerifiedExecutableTransaction,
3140        effects: &TransactionEffects,
3141        inner_temporary_store: &InnerTemporaryStore,
3142        epoch_store: &Arc<AuthorityPerEpochStore>,
3143    ) -> IotaResult {
3144        if self.indexes.is_none() {
3145            return Ok(());
3146        }
3147
3148        let _scope = monitored_scope("Execution::post_process_one_tx");
3149
3150        let tx_digest = transaction.digest();
3151        let timestamp_ms = Self::unixtime_now_ms();
3152        let events = &inner_temporary_store.events;
3153        let written = &inner_temporary_store.written;
3154        let tx_coins = self.fullnode_only_get_tx_coins_for_indexing(
3155            effects,
3156            inner_temporary_store,
3157            epoch_store,
3158        );
3159
3160        // Index tx
3161        if let Some(indexes) = &self.indexes {
3162            let _ = self
3163                .index_tx(
3164                    indexes.as_ref(),
3165                    tx_digest,
3166                    transaction,
3167                    effects,
3168                    events,
3169                    timestamp_ms,
3170                    tx_coins,
3171                    written,
3172                    inner_temporary_store,
3173                    epoch_store,
3174                )
3175                .tap_ok(|_| self.metrics.post_processing_total_tx_indexed.inc())
3176                .tap_err(|e| error!(?tx_digest, "Post processing - Couldn't index tx: {e}"))
3177                .expect("Indexing tx should not fail");
3178
3179            let effects: IotaTransactionBlockEffects = effects.clone().try_into()?;
3180            let events = self.make_transaction_block_events(
3181                events.clone(),
3182                *tx_digest,
3183                timestamp_ms,
3184                epoch_store,
3185                inner_temporary_store,
3186            )?;
3187            // Emit events
3188            self.subscription_handler
3189                .process_tx(transaction.data().transaction(), &effects, &events)
3190                .tap_ok(|_| {
3191                    self.metrics
3192                        .post_processing_total_tx_had_event_processed
3193                        .inc()
3194                })
3195                .tap_err(|e| {
3196                    warn!(
3197                        ?tx_digest,
3198                        "Post processing - Couldn't process events for tx: {}", e
3199                    )
3200                })?;
3201
3202            self.metrics
3203                .post_processing_total_events_emitted
3204                .inc_by(events.data.len() as u64);
3205        };
3206        Ok(())
3207    }
3208
3209    fn make_transaction_block_events(
3210        &self,
3211        transaction_events: TransactionEvents,
3212        digest: TransactionDigest,
3213        timestamp_ms: u64,
3214        epoch_store: &Arc<AuthorityPerEpochStore>,
3215        inner_temporary_store: &InnerTemporaryStore,
3216    ) -> IotaResult<IotaTransactionBlockEvents> {
3217        let mut layout_resolver =
3218            epoch_store
3219                .executor()
3220                .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
3221                    inner_temporary_store,
3222                    self.get_backing_package_store(),
3223                )));
3224        IotaTransactionBlockEvents::try_from(
3225            transaction_events,
3226            digest,
3227            Some(timestamp_ms),
3228            layout_resolver.as_mut(),
3229        )
3230    }
3231
3232    pub fn unixtime_now_ms() -> u64 {
3233        let now = SystemTime::now()
3234            .duration_since(UNIX_EPOCH)
3235            .expect("Time went backwards")
3236            .as_millis();
3237        u64::try_from(now).expect("Travelling in time machine")
3238    }
3239
3240    #[instrument(level = "trace", skip_all)]
3241    pub async fn handle_transaction_info_request(
3242        &self,
3243        request: TransactionInfoRequest,
3244    ) -> IotaResult<TransactionInfoResponse> {
3245        let epoch_store = self.load_epoch_store_one_call_per_task();
3246        let (transaction, status) = self
3247            .get_transaction_status(&request.transaction_digest, &epoch_store)?
3248            .ok_or(IotaError::TransactionNotFound {
3249                digest: request.transaction_digest,
3250            })?;
3251        Ok(TransactionInfoResponse {
3252            transaction,
3253            status,
3254        })
3255    }
3256
3257    #[instrument(level = "trace", skip_all)]
3258    pub async fn handle_object_info_request(
3259        &self,
3260        request: ObjectInfoRequest,
3261    ) -> IotaResult<ObjectInfoResponse> {
3262        let epoch_store = self.load_epoch_store_one_call_per_task();
3263
3264        let requested_object_seq = match request.request_kind {
3265            ObjectInfoRequestKind::LatestObjectInfo => {
3266                self.try_get_object_or_tombstone(request.object_id)?
3267                    .ok_or_else(|| {
3268                        IotaError::from(UserInputError::ObjectNotFound {
3269                            object_id: request.object_id,
3270                            version: None,
3271                        })
3272                    })?
3273                    .version
3274            }
3275            ObjectInfoRequestKind::PastObjectInfoDebug(seq) => seq,
3276        };
3277
3278        let object = self
3279            .get_object_store()
3280            .try_get_object_by_key(&request.object_id, requested_object_seq)?
3281            .ok_or_else(|| {
3282                IotaError::from(UserInputError::ObjectNotFound {
3283                    object_id: request.object_id,
3284                    version: Some(requested_object_seq),
3285                })
3286            })?;
3287
3288        let layout = if let (LayoutGenerationOption::Generate, Some(move_obj)) =
3289            (request.generate_layout, object.data.as_opt_struct())
3290        {
3291            Some(into_struct_layout(
3292                epoch_store
3293                    .executor()
3294                    .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
3295                    .get_annotated_layout(move_obj.struct_tag())?,
3296            )?)
3297        } else {
3298            None
3299        };
3300
3301        let lock = if !object.is_address_owned() {
3302            // Only address owned objects have locks.
3303            None
3304        } else {
3305            self.get_transaction_lock(&object.object_ref(), &epoch_store)?
3306                .map(|s| s.into_inner())
3307        };
3308
3309        Ok(ObjectInfoResponse {
3310            object,
3311            layout,
3312            lock_for_debugging: lock,
3313        })
3314    }
3315
3316    #[instrument(level = "trace", skip_all)]
3317    pub fn handle_checkpoint_request(
3318        &self,
3319        request: &CheckpointRequest,
3320    ) -> IotaResult<CheckpointResponse> {
3321        let summary = if request.certified {
3322            let summary = match request.sequence_number {
3323                Some(seq) => self
3324                    .checkpoint_store
3325                    .get_checkpoint_by_sequence_number(seq)?,
3326                None => self.checkpoint_store.get_latest_certified_checkpoint()?,
3327            }
3328            .map(|v| v.into_inner());
3329            summary.map(CheckpointSummaryResponse::Certified)
3330        } else {
3331            let summary = match request.sequence_number {
3332                Some(seq) => self.checkpoint_store.get_locally_computed_checkpoint(seq)?,
3333                None => self
3334                    .checkpoint_store
3335                    .get_latest_locally_computed_checkpoint()?,
3336            };
3337            summary.map(CheckpointSummaryResponse::Pending)
3338        };
3339        let contents = match &summary {
3340            Some(s) => self
3341                .checkpoint_store
3342                .get_checkpoint_contents(&s.contents_digest())?,
3343            None => None,
3344        };
3345        Ok(CheckpointResponse {
3346            checkpoint: summary,
3347            contents,
3348        })
3349    }
3350
3351    fn check_protocol_version(
3352        supported_protocol_versions: SupportedProtocolVersions,
3353        current_version: ProtocolVersion,
3354    ) {
3355        info!("current protocol version is now {:?}", current_version);
3356        info!("supported versions are: {:?}", supported_protocol_versions);
3357        if !supported_protocol_versions.is_version_supported(current_version) {
3358            let msg = format!(
3359                "Unsupported protocol version. The network is at {current_version:?}, but this IotaNode only supports: {supported_protocol_versions:?}. Shutting down.",
3360            );
3361
3362            error!("{}", msg);
3363            eprintln!("{msg}");
3364
3365            #[cfg(not(msim))]
3366            std::process::exit(1);
3367
3368            #[cfg(msim)]
3369            iota_simulator::task::shutdown_current_node();
3370        }
3371    }
3372
3373    #[expect(clippy::disallowed_methods)] // allow unbounded_channel()
3374    pub async fn new(
3375        name: AuthorityName,
3376        secret: StableSyncAuthoritySigner,
3377        supported_protocol_versions: SupportedProtocolVersions,
3378        store: Arc<AuthorityStore>,
3379        execution_cache_trait_pointers: ExecutionCacheTraitPointers,
3380        epoch_store: Arc<AuthorityPerEpochStore>,
3381        committee_store: Arc<CommitteeStore>,
3382        indexes: Option<Arc<IndexStore>>,
3383        grpc_indexes_store: Option<Arc<GrpcIndexesStore>>,
3384        checkpoint_store: Arc<CheckpointStore>,
3385        prometheus_registry: &Registry,
3386        genesis_objects: &[Object],
3387        config: NodeConfig,
3388        validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
3389        chain_identifier: ChainIdentifier,
3390        checkpoint_progress_tracker: Option<Arc<CheckpointProgressTracker>>,
3391        policy_config: Option<PolicyConfig>,
3392        epoch_end_db_snapshots: Option<EpochEndDbSnapshotHandle>,
3393    ) -> Arc<Self> {
3394        Self::check_protocol_version(supported_protocol_versions, epoch_store.protocol_version());
3395
3396        // Read by the quarantine flush and the execution watcher; the next
3397        // epoch's store inherits it.
3398        epoch_store.set_effects_store(
3399            execution_cache_trait_pointers
3400                .transaction_cache_reader
3401                .clone(),
3402        );
3403
3404        let metrics = Arc::new(AuthorityMetrics::new(prometheus_registry));
3405        let (tx_ready_transactions, rx_ready_transactions) = unbounded_channel();
3406        let execution_scheduler = Arc::new(ExecutionSchedulerWrapper::new(
3407            execution_cache_trait_pointers.object_cache_reader.clone(),
3408            execution_cache_trait_pointers
3409                .transaction_cache_reader
3410                .clone(),
3411            tx_ready_transactions,
3412            &epoch_store,
3413            metrics.clone(),
3414        ));
3415        let (tx_execution_shutdown, rx_execution_shutdown) = oneshot::channel();
3416
3417        let authority_per_epoch_pruner = AuthorityPerEpochStorePruner::new(
3418            epoch_store.get_parent_path(),
3419            config
3420                .authority_store_pruning_config
3421                .num_latest_epoch_dbs_to_retain,
3422        )
3423        .await;
3424        let pruner = AuthorityStorePruner::new(
3425            store.perpetual_tables.clone(),
3426            checkpoint_store.clone(),
3427            grpc_indexes_store.clone(),
3428            indexes.clone(),
3429            config.authority_store_pruning_config.clone(),
3430            epoch_store.committee().authority_exists(&name),
3431            epoch_store.epoch_start_state().epoch_duration_ms(),
3432            prometheus_registry,
3433            checkpoint_progress_tracker.clone(),
3434            epoch_store.object_pruning_limit(),
3435        );
3436        let input_loader =
3437            TransactionInputLoader::new(execution_cache_trait_pointers.object_cache_reader.clone());
3438        let epoch = epoch_store.epoch();
3439        let rgp = epoch_store.reference_gas_price();
3440        let traffic_controller_metrics =
3441            Arc::new(TrafficControllerMetrics::new(prometheus_registry));
3442        let traffic_controller = policy_config.map(|policy_config| {
3443            Arc::new(TrafficController::init(
3444                policy_config,
3445                traffic_controller_metrics,
3446            ))
3447        });
3448        let state = Arc::new(AuthorityState {
3449            name,
3450            secret,
3451            execution_lock: RwLock::new(epoch),
3452            epoch_store: ArcSwap::new(epoch_store.clone()),
3453            input_loader,
3454            execution_cache_trait_pointers,
3455            indexes,
3456            grpc_indexes_store,
3457            subscription_handler: Arc::new(SubscriptionHandler::new(prometheus_registry)),
3458            checkpoint_store,
3459            committee_store,
3460            execution_scheduler,
3461            tx_execution_shutdown: Mutex::new(Some(tx_execution_shutdown)),
3462            metrics,
3463            pruner,
3464            authority_per_epoch_pruner,
3465            checkpoint_progress_tracker,
3466            config,
3467            overload_info: AuthorityOverloadInfo::default(),
3468            validator_tx_finalizer,
3469            chain_identifier,
3470            congestion_tracker: Arc::new(CongestionTracker::new(rgp)),
3471            traffic_controller,
3472            epoch_end_db_snapshots,
3473        });
3474
3475        // Start a task to execute ready transactions.
3476        let authority_state = Arc::downgrade(&state);
3477        spawn_monitored_task!(execution_process(
3478            authority_state,
3479            rx_ready_transactions,
3480            rx_execution_shutdown,
3481        ));
3482        // TODO: This doesn't belong to the constructor of AuthorityState.
3483        state
3484            .create_owner_index_if_empty(genesis_objects, &epoch_store)
3485            .expect("Error indexing genesis objects.");
3486
3487        state
3488    }
3489
3490    pub fn epoch_db_pruner(&self) -> &AuthorityPerEpochStorePruner {
3491        &self.authority_per_epoch_pruner
3492    }
3493
3494    // TODO: Consolidate our traits to reduce the number of methods here.
3495    pub fn get_object_cache_reader(&self) -> &Arc<dyn ObjectCacheRead> {
3496        &self.execution_cache_trait_pointers.object_cache_reader
3497    }
3498
3499    pub fn get_transaction_cache_reader(&self) -> &Arc<dyn TransactionCacheRead> {
3500        &self.execution_cache_trait_pointers.transaction_cache_reader
3501    }
3502
3503    pub fn get_cache_writer(&self) -> &Arc<dyn ExecutionCacheWrite> {
3504        &self.execution_cache_trait_pointers.cache_writer
3505    }
3506
3507    pub fn get_backing_store(&self) -> &Arc<dyn BackingStore + Send + Sync> {
3508        &self.execution_cache_trait_pointers.backing_store
3509    }
3510
3511    pub fn get_backing_package_store(&self) -> &Arc<dyn BackingPackageStore + Send + Sync> {
3512        &self.execution_cache_trait_pointers.backing_package_store
3513    }
3514
3515    pub fn get_object_store(&self) -> &Arc<dyn ObjectStore + Send + Sync> {
3516        &self.execution_cache_trait_pointers.object_store
3517    }
3518
3519    pub fn get_reconfig_api(&self) -> &Arc<dyn ExecutionCacheReconfigAPI> {
3520        &self.execution_cache_trait_pointers.reconfig_api
3521    }
3522
3523    pub fn get_global_state_hash_store(&self) -> &Arc<dyn GlobalStateHashStore> {
3524        &self.execution_cache_trait_pointers.global_state_hash_store
3525    }
3526
3527    pub fn get_checkpoint_cache(&self) -> &Arc<dyn CheckpointCache> {
3528        &self.execution_cache_trait_pointers.checkpoint_cache
3529    }
3530
3531    pub fn get_state_sync_store(&self) -> &Arc<dyn StateSyncAPI> {
3532        &self.execution_cache_trait_pointers.state_sync_store
3533    }
3534
3535    pub fn get_cache_commit(&self) -> &Arc<dyn ExecutionCacheCommit> {
3536        &self.execution_cache_trait_pointers.cache_commit
3537    }
3538
3539    pub fn database_for_testing(&self) -> Arc<AuthorityStore> {
3540        self.execution_cache_trait_pointers
3541            .testing_api
3542            .database_for_testing()
3543    }
3544
3545    /// Drops the committed versions of `id` the execution cache holds in
3546    /// memory, so the next read of a committed version goes to the database.
3547    #[cfg(test)]
3548    pub fn evict_committed_object_for_testing(&self, id: &ObjectId) {
3549        self.execution_cache_trait_pointers
3550            .testing_api
3551            .evict_committed_object_for_testing(id)
3552    }
3553
3554    pub async fn prune_checkpoints_for_eligible_epochs_for_testing(
3555        &self,
3556        config: NodeConfig,
3557        metrics: Arc<AuthorityStorePruningMetrics>,
3558    ) -> anyhow::Result<()> {
3559        AuthorityStorePruner::prune_checkpoints_for_eligible_epochs(
3560            &self.database_for_testing().perpetual_tables,
3561            &self.checkpoint_store,
3562            self.grpc_indexes_store.as_deref(),
3563            config.authority_store_pruning_config,
3564            metrics,
3565            EPOCH_DURATION_MS_FOR_TESTING,
3566            self.checkpoint_progress_tracker.as_ref(),
3567        )
3568        .await
3569    }
3570
3571    pub fn execution_scheduler(&self) -> &Arc<ExecutionSchedulerWrapper> {
3572        &self.execution_scheduler
3573    }
3574
3575    /// Whether this authority runs the `ExecutionScheduler` rather than the
3576    /// `TransactionManager`.
3577    pub fn uses_execution_scheduler(&self) -> bool {
3578        self.execution_scheduler.uses_execution_scheduler()
3579    }
3580
3581    fn create_owner_index_if_empty(
3582        &self,
3583        genesis_objects: &[Object],
3584        epoch_store: &Arc<AuthorityPerEpochStore>,
3585    ) -> IotaResult {
3586        let Some(index_store) = &self.indexes else {
3587            return Ok(());
3588        };
3589        if !index_store.is_empty() {
3590            return Ok(());
3591        }
3592
3593        let mut new_owners = vec![];
3594        let mut new_dynamic_fields = vec![];
3595        let mut layout_resolver = epoch_store
3596            .executor()
3597            .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()));
3598        for o in genesis_objects.iter() {
3599            match o.owner {
3600                Owner::Address(addr) => {
3601                    new_owners.push(((addr, o.id()), ObjectInfo::new(&o.object_ref(), o)))
3602                }
3603                Owner::Object(object_id) => {
3604                    let id = o.id();
3605                    let info = match self.try_create_dynamic_field_info(
3606                        o,
3607                        &BTreeMap::new(),
3608                        layout_resolver.as_mut(),
3609                    ) {
3610                        Ok(Some(info)) => info,
3611                        Ok(None) => continue,
3612                        Err(IotaError::UserInput {
3613                            error:
3614                                UserInputError::ObjectNotFound {
3615                                    object_id: not_found_id,
3616                                    version,
3617                                },
3618                        }) => {
3619                            warn!(
3620                                ?not_found_id,
3621                                ?version,
3622                                object_owner=?object_id,
3623                                field=?id,
3624                                "Skipping dynamic field: referenced genesis object not found"
3625                            );
3626                            continue;
3627                        }
3628                        Err(e) => return Err(e),
3629                    };
3630                    new_dynamic_fields.push(((object_id, id), info));
3631                }
3632                _ => {}
3633            }
3634        }
3635
3636        index_store.insert_genesis_objects(ObjectIndexChanges {
3637            deleted_owners: vec![],
3638            deleted_dynamic_fields: vec![],
3639            new_owners,
3640            new_dynamic_fields,
3641        })
3642    }
3643
3644    /// Attempts to acquire execution lock for an executable transaction.
3645    /// Returns the lock if the transaction is matching current executed epoch
3646    /// Returns None otherwise
3647    pub fn execution_lock_for_executable_transaction(
3648        &self,
3649        transaction: &VerifiedExecutableTransaction,
3650    ) -> IotaResult<ExecutionLockReadGuard<'_>> {
3651        let lock = self
3652            .execution_lock
3653            .try_read()
3654            .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)?;
3655        if *lock == transaction.auth_sig().epoch() {
3656            Ok(lock)
3657        } else {
3658            Err(IotaError::WrongEpoch {
3659                expected_epoch: *lock,
3660                actual_epoch: transaction.auth_sig().epoch(),
3661            })
3662        }
3663    }
3664
3665    /// Acquires the execution lock for the duration of a transaction signing
3666    /// request. This prevents reconfiguration from starting until we are
3667    /// finished handling the signing request. Otherwise, in-memory lock
3668    /// state could be cleared (by `ObjectLocks::clear_cached_locks`)
3669    /// while we are attempting to acquire locks for the transaction.
3670    pub fn execution_lock_for_signing(&self) -> IotaResult<ExecutionLockReadGuard<'_>> {
3671        self.execution_lock
3672            .try_read()
3673            .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)
3674    }
3675
3676    pub async fn execution_lock_for_reconfiguration(&self) -> ExecutionLockWriteGuard<'_> {
3677        self.execution_lock.write().await
3678    }
3679
3680    /// Reports a mirror that diverged from the object at the epoch boundary,
3681    /// where the two must agree. Reporting is the remedy: reconfiguration
3682    /// re-seeds the mirror from the object, so failing here would only pin
3683    /// the node to the diverged state. A missing object is fatal instead.
3684    /// Objects cannot be deleted, so the local store lost it and there is
3685    /// nothing to re-seed from. Nodes outside the closing committee are
3686    /// exempt. So is an epoch this node's consensus did not close. A
3687    /// checkpoint catch-up leaves the mirror legitimately behind until the
3688    /// re-seed.
3689    pub(crate) fn check_transaction_deny_rules_consistency(
3690        &self,
3691        cur_epoch_store: &AuthorityPerEpochStore,
3692        epoch_start_configuration: &EpochStartConfiguration,
3693    ) {
3694        if self.is_fullnode(cur_epoch_store) {
3695            return;
3696        }
3697        let Some(walked_deny_rules) = epoch_start_configuration.transaction_deny_rules_state()
3698        else {
3699            if cur_epoch_store
3700                .epoch_start_config()
3701                .transaction_deny_rules_obj_initial_shared_version()
3702                .is_some()
3703            {
3704                fatal!(
3705                    "TransactionDenyRules object existed in epoch {} but is missing from the \
3706                     state walked for the next epoch — the local store is corrupted; restore or \
3707                     state-sync before rejoining",
3708                    cur_epoch_store.epoch(),
3709                );
3710            }
3711            return;
3712        };
3713        // RejectAllTx proves this node's consensus processed every commit of
3714        // the epoch, so the mirror is complete. Otherwise the tail came from
3715        // synced checkpoints and the mirror's lag carries no signal.
3716        if cur_epoch_store
3717            .get_reconfig_state_read_lock_guard()
3718            .should_accept_tx()
3719        {
3720            info!(
3721                "skipping the deny-rule mirror comparison: consensus did not close epoch {} on \
3722                 this node",
3723                cur_epoch_store.epoch(),
3724            );
3725            return;
3726        }
3727        let mirrored_deny_rules = cur_epoch_store.get_mirrored_transaction_deny_rules();
3728        if *walked_deny_rules != *mirrored_deny_rules {
3729            debug_fatal!(
3730                "TransactionDenyRules object diverged from the mirrored state at the end of \
3731                 epoch {}; continuing from the object (walked: {walked_deny_rules:?}, mirrored: \
3732                 {mirrored_deny_rules:?})",
3733                cur_epoch_store.epoch(),
3734            );
3735            cur_epoch_store.metrics.deny_rule_mirror_divergence.set(1);
3736        }
3737    }
3738
3739    /// Reports a `TransactionDenyRulesUpdate` whose execution failed — an
3740    /// invariant violation, the update is built to exclude every expected
3741    /// failure. The object misses the delta until the epoch boundary re-seeds
3742    /// the mirror. Identification is by kind, so the report needs no tracking
3743    /// state and holds across restarts and replays.
3744    ///
3745    /// `expected_effects_digest` is `Some` when these effects were handed to
3746    /// this node with the transaction, which is the case while executing a
3747    /// certified checkpoint: the failure is then part of agreed history, so it
3748    /// is reported without asserting. Effects the node derived itself assert,
3749    /// because only then is the broken invariant its own.
3750    pub(crate) fn report_failed_deny_rule_update_execution(
3751        &self,
3752        transaction: &VerifiedExecutableTransaction,
3753        effects: &TransactionEffects,
3754        expected_effects_digest: Option<TransactionEffectsDigest>,
3755        epoch_store: &AuthorityPerEpochStore,
3756    ) {
3757        if !matches!(
3758            transaction.transaction().kind(),
3759            TransactionKind::TransactionDenyRulesUpdate(_)
3760        ) || effects.status().is_success()
3761        {
3762            return;
3763        }
3764        epoch_store
3765            .metrics
3766            .deny_rule_update_execution_failures
3767            .inc();
3768        if expected_effects_digest.is_some() {
3769            error!(
3770                digest = ?transaction.digest(),
3771                status = ?effects.status(),
3772                "TransactionDenyRulesUpdate failed execution; the object misses its delta until \
3773                 the epoch boundary re-seeds the mirror"
3774            );
3775            return;
3776        }
3777        debug_fatal!(
3778            "TransactionDenyRulesUpdate failed execution; the object misses its delta until the \
3779             epoch boundary re-seeds the mirror (digest: {:?}, status: {:?})",
3780            transaction.digest(),
3781            effects.status(),
3782        );
3783    }
3784
3785    #[instrument(level = "error", skip_all)]
3786    pub async fn reconfigure(
3787        &self,
3788        cur_epoch_store: &AuthorityPerEpochStore,
3789        supported_protocol_versions: SupportedProtocolVersions,
3790        new_committee: Committee,
3791        epoch_start_configuration: EpochStartConfiguration,
3792        state_hasher: Arc<GlobalStateHasher>,
3793        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3794        epoch_supply_change: i64,
3795        epoch_last_checkpoint: CheckpointSequenceNumber,
3796    ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
3797        Self::check_protocol_version(
3798            supported_protocol_versions,
3799            epoch_start_configuration
3800                .epoch_start_state()
3801                .protocol_version(),
3802        );
3803        self.metrics.reset_on_reconfigure();
3804        self.committee_store.insert_new_committee(&new_committee)?;
3805
3806        // Wait until no transactions are being executed.
3807        let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3808
3809        // Terminate all epoch-specific tasks (those started with within_alive_epoch).
3810        cur_epoch_store.epoch_terminated().await;
3811
3812        let highest_locally_built_checkpoint_seq = self
3813            .checkpoint_store
3814            .get_latest_locally_computed_checkpoint()?
3815            .map(|c| c.sequence_number())
3816            .unwrap_or(0);
3817
3818        assert!(
3819            epoch_last_checkpoint >= highest_locally_built_checkpoint_seq,
3820            "expected {epoch_last_checkpoint} >= {highest_locally_built_checkpoint_seq}"
3821        );
3822
3823        // Safe to reconfigure now. No transactions are being executed,
3824        // and no epoch-specific tasks are running.
3825
3826        // TODO: revert_uncommitted_epoch_transactions will soon be unnecessary -
3827        // clear_state_end_of_epoch() can simply drop all uncommitted transactions
3828        self.revert_uncommitted_epoch_transactions(cur_epoch_store)
3829            .await?;
3830        self.get_reconfig_api()
3831            .clear_state_end_of_epoch(&execution_lock);
3832        self.check_system_consistency(
3833            cur_epoch_store,
3834            state_hasher,
3835            expensive_safety_check_config,
3836            epoch_supply_change,
3837        )?;
3838        self.check_transaction_deny_rules_consistency(cur_epoch_store, &epoch_start_configuration);
3839
3840        self.get_reconfig_api()
3841            .try_set_epoch_start_configuration(&epoch_start_configuration)?;
3842        self.hand_over_epoch_end_db_snapshot(cur_epoch_store.epoch())
3843            .await;
3844
3845        let new_epoch = new_committee.epoch;
3846        let new_epoch_store = self
3847            .reopen_epoch_db(
3848                cur_epoch_store,
3849                new_committee,
3850                epoch_start_configuration,
3851                expensive_safety_check_config,
3852                epoch_last_checkpoint,
3853            )
3854            .await?;
3855        assert_eq!(new_epoch_store.epoch(), new_epoch);
3856        match self.execution_scheduler.as_ref() {
3857            ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3858            ExecutionSchedulerWrapper::TransactionManager(tm) => {
3859                tm.reconfigure(new_epoch);
3860            }
3861        }
3862        *execution_lock = new_epoch;
3863        // drop execution_lock after epoch store was updated
3864        // see also assert in AuthorityState::process_transaction
3865        // on the epoch store and execution lock epoch match
3866        Ok(new_epoch_store)
3867    }
3868
3869    /// Advance the epoch store to the next epoch for testing only.
3870    /// This only manually sets all the places where we have the epoch number.
3871    /// It doesn't properly reconfigure the node, hence should be only used for
3872    /// testing.
3873    pub async fn reconfigure_for_testing(&self) {
3874        self.reconfigure_for_testing_impl(None).await;
3875    }
3876
3877    /// Like [`Self::reconfigure_for_testing`], but the next epoch uses the
3878    /// given protocol config.
3879    pub async fn reconfigure_for_testing_with_protocol_config(
3880        &self,
3881        protocol_config: ProtocolConfig,
3882    ) {
3883        self.reconfigure_for_testing_impl(Some(protocol_config))
3884            .await;
3885    }
3886
3887    async fn reconfigure_for_testing_impl(&self, protocol_config: Option<ProtocolConfig>) {
3888        let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3889        let epoch_store = self.epoch_store_for_testing().clone();
3890        // Default to the epoch store's config, whose override guard may have
3891        // been dropped. Read it under the lock so config and epoch store are
3892        // one snapshot.
3893        let protocol_config =
3894            protocol_config.unwrap_or_else(|| epoch_store.protocol_config().clone());
3895        let _guard =
3896            ProtocolConfig::apply_overrides_for_testing(move |_, _| protocol_config.clone());
3897        let new_epoch_store = epoch_store.new_at_next_epoch_for_testing(
3898            self.get_backing_package_store().clone(),
3899            &self.config.expensive_safety_check_config,
3900            self.checkpoint_store
3901                .get_epoch_last_checkpoint(epoch_store.epoch())
3902                .unwrap()
3903                .map(|c| c.sequence_number())
3904                .unwrap_or_default(),
3905        );
3906        let new_epoch = new_epoch_store.epoch();
3907        match self.execution_scheduler.as_ref() {
3908            ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3909            ExecutionSchedulerWrapper::TransactionManager(tm) => {
3910                tm.reconfigure(new_epoch);
3911            }
3912        }
3913        self.epoch_store.store(new_epoch_store);
3914        epoch_store.epoch_terminated().await;
3915        *execution_lock = new_epoch;
3916    }
3917
3918    #[instrument(level = "error", skip_all)]
3919    fn check_system_consistency(
3920        &self,
3921        cur_epoch_store: &AuthorityPerEpochStore,
3922        state_hasher: Arc<GlobalStateHasher>,
3923        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3924        epoch_supply_change: i64,
3925    ) -> IotaResult<()> {
3926        info!(
3927            "Performing iota conservation consistency check for epoch {}",
3928            cur_epoch_store.epoch()
3929        );
3930
3931        if cfg!(debug_assertions) {
3932            cur_epoch_store.check_all_executed_transactions_in_checkpoint();
3933        }
3934
3935        self.get_reconfig_api()
3936            .try_expensive_check_iota_conservation(cur_epoch_store, Some(epoch_supply_change))?;
3937
3938        // check for root state hash consistency with live object set
3939        if expensive_safety_check_config.enable_state_consistency_check() {
3940            info!(
3941                "Performing state consistency check for epoch {}",
3942                cur_epoch_store.epoch()
3943            );
3944            self.expensive_check_is_consistent_state(state_hasher, cur_epoch_store);
3945        }
3946
3947        if expensive_safety_check_config.enable_secondary_index_checks() {
3948            if let Some(indexes) = self.indexes.clone() {
3949                verify_indexes(self.get_global_state_hash_store().as_ref(), indexes)
3950                    .expect("secondary indexes are inconsistent");
3951            }
3952        }
3953
3954        Ok(())
3955    }
3956
3957    fn expensive_check_is_consistent_state(
3958        &self,
3959        state_hasher: Arc<GlobalStateHasher>,
3960        cur_epoch_store: &AuthorityPerEpochStore,
3961    ) {
3962        let live_object_set_hash = state_hasher.digest_live_object_set();
3963
3964        let root_state_hash: ECMHLiveObjectSetDigest = self
3965            .get_global_state_hash_store()
3966            .get_root_state_hash_for_epoch(cur_epoch_store.epoch())
3967            .expect("Retrieving root state hash cannot fail")
3968            .expect("Root state hash for epoch must exist")
3969            .1
3970            .digest()
3971            .into();
3972
3973        let is_inconsistent = root_state_hash != live_object_set_hash;
3974        if is_inconsistent {
3975            debug_fatal!(
3976                "Inconsistent state detected: root state hash: {:?}, live object set hash: {:?}",
3977                root_state_hash,
3978                live_object_set_hash
3979            );
3980        } else {
3981            info!("State consistency check passed");
3982        }
3983
3984        state_hasher.set_inconsistent_state(is_inconsistent);
3985    }
3986
3987    pub fn current_epoch_for_testing(&self) -> EpochId {
3988        self.epoch_store_for_testing().epoch()
3989    }
3990
3991    /// Lets the consumer take its database snapshot of the perpetual store as
3992    /// the epoch ends, when there is one. See
3993    /// [`EpochEndDbSnapshotHandle::hand_over`].
3994    #[instrument(level = "error", skip_all)]
3995    async fn hand_over_epoch_end_db_snapshot(&self, epoch: EpochId) {
3996        let Some(handle) = &self.epoch_end_db_snapshots else {
3997            return;
3998        };
3999        let _metrics_guard = self
4000            .metrics
4001            .epoch_end_db_snapshot_handover_latency
4002            .start_timer();
4003        if handle.hand_over(epoch).await == HandOver::Skipped {
4004            self.metrics.epoch_end_db_snapshots_skipped.inc();
4005        }
4006    }
4007
4008    /// Load the current epoch store. This can change during reconfiguration. To
4009    /// ensure that we never end up accessing different epoch stores in a
4010    /// single task, we need to make sure that this is called once per task.
4011    /// Each call needs to be carefully audited to ensure it is
4012    /// the case. This also means we should minimize the number of call-sites.
4013    /// Only call it when there is no way to obtain it from somewhere else.
4014    pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
4015        self.epoch_store.load()
4016    }
4017
4018    // Load the epoch store, should be used in tests only.
4019    pub fn epoch_store_for_testing(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
4020        self.load_epoch_store_one_call_per_task()
4021    }
4022
4023    pub fn clone_committee_for_testing(&self) -> Committee {
4024        Committee::clone(self.epoch_store_for_testing().committee())
4025    }
4026
4027    #[instrument(level = "trace", skip_all)]
4028    pub fn try_get_object(&self, object_id: &ObjectId) -> IotaResult<Option<Object>> {
4029        self.get_object_store()
4030            .try_get_object(object_id)
4031            .map_err(Into::into)
4032    }
4033
4034    /// Non-fallible version of `try_get_object`.
4035    pub fn get_object(&self, object_id: &ObjectId) -> Option<Object> {
4036        self.try_get_object(object_id)
4037            .expect("storage access failed")
4038    }
4039
4040    pub fn get_iota_system_package_object_ref(&self) -> IotaResult<ObjectReference> {
4041        Ok(self
4042            .try_get_object(&ObjectId::SYSTEM)?
4043            .expect("system package should always exist")
4044            .object_ref())
4045    }
4046
4047    // This function is only used for testing.
4048    pub fn get_iota_system_state_object_for_testing(&self) -> IotaResult<IotaSystemState> {
4049        self.get_object_cache_reader()
4050            .try_get_iota_system_state_object_unsafe()
4051    }
4052
4053    #[instrument(level = "trace", skip_all)]
4054    pub fn get_checkpoint_by_sequence_number(
4055        &self,
4056        sequence_number: CheckpointSequenceNumber,
4057    ) -> IotaResult<Option<VerifiedCheckpoint>> {
4058        Ok(self
4059            .checkpoint_store
4060            .get_checkpoint_by_sequence_number(sequence_number)?)
4061    }
4062
4063    /// Wait for the given transactions to be included in a checkpoint.
4064    ///
4065    /// Returns a mapping from transaction digest to
4066    /// `(checkpoint_sequence_number, checkpoint_timestamp_ms)`.
4067    /// On timeout, returns partial results for any transactions that were
4068    /// already checkpointed.
4069    ///
4070    /// The wait survives epoch boundaries: a transaction in flight at a
4071    /// boundary may only be checkpointed in the next epoch, and still resolves
4072    /// here under the original deadline.
4073    pub async fn wait_for_checkpoint_inclusion(
4074        &self,
4075        digests: &[TransactionDigest],
4076        timeout: Duration,
4077    ) -> IotaResult<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>> {
4078        let deadline = tokio::time::Instant::now() + timeout;
4079        let mut checkpoint_timestamp_cache = HashMap::<CheckpointSequenceNumber, u64>::new();
4080        let mut results = BTreeMap::new();
4081        let mut remaining = digests.to_vec();
4082        let mut epoch_store = self.load_epoch_store_one_call_per_task().clone();
4083
4084        loop {
4085            let wait = epoch_store.wait_for_transactions_in_checkpoint_with_timeout(
4086                &remaining,
4087                deadline.saturating_duration_since(tokio::time::Instant::now()),
4088                |seq| self.checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache),
4089            );
4090            tokio::select! {
4091                wait_results = wait => {
4092                    for (digest, seq_and_ts) in remaining.iter().zip(wait_results?) {
4093                        if let Some(seq_and_ts) = seq_and_ts {
4094                            results.insert(*digest, seq_and_ts);
4095                        }
4096                    }
4097                    return Ok(results);
4098                }
4099                _ = epoch_store.wait_epoch_terminated() => {}
4100            }
4101
4102            // The epoch ended mid-wait, and this epoch store's notifications
4103            // can no longer fire: whatever is still uncheckpointed here is
4104            // checkpointed in the next epoch, on the next store. Cancelling
4105            // the wait may also have dropped notifications it had already
4106            // received, but the table write precedes each notification, so
4107            // re-reading the table recovers them.
4108            let found = match epoch_store.multi_get_transaction_checkpoint(&remaining) {
4109                Ok(found) => found,
4110                // The table handles were already released. They are released
4111                // long after the epoch's checkpoints are executed, so nothing
4112                // waited on here can still be checkpointed in the old epoch;
4113                // move on to the next store.
4114                Err(IotaError::EpochEnded(_)) => vec![None; remaining.len()],
4115                Err(err) => return Err(err),
4116            };
4117            let mut still_uncheckpointed = Vec::new();
4118            for (digest, found_seq) in remaining.iter().zip(found) {
4119                match found_seq {
4120                    Some(seq) => {
4121                        let ts = self
4122                            .checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache);
4123                        results.insert(*digest, (seq, ts));
4124                    }
4125                    None => still_uncheckpointed.push(*digest),
4126                }
4127            }
4128            remaining = still_uncheckpointed;
4129            if remaining.is_empty() {
4130                return Ok(results);
4131            }
4132
4133            match self
4134                .wait_for_next_epoch_store(epoch_store.epoch(), deadline)
4135                .await
4136            {
4137                Some(next) => epoch_store = next,
4138                None => return Ok(results),
4139            }
4140        }
4141    }
4142
4143    /// Wait for the epoch store to be swapped to an epoch later than
4144    /// `prev_epoch`, returning `None` if `deadline` passes first.
4145    async fn wait_for_next_epoch_store(
4146        &self,
4147        prev_epoch: EpochId,
4148        deadline: tokio::time::Instant,
4149    ) -> Option<Arc<AuthorityPerEpochStore>> {
4150        // There is no notification for the epoch-store swap, and termination
4151        // and swap can come in either order (`reconfigure` terminates the old
4152        // epoch first, `reconfigure_for_testing` swaps first), so the swap is
4153        // polled at this interval.
4154        const EPOCH_STORE_SWAP_POLL_INTERVAL: Duration = Duration::from_millis(100);
4155
4156        loop {
4157            // Deliberately re-loaded on each poll; the one-call-per-task rule
4158            // guards against *unaware* mixing of epoch stores within a task.
4159            let current = self.load_epoch_store_one_call_per_task().clone();
4160            if current.epoch() > prev_epoch {
4161                return Some(current);
4162            }
4163            if tokio::time::Instant::now() >= deadline {
4164                return None;
4165            }
4166            tokio::time::sleep(EPOCH_STORE_SWAP_POLL_INTERVAL).await;
4167        }
4168    }
4169
4170    /// Resolve a checkpoint's timestamp, memoizing lookups in `cache` so
4171    /// multiple transactions in the same checkpoint trigger a single
4172    /// checkpoint summary lookup.
4173    fn checkpoint_timestamp_ms_cached(
4174        &self,
4175        seq: CheckpointSequenceNumber,
4176        cache: &mut HashMap<CheckpointSequenceNumber, u64>,
4177    ) -> u64 {
4178        *cache.entry(seq).or_insert_with(|| {
4179            self.get_checkpoint_by_sequence_number(seq)
4180                .ok()
4181                .flatten()
4182                .map(|c| c.timestamp_ms)
4183                .unwrap_or(0)
4184        })
4185    }
4186
4187    #[instrument(level = "trace", skip_all)]
4188    pub fn get_transaction_checkpoint_for_tests(
4189        &self,
4190        digest: &TransactionDigest,
4191        epoch_store: &AuthorityPerEpochStore,
4192    ) -> IotaResult<Option<VerifiedCheckpoint>> {
4193        let checkpoint = epoch_store.get_transaction_checkpoint(digest)?;
4194        let Some(checkpoint) = checkpoint else {
4195            return Ok(None);
4196        };
4197        let checkpoint = self
4198            .checkpoint_store
4199            .get_checkpoint_by_sequence_number(checkpoint)?;
4200        Ok(checkpoint)
4201    }
4202
4203    #[instrument(level = "trace", skip_all)]
4204    pub fn get_object_read(&self, object_id: &ObjectId) -> IotaResult<ObjectRead> {
4205        Ok(
4206            match self
4207                .get_object_cache_reader()
4208                .try_get_latest_object_or_tombstone(*object_id)?
4209            {
4210                Some((_, ObjectOrTombstone::Object(object))) => {
4211                    let layout = self.get_object_layout(&object)?;
4212                    ObjectRead::Exists(object.object_ref(), object, layout)
4213                }
4214                Some((_, ObjectOrTombstone::Tombstone(objref))) => ObjectRead::Deleted(objref),
4215                None => ObjectRead::NotExists(*object_id),
4216            },
4217        )
4218    }
4219
4220    /// Chain Identifier is the digest of the genesis checkpoint.
4221    pub fn get_chain_identifier(&self) -> ChainIdentifier {
4222        self.chain_identifier
4223    }
4224
4225    #[instrument(level = "trace", skip_all)]
4226    pub fn get_move_object<T>(&self, object_id: &ObjectId) -> IotaResult<T>
4227    where
4228        T: DeserializeOwned,
4229    {
4230        let o = self.get_object_read(object_id)?.into_object()?;
4231        if let Some(move_object) = o.data.as_opt_struct() {
4232            Ok(bcs::from_bytes(move_object.contents()).map_err(|e| {
4233                IotaError::ObjectDeserialization {
4234                    error: format!("{e}"),
4235                }
4236            })?)
4237        } else {
4238            Err(IotaError::ObjectDeserialization {
4239                error: format!("Provided object : [{object_id}] is not a Move object."),
4240            })
4241        }
4242    }
4243
4244    /// This function aims to serve rpc reads on past objects and
4245    /// we don't expect it to be called for other purposes.
4246    /// Depending on the object pruning policies that will be enforced in the
4247    /// future there is no software-level guarantee/SLA to retrieve an object
4248    /// with an old version even if it exists/existed.
4249    #[instrument(level = "trace", skip_all)]
4250    pub fn get_past_object_read(
4251        &self,
4252        object_id: &ObjectId,
4253        version: Version,
4254    ) -> IotaResult<PastObjectRead> {
4255        // Firstly we see if the object ever existed by getting its latest data
4256        let Some(obj_ref) = self
4257            .get_object_cache_reader()
4258            .try_get_latest_object_ref_or_tombstone(*object_id)?
4259        else {
4260            return Ok(PastObjectRead::ObjectNotExists(*object_id));
4261        };
4262
4263        if version > obj_ref.version {
4264            return Ok(PastObjectRead::VersionTooHigh {
4265                object_id: *object_id,
4266                asked_version: version,
4267                latest_version: obj_ref.version,
4268            });
4269        }
4270
4271        if version < obj_ref.version {
4272            // Read past objects
4273            return Ok(match self.read_object_at_version(object_id, version)? {
4274                Some((object, layout)) => {
4275                    let obj_ref = object.object_ref();
4276                    PastObjectRead::VersionFound(obj_ref, object, layout)
4277                }
4278
4279                None => PastObjectRead::VersionNotFound(*object_id, version),
4280            });
4281        }
4282
4283        if !obj_ref.digest.is_alive() {
4284            return Ok(PastObjectRead::ObjectDeleted(obj_ref));
4285        }
4286
4287        match self.read_object_at_version(object_id, obj_ref.version)? {
4288            Some((object, layout)) => Ok(PastObjectRead::VersionFound(obj_ref, object, layout)),
4289            None => {
4290                debug_fatal!(
4291                    "Object with in parent_entry is missing from object store, datastore is \
4292                     inconsistent",
4293                );
4294                Err(UserInputError::ObjectNotFound {
4295                    object_id: *object_id,
4296                    version: Some(obj_ref.version),
4297                }
4298                .into())
4299            }
4300        }
4301    }
4302
4303    #[instrument(level = "trace", skip_all)]
4304    fn read_object_at_version(
4305        &self,
4306        object_id: &ObjectId,
4307        version: Version,
4308    ) -> IotaResult<Option<(Object, Option<MoveStructLayout>)>> {
4309        let Some(object) = self
4310            .get_object_cache_reader()
4311            .try_get_object_by_key(object_id, version)?
4312        else {
4313            return Ok(None);
4314        };
4315
4316        let layout = self.get_object_layout(&object)?;
4317        Ok(Some((object, layout)))
4318    }
4319
4320    fn get_object_layout(&self, object: &Object) -> IotaResult<Option<MoveStructLayout>> {
4321        let layout = object
4322            .data
4323            .as_opt_struct()
4324            .map(|object| {
4325                into_struct_layout(
4326                    self.load_epoch_store_one_call_per_task()
4327                        .executor()
4328                        // TODO(cache) - must read through cache
4329                        .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
4330                        .get_annotated_layout(object.struct_tag())?,
4331                )
4332            })
4333            .transpose()?;
4334        Ok(layout)
4335    }
4336
4337    fn get_owner_at_version(&self, object_id: &ObjectId, version: Version) -> IotaResult<Owner> {
4338        self.get_object_store()
4339            .try_get_object_by_key(object_id, version)?
4340            .ok_or_else(|| {
4341                IotaError::from(UserInputError::ObjectNotFound {
4342                    object_id: *object_id,
4343                    version: Some(version),
4344                })
4345            })
4346            .map(|o| o.owner)
4347    }
4348
4349    #[instrument(level = "trace", skip_all)]
4350    pub fn get_owner_objects(
4351        &self,
4352        owner: Address,
4353        // If `Some`, the query will start from the next item after the specified cursor
4354        cursor: Option<ObjectId>,
4355        limit: usize,
4356        filter: Option<IotaObjectDataFilter>,
4357    ) -> IotaResult<Vec<ObjectInfo>> {
4358        if let Some(indexes) = &self.indexes {
4359            indexes.get_owner_objects(owner, cursor, limit, filter)
4360        } else {
4361            Err(IotaError::IndexStoreNotAvailable)
4362        }
4363    }
4364
4365    #[instrument(level = "trace", skip_all)]
4366    pub fn get_owned_coins_iterator_with_cursor(
4367        &self,
4368        owner: Address,
4369        // If `Some`, the query will start from the next item after the specified cursor
4370        cursor: (String, ObjectId),
4371        limit: usize,
4372        one_coin_type_only: bool,
4373    ) -> IotaResult<impl Iterator<Item = (String, ObjectId, CoinInfo)> + '_> {
4374        if let Some(indexes) = &self.indexes {
4375            indexes.get_owned_coins_iterator_with_cursor(owner, cursor, limit, one_coin_type_only)
4376        } else {
4377            Err(IotaError::IndexStoreNotAvailable)
4378        }
4379    }
4380
4381    #[instrument(level = "trace", skip_all)]
4382    pub fn get_owner_objects_iterator(
4383        &self,
4384        owner: Address,
4385        // If `Some`, the query will start from the next item after the specified cursor
4386        cursor: Option<ObjectId>,
4387        filter: Option<IotaObjectDataFilter>,
4388    ) -> IotaResult<impl Iterator<Item = ObjectInfo> + '_> {
4389        if let Some(indexes) = &self.indexes {
4390            indexes.get_owner_objects_iterator(owner, cursor, filter)
4391        } else {
4392            Err(IotaError::IndexStoreNotAvailable)
4393        }
4394    }
4395
4396    #[instrument(level = "trace", skip_all)]
4397    pub fn get_move_objects<T>(&self, owner: Address, tag: StructTag) -> IotaResult<Vec<T>>
4398    where
4399        T: DeserializeOwned,
4400    {
4401        let object_ids = self
4402            .get_owner_objects_iterator(owner, None, None)?
4403            .filter(|o| match &o.object_type {
4404                ObjectType::Struct(s) => *s == tag,
4405                ObjectType::Package => false,
4406            })
4407            .map(|info| ObjectKey(info.object_id, info.version))
4408            .collect::<Vec<_>>();
4409        let mut move_objects = vec![];
4410
4411        let objects = self
4412            .get_object_store()
4413            .try_multi_get_objects_by_key(&object_ids)?;
4414
4415        for (o, id) in objects.into_iter().zip(object_ids) {
4416            let object = o.ok_or_else(|| {
4417                IotaError::from(UserInputError::ObjectNotFound {
4418                    object_id: id.0,
4419                    version: Some(id.1),
4420                })
4421            })?;
4422            let move_object = object.data.as_opt_struct().ok_or_else(|| {
4423                IotaError::from(UserInputError::MovePackageAsObject { object_id: id.0 })
4424            })?;
4425            move_objects.push(bcs::from_bytes(move_object.contents()).map_err(|e| {
4426                IotaError::ObjectDeserialization {
4427                    error: format!("{e}"),
4428                }
4429            })?);
4430        }
4431        Ok(move_objects)
4432    }
4433
4434    #[instrument(level = "trace", skip_all)]
4435    pub fn get_dynamic_fields(
4436        &self,
4437        owner: ObjectId,
4438        // If `Some`, the query will start from the next item after the specified cursor
4439        cursor: Option<ObjectId>,
4440        limit: usize,
4441    ) -> IotaResult<Vec<(ObjectId, DynamicFieldInfo)>> {
4442        Ok(self
4443            .get_dynamic_fields_iterator(owner, cursor)?
4444            .take(limit)
4445            .collect::<Result<Vec<_>, _>>()?)
4446    }
4447
4448    fn get_dynamic_fields_iterator(
4449        &self,
4450        owner: ObjectId,
4451        // If `Some`, the query will start from the next item after the specified cursor
4452        cursor: Option<ObjectId>,
4453    ) -> IotaResult<impl Iterator<Item = Result<(ObjectId, DynamicFieldInfo), TypedStoreError>> + '_>
4454    {
4455        if let Some(indexes) = &self.indexes {
4456            indexes.get_dynamic_fields_iterator(owner, cursor)
4457        } else {
4458            Err(IotaError::IndexStoreNotAvailable)
4459        }
4460    }
4461
4462    #[instrument(level = "trace", skip_all)]
4463    pub fn get_dynamic_field_object_id(
4464        &self,
4465        owner: ObjectId,
4466        name_type: TypeTag,
4467        name_bcs_bytes: &[u8],
4468    ) -> IotaResult<Option<ObjectId>> {
4469        if let Some(indexes) = &self.indexes {
4470            indexes.get_dynamic_field_object_id(owner, name_type, name_bcs_bytes)
4471        } else {
4472            Err(IotaError::IndexStoreNotAvailable)
4473        }
4474    }
4475
4476    #[instrument(level = "trace", skip_all)]
4477    pub fn get_total_transaction_blocks(&self) -> IotaResult<u64> {
4478        Ok(self.get_indexes()?.next_sequence_number())
4479    }
4480
4481    #[instrument(level = "trace", skip_all)]
4482    pub async fn get_executed_transaction_and_effects(
4483        &self,
4484        digest: TransactionDigest,
4485        kv_store: Arc<TransactionKeyValueStore>,
4486    ) -> IotaResult<(TransactionEnvelope, TransactionEffects)> {
4487        let transaction = kv_store.get_tx(digest).await?;
4488        let effects = kv_store.get_fx_by_tx_digest(digest).await?;
4489        Ok((transaction, effects))
4490    }
4491
4492    #[instrument(level = "trace", skip_all)]
4493    pub fn multi_get_checkpoint_by_sequence_number(
4494        &self,
4495        sequence_numbers: &[CheckpointSequenceNumber],
4496    ) -> IotaResult<Vec<Option<VerifiedCheckpoint>>> {
4497        Ok(self
4498            .checkpoint_store
4499            .multi_get_checkpoint_by_sequence_number(sequence_numbers)?)
4500    }
4501
4502    #[instrument(level = "trace", skip_all)]
4503    pub fn get_transaction_events(
4504        &self,
4505        digest: &TransactionDigest,
4506    ) -> IotaResult<TransactionEvents> {
4507        self.get_transaction_cache_reader()
4508            .try_get_events(digest)?
4509            .ok_or(IotaError::TransactionEventsNotFound { digest: *digest })
4510    }
4511
4512    pub fn get_transaction_input_objects(
4513        &self,
4514        effects: &TransactionEffects,
4515    ) -> anyhow::Result<Vec<Object>> {
4516        iota_types::storage::get_transaction_input_objects(self.get_object_store(), effects)
4517            .map_err(Into::into)
4518    }
4519
4520    pub fn get_transaction_output_objects(
4521        &self,
4522        effects: &TransactionEffects,
4523    ) -> anyhow::Result<Vec<Object>> {
4524        iota_types::storage::get_transaction_output_objects(self.get_object_store(), effects)
4525            .map_err(Into::into)
4526    }
4527
4528    fn get_indexes(&self) -> IotaResult<Arc<IndexStore>> {
4529        match &self.indexes {
4530            Some(i) => Ok(i.clone()),
4531            None => Err(IotaError::UnsupportedFeature {
4532                error: "extended object indexing is not enabled on this server".into(),
4533            }),
4534        }
4535    }
4536
4537    pub async fn get_transactions_for_tests(
4538        self: &Arc<Self>,
4539        filter: Option<TransactionFilter>,
4540        cursor: Option<TransactionDigest>,
4541        limit: Option<usize>,
4542        reverse: bool,
4543    ) -> IotaResult<Vec<TransactionDigest>> {
4544        let metrics = KeyValueStoreMetrics::new_for_tests();
4545        let kv_store = Arc::new(TransactionKeyValueStore::new(
4546            "rocksdb",
4547            metrics,
4548            self.clone(),
4549        ));
4550        self.get_transactions(&kv_store, filter, cursor, limit, reverse)
4551            .await
4552    }
4553
4554    #[instrument(level = "trace", skip_all)]
4555    pub async fn get_transactions(
4556        &self,
4557        kv_store: &Arc<TransactionKeyValueStore>,
4558        filter: Option<TransactionFilter>,
4559        // If `Some`, the query will start from the next item after the specified cursor
4560        cursor: Option<TransactionDigest>,
4561        limit: Option<usize>,
4562        reverse: bool,
4563    ) -> IotaResult<Vec<TransactionDigest>> {
4564        if let Some(TransactionFilter::Checkpoint(sequence_number)) = filter {
4565            let checkpoint_contents = kv_store.get_checkpoint_contents(sequence_number).await?;
4566            let iter = checkpoint_contents.iter().map(|c| c.transaction);
4567            if reverse {
4568                let iter = iter
4569                    .rev()
4570                    .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4571                    .skip(usize::from(cursor.is_some()));
4572                return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4573            } else {
4574                let iter = iter
4575                    .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4576                    .skip(usize::from(cursor.is_some()));
4577                return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4578            }
4579        }
4580        self.get_indexes()?
4581            .get_transactions(filter, cursor, limit, reverse)
4582    }
4583
4584    pub fn get_checkpoint_store(&self) -> &Arc<CheckpointStore> {
4585        &self.checkpoint_store
4586    }
4587
4588    /// The store pruner; the checkpoint executor uses it to nudge the pruner
4589    /// after each checkpoint.
4590    pub fn pruner(&self) -> &AuthorityStorePruner {
4591        &self.pruner
4592    }
4593
4594    /// Keeps the object versions that transactions in the highest executed
4595    /// checkpoint, and in every later one, supersede readable until the
4596    /// returned guard is dropped. Take it before submitting a transaction whose
4597    /// input or output objects are read from the store once it is
4598    /// checkpointed.
4599    pub fn retain_objects(&self) -> ObjectRetentionGuard {
4600        self.pruner.retain_objects()
4601    }
4602
4603    pub fn get_latest_checkpoint_sequence_number(&self) -> IotaResult<CheckpointSequenceNumber> {
4604        self.get_checkpoint_store()
4605            .get_highest_executed_checkpoint_seq_number()?
4606            .ok_or(IotaError::UserInput {
4607                error: UserInputError::LatestCheckpointSequenceNumberNotFound,
4608            })
4609    }
4610
4611    #[cfg(msim)]
4612    pub fn get_highest_pruned_checkpoint_for_testing(
4613        &self,
4614    ) -> IotaResult<CheckpointSequenceNumber> {
4615        self.database_for_testing()
4616            .perpetual_tables
4617            .get_highest_pruned_checkpoint()
4618            .map(|c| c.unwrap_or(0))
4619            .map_err(Into::into)
4620    }
4621
4622    #[instrument(level = "trace", skip_all)]
4623    pub fn get_checkpoint_summary_by_sequence_number(
4624        &self,
4625        sequence_number: CheckpointSequenceNumber,
4626    ) -> IotaResult<CheckpointSummary> {
4627        let verified_checkpoint = self
4628            .get_checkpoint_store()
4629            .get_checkpoint_by_sequence_number(sequence_number)?;
4630        match verified_checkpoint {
4631            Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4632            None => Err(IotaError::UserInput {
4633                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4634            }),
4635        }
4636    }
4637
4638    #[instrument(level = "trace", skip_all)]
4639    pub fn get_checkpoint_summary_by_digest(
4640        &self,
4641        digest: CheckpointDigest,
4642    ) -> IotaResult<CheckpointSummary> {
4643        let verified_checkpoint = self
4644            .get_checkpoint_store()
4645            .get_checkpoint_by_digest(&digest)?;
4646        match verified_checkpoint {
4647            Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4648            None => Err(IotaError::UserInput {
4649                error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4650            }),
4651        }
4652    }
4653
4654    #[instrument(level = "trace", skip_all)]
4655    pub fn find_publish_txn_digest(&self, package_id: ObjectId) -> IotaResult<TransactionDigest> {
4656        if package_id.is_system_package() {
4657            return self.find_genesis_txn_digest();
4658        }
4659        Ok(self
4660            .get_object_read(&package_id)?
4661            .into_object()?
4662            .previous_transaction)
4663    }
4664
4665    #[instrument(level = "trace", skip_all)]
4666    pub fn find_genesis_txn_digest(&self) -> IotaResult<TransactionDigest> {
4667        let summary = self
4668            .get_verified_checkpoint_by_sequence_number(0)?
4669            .into_message();
4670        let content = self.get_checkpoint_contents(summary.contents_digest)?;
4671        let genesis_transaction = content.enumerate_transactions(&summary).next();
4672        Ok(genesis_transaction
4673            .ok_or(IotaError::UserInput {
4674                error: UserInputError::GenesisTransactionNotFound,
4675            })?
4676            .1
4677            .transaction)
4678    }
4679
4680    #[instrument(level = "trace", skip_all)]
4681    pub fn get_verified_checkpoint_by_sequence_number(
4682        &self,
4683        sequence_number: CheckpointSequenceNumber,
4684    ) -> IotaResult<VerifiedCheckpoint> {
4685        let verified_checkpoint = self
4686            .get_checkpoint_store()
4687            .get_checkpoint_by_sequence_number(sequence_number)?;
4688        match verified_checkpoint {
4689            Some(verified_checkpoint) => Ok(verified_checkpoint),
4690            None => Err(IotaError::UserInput {
4691                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4692            }),
4693        }
4694    }
4695
4696    #[instrument(level = "trace", skip_all)]
4697    pub fn get_verified_checkpoint_summary_by_digest(
4698        &self,
4699        digest: CheckpointDigest,
4700    ) -> IotaResult<VerifiedCheckpoint> {
4701        let verified_checkpoint = self
4702            .get_checkpoint_store()
4703            .get_checkpoint_by_digest(&digest)?;
4704        match verified_checkpoint {
4705            Some(verified_checkpoint) => Ok(verified_checkpoint),
4706            None => Err(IotaError::UserInput {
4707                error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4708            }),
4709        }
4710    }
4711
4712    #[instrument(level = "trace", skip_all)]
4713    pub fn get_checkpoint_contents(
4714        &self,
4715        digest: CheckpointContentsDigest,
4716    ) -> IotaResult<CheckpointContents> {
4717        self.get_checkpoint_store()
4718            .get_checkpoint_contents(&digest)?
4719            .ok_or(IotaError::UserInput {
4720                error: UserInputError::CheckpointContentsNotFound(digest),
4721            })
4722    }
4723
4724    #[instrument(level = "trace", skip_all)]
4725    pub fn get_checkpoint_contents_by_sequence_number(
4726        &self,
4727        sequence_number: CheckpointSequenceNumber,
4728    ) -> IotaResult<CheckpointContents> {
4729        let verified_checkpoint = self
4730            .get_checkpoint_store()
4731            .get_checkpoint_by_sequence_number(sequence_number)?;
4732        match verified_checkpoint {
4733            Some(verified_checkpoint) => {
4734                let contents_digest = verified_checkpoint.into_inner().contents_digest;
4735                self.get_checkpoint_contents(contents_digest)
4736            }
4737            None => Err(IotaError::UserInput {
4738                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4739            }),
4740        }
4741    }
4742
4743    #[instrument(level = "trace", skip_all)]
4744    pub async fn query_events(
4745        &self,
4746        kv_store: &Arc<TransactionKeyValueStore>,
4747        query: EventFilter,
4748        // If `Some`, the query will start from the next item after the specified cursor
4749        cursor: Option<EventID>,
4750        limit: usize,
4751        descending: bool,
4752    ) -> IotaResult<Vec<IotaEvent>> {
4753        let index_store = self.get_indexes()?;
4754
4755        // Get the tx_num from tx_digest
4756        let (tx_num, event_num) = if let Some(cursor) = cursor.as_ref() {
4757            let tx_seq = index_store.get_transaction_seq(&cursor.tx_digest)?.ok_or(
4758                IotaError::TransactionNotFound {
4759                    digest: cursor.tx_digest,
4760                },
4761            )?;
4762            (tx_seq, cursor.event_seq as usize)
4763        } else if descending {
4764            (u64::MAX, usize::MAX)
4765        } else {
4766            (0, 0)
4767        };
4768
4769        let limit = limit + 1;
4770        let mut event_keys = match query {
4771            EventFilter::All(filters) => {
4772                if filters.is_empty() {
4773                    index_store.all_events(tx_num, event_num, limit, descending)?
4774                } else {
4775                    return Err(IotaError::UserInput {
4776                        error: UserInputError::Unsupported(
4777                            "This query type does not currently support filter combinations"
4778                                .to_string(),
4779                        ),
4780                    });
4781                }
4782            }
4783            EventFilter::Transaction(digest) => {
4784                index_store.events_by_transaction(&digest, tx_num, event_num, limit, descending)?
4785            }
4786            EventFilter::MoveModule { package, module } => {
4787                let module_id = ModuleId::new(
4788                    AccountAddress::new(package.into_bytes()),
4789                    move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4790                );
4791                index_store.events_by_module_id(&module_id, tx_num, event_num, limit, descending)?
4792            }
4793            EventFilter::MoveEventType(struct_name) => index_store
4794                .events_by_move_event_struct_name(
4795                    &struct_name,
4796                    tx_num,
4797                    event_num,
4798                    limit,
4799                    descending,
4800                )?,
4801            EventFilter::Sender(sender) => {
4802                index_store.events_by_sender(&sender, tx_num, event_num, limit, descending)?
4803            }
4804            EventFilter::TimeRange {
4805                start_time,
4806                end_time,
4807            } => index_store
4808                .event_iterator(start_time, end_time, tx_num, event_num, limit, descending)?,
4809            EventFilter::MoveEventModule { package, module } => index_store
4810                .events_by_move_event_module(
4811                    &ModuleId::new(
4812                        AccountAddress::new(package.into_bytes()),
4813                        move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4814                    ),
4815                    tx_num,
4816                    event_num,
4817                    limit,
4818                    descending,
4819                )?,
4820            // not using "_ =>" because we want to make sure we remember to add new variants here
4821            EventFilter::Package(_)
4822            | EventFilter::MoveEventField { .. }
4823            | EventFilter::Any(_)
4824            | EventFilter::And(_, _)
4825            | EventFilter::Or(_, _) => {
4826                return Err(IotaError::UserInput {
4827                    error: UserInputError::Unsupported(
4828                        "This query type is not supported by the full node.".to_string(),
4829                    ),
4830                });
4831            }
4832        };
4833
4834        // skip one event if exclusive cursor is provided,
4835        // otherwise truncate to the original limit.
4836        if cursor.is_some() {
4837            if !event_keys.is_empty() {
4838                event_keys.remove(0);
4839            }
4840        } else {
4841            event_keys.truncate(limit - 1);
4842        }
4843
4844        // get the unique set of digests from the event_keys
4845        let transaction_digests = event_keys
4846            .iter()
4847            .map(|(_, digest, _, _)| *digest)
4848            .collect::<HashSet<_>>()
4849            .into_iter()
4850            .collect::<Vec<_>>();
4851
4852        let events = kv_store
4853            .multi_get_events_by_tx_digests(&transaction_digests)
4854            .await?;
4855
4856        let events_map: HashMap<_, _> =
4857            transaction_digests.iter().zip(events.into_iter()).collect();
4858
4859        let stored_events = event_keys
4860            .into_iter()
4861            .map(|k| {
4862                (
4863                    k,
4864                    events_map
4865                        .get(&k.1)
4866                        .expect("fetched digest is missing")
4867                        .clone()
4868                        .and_then(|e| e.get(k.2).cloned()),
4869                )
4870            })
4871            .map(
4872                |((_event_digest, tx_digest, event_seq, timestamp), event)| {
4873                    event
4874                        .map(|e| (e, tx_digest, event_seq, timestamp))
4875                        .ok_or(IotaError::TransactionEventsNotFound { digest: tx_digest })
4876                },
4877            )
4878            .collect::<Result<Vec<_>, _>>()?;
4879
4880        let epoch_store = self.load_epoch_store_one_call_per_task();
4881        let backing_store = self.get_backing_package_store().as_ref();
4882        let mut layout_resolver = epoch_store
4883            .executor()
4884            .type_layout_resolver(Box::new(backing_store));
4885        let mut events = vec![];
4886        for (e, tx_digest, event_seq, timestamp) in stored_events.into_iter() {
4887            events.push(IotaEvent::try_from(
4888                e.clone(),
4889                tx_digest,
4890                event_seq as u64,
4891                Some(timestamp),
4892                layout_resolver.get_annotated_layout(&e.struct_tag)?,
4893            )?)
4894        }
4895        Ok(events)
4896    }
4897
4898    pub fn insert_genesis_object(&self, object: Object) {
4899        self.get_reconfig_api()
4900            .try_insert_genesis_object(object)
4901            .expect("Cannot insert genesis object")
4902    }
4903
4904    pub fn insert_genesis_objects(&self, objects: &[Object]) {
4905        for o in objects {
4906            self.insert_genesis_object(o.clone());
4907        }
4908    }
4909
4910    /// Make a status response for a transaction
4911    #[instrument(level = "trace", skip_all)]
4912    pub fn get_transaction_status(
4913        &self,
4914        transaction_digest: &TransactionDigest,
4915        epoch_store: &Arc<AuthorityPerEpochStore>,
4916    ) -> IotaResult<Option<(SenderSignedTransaction, TransactionStatus)>> {
4917        // TODO: In the case of read path, we should not have to re-sign the effects.
4918        if let Some(effects) =
4919            self.get_signed_effects_and_maybe_resign(transaction_digest, epoch_store)?
4920        {
4921            if let Some(transaction) = self
4922                .get_transaction_cache_reader()
4923                .try_get_transaction_block(transaction_digest)?
4924            {
4925                let cert_sig = epoch_store.get_transaction_cert_sig(transaction_digest)?;
4926                let events = if effects.events_digest().is_some() {
4927                    self.get_transaction_events(effects.transaction_digest())?
4928                } else {
4929                    TransactionEvents::default()
4930                };
4931                return Ok(Some((
4932                    (*transaction).clone().into_message(),
4933                    TransactionStatus::Executed(cert_sig, effects.into_inner(), events),
4934                )));
4935            } else {
4936                // The read of effects and read of transaction are not atomic. It's possible
4937                // that we reverted the transaction (during epoch change) in
4938                // between the above two reads, and we end up having effects but
4939                // not transaction. In this case, we just fall through.
4940                debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
4941            }
4942        }
4943        if let Some(signed) = epoch_store.get_signed_transaction(transaction_digest)? {
4944            self.metrics.tx_already_processed.inc();
4945            let (transaction, sig) = signed.into_inner().into_data_and_sig();
4946            Ok(Some((transaction, TransactionStatus::Signed(sig))))
4947        } else {
4948            Ok(None)
4949        }
4950    }
4951
4952    /// Get the signed effects of the given transaction. If the effects was
4953    /// signed in a previous epoch, re-sign it so that the caller is able to
4954    /// form a cert of the effects in the current epoch.
4955    #[instrument(level = "trace", skip_all)]
4956    pub fn get_signed_effects_and_maybe_resign(
4957        &self,
4958        transaction_digest: &TransactionDigest,
4959        epoch_store: &Arc<AuthorityPerEpochStore>,
4960    ) -> IotaResult<Option<VerifiedSignedTransactionEffects>> {
4961        let effects = self
4962            .get_transaction_cache_reader()
4963            .try_get_executed_effects(transaction_digest)?;
4964        match effects {
4965            Some(effects) => {
4966                // If the transaction was executed in previous epochs, the validator will
4967                // re-sign the effects with new current epoch so that a client is always able to
4968                // obtain an effects certificate at the current epoch.
4969                //
4970                // Why is this necessary? Consider the following case:
4971                // - assume there are 4 validators
4972                // - Quorum driver gets 2 signed effects before reconfig halt
4973                // - The tx makes it into final checkpoint.
4974                // - 2 validators go away and are replaced in the new epoch.
4975                // - The new epoch begins.
4976                // - The quorum driver cannot complete the partial effects cert from the previous
4977                //   epoch, because it may not be able to reach either of the 2 former validators.
4978                // - But, if the 2 validators that stayed are willing to re-sign the effects in the
4979                //   new epoch, the QD can make a new effects cert and return it to the client.
4980                //
4981                // This is a considered a short-term workaround. Eventually, Quorum Driver
4982                // should be able to return either an effects certificate, -or-
4983                // a proof of inclusion in a checkpoint. In the case above, the
4984                // Quorum Driver would return a proof of inclusion in the final
4985                // checkpoint, and this code would no longer be necessary.
4986                if effects.epoch() != epoch_store.epoch() {
4987                    debug!(
4988                        tx_digest=?transaction_digest,
4989                        effects_epoch=?effects.epoch(),
4990                        epoch=?epoch_store.epoch(),
4991                        "Re-signing the effects with the current epoch"
4992                    );
4993                }
4994                Ok(Some(self.sign_effects(effects, epoch_store)?))
4995            }
4996            None => Ok(None),
4997        }
4998    }
4999
5000    /// A client aggregating effects signatures towards a quorum assumes
5001    /// finality once it collects 2f+1 of them, so within an epoch this
5002    /// validator must never assert two different effects for the same
5003    /// transaction on any RPC surface, signed or unsigned. Executed effects
5004    /// can change across a restart if an uncommitted transaction is
5005    /// re-executed with divergent results (e.g. by a new binary), so every
5006    /// effects-reporting path calls this before returning effects, and
5007    /// refuses to contradict a signature that may already be in a client's
5008    /// hands.
5009    pub fn check_effects_against_previously_signed(
5010        &self,
5011        epoch_store: &AuthorityPerEpochStore,
5012        tx_digest: &TransactionDigest,
5013        effects_digest: &TransactionEffectsDigest,
5014        surface: &'static str,
5015    ) -> IotaResult<()> {
5016        if let Some(previously_signed_digest) = epoch_store.get_signed_effects_digest(tx_digest)? {
5017            if previously_signed_digest != *effects_digest {
5018                self.metrics
5019                    .signed_effects_equivocation_prevented
5020                    .with_label_values(&[surface])
5021                    .inc();
5022                error!(
5023                    ?tx_digest,
5024                    ?previously_signed_digest,
5025                    executed_digest = ?effects_digest,
5026                    surface,
5027                    "refusing to report effects that differ from previously signed effects"
5028                );
5029                return Err(IotaError::GenericAuthority {
5030                    error: format!(
5031                        "Refusing to report effects for transaction {tx_digest}: effects digest \
5032                         {effects_digest} differs from previously signed effects digest \
5033                         {previously_signed_digest}"
5034                    ),
5035                });
5036            }
5037        }
5038        Ok(())
5039    }
5040
5041    #[instrument(level = "trace", skip_all)]
5042    pub(crate) fn sign_effects(
5043        &self,
5044        effects: TransactionEffects,
5045        epoch_store: &Arc<AuthorityPerEpochStore>,
5046    ) -> IotaResult<VerifiedSignedTransactionEffects> {
5047        let tx_digest = *effects.transaction_digest();
5048
5049        self.check_effects_against_previously_signed(
5050            epoch_store,
5051            &tx_digest,
5052            &effects.digest(),
5053            "sign_effects",
5054        )?;
5055
5056        let signed_effects = match epoch_store.get_effects_signature(&tx_digest)? {
5057            Some(sig) => {
5058                debug_assert!(sig.epoch == epoch_store.epoch());
5059                SignedTransactionEffects::new_from_data_and_sig(effects, sig)
5060            }
5061            _ => {
5062                let sig = AuthoritySignInfo::new(
5063                    epoch_store.epoch(),
5064                    &effects,
5065                    Intent::iota_app(IntentScope::TransactionEffects),
5066                    self.name,
5067                    &*self.secret,
5068                );
5069
5070                let effects = SignedTransactionEffects::new_from_data_and_sig(effects, sig.clone());
5071
5072                epoch_store.insert_effects_digest_and_signature(
5073                    &tx_digest,
5074                    effects.digest(),
5075                    &sig,
5076                )?;
5077
5078                effects
5079            }
5080        };
5081
5082        Ok(VerifiedSignedTransactionEffects::new_unchecked(
5083            signed_effects,
5084        ))
5085    }
5086
5087    // Returns coin objects for indexing for fullnode if indexing is enabled.
5088    #[instrument(level = "trace", skip_all)]
5089    fn fullnode_only_get_tx_coins_for_indexing(
5090        &self,
5091        effects: &TransactionEffects,
5092        inner_temporary_store: &InnerTemporaryStore,
5093        epoch_store: &Arc<AuthorityPerEpochStore>,
5094    ) -> Option<TxCoins> {
5095        if self.indexes.is_none() || self.is_committee_validator(epoch_store) {
5096            return None;
5097        }
5098        let written_coin_objects = inner_temporary_store
5099            .written
5100            .iter()
5101            .filter_map(|(k, v)| {
5102                if v.is_coin() {
5103                    Some((*k, v.clone()))
5104                } else {
5105                    None
5106                }
5107            })
5108            .collect();
5109        let mut input_coin_objects = inner_temporary_store
5110            .input_objects
5111            .iter()
5112            .filter_map(|(k, v)| {
5113                if v.is_coin() {
5114                    Some((*k, v.clone()))
5115                } else {
5116                    None
5117                }
5118            })
5119            .collect::<ObjectMap>();
5120
5121        // Check for receiving objects that were actually used and modified during
5122        // execution. Their updated version will already showup in
5123        // "written_coins" but their input isn't included in the set of input
5124        // objects in a inner_temporary_store.
5125        for modified in effects.modified_at_versions() {
5126            let (object_id, version) = (*modified.object_id(), modified.version());
5127            if inner_temporary_store
5128                .loaded_runtime_objects
5129                .contains_key(&object_id)
5130            {
5131                if let Some(object) = self
5132                    .get_object_store()
5133                    .get_object_by_key(&object_id, version)
5134                {
5135                    if object.is_coin() {
5136                        input_coin_objects.insert(object_id, object);
5137                    }
5138                }
5139            }
5140        }
5141
5142        Some((input_coin_objects, written_coin_objects))
5143    }
5144
5145    /// Get the transaction envelope that currently locks the given object, if
5146    /// any. Since object locks are only valid for one epoch, we also need
5147    /// the epoch_id in the query. Returns UserInputError::ObjectNotFound if
5148    /// no lock records for the given object can be found.
5149    /// Returns UserInputError::ObjectVersionUnavailableForConsumption if the
5150    /// object record is at a different version.
5151    /// Returns Some(VerifiedEnvelope) if the given ObjectReference is locked by
5152    /// a certain transaction. Returns None if the a lock record is
5153    /// initialized for the given ObjectReference but not yet locked by any
5154    /// transaction,     or cannot find the transaction in transaction
5155    /// table, because of data race etc.
5156    #[instrument(level = "trace", skip_all)]
5157    pub fn get_transaction_lock(
5158        &self,
5159        object_ref: &ObjectReference,
5160        epoch_store: &AuthorityPerEpochStore,
5161    ) -> IotaResult<Option<VerifiedSignedTransaction>> {
5162        let lock_info = self
5163            .get_object_cache_reader()
5164            .try_get_lock(*object_ref, epoch_store)?;
5165        let lock_info = match lock_info {
5166            ObjectLockStatus::LockedAtDifferentVersion { locked_ref } => {
5167                return Err(UserInputError::ObjectVersionUnavailableForConsumption {
5168                    provided_obj_ref: *object_ref,
5169                    current_version: locked_ref.version,
5170                }
5171                .into());
5172            }
5173            ObjectLockStatus::Initialized => {
5174                return Ok(None);
5175            }
5176            ObjectLockStatus::LockedToTx { locked_by_tx } => locked_by_tx,
5177        };
5178
5179        epoch_store.get_signed_transaction(&lock_info)
5180    }
5181
5182    pub fn try_get_objects(&self, objects: &[ObjectId]) -> IotaResult<Vec<Option<Object>>> {
5183        self.get_object_cache_reader().try_get_objects(objects)
5184    }
5185
5186    /// Non-fallible version of `try_get_objects`.
5187    pub fn get_objects(&self, objects: &[ObjectId]) -> Vec<Option<Object>> {
5188        self.try_get_objects(objects)
5189            .expect("storage access failed")
5190    }
5191
5192    pub fn try_get_object_or_tombstone(
5193        &self,
5194        object_id: ObjectId,
5195    ) -> IotaResult<Option<ObjectReference>> {
5196        self.get_object_cache_reader()
5197            .try_get_latest_object_ref_or_tombstone(object_id)
5198    }
5199
5200    /// Non-fallible version of `try_get_object_or_tombstone`.
5201    pub fn get_object_or_tombstone(&self, object_id: ObjectId) -> Option<ObjectReference> {
5202        self.try_get_object_or_tombstone(object_id)
5203            .expect("storage access failed")
5204    }
5205
5206    /// Ordinarily, protocol upgrades occur when 2f + 1 + (f *
5207    /// ProtocolConfig::buffer_stake_for_protocol_upgrade_bps) vote for the
5208    /// upgrade.
5209    ///
5210    /// This method can be used to dynamic adjust the amount of buffer. If set
5211    /// to 0, the upgrade will go through with only 2f+1 votes.
5212    ///
5213    /// IMPORTANT: If this is used, it must be used on >=2f+1 validators (all
5214    /// should have the same value), or you risk halting the chain.
5215    pub fn set_override_protocol_upgrade_buffer_stake(
5216        &self,
5217        expected_epoch: EpochId,
5218        buffer_stake_bps: u64,
5219    ) -> IotaResult {
5220        let epoch_store = self.load_epoch_store_one_call_per_task();
5221        let actual_epoch = epoch_store.epoch();
5222        if actual_epoch != expected_epoch {
5223            return Err(IotaError::WrongEpoch {
5224                expected_epoch,
5225                actual_epoch,
5226            });
5227        }
5228
5229        epoch_store.set_override_protocol_upgrade_buffer_stake(buffer_stake_bps)
5230    }
5231
5232    pub fn clear_override_protocol_upgrade_buffer_stake(
5233        &self,
5234        expected_epoch: EpochId,
5235    ) -> IotaResult {
5236        let epoch_store = self.load_epoch_store_one_call_per_task();
5237        let actual_epoch = epoch_store.epoch();
5238        if actual_epoch != expected_epoch {
5239            return Err(IotaError::WrongEpoch {
5240                expected_epoch,
5241                actual_epoch,
5242            });
5243        }
5244
5245        epoch_store.clear_override_protocol_upgrade_buffer_stake()
5246    }
5247
5248    /// Get the set of system packages that are compiled in to this build, if
5249    /// those packages are compatible with the current versions of those
5250    /// packages on-chain.
5251    pub async fn get_available_system_packages(
5252        &self,
5253        protocol_config: &ProtocolConfig,
5254    ) -> Vec<ObjectReference> {
5255        let mut results = vec![];
5256
5257        let system_packages = BuiltInFramework::iter_system_packages();
5258
5259        // Add extra framework packages during simtest
5260        #[cfg(msim)]
5261        let extra_packages = framework_injection::get_extra_packages(self.name);
5262        #[cfg(msim)]
5263        let system_packages = {
5264            let mut packages: Vec<_> = system_packages.collect();
5265            packages.extend(extra_packages.iter());
5266            packages
5267        };
5268
5269        for system_package in system_packages {
5270            let modules = system_package.modules().to_vec();
5271            // In simtests, we could override the current built-in framework packages.
5272            #[cfg(msim)]
5273            let modules = framework_injection::get_override_modules(&system_package.id, self.name)
5274                .unwrap_or(modules);
5275
5276            let Some(obj_ref) = iota_framework::compare_system_package(
5277                &self.get_object_store(),
5278                &system_package.id,
5279                &modules,
5280                system_package.dependencies.to_vec(),
5281                protocol_config,
5282            )
5283            .await
5284            else {
5285                return vec![];
5286            };
5287            results.push(obj_ref);
5288        }
5289
5290        results
5291    }
5292
5293    /// Return the new versions, module bytes, and dependencies for the packages
5294    /// that have been committed to for a framework upgrade, in
5295    /// `system_packages`.  Loads the module contents from the binary, and
5296    /// performs the following checks:
5297    ///
5298    /// - Whether its contents matches what is on-chain already, in which case no upgrade is
5299    ///   required, and its contents are omitted from the output.
5300    /// - Whether the contents in the binary can form a package whose digest matches the input,
5301    ///   meaning the framework will be upgraded, and this authority can satisfy that upgrade, in
5302    ///   which case the contents are included in the output.
5303    ///
5304    /// If a needed version of the framework can't be loaded, the binary does
5305    /// not contain the bytes for that framework ID, or the resulting
5306    /// package fails the digest check, `None` is returned indicating that
5307    /// this authority cannot run the upgrade that the network voted on.
5308    ///
5309    /// All object lookups are pinned to the versions in `system_packages`
5310    /// instead of using the latest versions, so that the result is
5311    /// deterministic even if the change epoch transaction that performs the
5312    /// upgrade has already been executed locally (e.g. via state sync). In
5313    /// that case the reconstructed change epoch transaction is byte-identical
5314    /// to the executed one, and the caller detects it as already executed.
5315    async fn get_system_package_bytes(
5316        &self,
5317        system_packages: Vec<ObjectReference>,
5318        binary_config: &BinaryConfig,
5319    ) -> Option<Vec<SystemPackage>> {
5320        let object_store = self.get_object_cache_reader();
5321
5322        let mut res = Vec::with_capacity(system_packages.len());
5323        for system_package_ref in system_packages {
5324            if object_store
5325                .get_object_by_key(&system_package_ref.object_id, system_package_ref.version)
5326                .is_some_and(|object| object.object_ref() == system_package_ref)
5327            {
5328                // Skip this one because it doesn't need to be upgraded.
5329                info!(
5330                    "Framework {} does not need updating",
5331                    system_package_ref.object_id
5332                );
5333                continue;
5334            }
5335
5336            // The digest in `system_package_ref` commits to a package built on top of the
5337            // predecessor version's `previous_transaction` (see `compare_system_package`),
5338            // so it must be re-derived from that version. A ref at
5339            // `Version::OBJECT_START` is a freshly created package with no predecessor.
5340            let prev_transaction = if system_package_ref.version == Version::OBJECT_START {
5341                TransactionDigest::GENESIS_MARKER
5342            } else {
5343                let prev_version = system_package_ref
5344                    .version
5345                    .previous()
5346                    .expect("version is greater than Version::OBJECT_START");
5347                let Some(prev_object) =
5348                    object_store.get_object_by_key(&system_package_ref.object_id, prev_version)
5349                else {
5350                    error!(
5351                        "Framework {} not available locally at version {prev_version:?}, cannot \
5352                         derive upgrade to {system_package_ref:?}",
5353                        system_package_ref.object_id
5354                    );
5355                    return None;
5356                };
5357                prev_object.previous_transaction
5358            };
5359
5360            #[cfg(msim)]
5361            let FrameworkSystemPackage {
5362                id: _,
5363                bytes,
5364                dependencies,
5365            } = framework_injection::get_override_system_package(
5366                &system_package_ref.object_id,
5367                self.name,
5368            )
5369            .unwrap_or_else(|| {
5370                BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone()
5371            });
5372
5373            #[cfg(not(msim))]
5374            let FrameworkSystemPackage {
5375                id: _,
5376                bytes,
5377                dependencies,
5378            } = BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone();
5379
5380            let modules: Vec<_> = bytes
5381                .iter()
5382                .map(|m| CompiledModule::deserialize_with_config(m, binary_config).unwrap())
5383                .collect();
5384
5385            let new_object = Object::new_system_package(
5386                &modules,
5387                system_package_ref.version,
5388                dependencies.clone(),
5389                prev_transaction,
5390            );
5391
5392            let new_ref = new_object.object_ref();
5393            if new_ref != system_package_ref {
5394                debug_fatal!(
5395                    "Framework mismatch -- binary: {new_ref:?}\n  upgrade: {system_package_ref:?}"
5396                );
5397                return None;
5398            }
5399
5400            res.push(SystemPackage {
5401                version: system_package_ref.version,
5402                modules: bytes,
5403                dependencies,
5404            });
5405        }
5406
5407        Some(res)
5408    }
5409
5410    /// Returns the new protocol version and system packages that the network
5411    /// has voted to upgrade to. If the proposed protocol version is not
5412    /// supported, None is returned.
5413    fn is_protocol_version_supported_v1(
5414        proposed_protocol_version: ProtocolVersion,
5415        committee: &Committee,
5416        capabilities: Vec<AuthorityCapabilitiesV1>,
5417        mut buffer_stake_bps: u64,
5418    ) -> Option<(ProtocolVersion, Digest, Vec<ObjectReference>)> {
5419        if buffer_stake_bps > 10000 {
5420            warn!("clamping buffer_stake_bps to 10000");
5421            buffer_stake_bps = 10000;
5422        }
5423
5424        // For each validator, gather the protocol version and system packages that it
5425        // would like to upgrade to in the next epoch.
5426        let mut desired_upgrades: Vec<_> = capabilities
5427            .into_iter()
5428            .filter_map(|mut cap| {
5429                // A validator that lists no packages is voting against any change at all.
5430                if cap.available_system_packages.is_empty() {
5431                    return None;
5432                }
5433
5434                cap.available_system_packages.sort();
5435
5436                info!(
5437                    "validator {:?} supports {:?} with system packages: {:?}",
5438                    cap.authority.concise(),
5439                    cap.supported_protocol_versions,
5440                    cap.available_system_packages,
5441                );
5442
5443                // A validator that only supports the current protocol version is also voting
5444                // against any change, because framework upgrades always require a protocol
5445                // version bump.
5446                cap.supported_protocol_versions
5447                    .get_version_digest(proposed_protocol_version)
5448                    .map(|digest| (digest, cap.available_system_packages, cap.authority))
5449            })
5450            .collect();
5451
5452        // There can only be one set of votes that have a majority, find one if it
5453        // exists.
5454        desired_upgrades.sort();
5455        desired_upgrades
5456            .into_iter()
5457            .chunk_by(|(digest, packages, _authority)| (*digest, packages.clone()))
5458            .into_iter()
5459            .find_map(|((digest, packages), group)| {
5460                // should have been filtered out earlier.
5461                assert!(!packages.is_empty());
5462
5463                let mut stake_aggregator: StakeAggregator<(), true> =
5464                    StakeAggregator::new(Arc::new(committee.clone()));
5465
5466                for (_, _, authority) in group {
5467                    stake_aggregator.insert_generic(authority, ());
5468                }
5469
5470                let total_votes = stake_aggregator.total_votes();
5471                let quorum_threshold = committee.quorum_threshold();
5472                let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5473
5474                info!(
5475                    protocol_config_digest = ?digest,
5476                    ?total_votes,
5477                    ?quorum_threshold,
5478                    ?buffer_stake_bps,
5479                    ?effective_threshold,
5480                    ?proposed_protocol_version,
5481                    ?packages,
5482                    "support for upgrade"
5483                );
5484
5485                let has_support = total_votes >= effective_threshold;
5486                has_support.then_some((proposed_protocol_version, digest, packages))
5487            })
5488    }
5489
5490    /// Selects the highest supported protocol version and system packages that
5491    /// the network has voted to upgrade to. If no upgrade is supported,
5492    /// returns the current protocol version and system packages.
5493    fn choose_protocol_version_and_system_packages_v1(
5494        current_protocol_version: ProtocolVersion,
5495        current_protocol_digest: Digest,
5496        committee: &Committee,
5497        capabilities: Vec<AuthorityCapabilitiesV1>,
5498        buffer_stake_bps: u64,
5499    ) -> (ProtocolVersion, Digest, Vec<ObjectReference>) {
5500        let mut next_protocol_version = current_protocol_version;
5501        let mut system_packages = vec![];
5502        let mut protocol_version_digest = current_protocol_digest;
5503
5504        // Finds the highest supported protocol version and system packages by
5505        // incrementing the proposed protocol version by one until no further
5506        // upgrades are supported.
5507        while let Some((version, digest, packages)) = Self::is_protocol_version_supported_v1(
5508            next_protocol_version + 1,
5509            committee,
5510            capabilities.clone(),
5511            buffer_stake_bps,
5512        ) {
5513            next_protocol_version = version;
5514            protocol_version_digest = digest;
5515            system_packages = packages;
5516        }
5517
5518        (
5519            next_protocol_version,
5520            protocol_version_digest,
5521            system_packages,
5522        )
5523    }
5524
5525    /// Returns the indices of validators that support the given protocol
5526    /// version and digest. This includes both committee and non-committee
5527    /// validators based on their capabilities. Uses active validators
5528    /// instead of committee indices.
5529    fn get_validators_supporting_protocol_version(
5530        target_protocol_version: ProtocolVersion,
5531        target_digest: Digest,
5532        active_validators: &[AggregateAuthorityPublicKey],
5533        capabilities: &[AuthorityCapabilitiesV1],
5534    ) -> Vec<u64> {
5535        let mut eligible_validators = Vec::new();
5536
5537        for capability in capabilities {
5538            // Check if this validator supports the target protocol version and digest
5539            if let Some(digest) = capability
5540                .supported_protocol_versions
5541                .get_version_digest(target_protocol_version)
5542            {
5543                if digest == target_digest {
5544                    // Find the validator's index in the active validators list
5545                    if let Some(index) = active_validators
5546                        .iter()
5547                        .position(|name| AuthorityName::from(name) == capability.authority)
5548                    {
5549                        eligible_validators.push(index as u64);
5550                    }
5551                }
5552            }
5553        }
5554
5555        // Sort indices for deterministic behavior
5556        eligible_validators.sort();
5557        eligible_validators
5558    }
5559
5560    /// Calculates the sum of weights for eligible validators that are part of
5561    /// the committee. Takes the indices from
5562    /// get_validators_supporting_protocol_version and maps them back
5563    /// to committee members to get their weights.
5564    fn calculate_eligible_validators_weight(
5565        eligible_validator_indices: &[u64],
5566        active_validators: &[AggregateAuthorityPublicKey],
5567        committee: &Committee,
5568    ) -> u64 {
5569        let mut total_weight = 0u64;
5570
5571        for &index in eligible_validator_indices {
5572            let authority_pubkey = &active_validators[index as usize];
5573            // Check if this validator is in the committee and get their weight
5574            if let Some((_, weight)) = committee
5575                .members()
5576                .find(|(name, _)| *name == AuthorityName::from(authority_pubkey))
5577            {
5578                total_weight += weight;
5579            }
5580        }
5581
5582        total_weight
5583    }
5584
5585    /// Creates and execute the advance epoch transaction to effects without
5586    /// committing it to the database. The effects of the change epoch tx
5587    /// are only written to the database after a certified checkpoint has been
5588    /// formed and executed by CheckpointExecutor.
5589    ///
5590    /// When a framework upgraded has been decided on, but the validator does
5591    /// not have the new versions of the packages locally, the validator
5592    /// cannot form the ChangeEpochTx. In this case it returns Err,
5593    /// indicating that the checkpoint builder should give up trying to make the
5594    /// final checkpoint. As long as the network is able to create a certified
5595    /// checkpoint (which should be ensured by the capabilities vote), it
5596    /// will arrive via state sync and be executed by CheckpointExecutor.
5597    #[instrument(level = "error", skip_all)]
5598    pub async fn create_and_execute_advance_epoch_tx(
5599        &self,
5600        epoch_store: &Arc<AuthorityPerEpochStore>,
5601        gas_cost_summary: &GasCostSummary,
5602        checkpoint: CheckpointSequenceNumber,
5603        epoch_start_timestamp_ms: CheckpointTimestamp,
5604        scores: Vec<u64>,
5605    ) -> CheckpointBuilderResult<(
5606        IotaSystemState,
5607        Option<SystemEpochInfoEvent>,
5608        TransactionEffects,
5609    )> {
5610        let mut txns = Vec::new();
5611
5612        // Create the TransactionDenyRules object once: the epoch-start
5613        // configuration is identical on every validator, so the whole
5614        // committee injects (or skips) the kind together. If this epoch
5615        // change falls into safe mode the creation is dropped with it, the
5616        // object stays absent, and the next epoch end injects it again.
5617        if epoch_store.protocol_config().enable_pcool_flow()
5618            && epoch_store
5619                .epoch_start_config()
5620                .transaction_deny_rules_obj_initial_shared_version()
5621                .is_none()
5622        {
5623            txns.push(EndOfEpochTransactionKind::TransactionDenyRulesCreate);
5624        }
5625
5626        let next_epoch = epoch_store.epoch() + 1;
5627
5628        let buffer_stake_bps = epoch_store.get_effective_buffer_stake_bps();
5629        let authority_capabilities = epoch_store
5630            .get_capabilities_v1()
5631            .expect("read capabilities from db cannot fail");
5632        let (next_epoch_protocol_version, next_epoch_protocol_digest, next_epoch_system_packages) =
5633            Self::choose_protocol_version_and_system_packages_v1(
5634                epoch_store.protocol_version(),
5635                SupportedProtocolVersionsWithHashes::protocol_config_digest(
5636                    epoch_store.protocol_config(),
5637                ),
5638                epoch_store.committee(),
5639                authority_capabilities.clone(),
5640                buffer_stake_bps,
5641            );
5642
5643        // since system packages are created during the current epoch, they should abide
5644        // by the rules of the current epoch, including the current epoch's max
5645        // Move binary format version
5646        let config = epoch_store.protocol_config();
5647        let binary_config = to_binary_config(config, None);
5648        let Some(next_epoch_system_package_bytes) = self
5649            .get_system_package_bytes(next_epoch_system_packages.clone(), &binary_config)
5650            .await
5651        else {
5652            debug_fatal!(
5653                "upgraded system packages {:?} are not locally available, cannot create \
5654                ChangeEpochTx. validator binary must be upgraded to the correct version!",
5655                next_epoch_system_packages
5656            );
5657            // the checkpoint builder will keep retrying forever when it hits this error.
5658            // Eventually, one of two things will happen:
5659            // - The operator will upgrade this binary to one that has the new packages locally, and
5660            //   this function will succeed.
5661            // - The final checkpoint will be certified by other validators, we will receive it via
5662            //   state sync, and execute it. This will upgrade the framework packages, reconfigure,
5663            //   and most likely shut down in the new epoch (this validator likely doesn't support
5664            //   the new protocol version, or else it should have had the packages.)
5665            return Err(CheckpointBuilderError::SystemPackagesMissing);
5666        };
5667
5668        // Use ChangeEpochV3 or ChangeEpochV4 when the feature flags are enabled and
5669        // ChangeEpochV2 requirements are met
5670        if config.select_committee_from_eligible_validators() {
5671            // Get the list of eligible validators that support the target protocol version
5672            let active_validators = epoch_store.epoch_start_state().get_active_validators();
5673
5674            let mut eligible_active_validators = (0..active_validators.len() as u64).collect();
5675
5676            // Use validators supporting the target protocol version as eligible validators
5677            // in the next version if select_committee_supporting_next_epoch_version feature
5678            // flag is set to true.
5679            if config.select_committee_supporting_next_epoch_version() {
5680                eligible_active_validators = Self::get_validators_supporting_protocol_version(
5681                    next_epoch_protocol_version,
5682                    next_epoch_protocol_digest,
5683                    &active_validators,
5684                    &authority_capabilities,
5685                );
5686
5687                // Calculate the total weight of eligible validators in the committee
5688                let eligible_validators_weight = Self::calculate_eligible_validators_weight(
5689                    &eligible_active_validators,
5690                    &active_validators,
5691                    epoch_store.committee(),
5692                );
5693
5694                // Safety check: ensure eligible validators have enough stake
5695                // Use the same effective threshold calculation that was used to decide the
5696                // protocol version
5697                let committee = epoch_store.committee();
5698                let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5699
5700                if eligible_validators_weight < effective_threshold {
5701                    error!(
5702                        "Eligible validators weight {eligible_validators_weight} is less than effective threshold {effective_threshold}. \
5703                        This could indicate a bug in validator selection logic or inconsistency with protocol version decision.",
5704                    );
5705                    // Pass all active validator indices as eligible validators
5706                    // to perform selection among all of them.
5707                    eligible_active_validators = (0..active_validators.len() as u64).collect();
5708                }
5709            }
5710
5711            // Use ChangeEpochV4 when the pass_validator_scores_to_advance_epoch feature
5712            // flag is enabled.
5713            if config.pass_validator_scores_to_advance_epoch() {
5714                txns.push(EndOfEpochTransactionKind::new_change_epoch_v4(
5715                    next_epoch,
5716                    next_epoch_protocol_version.as_u64(),
5717                    gas_cost_summary.storage_cost,
5718                    gas_cost_summary.computation_cost,
5719                    gas_cost_summary.computation_cost_burned,
5720                    gas_cost_summary.storage_rebate,
5721                    gas_cost_summary.non_refundable_storage_fee,
5722                    epoch_start_timestamp_ms,
5723                    next_epoch_system_package_bytes,
5724                    eligible_active_validators,
5725                    scores,
5726                    config.adjust_rewards_by_score(),
5727                ));
5728            } else {
5729                txns.push(EndOfEpochTransactionKind::new_change_epoch_v3(
5730                    next_epoch,
5731                    next_epoch_protocol_version.as_u64(),
5732                    gas_cost_summary.storage_cost,
5733                    gas_cost_summary.computation_cost,
5734                    gas_cost_summary.computation_cost_burned,
5735                    gas_cost_summary.storage_rebate,
5736                    gas_cost_summary.non_refundable_storage_fee,
5737                    epoch_start_timestamp_ms,
5738                    next_epoch_system_package_bytes,
5739                    eligible_active_validators,
5740                ));
5741            }
5742        } else if config.protocol_defined_base_fee()
5743            && config.max_committee_members_count_as_option().is_some()
5744        {
5745            txns.push(EndOfEpochTransactionKind::new_change_epoch_v2(
5746                next_epoch,
5747                next_epoch_protocol_version.as_u64(),
5748                gas_cost_summary.storage_cost,
5749                gas_cost_summary.computation_cost,
5750                gas_cost_summary.computation_cost_burned,
5751                gas_cost_summary.storage_rebate,
5752                gas_cost_summary.non_refundable_storage_fee,
5753                epoch_start_timestamp_ms,
5754                next_epoch_system_package_bytes,
5755            ));
5756        } else {
5757            txns.push(EndOfEpochTransactionKind::new_change_epoch(
5758                next_epoch,
5759                next_epoch_protocol_version.as_u64(),
5760                gas_cost_summary.storage_cost,
5761                gas_cost_summary.computation_cost,
5762                gas_cost_summary.storage_rebate,
5763                gas_cost_summary.non_refundable_storage_fee,
5764                epoch_start_timestamp_ms,
5765                next_epoch_system_package_bytes,
5766            ));
5767        }
5768
5769        let tx = VerifiedTransaction::new_end_of_epoch_transaction(txns);
5770
5771        let executable_tx = VerifiedExecutableTransaction::new_from_checkpoint(
5772            tx.clone(),
5773            epoch_store.epoch(),
5774            checkpoint,
5775        );
5776
5777        let tx_digest = executable_tx.digest();
5778
5779        info!(
5780            ?next_epoch,
5781            ?next_epoch_protocol_version,
5782            ?next_epoch_system_packages,
5783            computation_cost=?gas_cost_summary.computation_cost,
5784            computation_cost_burned=?gas_cost_summary.computation_cost_burned,
5785            storage_cost=?gas_cost_summary.storage_cost,
5786            storage_rebate=?gas_cost_summary.storage_rebate,
5787            non_refundable_storage_fee=?gas_cost_summary.non_refundable_storage_fee,
5788            ?tx_digest,
5789            "Creating advance epoch transaction"
5790        );
5791
5792        fail_point_async!("change_epoch_tx_delay");
5793        let tx_lock = epoch_store.acquire_tx_lock(tx_digest);
5794
5795        // The tx could have been executed by state sync already - if so simply return
5796        // an error. The checkpoint builder will shortly be terminated by
5797        // reconfiguration anyway.
5798        if self
5799            .get_transaction_cache_reader()
5800            .try_is_tx_already_executed(tx_digest)?
5801        {
5802            warn!("change epoch tx has already been executed via state sync");
5803            return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
5804        }
5805
5806        let execution_guard = self.execution_lock_for_executable_transaction(&executable_tx)?;
5807
5808        // We must manually assign the shared object versions to the transaction before
5809        // executing it. This is because we do not sequence end-of-epoch
5810        // transactions through consensus.
5811        let assigned_versions = epoch_store.assign_shared_object_versions_idempotent(
5812            self.get_object_cache_reader().as_ref(),
5813            std::iter::once(&Schedulable::Transaction(&executable_tx)),
5814        )?;
5815
5816        assert_eq!(assigned_versions.0.len(), 1);
5817        let assigned_versions = assigned_versions.0.into_iter().next().unwrap().1;
5818
5819        let (input_objects, _) = self.read_objects_for_execution(
5820            &tx_lock,
5821            &executable_tx,
5822            assigned_versions,
5823            epoch_store,
5824        )?;
5825
5826        let (temporary_store, effects, _execution_error_opt) = self.execute_transaction(
5827            &execution_guard,
5828            &executable_tx,
5829            input_objects,
5830            vec![],
5831            epoch_store,
5832        )?;
5833        let system_obj = get_iota_system_state(&temporary_store.written)
5834            .expect("change epoch tx must write to system object");
5835        // Find the SystemEpochInfoEvent emitted by the advance_epoch transaction.
5836        let system_epoch_info_event = temporary_store
5837            .events
5838            .0
5839            .into_iter()
5840            .find(|event| event.is_system_epoch_info_event())
5841            .map(SystemEpochInfoEvent::from);
5842        // The system epoch info event can be `None` in case if the `advance_epoch`
5843        // Move function call failed and was executed in the safe mode.
5844        assert!(system_epoch_info_event.is_some() || system_obj.safe_mode());
5845
5846        // We must write tx and effects to the state sync tables so that state sync is
5847        // able to deliver to the transaction to CheckpointExecutor after it is
5848        // included in a certified checkpoint.
5849        self.get_state_sync_store()
5850            .try_insert_transaction_and_effects(&tx, &effects)?;
5851
5852        info!(
5853            "Effects summary of the change epoch transaction: {:?}",
5854            effects.summary_for_debug()
5855        );
5856        epoch_store.record_checkpoint_builder_is_safe_mode_metric(system_obj.safe_mode());
5857        // The change epoch transaction cannot fail to execute.
5858        assert!(effects.status().is_success());
5859        Ok((system_obj, system_epoch_info_event, effects))
5860    }
5861
5862    /// This function is called at the very end of the epoch.
5863    /// This step is required before updating new epoch in the db and calling
5864    /// reopen_epoch_db.
5865    #[instrument(level = "error", skip_all)]
5866    async fn revert_uncommitted_epoch_transactions(
5867        &self,
5868        epoch_store: &AuthorityPerEpochStore,
5869    ) -> IotaResult {
5870        {
5871            let state = epoch_store.get_reconfig_state_write_lock_guard();
5872            if state.should_accept_user_certs() {
5873                // Need to change this so that consensus adapter do not accept certificates from
5874                // user. This can happen if our local validator did not initiate
5875                // epoch change locally, but 2f+1 nodes already concluded the
5876                // epoch.
5877                //
5878                // This lock is essentially a barrier (in the certificate mode only) for
5879                // `epoch_store.pending_consensus_certificates` table we are reading on the line
5880                // after this block
5881                epoch_store.close_user_certs(state);
5882            }
5883            // lock is dropped here
5884        }
5885
5886        // In the P-COOL flow, the list of pending consensus certificates is
5887        // always empty, so the reverting below is only for the certificate mode.
5888        if !epoch_store.protocol_config().enable_pcool_flow() {
5889            let pending_certificates = epoch_store.pending_consensus_certificates();
5890            info!(
5891                "Reverting {} locally executed transactions that was not included in the epoch: \
5892                    {:?}",
5893                pending_certificates.len(),
5894                pending_certificates,
5895            );
5896            for digest in pending_certificates {
5897                if epoch_store.is_transaction_executed_in_checkpoint(&digest)? {
5898                    info!(
5899                        "Not reverting pending consensus transaction {:?} - it was included in \
5900                            checkpoint",
5901                        digest
5902                    );
5903                    continue;
5904                }
5905                info!("Reverting {:?} at the end of epoch", digest);
5906                epoch_store.revert_executed_transaction(&digest)?;
5907                self.get_reconfig_api().try_revert_state_update(&digest)?;
5908            }
5909            info!("All uncommitted local transactions reverted");
5910        } else {
5911            info!("P-COOL mode: skipping revert of uncommitted epoch transactions");
5912        }
5913
5914        Ok(())
5915    }
5916
5917    #[instrument(level = "error", skip_all)]
5918    async fn reopen_epoch_db(
5919        &self,
5920        cur_epoch_store: &AuthorityPerEpochStore,
5921        new_committee: Committee,
5922        epoch_start_configuration: EpochStartConfiguration,
5923        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
5924        epoch_last_checkpoint: CheckpointSequenceNumber,
5925    ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
5926        let new_epoch = new_committee.epoch;
5927        info!(new_epoch = ?new_epoch, "re-opening AuthorityEpochTables for new epoch");
5928        assert_eq!(
5929            epoch_start_configuration.epoch_start_state().epoch(),
5930            new_committee.epoch
5931        );
5932        fail_point!("before-open-new-epoch-store");
5933        let new_epoch_store = cur_epoch_store.new_at_next_epoch(
5934            self.name,
5935            new_committee,
5936            epoch_start_configuration,
5937            self.get_backing_package_store().clone(),
5938            expensive_safety_check_config,
5939            epoch_last_checkpoint,
5940        )?;
5941        self.epoch_store.store(new_epoch_store.clone());
5942        Ok(new_epoch_store)
5943    }
5944
5945    /// Resolves the account's `AuthenticatorFunctionRef` on the execution path,
5946    /// where the certificate has already passed validation before consensus.
5947    ///
5948    /// A deleted or cancelled account object is not an error here: its version
5949    /// is returned so execution can proceed and surface the proper effect
5950    /// (e.g. `InputObjectDeleted` or a shared-object congestion cancellation).
5951    ///
5952    /// # Errors
5953    ///
5954    /// Any failure the check finds with the transaction, as the error the
5955    /// transaction fails with, with the original error as the source:
5956    /// [`ExecutionErrorKind::AuthenticatorFunctionNotFound`] when the account
5957    /// has no authenticator function field or the field cannot be read, and
5958    /// [`ExecutionErrorKind::AccountNotSharedObject`] when the account is not a
5959    /// shared object.
5960    ///
5961    /// # Panics
5962    ///
5963    /// When the store cannot be read: that says nothing about the transaction,
5964    /// so nobody can be charged for it, and effects written here would differ
5965    /// from the other validators'.
5966    fn check_move_account_for_execution(
5967        &self,
5968        auth_account_object_id: ObjectId,
5969        auth_account_object_seq_number: Option<Version>,
5970        auth_account_object_digest: Option<ObjectDigest>,
5971        account_object: ObjectReadResult,
5972        signer: &Address,
5973        protocol_config: &ProtocolConfig,
5974    ) -> Result<AuthenticatorFunctionRefForExecution, ExecutionError> {
5975        match self.check_move_account(
5976            auth_account_object_id,
5977            auth_account_object_seq_number,
5978            auth_account_object_digest,
5979            account_object,
5980            signer,
5981            true,
5982            protocol_config,
5983        ) {
5984            Ok(function_ref) => Ok(function_ref),
5985            Err(MoveAccountCheckError::Input(input_error)) => {
5986                let status = match &input_error {
5987                    UserInputError::MoveAuthenticatorNotFound {
5988                        account_object_id, ..
5989                    }
5990                    | UserInputError::InvalidAuthenticatorFunctionRefField { account_object_id } => {
5991                        ExecutionErrorKind::AuthenticatorFunctionNotFound {
5992                            object_id: *account_object_id,
5993                        }
5994                    }
5995                    // Since protocol version 36, only a shared account named with
5996                    // an immutable or owned reference reaches the digest
5997                    // comparison. The fix is the same as for the other two: name
5998                    // the account as a shared object.
5999                    UserInputError::AccountObjectNotSupported { object_id }
6000                    | UserInputError::ImmutableAccountObjectNotSupported { object_id }
6001                    | UserInputError::InvalidAccountObjectDigest { object_id, .. } => {
6002                        ExecutionErrorKind::AccountNotSharedObject {
6003                            object_id: *object_id,
6004                        }
6005                    }
6006                    // The check produces nothing else today. A failure added to
6007                    // it gets this status until it is given one of its own.
6008                    _ => ExecutionErrorKind::FunctionNotFound,
6009                };
6010                Err(ExecutionError::new_with_source(status, input_error))
6011            }
6012            Err(MoveAccountCheckError::Storage(storage_error)) => {
6013                panic!("failed to read the store while checking a Move account: {storage_error}")
6014            }
6015        }
6016    }
6017
6018    /// Resolves the account's `AuthenticatorFunctionRef` on the validation
6019    /// (signing) path, rejecting the transaction when the account object was
6020    /// deleted or belongs to a cancelled transaction.
6021    fn check_move_account_for_validation(
6022        &self,
6023        auth_account_object_id: ObjectId,
6024        auth_account_object_seq_number: Option<Version>,
6025        auth_account_object_digest: Option<ObjectDigest>,
6026        account_object: ObjectReadResult,
6027        signer: &Address,
6028        protocol_config: &ProtocolConfig,
6029    ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
6030        self.check_move_account(
6031            auth_account_object_id,
6032            auth_account_object_seq_number,
6033            auth_account_object_digest,
6034            account_object,
6035            signer,
6036            false,
6037            protocol_config,
6038        )
6039        .map_err(IotaError::from)
6040    }
6041
6042    /// Checks whether `authenticator` unlocks a valid Move account and returns
6043    /// the account-related `AuthenticatorFunctionRef`. Where the protocol
6044    /// config requires it, the account object must be shared, so that a
6045    /// transaction carrying a `MoveAuthenticator` always has a shared input
6046    /// and is ordered by consensus. When `is_execution` is
6047    /// set, a deleted or cancelled account object yields its version instead of
6048    /// an error, so execution can proceed to the proper effect. Prefer the
6049    /// `check_move_account_for_execution` / `check_move_account_for_validation`
6050    /// wrappers over calling this directly.
6051    ///
6052    /// # Errors
6053    ///
6054    /// [`MoveAccountCheckError::Input`] when the account fails a check, and
6055    /// [`MoveAccountCheckError::Storage`] when the store cannot be read. The
6056    /// error type is what lets the execution path distinguish the two, so a
6057    /// new kind of failure here has to be added to it.
6058    fn check_move_account(
6059        &self,
6060        auth_account_object_id: ObjectId,
6061        auth_account_object_seq_number: Option<Version>,
6062        auth_account_object_digest: Option<ObjectDigest>,
6063        account_object: ObjectReadResult,
6064        signer: &Address,
6065        is_execution: bool,
6066        protocol_config: &ProtocolConfig,
6067    ) -> Result<AuthenticatorFunctionRefForExecution, MoveAccountCheckError> {
6068        let auth_account_object_seq_number = match (&account_object.object, is_execution) {
6069            // In any case, if the account object is loaded, we can check its version and digest.
6070            // Then we return the version of the account object to be used for reading the
6071            // authenticator function ref dynamic field.
6072            (ObjectReadResultKind::Object(object), _) => {
6073                let account_object_addr = Address::from(auth_account_object_id);
6074                fp_ensure!(
6075                    signer == &account_object_addr,
6076                    UserInputError::IncorrectUserSignature {
6077                        error: format!("Move authenticator is trying to unlock {account_object_addr:?}, but given signer address is {signer:?}")
6078                    }
6079                    .into()
6080                );
6081
6082                if protocol_config.reject_immutable_account_objects() {
6083                    fp_ensure!(
6084                        !object.is_immutable(),
6085                        UserInputError::ImmutableAccountObjectNotSupported {
6086                            object_id: auth_account_object_id
6087                        }
6088                        .into()
6089                    );
6090                }
6091
6092                fp_ensure!(
6093                    object.is_shared() || object.is_immutable(),
6094                    UserInputError::AccountObjectNotSupported {
6095                        object_id: auth_account_object_id
6096                    }
6097                    .into()
6098                );
6099
6100                let auth_account_object_seq_number =
6101                    if let Some(expected_version) = auth_account_object_seq_number {
6102                        let account_object_version = object.version();
6103
6104                        fp_ensure!(
6105                            account_object_version == expected_version,
6106                            UserInputError::AccountObjectVersionMismatch {
6107                                object_id: auth_account_object_id,
6108                                expected_version,
6109                                actual_version: account_object_version,
6110                            }
6111                            .into()
6112                        );
6113
6114                        expected_version
6115                    } else {
6116                        object.version()
6117                    };
6118
6119                if let Some(expected_digest) = auth_account_object_digest {
6120                    let account_object_digest = object.digest();
6121                    fp_ensure!(
6122                        account_object_digest == expected_digest,
6123                        UserInputError::InvalidAccountObjectDigest {
6124                            object_id: auth_account_object_id,
6125                            expected_digest,
6126                            actual_digest: account_object_digest,
6127                        }
6128                        .into()
6129                    );
6130                }
6131
6132                Ok(auth_account_object_seq_number)
6133            }
6134            // If the account object is not loaded because it was deleted, we return the error in
6135            // the case in which we are not executing the transaction right after.
6136            (ObjectReadResultKind::DeletedSharedObject(version, digest), false) => {
6137                Err(UserInputError::AccountObjectDeleted {
6138                    account_id: account_object.id(),
6139                    account_version: *version,
6140                    transaction_digest: *digest,
6141                })
6142            }
6143            // If the account object is not loaded because the transaction was canceled, we return
6144            // the error in the case in which we are not executing the transaction right
6145            // after.
6146            (ObjectReadResultKind::CancelledTransactionObject(version), false) => {
6147                Err(UserInputError::AccountObjectInCanceledTransaction {
6148                    account_id: account_object.id(),
6149                    account_version: *version,
6150                })
6151            }
6152            // If the account object is not loaded because it was deleted, we return the version in
6153            // the case in which we are executing the transaction right after.
6154            // This version is used to read the authenticator function ref dynamic field because it
6155            // is greater than the version of the child dynamic field.
6156            (ObjectReadResultKind::DeletedSharedObject(version, _), true) => Ok(*version),
6157            // If the account object is not loaded because the transaction was canceled, we return
6158            // the version in the case in which we are executing the transaction right
6159            // after. This version is used to read the authenticator function ref
6160            // dynamic field because it is greater than the version of the child dynamic
6161            // field.
6162            (ObjectReadResultKind::CancelledTransactionObject(version), true) => Ok(*version),
6163            // A transaction validated post-consensus at a commit leaves its account
6164            // to execution, which reads it, so no check gets an unread account.
6165            (ObjectReadResultKind::UnreadSharedObject, _) => unreachable!(
6166                "only post-consensus validation at a commit lists an unread shared object, and \
6167                    it leaves the account to execution"
6168            ),
6169        }?;
6170
6171        let authenticator_function_ref_field_id =
6172            derive_authenticator_function_ref_v1_dynamic_field_id(auth_account_object_id)?;
6173
6174        let authenticator_function_ref_field = self
6175            .get_object_cache_reader()
6176            .try_find_object_lt_or_eq_version(
6177                authenticator_function_ref_field_id,
6178                auth_account_object_seq_number,
6179            )
6180            .map_err(MoveAccountCheckError::Storage)?;
6181
6182        if let Some(authenticator_function_ref_field_obj) = authenticator_function_ref_field {
6183            Ok(authenticator_function_ref_v1_from_dynamic_field_object(
6184                auth_account_object_id,
6185                &authenticator_function_ref_field_obj,
6186            )?)
6187        } else {
6188            Err(UserInputError::MoveAuthenticatorNotFound {
6189                authenticator_function_ref_id: authenticator_function_ref_field_id,
6190                account_object_id: auth_account_object_id,
6191                account_object_version: auth_account_object_seq_number,
6192            }
6193            .into())
6194        }
6195    }
6196
6197    #[allow(clippy::type_complexity)]
6198    fn read_objects_for_validation(
6199        &self,
6200        transaction: &VerifiedTransaction,
6201        epoch: u64,
6202    ) -> IotaResult<(
6203        InputObjects,
6204        ReceivingObjects,
6205        Vec<(InputObjects, ObjectReadResult)>,
6206    )> {
6207        let (input_objects, tx_receiving_objects) = self.input_loader.read_objects_for_signing(
6208            Some(transaction.digest()),
6209            &transaction.collect_all_input_object_kind_for_reading()?,
6210            &transaction.data().transaction().receiving_objects(),
6211            epoch,
6212        )?;
6213
6214        transaction
6215            .split_input_objects_into_groups_for_reading(input_objects)
6216            .map(|(tx_input_objects, per_authenticator_inputs)| {
6217                (
6218                    tx_input_objects,
6219                    tx_receiving_objects,
6220                    per_authenticator_inputs,
6221                )
6222            })
6223    }
6224
6225    /// Like [`Self::read_objects_for_validation`], but for post-consensus
6226    /// validation at the commit `reader` was built for. Every input and every
6227    /// receiving object comes from the commit-indexed reader, the inputs
6228    /// first, so the first of them that decides is reported as at admission.
6229    fn read_objects_for_validation_at_commit(
6230        &self,
6231        reader: &CommitIndexedReader,
6232        transaction: &VerifiedTransaction,
6233    ) -> IotaResult<ValidationInputsAtCommit> {
6234        let input_objects = match self.input_loader.read_objects_at_commit(
6235            reader,
6236            &transaction.collect_all_input_object_kind_for_reading()?,
6237        )? {
6238            InputResolution::Loaded(input_objects) => input_objects,
6239            InputResolution::Drop(kind, reason) => {
6240                return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6241            }
6242            InputResolution::Missing(kind, reason) => {
6243                return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6244            }
6245        };
6246        let tx_receiving_objects = match self.input_loader.read_receiving_objects_at_commit(
6247            reader,
6248            &transaction.data().transaction().receiving_objects(),
6249        )? {
6250            ReceivingObjectsResolution::Loaded(receiving_objects) => receiving_objects,
6251            ReceivingObjectsResolution::Drop(kind, reason) => {
6252                return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6253            }
6254            ReceivingObjectsResolution::Missing(kind, reason) => {
6255                return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6256            }
6257        };
6258
6259        let (tx_input_objects, per_authenticator_inputs) =
6260            transaction.split_input_objects_into_groups_for_reading(input_objects)?;
6261        Ok(ValidationInputsAtCommit::Loaded {
6262            tx_input_objects,
6263            tx_receiving_objects,
6264            per_authenticator_inputs,
6265        })
6266    }
6267
6268    #[allow(clippy::type_complexity)]
6269    fn check_transaction_inputs_for_validation(
6270        &self,
6271        protocol_config: &ProtocolConfig,
6272        reference_gas_price: u64,
6273        tx: &Transaction,
6274        tx_input_objects: InputObjects,
6275        tx_receiving_objects: &ReceivingObjects,
6276        move_authenticators: &Vec<&MoveAuthenticator>,
6277        per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6278        verifier_limits_source: VerifierLimitsSource<'_>,
6279    ) -> IotaResult<(
6280        IotaGasStatus,
6281        CheckedInputObjects,
6282        Vec<(CheckedInputObjects, AuthenticatorFunctionRef)>,
6283    )> {
6284        let authenticator_gas_budget = if move_authenticators.is_empty() {
6285            0
6286        } else {
6287            // `max_auth_gas` is used here as a Move authenticator gas budget until it is
6288            // not a part of the transaction data.
6289            protocol_config.max_auth_gas()
6290        };
6291
6292        debug_assert_eq!(
6293            move_authenticators.len(),
6294            per_authenticator_inputs.len(),
6295            "Move authenticators amount must match the number of authenticator inputs"
6296        );
6297
6298        let per_authenticator_checked_inputs = move_authenticators
6299            .iter()
6300            .zip(per_authenticator_inputs)
6301            .map(
6302                |(move_authenticator, (authenticator_input_objects, account_object))| {
6303                    // Check basic `object_to_authenticate` preconditions and get its components.
6304                    let (
6305                        auth_account_object_id,
6306                        auth_account_object_seq_number,
6307                        auth_account_object_digest,
6308                    ) = move_authenticator.object_to_authenticate_components()?;
6309
6310                    let signer = move_authenticator.address();
6311
6312                    // Make sure the signer is a Move account.
6313                    let AuthenticatorFunctionRefForExecution {
6314                        authenticator_function_ref,
6315                        ..
6316                    } = self.check_move_account_for_validation(
6317                        auth_account_object_id,
6318                        auth_account_object_seq_number,
6319                        auth_account_object_digest,
6320                        account_object,
6321                        &signer,
6322                        protocol_config,
6323                    )?;
6324
6325                    // Check the MoveAuthenticator input objects.
6326                    let authenticator_checked_input_objects =
6327                        iota_transaction_checks::check_move_authenticator_input_for_validation(
6328                            authenticator_input_objects,
6329                        )?;
6330
6331                    Ok((
6332                        authenticator_checked_input_objects,
6333                        authenticator_function_ref,
6334                    ))
6335                },
6336            )
6337            .collect::<IotaResult<Vec<_>>>()?;
6338
6339        // Check the transaction inputs.
6340        let (gas_status, tx_checked_input_objects) =
6341            iota_transaction_checks::check_transaction_input(
6342                protocol_config,
6343                reference_gas_price,
6344                tx,
6345                tx_input_objects,
6346                tx_receiving_objects,
6347                &self.metrics.bytecode_verifier_metrics,
6348                verifier_limits_source,
6349                authenticator_gas_budget,
6350            )?;
6351
6352        Ok((
6353            gas_status,
6354            tx_checked_input_objects,
6355            per_authenticator_checked_inputs,
6356        ))
6357    }
6358
6359    /// Like [`Self::check_transaction_inputs_for_validation`], but for
6360    /// post-consensus validation at a commit. One difference: the Move
6361    /// account is not resolved here, only the authenticator's inputs are
6362    /// checked, so no function reference comes back. The receiving objects,
6363    /// read through the commit-indexed reader, get the same checks as at
6364    /// admission.
6365    fn check_transaction_inputs_at_commit(
6366        &self,
6367        protocol_config: &ProtocolConfig,
6368        reference_gas_price: u64,
6369        tx: &Transaction,
6370        tx_input_objects: InputObjects,
6371        tx_receiving_objects: &ReceivingObjects,
6372        move_authenticators: &[&MoveAuthenticator],
6373        per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6374        verifier_limits_source: VerifierLimitsSource<'_>,
6375    ) -> IotaResult<CheckedValidationInputs> {
6376        let authenticator_gas_budget = if move_authenticators.is_empty() {
6377            0
6378        } else {
6379            protocol_config.max_auth_gas()
6380        };
6381
6382        debug_assert_eq!(
6383            move_authenticators.len(),
6384            per_authenticator_inputs.len(),
6385            "Move authenticators amount must match the number of authenticator inputs"
6386        );
6387
6388        // The account object is among the authenticator's inputs. An account
6389        // named as a shared object was decided by the reader from its rows,
6390        // which drop the transaction when the object was not created shared.
6391        // An account named as an immutable-or-owned input was read at the
6392        // version the transaction names, and this check rejects one owned by
6393        // an address or by another object. An immutable account is not
6394        // rejected here. Looking up the account's authenticator function is
6395        // left to execution.
6396        let per_authenticator_checked_inputs = per_authenticator_inputs
6397            .into_iter()
6398            .map(|(authenticator_input_objects, _account_object)| {
6399                iota_transaction_checks::check_move_authenticator_input_for_validation(
6400                    authenticator_input_objects,
6401                )
6402            })
6403            .collect::<IotaResult<Vec<_>>>()?;
6404
6405        // The gas status only meters an authenticator run, which does not happen here.
6406        let (_gas_status, tx_checked_input_objects) =
6407            iota_transaction_checks::check_transaction_input(
6408                protocol_config,
6409                reference_gas_price,
6410                tx,
6411                tx_input_objects,
6412                tx_receiving_objects,
6413                &self.metrics.bytecode_verifier_metrics,
6414                verifier_limits_source,
6415                authenticator_gas_budget,
6416            )?;
6417
6418        Ok((tx_checked_input_objects, per_authenticator_checked_inputs))
6419    }
6420
6421    #[cfg(test)]
6422    pub(crate) fn iter_live_object_set_for_testing(
6423        &self,
6424    ) -> impl Iterator<Item = authority_store_tables::LiveObject> + '_ {
6425        self.get_global_state_hash_store()
6426            .iter_cached_live_object_set_for_testing()
6427    }
6428
6429    #[cfg(test)]
6430    pub(crate) fn shutdown_execution_for_test(&self) {
6431        self.tx_execution_shutdown
6432            .lock()
6433            .take()
6434            .unwrap()
6435            .send(())
6436            .unwrap();
6437    }
6438
6439    /// NOTE: this function is only to be used for fuzzing and testing. Never
6440    /// use in prod
6441    pub async fn insert_objects_unsafe_for_testing_only(&self, objects: &[Object]) {
6442        self.get_reconfig_api().bulk_insert_genesis_objects(objects);
6443        self.get_object_cache_reader()
6444            .force_reload_system_packages(&BuiltInFramework::all_package_ids());
6445        self.get_reconfig_api()
6446            .clear_state_end_of_epoch(&self.execution_lock_for_reconfiguration().await);
6447    }
6448}
6449
6450pub struct RandomnessRoundReceiver {
6451    authority_state: Arc<AuthorityState>,
6452    randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6453}
6454
6455impl RandomnessRoundReceiver {
6456    pub fn spawn(
6457        authority_state: Arc<AuthorityState>,
6458        randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6459    ) -> JoinHandle<()> {
6460        let rrr = RandomnessRoundReceiver {
6461            authority_state,
6462            randomness_rx,
6463        };
6464        spawn_monitored_task!(rrr.run())
6465    }
6466
6467    async fn run(mut self) {
6468        info!("RandomnessRoundReceiver event loop started");
6469
6470        loop {
6471            tokio::select! {
6472                maybe_recv = self.randomness_rx.recv() => {
6473                    if let Some((epoch, round, bytes)) = maybe_recv {
6474                        self.handle_new_randomness(epoch, round, bytes).await;
6475                    } else {
6476                        break;
6477                    }
6478                },
6479            }
6480        }
6481
6482        info!("RandomnessRoundReceiver event loop ended");
6483    }
6484
6485    #[instrument(level = "debug", skip_all, fields(?epoch, ?round))]
6486    async fn handle_new_randomness(&self, epoch: EpochId, round: RandomnessRound, bytes: Vec<u8>) {
6487        fail_point_async!("randomness-delay");
6488
6489        let epoch_store = self.authority_state.load_epoch_store_one_call_per_task();
6490        if epoch_store.epoch() != epoch {
6491            warn!(
6492                "dropping randomness for epoch {epoch}, round {round}, because we are in epoch {}",
6493                epoch_store.epoch()
6494            );
6495            return;
6496        }
6497        let key = TransactionKey::RandomnessRound(epoch, round);
6498        let transaction = VerifiedTransaction::new_randomness_state_update(
6499            epoch,
6500            round,
6501            bytes,
6502            epoch_store
6503                .epoch_start_config()
6504                .randomness_obj_initial_shared_version(),
6505        );
6506        debug!(
6507            "created randomness state update transaction with digest: {:?}",
6508            transaction.digest()
6509        );
6510        let transaction = VerifiedExecutableTransaction::new_system(transaction, epoch);
6511        let digest = *transaction.digest();
6512
6513        // Randomness state updates contain the full bls signature for the random round,
6514        // which cannot necessarily be reconstructed again later. Therefore we must
6515        // immediately persist this transaction. If we crash before its outputs
6516        // are committed, this ensures we will be able to re-execute it.
6517        self.authority_state
6518            .get_cache_commit()
6519            .persist_transaction(&transaction);
6520
6521        // Notify the scheduler that the transaction key now has a known digest
6522        if epoch_store.insert_tx_key(key, digest).is_err() {
6523            warn!("epoch ended while handling new randomness");
6524        }
6525
6526        // TODO: delete this when transaction manager is deleted
6527        match self.authority_state.execution_scheduler().as_ref() {
6528            ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
6529            ExecutionSchedulerWrapper::TransactionManager(manager) => {
6530                // Notifies transaction manager about transaction and output objects
6531                // committed. This provides necessary information to transaction manager
6532                // to start executing additional ready transactions.
6533                manager.notify_transaction_key(&epoch_store, key, digest);
6534            }
6535        }
6536
6537        let authority_state = self.authority_state.clone();
6538        spawn_monitored_task!(async move {
6539            // Wait for transaction execution in a separate task, to avoid deadlock in case
6540            // of out-of-order randomness generation. (Each
6541            // RandomnessStateUpdate depends on the output of the
6542            // RandomnessStateUpdate from the previous round.)
6543            //
6544            // We set a very long timeout so that in case this gets stuck for some reason,
6545            // the validator will eventually crash rather than continuing in a
6546            // zombie mode.
6547            const RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT: Duration = Duration::from_secs(300);
6548            let result = tokio::time::timeout(
6549                RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT,
6550                authority_state
6551                    .get_transaction_cache_reader()
6552                    .try_notify_read_executed_effects(
6553                        "RandomnessRoundReceiver::notify_read_executed_effects_first",
6554                        &[digest],
6555                    ),
6556            )
6557            .await;
6558            let result = match result {
6559                Ok(result) => result,
6560                Err(_) => {
6561                    if cfg!(debug_assertions) {
6562                        // Crash on randomness update execution timeout in debug builds.
6563                        panic!(
6564                            "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6565                        );
6566                    }
6567                    warn!(
6568                        "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6569                    );
6570                    // Continue waiting as long as necessary in non-debug builds.
6571                    authority_state
6572                        .get_transaction_cache_reader()
6573                        .try_notify_read_executed_effects(
6574                            "RandomnessRoundReceiver::notify_read_executed_effects_second",
6575                            &[digest],
6576                        )
6577                        .await
6578                }
6579            };
6580
6581            let mut effects = result.unwrap_or_else(|_| panic!("failed to get effects for randomness state update transaction at epoch {epoch}, round {round}"));
6582            let effects = effects.pop().expect("should return effects");
6583            if *effects.status() != ExecutionStatus::Success {
6584                fatal!(
6585                    "failed to execute randomness state update transaction at epoch {epoch}, round {round}: {effects:?}"
6586                );
6587            }
6588            debug!(
6589                "successfully executed randomness state update transaction at epoch {epoch}, round {round}"
6590            );
6591        });
6592    }
6593}
6594
6595#[async_trait]
6596impl TransactionKeyValueStoreTrait for AuthorityState {
6597    async fn multi_get(
6598        &self,
6599        transaction_keys: &[TransactionDigest],
6600        effects_keys: &[TransactionDigest],
6601    ) -> IotaResult<KVStoreTransactionData> {
6602        let txns = if !transaction_keys.is_empty() {
6603            self.get_transaction_cache_reader()
6604                .try_multi_get_transaction_blocks(transaction_keys)?
6605                .into_iter()
6606                .map(|t| t.map(|t| (*t).clone().into_inner()))
6607                .collect()
6608        } else {
6609            vec![]
6610        };
6611
6612        let fx = if !effects_keys.is_empty() {
6613            self.get_transaction_cache_reader()
6614                .try_multi_get_executed_effects(effects_keys)?
6615        } else {
6616            vec![]
6617        };
6618
6619        Ok((txns, fx))
6620    }
6621
6622    async fn multi_get_checkpoints(
6623        &self,
6624        checkpoint_summaries: &[CheckpointSequenceNumber],
6625        checkpoint_contents: &[CheckpointSequenceNumber],
6626        checkpoint_summaries_by_digest: &[CheckpointDigest],
6627    ) -> IotaResult<(
6628        Vec<Option<CertifiedCheckpointSummary>>,
6629        Vec<Option<CheckpointContents>>,
6630        Vec<Option<CertifiedCheckpointSummary>>,
6631    )> {
6632        // TODO: use multi-get methods if it ever becomes important (unlikely)
6633        let mut summaries = Vec::with_capacity(checkpoint_summaries.len());
6634        let store = self.get_checkpoint_store();
6635        for seq in checkpoint_summaries {
6636            let checkpoint = store
6637                .get_checkpoint_by_sequence_number(*seq)?
6638                .map(|c| c.into_inner());
6639
6640            summaries.push(checkpoint);
6641        }
6642
6643        let mut contents = Vec::with_capacity(checkpoint_contents.len());
6644        for seq in checkpoint_contents {
6645            let checkpoint = store
6646                .get_checkpoint_by_sequence_number(*seq)?
6647                .and_then(|summary| {
6648                    store
6649                        .get_checkpoint_contents(&summary.contents_digest)
6650                        .expect("db read cannot fail")
6651                });
6652            contents.push(checkpoint);
6653        }
6654
6655        let mut summaries_by_digest = Vec::with_capacity(checkpoint_summaries_by_digest.len());
6656        for digest in checkpoint_summaries_by_digest {
6657            let checkpoint = store
6658                .get_checkpoint_by_digest(digest)?
6659                .map(|c| c.into_inner());
6660            summaries_by_digest.push(checkpoint);
6661        }
6662
6663        Ok((summaries, contents, summaries_by_digest))
6664    }
6665
6666    async fn get_transaction_perpetual_checkpoint(
6667        &self,
6668        digest: TransactionDigest,
6669    ) -> IotaResult<Option<CheckpointSequenceNumber>> {
6670        self.get_checkpoint_cache()
6671            .try_get_transaction_perpetual_checkpoint(&digest)
6672            .map(|res| res.map(|(_epoch, checkpoint)| checkpoint))
6673    }
6674
6675    async fn get_object(
6676        &self,
6677        object_id: ObjectId,
6678        version: VersionNumber,
6679    ) -> IotaResult<Option<Object>> {
6680        self.get_object_cache_reader()
6681            .try_get_object_by_key(&object_id, version)
6682    }
6683
6684    #[instrument(skip_all)]
6685    async fn multi_get_objects(
6686        &self,
6687        object_keys: &[ObjectKey],
6688    ) -> IotaResult<Vec<Option<Object>>> {
6689        Ok(self
6690            .get_object_cache_reader()
6691            .multi_get_objects_by_key(object_keys))
6692    }
6693
6694    async fn multi_get_transactions_perpetual_checkpoints(
6695        &self,
6696        digests: &[TransactionDigest],
6697    ) -> IotaResult<Vec<Option<CheckpointSequenceNumber>>> {
6698        let res = self
6699            .get_checkpoint_cache()
6700            .try_multi_get_transactions_perpetual_checkpoints(digests)?;
6701
6702        Ok(res
6703            .into_iter()
6704            .map(|maybe| maybe.map(|(_epoch, checkpoint)| checkpoint))
6705            .collect())
6706    }
6707
6708    #[instrument(skip(self, digests), fields(digests = digests.iter().map(|d| d.to_string()).collect::<Vec<String>>().join(", ")))]
6709    async fn multi_get_events_by_tx_digests(
6710        &self,
6711        digests: &[TransactionDigest],
6712    ) -> IotaResult<Vec<Option<TransactionEvents>>> {
6713        if digests.is_empty() {
6714            return Ok(vec![]);
6715        }
6716
6717        Ok(self
6718            .get_transaction_cache_reader()
6719            .multi_get_events(digests))
6720    }
6721}
6722
6723#[cfg(msim)]
6724pub mod framework_injection {
6725    use std::{
6726        cell::RefCell,
6727        collections::{BTreeMap, BTreeSet},
6728    };
6729
6730    use iota_framework::{BuiltInFramework, SystemPackage};
6731    use iota_sdk_types::ObjectId;
6732    use iota_types::base_types::AuthorityName;
6733    use move_binary_format::CompiledModule;
6734
6735    type FrameworkOverrideConfig = BTreeMap<ObjectId, PackageOverrideConfig>;
6736
6737    // Thread local cache because all simtests run in a single unique thread.
6738    thread_local! {
6739        static OVERRIDE: RefCell<FrameworkOverrideConfig> = RefCell::new(FrameworkOverrideConfig::default());
6740    }
6741
6742    type Framework = Vec<CompiledModule>;
6743
6744    pub type PackageUpgradeCallback =
6745        Box<dyn Fn(AuthorityName) -> Option<Framework> + Send + Sync + 'static>;
6746
6747    enum PackageOverrideConfig {
6748        Global(Framework),
6749        PerValidator(PackageUpgradeCallback),
6750    }
6751
6752    fn compiled_modules_to_bytes(modules: &[CompiledModule]) -> Vec<Vec<u8>> {
6753        modules
6754            .iter()
6755            .map(|m| {
6756                let mut buf = Vec::new();
6757                m.serialize_with_version(m.version, &mut buf).unwrap();
6758                buf
6759            })
6760            .collect()
6761    }
6762
6763    pub fn set_override(package_id: ObjectId, modules: Vec<CompiledModule>) {
6764        OVERRIDE.with(|bs| {
6765            bs.borrow_mut()
6766                .insert(package_id, PackageOverrideConfig::Global(modules))
6767        });
6768    }
6769
6770    pub fn set_override_cb(package_id: ObjectId, func: PackageUpgradeCallback) {
6771        OVERRIDE.with(|bs| {
6772            bs.borrow_mut()
6773                .insert(package_id, PackageOverrideConfig::PerValidator(func))
6774        });
6775    }
6776
6777    pub fn get_override_bytes(package_id: &ObjectId, name: AuthorityName) -> Option<Vec<Vec<u8>>> {
6778        OVERRIDE.with(|cfg| {
6779            cfg.borrow().get(package_id).and_then(|entry| match entry {
6780                PackageOverrideConfig::Global(framework) => {
6781                    Some(compiled_modules_to_bytes(framework))
6782                }
6783                PackageOverrideConfig::PerValidator(func) => {
6784                    func(name).map(|fw| compiled_modules_to_bytes(&fw))
6785                }
6786            })
6787        })
6788    }
6789
6790    pub fn get_override_modules(
6791        package_id: &ObjectId,
6792        name: AuthorityName,
6793    ) -> Option<Vec<CompiledModule>> {
6794        OVERRIDE.with(|cfg| {
6795            cfg.borrow().get(package_id).and_then(|entry| match entry {
6796                PackageOverrideConfig::Global(framework) => Some(framework.clone()),
6797                PackageOverrideConfig::PerValidator(func) => func(name),
6798            })
6799        })
6800    }
6801
6802    pub fn get_override_system_package(
6803        package_id: &ObjectId,
6804        name: AuthorityName,
6805    ) -> Option<SystemPackage> {
6806        let bytes = get_override_bytes(package_id, name)?;
6807        // A built-in package keeps the dependencies it declares. Anything else is a
6808        // package being added -- including one at a system address that is not built in
6809        // yet -- and is assumed to depend on all existing system packages.
6810        let dependencies = BuiltInFramework::try_get_package_by_id(package_id)
6811            .map_or_else(BuiltInFramework::all_package_ids, |package| {
6812                package.dependencies.to_vec()
6813            });
6814        Some(SystemPackage {
6815            id: *package_id,
6816            bytes,
6817            dependencies,
6818        })
6819    }
6820
6821    pub fn get_extra_packages(name: AuthorityName) -> Vec<SystemPackage> {
6822        let built_in = BTreeSet::from_iter(BuiltInFramework::all_package_ids());
6823        let extra: Vec<ObjectId> = OVERRIDE.with(|cfg| {
6824            cfg.borrow()
6825                .keys()
6826                .filter_map(|package| (!built_in.contains(package)).then_some(*package))
6827                .collect()
6828        });
6829
6830        extra
6831            .into_iter()
6832            .map(|package| SystemPackage {
6833                id: package,
6834                bytes: get_override_bytes(&package, name).unwrap(),
6835                dependencies: BuiltInFramework::all_package_ids(),
6836            })
6837            .collect()
6838    }
6839}
6840
6841#[derive(Debug, Serialize, Deserialize, Clone)]
6842pub struct ObjDumpFormat {
6843    pub id: ObjectId,
6844    pub version: VersionNumber,
6845    pub digest: ObjectDigest,
6846    pub object: Object,
6847}
6848
6849impl ObjDumpFormat {
6850    fn new(object: Object) -> Self {
6851        let oref = object.object_ref();
6852        Self {
6853            id: oref.object_id,
6854            version: oref.version,
6855            digest: oref.digest,
6856            object,
6857        }
6858    }
6859}
6860
6861#[derive(Debug, Serialize, Deserialize, Clone)]
6862pub struct NodeStateDump {
6863    pub tx_digest: TransactionDigest,
6864    pub sender_signed_data: SenderSignedTransaction,
6865    pub executed_epoch: u64,
6866    pub reference_gas_price: u64,
6867    pub protocol_version: u64,
6868    pub epoch_start_timestamp_ms: u64,
6869    pub computed_effects: TransactionEffects,
6870    pub expected_effects_digest: TransactionEffectsDigest,
6871    pub relevant_system_packages: Vec<ObjDumpFormat>,
6872    pub shared_objects: Vec<ObjDumpFormat>,
6873    pub loaded_child_objects: Vec<ObjDumpFormat>,
6874    pub modified_at_versions: Vec<ObjDumpFormat>,
6875    pub runtime_reads: Vec<ObjDumpFormat>,
6876    pub input_objects: Vec<ObjDumpFormat>,
6877}
6878
6879impl NodeStateDump {
6880    pub fn new(
6881        tx_digest: &TransactionDigest,
6882        effects: &TransactionEffects,
6883        expected_effects_digest: TransactionEffectsDigest,
6884        object_store: &dyn ObjectStore,
6885        epoch_store: &Arc<AuthorityPerEpochStore>,
6886        inner_temporary_store: &InnerTemporaryStore,
6887        transaction: &VerifiedExecutableTransaction,
6888    ) -> IotaResult<Self> {
6889        // Epoch info
6890        let executed_epoch = epoch_store.epoch();
6891        let reference_gas_price = epoch_store.reference_gas_price();
6892        let epoch_start_config = epoch_store.epoch_start_config();
6893        let protocol_version = epoch_store.protocol_version().as_u64();
6894        let epoch_start_timestamp_ms = epoch_start_config.epoch_data().epoch_start_timestamp();
6895
6896        // Record all system packages at this version
6897        let mut relevant_system_packages = Vec::new();
6898        for sys_package_id in BuiltInFramework::all_package_ids() {
6899            if let Some(w) = object_store.try_get_object(&sys_package_id)? {
6900                relevant_system_packages.push(ObjDumpFormat::new(w))
6901            }
6902        }
6903
6904        // Record all the shared objects
6905        let mut shared_objects = Vec::new();
6906        for kind in effects.input_shared_objects() {
6907            match kind {
6908                InputSharedObject::Mutate(obj_ref) | InputSharedObject::ReadOnly(obj_ref) => {
6909                    if let Some(w) =
6910                        object_store.try_get_object_by_key(&obj_ref.object_id, obj_ref.version)?
6911                    {
6912                        shared_objects.push(ObjDumpFormat::new(w))
6913                    }
6914                }
6915                InputSharedObject::ReadDeleted(..)
6916                | InputSharedObject::MutateDeleted(..)
6917                // TODO: consider record congested objects.
6918                | InputSharedObject::Canceled(..) => (),
6919                _ => unimplemented!(
6920                    "a new InputSharedObject enum variant was added and needs to be handled"
6921                ),
6922            }
6923        }
6924
6925        // Record all loaded child objects
6926        // Child objects which are read but not mutated are not tracked anywhere else
6927        let mut loaded_child_objects = Vec::new();
6928        for (id, meta) in &inner_temporary_store.loaded_runtime_objects {
6929            if let Some(w) = object_store.try_get_object_by_key(id, meta.version)? {
6930                loaded_child_objects.push(ObjDumpFormat::new(w))
6931            }
6932        }
6933
6934        // Record all modified objects
6935        let mut modified_at_versions = Vec::new();
6936        for modified in effects.modified_at_versions() {
6937            let (id, ver) = (modified.object_id(), modified.version());
6938            if let Some(w) = object_store.try_get_object_by_key(id, ver)? {
6939                modified_at_versions.push(ObjDumpFormat::new(w))
6940            }
6941        }
6942
6943        // Packages read at runtime, which were not previously loaded into the temoorary
6944        // store Some packages may be fetched at runtime and wont show up in
6945        // input objects
6946        let mut runtime_reads = Vec::new();
6947        for obj in inner_temporary_store
6948            .runtime_packages_loaded_from_db
6949            .values()
6950        {
6951            runtime_reads.push(ObjDumpFormat::new(obj.object().clone()));
6952        }
6953
6954        // All other input objects should already be in `inner_temporary_store.objects`
6955
6956        Ok(Self {
6957            tx_digest: *tx_digest,
6958            executed_epoch,
6959            reference_gas_price,
6960            epoch_start_timestamp_ms,
6961            protocol_version,
6962            relevant_system_packages,
6963            shared_objects,
6964            loaded_child_objects,
6965            modified_at_versions,
6966            runtime_reads,
6967            sender_signed_data: transaction.clone().into_message(),
6968            input_objects: inner_temporary_store
6969                .input_objects
6970                .values()
6971                .map(|o| ObjDumpFormat::new(o.clone()))
6972                .collect(),
6973            computed_effects: effects.clone(),
6974            expected_effects_digest,
6975        })
6976    }
6977
6978    pub fn all_objects(&self) -> Vec<ObjDumpFormat> {
6979        let mut objects = Vec::new();
6980        objects.extend(self.relevant_system_packages.clone());
6981        objects.extend(self.shared_objects.clone());
6982        objects.extend(self.loaded_child_objects.clone());
6983        objects.extend(self.modified_at_versions.clone());
6984        objects.extend(self.runtime_reads.clone());
6985        objects.extend(self.input_objects.clone());
6986        objects
6987    }
6988
6989    pub fn write_to_file(&self, path: &Path) -> Result<PathBuf, anyhow::Error> {
6990        let file_name = format!(
6991            "{}_{}_NODE_DUMP.json",
6992            self.tx_digest,
6993            AuthorityState::unixtime_now_ms()
6994        );
6995        let mut path = path.to_path_buf();
6996        path.push(&file_name);
6997        let mut file = File::create(path.clone())?;
6998        file.write_all(serde_json::to_string_pretty(self)?.as_bytes())?;
6999        Ok(path)
7000    }
7001
7002    pub fn read_from_file(path: &PathBuf) -> Result<Self, anyhow::Error> {
7003        let file = File::open(path)?;
7004        serde_json::from_reader(file).map_err(|e| anyhow::anyhow!(e))
7005    }
7006}
7007
7008/// The reason [`AuthorityState::check_move_account`] failed.
7009/// Execution treats the two cases differently, because only
7010/// the first one is about the transaction.
7011enum MoveAccountCheckError {
7012    /// The account fails a check.
7013    Input(UserInputError),
7014
7015    /// This validator failed to read its store.
7016    Storage(IotaError),
7017}
7018
7019impl From<UserInputError> for MoveAccountCheckError {
7020    fn from(error: UserInputError) -> Self {
7021        Self::Input(error)
7022    }
7023}
7024
7025impl From<MoveAccountCheckError> for IotaError {
7026    fn from(error: MoveAccountCheckError) -> Self {
7027        match error {
7028            MoveAccountCheckError::Input(error) => IotaError::UserInput { error },
7029            MoveAccountCheckError::Storage(error) => error,
7030        }
7031    }
7032}
7033
7034/// Returns the [`MoveAuthenticator`]s to execute during the pre-consensus
7035/// phase.
7036///
7037/// When `pre_consensus_sponsor_only_move_authentication` is enabled:
7038/// - For sponsored transactions: only the sponsor's [`MoveAuthenticator`] is returned (empty if the
7039///   sponsor does not use one).
7040/// - For non-sponsored transactions: all [`MoveAuthenticator`]s are returned (currently only the
7041///   sender's).
7042///
7043/// When the flag is not set, all [`MoveAuthenticator`]s are returned for
7044/// compatibility.
7045fn pre_consensus_move_authenticators<'a>(
7046    tx: &'a VerifiedTransaction,
7047    protocol_config: &ProtocolConfig,
7048) -> Vec<&'a MoveAuthenticator> {
7049    if protocol_config.pre_consensus_sponsor_only_move_authentication() {
7050        if tx.transaction().is_sponsored_tx() {
7051            if let Some(sponsor_move_authenticator) = tx.sponsor_move_authenticator() {
7052                vec![sponsor_move_authenticator]
7053            } else {
7054                vec![]
7055            }
7056        } else {
7057            tx.move_authenticators()
7058        }
7059    } else {
7060        tx.move_authenticators()
7061    }
7062}