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    /// Whatever the budget resolves to, the gas coins have to cover it, since
2535    /// execution reserves the whole budget from them before running any command
2536    /// and refunds it afterwards. A caller leaving the budget at zero to have
2537    /// the cost estimated therefore gets an estimate whatever its coins hold,
2538    /// but the reserved budget is off limits for the duration of the
2539    /// programmable transaction: a transaction that also pays out of its gas
2540    /// coin has to declare a budget leaving room for that, exactly as it would
2541    /// on chain. A balance too small to declare the minimum budget at all is
2542    /// rejected with [`UserInputError::GasBalanceTooLow`].
2543    pub fn simulate_transaction(
2544        &self,
2545        transaction: Transaction,
2546        checks: VmChecks,
2547    ) -> IotaResult<SimulateTransactionResult> {
2548        let epoch_store = self.load_epoch_store_one_call_per_task();
2549        self.simulate_transaction_in_epoch(&epoch_store, transaction, checks)
2550    }
2551
2552    /// Same as [`AuthorityState::simulate_transaction`], for callers that
2553    /// already hold an epoch store.
2554    ///
2555    /// Callers that derive gas parameters from an epoch, or resolve types
2556    /// against its executor once the simulation returns, should pass that same
2557    /// epoch store here so the whole operation observes one epoch.
2558    ///
2559    /// Nothing here checks that `epoch_store` is the current one — pinning a
2560    /// superseded epoch is the point, and is what
2561    /// [`AuthorityState::simulate_transaction`] does for the span of its own
2562    /// call. Keeping one across an unbounded period is the caller's problem:
2563    /// the simulation would run against that epoch's protocol config,
2564    /// executor, and reference gas price.
2565    #[instrument("simulate_tx", level = "trace", skip_all)]
2566    pub fn simulate_transaction_in_epoch(
2567        &self,
2568        epoch_store: &AuthorityPerEpochStore,
2569        transaction: Transaction,
2570        checks: VmChecks,
2571    ) -> IotaResult<SimulateTransactionResult> {
2572        if !self.is_fullnode(epoch_store) {
2573            return Err(IotaError::UnsupportedFeature {
2574                error: "simulate is only supported on fullnodes".to_string(),
2575            });
2576        }
2577
2578        self.simulate_transaction_inner(epoch_store, transaction, checks)
2579    }
2580
2581    /// Same as [`AuthorityState::simulate_transaction`], but runs on a
2582    /// validator too. Only the single-node benchmark, which has no fullnode
2583    /// to run against, needs this.
2584    pub fn simulate_transaction_for_benchmark(
2585        &self,
2586        transaction: Transaction,
2587        checks: VmChecks,
2588    ) -> IotaResult<SimulateTransactionResult> {
2589        let epoch_store = self.load_epoch_store_one_call_per_task();
2590        self.simulate_transaction_inner(&epoch_store, transaction, checks)
2591    }
2592
2593    #[instrument(level = "trace", skip_all)]
2594    fn simulate_transaction_inner(
2595        &self,
2596        epoch_store: &AuthorityPerEpochStore,
2597        mut transaction: Transaction,
2598        checks: VmChecks,
2599    ) -> IotaResult<SimulateTransactionResult> {
2600        if transaction.kind().is_system() {
2601            return Err(IotaError::UnsupportedFeature {
2602                error: "simulate does not support system transactions".to_string(),
2603            });
2604        }
2605
2606        transaction.check_serialized_size(epoch_store.protocol_config())?;
2607
2608        // Cheap validity checks for a transaction, including input size limits.
2609        // This does not check if gas objects are missing since we may create a
2610        // mock gas object. It checks for other transaction input validity.
2611        transaction.validity_check_no_gas_check(epoch_store.protocol_config())?;
2612
2613        // The full validity check caps the gas payment size alongside requiring a
2614        // gas payment at all, which a simulation relaxes so it can mock one. The cap
2615        // still applies, and is cheapest before any object is loaded.
2616        transaction.check_gas_payment_size(epoch_store.protocol_config())?;
2617
2618        let input_object_kinds = transaction.input_objects()?;
2619        let receiving_object_refs = transaction.receiving_objects();
2620
2621        // Since we need to simulate a validator signing the transaction, the first step
2622        // is to check if some transaction elements are denied.
2623        iota_transaction_checks::deny::check_transaction_for_validation(
2624            &transaction,
2625            &[],
2626            &input_object_kinds,
2627            &receiving_object_refs,
2628            &self.config.transaction_deny_config,
2629            self.get_backing_package_store().as_ref(),
2630        )?;
2631
2632        // Load input and receiving objects
2633        let (mut input_objects, receiving_objects) = self.input_loader.read_objects_for_signing(
2634            // We don't want to cache this transaction since it's a simulation.
2635            None,
2636            &input_object_kinds,
2637            &receiving_object_refs,
2638            epoch_store.epoch(),
2639        )?;
2640
2641        // Create a mock gas object if one was not provided
2642        let mock_gas_id = if transaction.gas().is_empty() {
2643            let mock_gas_object = mock_simulation_gas_coin(transaction.gas_data().owner);
2644            let mock_gas_object_ref = mock_gas_object.object_ref();
2645            transaction.gas_data_mut().objects = vec![mock_gas_object_ref];
2646            input_objects.push(ObjectReadResult::new_from_gas_object(&mock_gas_object));
2647            Some(mock_gas_object.id())
2648        } else {
2649            None
2650        };
2651
2652        let protocol_config = epoch_store.protocol_config();
2653
2654        iota_types::gas::fill_in_unset_simulation_gas(
2655            &mut transaction,
2656            &input_objects,
2657            epoch_store.reference_gas_price(),
2658            protocol_config,
2659        );
2660
2661        // `MoveAuthenticator`s are not supported in simulation, so we set the
2662        // `authenticator_gas_budget` to 0.
2663        let authenticator_gas_budget = 0;
2664
2665        // Checks enabled -> DRY-RUN, it means we are simulating a real TX
2666        // Checks disabled -> DEV-INSPECT, more relaxed Move VM checks
2667        let (gas_status, checked_input_objects) = if checks.enabled() {
2668            iota_transaction_checks::check_transaction_input(
2669                protocol_config,
2670                epoch_store.reference_gas_price(),
2671                &transaction,
2672                input_objects,
2673                &receiving_objects,
2674                &self.metrics.bytecode_verifier_metrics,
2675                VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2676                authenticator_gas_budget,
2677            )?
2678        } else {
2679            // Execution smashes the gas coins and reserves the whole budget from them
2680            // before running any command, treating the input checks as having verified
2681            // that they are gas coins at all — so with those checks skipped here, this
2682            // has to stand in for them. With the checks enabled,
2683            // `check_transaction_input` covers it.
2684            iota_types::gas::check_gas_coins_cover_budget_in_simulation(
2685                &input_objects,
2686                transaction.gas(),
2687                transaction.gas_budget(),
2688            )?;
2689
2690            let checked_input_objects = iota_transaction_checks::check_simulation_input(
2691                protocol_config,
2692                transaction.kind(),
2693                input_objects,
2694                receiving_objects,
2695            )?;
2696            let gas_status = IotaGasStatus::new(
2697                transaction.gas_budget(),
2698                transaction.gas_price(),
2699                epoch_store.reference_gas_price(),
2700                protocol_config,
2701            )?;
2702
2703            (gas_status, checked_input_objects)
2704        };
2705
2706        // Create a new executor for the simulation
2707        let executor = iota_execution::executor(
2708            protocol_config,
2709            true, // silent
2710            None,
2711        )
2712        .expect("Creating an executor should not fail here");
2713
2714        // Execute the simulation
2715        let (kind, signer, gas_data) = transaction.execution_parts();
2716        let (inner_temp_store, _, effects, execution_result) = executor.dev_inspect_transaction(
2717            self.get_backing_store().as_ref(),
2718            protocol_config,
2719            self.metrics.limits_metrics.clone(),
2720            false, // expensive_checks
2721            self.config.certificate_deny_config.certificate_deny_set(),
2722            &epoch_store.epoch_start_config().epoch_data().epoch_id(),
2723            epoch_store
2724                .epoch_start_config()
2725                .epoch_data()
2726                .epoch_start_timestamp(),
2727            checked_input_objects,
2728            gas_data,
2729            gas_status,
2730            kind,
2731            signer,
2732            transaction.digest(),
2733            checks.disabled(),
2734        );
2735
2736        let mut input_objects = inner_temp_store.input_objects;
2737        iota_types::storage::extend_input_objects_with_loaded_runtime_objects(
2738            &mut input_objects,
2739            &effects,
2740            &inner_temp_store.loaded_runtime_objects,
2741            self.get_backing_store().as_object_store(),
2742        );
2743
2744        Ok(SimulateTransactionResult {
2745            input_objects,
2746            output_objects: inner_temp_store.written,
2747            events: effects.events_digest().map(|_| inner_temp_store.events),
2748            effects,
2749            execution_result,
2750            suggested_gas_price: self
2751                .congestion_tracker
2752                .get_prediction_suggested_gas_price(&transaction),
2753            mock_gas_id,
2754            gas_data: transaction.gas_data().clone(),
2755        })
2756    }
2757
2758    // Only used for testing because of how epoch store is loaded.
2759    pub fn reference_gas_price_for_testing(&self) -> Result<u64, anyhow::Error> {
2760        let epoch_store = self.epoch_store_for_testing();
2761        Ok(epoch_store.reference_gas_price())
2762    }
2763
2764    #[instrument(level = "trace", skip_all)]
2765    pub fn try_is_tx_already_executed(&self, digest: &TransactionDigest) -> IotaResult<bool> {
2766        self.get_transaction_cache_reader()
2767            .try_is_tx_already_executed(digest)
2768    }
2769
2770    /// Non-fallible version of `try_is_tx_already_executed`.
2771    pub fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
2772        self.try_is_tx_already_executed(digest)
2773            .expect("storage access failed")
2774    }
2775
2776    /// Indexes a transaction by updating various indexes in the `IndexStore`.
2777    #[instrument(level = "debug", skip_all, err)]
2778    fn index_tx(
2779        &self,
2780        indexes: &IndexStore,
2781        digest: &TransactionDigest,
2782        // TODO: index_tx really just need the transaction data here.
2783        transaction: &VerifiedExecutableTransaction,
2784        effects: &TransactionEffects,
2785        events: &TransactionEvents,
2786        timestamp_ms: u64,
2787        tx_coins: Option<TxCoins>,
2788        written: &WrittenObjects,
2789        inner_temporary_store: &InnerTemporaryStore,
2790        epoch_store: &Arc<AuthorityPerEpochStore>,
2791    ) -> IotaResult<u64> {
2792        let changes = self
2793            .process_object_index(effects, written, inner_temporary_store, epoch_store)
2794            .tap_err(|e| warn!(tx_digest=?digest, "Failed to process object index, index_tx is skipped: {e}"))?;
2795
2796        indexes.index_tx(
2797            transaction.data().transaction().sender(),
2798            transaction
2799                .data()
2800                .transaction()
2801                .input_objects()?
2802                .iter()
2803                .map(|o| o.object_id()),
2804            effects
2805                .all_changed_objects()
2806                .into_iter()
2807                .map(|(changed, _kind)| (*changed.reference(), *changed.owner())),
2808            transaction
2809                .data()
2810                .transaction()
2811                .move_calls()
2812                .into_iter()
2813                .map(|(package, module, function)| {
2814                    (*package, module.to_owned(), function.to_owned())
2815                }),
2816            events,
2817            changes,
2818            digest,
2819            timestamp_ms,
2820            tx_coins,
2821        )
2822    }
2823
2824    #[cfg(msim)]
2825    fn create_fail_state(
2826        &self,
2827        transaction: &VerifiedExecutableTransaction,
2828        epoch_store: &Arc<AuthorityPerEpochStore>,
2829        effects: &mut TransactionEffects,
2830    ) {
2831        use std::cell::RefCell;
2832
2833        use iota_types::effects::TransactionEffectsAPIForTesting;
2834        thread_local! {
2835            static FAIL_STATE: RefCell<(u64, HashSet<AuthorityName>)> = RefCell::new((0, HashSet::new()));
2836        }
2837        if !transaction.data().transaction().is_system_tx() {
2838            let committee = epoch_store.committee();
2839            let cur_stake = (**committee).weight(&self.name);
2840            if cur_stake > 0 {
2841                FAIL_STATE.with_borrow_mut(|fail_state| {
2842                    // let (&mut failing_stake, &mut failing_validators) = fail_state;
2843                    if fail_state.0 < committee.validity_threshold() {
2844                        fail_state.0 += cur_stake;
2845                        fail_state.1.insert(self.name);
2846                    }
2847
2848                    if fail_state.1.contains(&self.name) {
2849                        info!("cp_exec failing tx");
2850                        effects.gas_cost_summary_mut_for_testing().computation_cost += 1;
2851                    }
2852                });
2853            }
2854        }
2855    }
2856
2857    fn process_object_index(
2858        &self,
2859        effects: &TransactionEffects,
2860        written: &WrittenObjects,
2861        inner_temporary_store: &InnerTemporaryStore,
2862        epoch_store: &Arc<AuthorityPerEpochStore>,
2863    ) -> IotaResult<ObjectIndexChanges> {
2864        let mut layout_resolver =
2865            epoch_store
2866                .executor()
2867                .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
2868                    inner_temporary_store,
2869                    self.get_backing_package_store(),
2870                )));
2871
2872        let modified_at_version = effects
2873            .modified_at_versions()
2874            .into_iter()
2875            .map(|modified| (*modified.object_id(), modified.version()))
2876            .collect::<HashMap<_, _>>();
2877
2878        let tx_digest = effects.transaction_digest();
2879        let mut deleted_owners = vec![];
2880        let mut deleted_dynamic_fields = vec![];
2881        for object_ref in effects.deleted().into_iter().chain(effects.wrapped()) {
2882            let old_version = modified_at_version.get(&object_ref.object_id).unwrap();
2883            // When we process the index, the latest object hasn't been written yet so
2884            // the old object must be present.
2885            match self.get_owner_at_version(&object_ref.object_id, *old_version).unwrap_or_else(
2886                |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)
2887            ) {
2888                Owner::Address(addr) => deleted_owners.push((addr, object_ref.object_id)),
2889                Owner::Object(object_id) => {
2890                    deleted_dynamic_fields.push((object_id, object_ref.object_id))
2891                }
2892                _ => {}
2893            }
2894        }
2895
2896        let mut new_owners = vec![];
2897        let mut new_dynamic_fields = vec![];
2898
2899        for (changed, kind) in effects.all_changed_objects() {
2900            let (oref, owner) = (*changed.reference(), *changed.owner());
2901            let id = &oref.object_id;
2902            // For mutated objects, retrieve old owner and delete old index if there is a
2903            // owner change.
2904            if let WriteKind::Mutate = kind {
2905                let Some(old_version) = modified_at_version.get(id) else {
2906                    panic!(
2907                        "tx_digest={tx_digest}, error processing object owner index, cannot find modified at version for mutated object [{id}]."
2908                    );
2909                };
2910                // When we process the index, the latest object hasn't been written yet so
2911                // the old object must be present.
2912                let Some(old_object) = self
2913                    .get_object_store()
2914                    .try_get_object_by_key(id, *old_version)?
2915                else {
2916                    panic!(
2917                        "tx_digest={tx_digest}, error processing object owner index, cannot find owner for object {id} at version {old_version:?}"
2918                    );
2919                };
2920                if old_object.owner != owner {
2921                    match old_object.owner {
2922                        Owner::Address(addr) => {
2923                            deleted_owners.push((addr, *id));
2924                        }
2925                        Owner::Object(object_id) => deleted_dynamic_fields.push((object_id, *id)),
2926                        _ => {}
2927                    }
2928                }
2929            }
2930
2931            match owner {
2932                Owner::Address(addr) => {
2933                    // TODO: We can remove the object fetching after we added ObjectType to
2934                    // TransactionEffects
2935                    let new_object = written.get(id).unwrap_or_else(
2936                        || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2937                    );
2938                    assert_eq!(
2939                        new_object.version(),
2940                        oref.version,
2941                        "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2942                        tx_digest,
2943                        id,
2944                        new_object.version(),
2945                        oref.version
2946                    );
2947
2948                    let object_type = new_object
2949                        .data
2950                        .opt_object_type()
2951                        .map(|ty| ObjectType::Struct(ty.clone()))
2952                        .unwrap_or(ObjectType::Package);
2953
2954                    new_owners.push((
2955                        (addr, *id),
2956                        ObjectInfo {
2957                            object_id: *id,
2958                            version: oref.version,
2959                            digest: oref.digest,
2960                            object_type,
2961                            owner,
2962                            previous_transaction: *effects.transaction_digest(),
2963                        },
2964                    ));
2965                }
2966                Owner::Object(owner) => {
2967                    let new_object = written.get(id).unwrap_or_else(
2968                        || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2969                    );
2970                    assert_eq!(
2971                        new_object.version(),
2972                        oref.version,
2973                        "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2974                        tx_digest,
2975                        id,
2976                        new_object.version(),
2977                        oref.version
2978                    );
2979
2980                    let Some(df_info) = self
2981                        .try_create_dynamic_field_info(new_object, written, layout_resolver.as_mut())
2982                        .unwrap_or_else(|e| {
2983                            error!(
2984                                "try_create_dynamic_field_info should not fail, {}, new_object={}, new_object_type={}",
2985                                e,
2986                                new_object.id(),
2987                                ObjectType::from(new_object)
2988                            );
2989                            None
2990                        }
2991                        )
2992                    else {
2993                        // Skip indexing for non dynamic field objects.
2994                        continue;
2995                    };
2996                    new_dynamic_fields.push(((owner, *id), df_info))
2997                }
2998                _ => {}
2999            }
3000        }
3001
3002        Ok(ObjectIndexChanges {
3003            deleted_owners,
3004            deleted_dynamic_fields,
3005            new_owners,
3006            new_dynamic_fields,
3007        })
3008    }
3009
3010    fn try_create_dynamic_field_info(
3011        &self,
3012        o: &Object,
3013        written: &WrittenObjects,
3014        resolver: &mut dyn LayoutResolver,
3015    ) -> IotaResult<Option<DynamicFieldInfo>> {
3016        // Skip if not a move object
3017        let Some(move_object) = o.data.as_opt_struct().cloned() else {
3018            return Ok(None);
3019        };
3020
3021        // We only index dynamic field objects
3022        if !move_object.struct_tag().is_dynamic_field() {
3023            return Ok(None);
3024        }
3025
3026        let layout = match resolver.get_annotated_layout(move_object.struct_tag()) {
3027            Ok(annotated_layout) => annotated_layout.into_layout(),
3028            Err(e) => {
3029                error!(
3030                    "unable to load layout for type `{:?}`: {e}",
3031                    move_object.struct_tag()
3032                );
3033                return Ok(None);
3034            }
3035        };
3036
3037        let field =
3038            DFV::FieldVisitor::deserialize(move_object.contents(), &layout).map_err(|e| {
3039                IotaError::ObjectDeserialization {
3040                    error: e.to_string(),
3041                }
3042            })?;
3043
3044        let type_ = field.kind;
3045        let name_type: TypeTag = type_tag_core_to_sdk(&field.name_layout.into());
3046        let bcs_name = field.name_bytes.to_owned();
3047
3048        let name_value = BoundedVisitor::deserialize_value(field.name_bytes, field.name_layout)
3049            .map_err(|e| {
3050                warn!("{e}");
3051                IotaError::ObjectDeserialization {
3052                    error: e.to_string(),
3053                }
3054            })?;
3055
3056        let name = DynamicFieldName {
3057            type_tag: name_type,
3058            value: IotaMoveValue::from(name_value).to_json_value(),
3059        };
3060
3061        let value_metadata = field.value_metadata().map_err(|e| {
3062            warn!("{e}");
3063            IotaError::ObjectDeserialization {
3064                error: e.to_string(),
3065            }
3066        })?;
3067
3068        Ok(Some(match value_metadata {
3069            DFV::ValueMetadata::DynamicField(object_type) => DynamicFieldInfo {
3070                name,
3071                bcs_name,
3072                type_,
3073                object_type: object_type.to_canonical_string(/* with_prefix */ true),
3074                object_id: o.id(),
3075                version: o.version(),
3076                digest: o.digest(),
3077            },
3078
3079            DFV::ValueMetadata::DynamicObjectField(object_id) => {
3080                // Find the actual object from storage using the object id obtained from the
3081                // wrapper.
3082
3083                // Try to find the object in the written objects first.
3084                let (version, digest, object_type) = if let Some(object) = written.get(&object_id) {
3085                    (
3086                        object.version(),
3087                        object.digest(),
3088                        object.data.opt_object_type().unwrap().clone(),
3089                    )
3090                } else {
3091                    // If not found, try to find it in the database.
3092                    let object = self
3093                        .get_object_store()
3094                        .try_get_object_by_key(&object_id, o.version())?
3095                        .ok_or_else(|| UserInputError::ObjectNotFound {
3096                            object_id,
3097                            version: Some(o.version()),
3098                        })?;
3099                    let version = object.version();
3100                    let digest = object.digest();
3101                    let object_type = object.data.opt_object_type().unwrap().clone();
3102                    (version, digest, object_type)
3103                };
3104
3105                DynamicFieldInfo {
3106                    name,
3107                    bcs_name,
3108                    type_,
3109                    object_type: object_type.to_string(),
3110                    object_id,
3111                    version,
3112                    digest,
3113                }
3114            }
3115        }))
3116    }
3117
3118    #[instrument(level = "trace", skip_all, err)]
3119    fn post_process_one_tx(
3120        &self,
3121        transaction: &VerifiedExecutableTransaction,
3122        effects: &TransactionEffects,
3123        inner_temporary_store: &InnerTemporaryStore,
3124        epoch_store: &Arc<AuthorityPerEpochStore>,
3125    ) -> IotaResult {
3126        if self.indexes.is_none() {
3127            return Ok(());
3128        }
3129
3130        let _scope = monitored_scope("Execution::post_process_one_tx");
3131
3132        let tx_digest = transaction.digest();
3133        let timestamp_ms = Self::unixtime_now_ms();
3134        let events = &inner_temporary_store.events;
3135        let written = &inner_temporary_store.written;
3136        let tx_coins = self.fullnode_only_get_tx_coins_for_indexing(
3137            effects,
3138            inner_temporary_store,
3139            epoch_store,
3140        );
3141
3142        // Index tx
3143        if let Some(indexes) = &self.indexes {
3144            let _ = self
3145                .index_tx(
3146                    indexes.as_ref(),
3147                    tx_digest,
3148                    transaction,
3149                    effects,
3150                    events,
3151                    timestamp_ms,
3152                    tx_coins,
3153                    written,
3154                    inner_temporary_store,
3155                    epoch_store,
3156                )
3157                .tap_ok(|_| self.metrics.post_processing_total_tx_indexed.inc())
3158                .tap_err(|e| error!(?tx_digest, "Post processing - Couldn't index tx: {e}"))
3159                .expect("Indexing tx should not fail");
3160
3161            let effects: IotaTransactionBlockEffects = effects.clone().try_into()?;
3162            let events = self.make_transaction_block_events(
3163                events.clone(),
3164                *tx_digest,
3165                timestamp_ms,
3166                epoch_store,
3167                inner_temporary_store,
3168            )?;
3169            // Emit events
3170            self.subscription_handler
3171                .process_tx(transaction.data().transaction(), &effects, &events)
3172                .tap_ok(|_| {
3173                    self.metrics
3174                        .post_processing_total_tx_had_event_processed
3175                        .inc()
3176                })
3177                .tap_err(|e| {
3178                    warn!(
3179                        ?tx_digest,
3180                        "Post processing - Couldn't process events for tx: {}", e
3181                    )
3182                })?;
3183
3184            self.metrics
3185                .post_processing_total_events_emitted
3186                .inc_by(events.data.len() as u64);
3187        };
3188        Ok(())
3189    }
3190
3191    fn make_transaction_block_events(
3192        &self,
3193        transaction_events: TransactionEvents,
3194        digest: TransactionDigest,
3195        timestamp_ms: u64,
3196        epoch_store: &Arc<AuthorityPerEpochStore>,
3197        inner_temporary_store: &InnerTemporaryStore,
3198    ) -> IotaResult<IotaTransactionBlockEvents> {
3199        let mut layout_resolver =
3200            epoch_store
3201                .executor()
3202                .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
3203                    inner_temporary_store,
3204                    self.get_backing_package_store(),
3205                )));
3206        IotaTransactionBlockEvents::try_from(
3207            transaction_events,
3208            digest,
3209            Some(timestamp_ms),
3210            layout_resolver.as_mut(),
3211        )
3212    }
3213
3214    pub fn unixtime_now_ms() -> u64 {
3215        let now = SystemTime::now()
3216            .duration_since(UNIX_EPOCH)
3217            .expect("Time went backwards")
3218            .as_millis();
3219        u64::try_from(now).expect("Travelling in time machine")
3220    }
3221
3222    #[instrument(level = "trace", skip_all)]
3223    pub async fn handle_transaction_info_request(
3224        &self,
3225        request: TransactionInfoRequest,
3226    ) -> IotaResult<TransactionInfoResponse> {
3227        let epoch_store = self.load_epoch_store_one_call_per_task();
3228        let (transaction, status) = self
3229            .get_transaction_status(&request.transaction_digest, &epoch_store)?
3230            .ok_or(IotaError::TransactionNotFound {
3231                digest: request.transaction_digest,
3232            })?;
3233        Ok(TransactionInfoResponse {
3234            transaction,
3235            status,
3236        })
3237    }
3238
3239    #[instrument(level = "trace", skip_all)]
3240    pub async fn handle_object_info_request(
3241        &self,
3242        request: ObjectInfoRequest,
3243    ) -> IotaResult<ObjectInfoResponse> {
3244        let epoch_store = self.load_epoch_store_one_call_per_task();
3245
3246        let requested_object_seq = match request.request_kind {
3247            ObjectInfoRequestKind::LatestObjectInfo => {
3248                self.try_get_object_or_tombstone(request.object_id)?
3249                    .ok_or_else(|| {
3250                        IotaError::from(UserInputError::ObjectNotFound {
3251                            object_id: request.object_id,
3252                            version: None,
3253                        })
3254                    })?
3255                    .version
3256            }
3257            ObjectInfoRequestKind::PastObjectInfoDebug(seq) => seq,
3258        };
3259
3260        let object = self
3261            .get_object_store()
3262            .try_get_object_by_key(&request.object_id, requested_object_seq)?
3263            .ok_or_else(|| {
3264                IotaError::from(UserInputError::ObjectNotFound {
3265                    object_id: request.object_id,
3266                    version: Some(requested_object_seq),
3267                })
3268            })?;
3269
3270        let layout = if let (LayoutGenerationOption::Generate, Some(move_obj)) =
3271            (request.generate_layout, object.data.as_opt_struct())
3272        {
3273            Some(into_struct_layout(
3274                epoch_store
3275                    .executor()
3276                    .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
3277                    .get_annotated_layout(move_obj.struct_tag())?,
3278            )?)
3279        } else {
3280            None
3281        };
3282
3283        let lock = if !object.is_address_owned() {
3284            // Only address owned objects have locks.
3285            None
3286        } else {
3287            self.get_transaction_lock(&object.object_ref(), &epoch_store)?
3288                .map(|s| s.into_inner())
3289        };
3290
3291        Ok(ObjectInfoResponse {
3292            object,
3293            layout,
3294            lock_for_debugging: lock,
3295        })
3296    }
3297
3298    #[instrument(level = "trace", skip_all)]
3299    pub fn handle_checkpoint_request(
3300        &self,
3301        request: &CheckpointRequest,
3302    ) -> IotaResult<CheckpointResponse> {
3303        let summary = if request.certified {
3304            let summary = match request.sequence_number {
3305                Some(seq) => self
3306                    .checkpoint_store
3307                    .get_checkpoint_by_sequence_number(seq)?,
3308                None => self.checkpoint_store.get_latest_certified_checkpoint()?,
3309            }
3310            .map(|v| v.into_inner());
3311            summary.map(CheckpointSummaryResponse::Certified)
3312        } else {
3313            let summary = match request.sequence_number {
3314                Some(seq) => self.checkpoint_store.get_locally_computed_checkpoint(seq)?,
3315                None => self
3316                    .checkpoint_store
3317                    .get_latest_locally_computed_checkpoint()?,
3318            };
3319            summary.map(CheckpointSummaryResponse::Pending)
3320        };
3321        let contents = match &summary {
3322            Some(s) => self
3323                .checkpoint_store
3324                .get_checkpoint_contents(&s.contents_digest())?,
3325            None => None,
3326        };
3327        Ok(CheckpointResponse {
3328            checkpoint: summary,
3329            contents,
3330        })
3331    }
3332
3333    fn check_protocol_version(
3334        supported_protocol_versions: SupportedProtocolVersions,
3335        current_version: ProtocolVersion,
3336    ) {
3337        info!("current protocol version is now {:?}", current_version);
3338        info!("supported versions are: {:?}", supported_protocol_versions);
3339        if !supported_protocol_versions.is_version_supported(current_version) {
3340            let msg = format!(
3341                "Unsupported protocol version. The network is at {current_version:?}, but this IotaNode only supports: {supported_protocol_versions:?}. Shutting down.",
3342            );
3343
3344            error!("{}", msg);
3345            eprintln!("{msg}");
3346
3347            #[cfg(not(msim))]
3348            std::process::exit(1);
3349
3350            #[cfg(msim)]
3351            iota_simulator::task::shutdown_current_node();
3352        }
3353    }
3354
3355    #[expect(clippy::disallowed_methods)] // allow unbounded_channel()
3356    pub async fn new(
3357        name: AuthorityName,
3358        secret: StableSyncAuthoritySigner,
3359        supported_protocol_versions: SupportedProtocolVersions,
3360        store: Arc<AuthorityStore>,
3361        execution_cache_trait_pointers: ExecutionCacheTraitPointers,
3362        epoch_store: Arc<AuthorityPerEpochStore>,
3363        committee_store: Arc<CommitteeStore>,
3364        indexes: Option<Arc<IndexStore>>,
3365        grpc_indexes_store: Option<Arc<GrpcIndexesStore>>,
3366        checkpoint_store: Arc<CheckpointStore>,
3367        prometheus_registry: &Registry,
3368        genesis_objects: &[Object],
3369        config: NodeConfig,
3370        validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
3371        chain_identifier: ChainIdentifier,
3372        checkpoint_progress_tracker: Option<Arc<CheckpointProgressTracker>>,
3373        policy_config: Option<PolicyConfig>,
3374        epoch_end_db_snapshots: Option<EpochEndDbSnapshotHandle>,
3375    ) -> Arc<Self> {
3376        Self::check_protocol_version(supported_protocol_versions, epoch_store.protocol_version());
3377
3378        // Read by the quarantine flush and the execution watcher; the next
3379        // epoch's store inherits it.
3380        epoch_store.set_effects_store(
3381            execution_cache_trait_pointers
3382                .transaction_cache_reader
3383                .clone(),
3384        );
3385
3386        let metrics = Arc::new(AuthorityMetrics::new(prometheus_registry));
3387        let (tx_ready_transactions, rx_ready_transactions) = unbounded_channel();
3388        let execution_scheduler = Arc::new(ExecutionSchedulerWrapper::new(
3389            execution_cache_trait_pointers.object_cache_reader.clone(),
3390            execution_cache_trait_pointers
3391                .transaction_cache_reader
3392                .clone(),
3393            tx_ready_transactions,
3394            &epoch_store,
3395            metrics.clone(),
3396        ));
3397        let (tx_execution_shutdown, rx_execution_shutdown) = oneshot::channel();
3398
3399        let authority_per_epoch_pruner = AuthorityPerEpochStorePruner::new(
3400            epoch_store.get_parent_path(),
3401            config
3402                .authority_store_pruning_config
3403                .num_latest_epoch_dbs_to_retain,
3404        )
3405        .await;
3406        let pruner = AuthorityStorePruner::new(
3407            store.perpetual_tables.clone(),
3408            checkpoint_store.clone(),
3409            grpc_indexes_store.clone(),
3410            indexes.clone(),
3411            config.authority_store_pruning_config.clone(),
3412            epoch_store.committee().authority_exists(&name),
3413            epoch_store.epoch_start_state().epoch_duration_ms(),
3414            prometheus_registry,
3415            checkpoint_progress_tracker.clone(),
3416            epoch_store.object_pruning_limit(),
3417        );
3418        let input_loader =
3419            TransactionInputLoader::new(execution_cache_trait_pointers.object_cache_reader.clone());
3420        let epoch = epoch_store.epoch();
3421        let rgp = epoch_store.reference_gas_price();
3422        let traffic_controller_metrics =
3423            Arc::new(TrafficControllerMetrics::new(prometheus_registry));
3424        let traffic_controller = policy_config.map(|policy_config| {
3425            Arc::new(TrafficController::init(
3426                policy_config,
3427                traffic_controller_metrics,
3428            ))
3429        });
3430        let state = Arc::new(AuthorityState {
3431            name,
3432            secret,
3433            execution_lock: RwLock::new(epoch),
3434            epoch_store: ArcSwap::new(epoch_store.clone()),
3435            input_loader,
3436            execution_cache_trait_pointers,
3437            indexes,
3438            grpc_indexes_store,
3439            subscription_handler: Arc::new(SubscriptionHandler::new(prometheus_registry)),
3440            checkpoint_store,
3441            committee_store,
3442            execution_scheduler,
3443            tx_execution_shutdown: Mutex::new(Some(tx_execution_shutdown)),
3444            metrics,
3445            pruner,
3446            authority_per_epoch_pruner,
3447            checkpoint_progress_tracker,
3448            config,
3449            overload_info: AuthorityOverloadInfo::default(),
3450            validator_tx_finalizer,
3451            chain_identifier,
3452            congestion_tracker: Arc::new(CongestionTracker::new(rgp)),
3453            traffic_controller,
3454            epoch_end_db_snapshots,
3455        });
3456
3457        // Start a task to execute ready transactions.
3458        let authority_state = Arc::downgrade(&state);
3459        spawn_monitored_task!(execution_process(
3460            authority_state,
3461            rx_ready_transactions,
3462            rx_execution_shutdown,
3463        ));
3464        // TODO: This doesn't belong to the constructor of AuthorityState.
3465        state
3466            .create_owner_index_if_empty(genesis_objects, &epoch_store)
3467            .expect("Error indexing genesis objects.");
3468
3469        state
3470    }
3471
3472    pub fn epoch_db_pruner(&self) -> &AuthorityPerEpochStorePruner {
3473        &self.authority_per_epoch_pruner
3474    }
3475
3476    // TODO: Consolidate our traits to reduce the number of methods here.
3477    pub fn get_object_cache_reader(&self) -> &Arc<dyn ObjectCacheRead> {
3478        &self.execution_cache_trait_pointers.object_cache_reader
3479    }
3480
3481    pub fn get_transaction_cache_reader(&self) -> &Arc<dyn TransactionCacheRead> {
3482        &self.execution_cache_trait_pointers.transaction_cache_reader
3483    }
3484
3485    pub fn get_cache_writer(&self) -> &Arc<dyn ExecutionCacheWrite> {
3486        &self.execution_cache_trait_pointers.cache_writer
3487    }
3488
3489    pub fn get_backing_store(&self) -> &Arc<dyn BackingStore + Send + Sync> {
3490        &self.execution_cache_trait_pointers.backing_store
3491    }
3492
3493    pub fn get_backing_package_store(&self) -> &Arc<dyn BackingPackageStore + Send + Sync> {
3494        &self.execution_cache_trait_pointers.backing_package_store
3495    }
3496
3497    pub fn get_object_store(&self) -> &Arc<dyn ObjectStore + Send + Sync> {
3498        &self.execution_cache_trait_pointers.object_store
3499    }
3500
3501    pub fn get_reconfig_api(&self) -> &Arc<dyn ExecutionCacheReconfigAPI> {
3502        &self.execution_cache_trait_pointers.reconfig_api
3503    }
3504
3505    pub fn get_global_state_hash_store(&self) -> &Arc<dyn GlobalStateHashStore> {
3506        &self.execution_cache_trait_pointers.global_state_hash_store
3507    }
3508
3509    pub fn get_checkpoint_cache(&self) -> &Arc<dyn CheckpointCache> {
3510        &self.execution_cache_trait_pointers.checkpoint_cache
3511    }
3512
3513    pub fn get_state_sync_store(&self) -> &Arc<dyn StateSyncAPI> {
3514        &self.execution_cache_trait_pointers.state_sync_store
3515    }
3516
3517    pub fn get_cache_commit(&self) -> &Arc<dyn ExecutionCacheCommit> {
3518        &self.execution_cache_trait_pointers.cache_commit
3519    }
3520
3521    pub fn database_for_testing(&self) -> Arc<AuthorityStore> {
3522        self.execution_cache_trait_pointers
3523            .testing_api
3524            .database_for_testing()
3525    }
3526
3527    /// Drops the committed versions of `id` the execution cache holds in
3528    /// memory, so the next read of a committed version goes to the database.
3529    #[cfg(test)]
3530    pub fn evict_committed_object_for_testing(&self, id: &ObjectId) {
3531        self.execution_cache_trait_pointers
3532            .testing_api
3533            .evict_committed_object_for_testing(id)
3534    }
3535
3536    pub async fn prune_checkpoints_for_eligible_epochs_for_testing(
3537        &self,
3538        config: NodeConfig,
3539        metrics: Arc<AuthorityStorePruningMetrics>,
3540    ) -> anyhow::Result<()> {
3541        AuthorityStorePruner::prune_checkpoints_for_eligible_epochs(
3542            &self.database_for_testing().perpetual_tables,
3543            &self.checkpoint_store,
3544            self.grpc_indexes_store.as_deref(),
3545            config.authority_store_pruning_config,
3546            metrics,
3547            EPOCH_DURATION_MS_FOR_TESTING,
3548            self.checkpoint_progress_tracker.as_ref(),
3549        )
3550        .await
3551    }
3552
3553    pub fn execution_scheduler(&self) -> &Arc<ExecutionSchedulerWrapper> {
3554        &self.execution_scheduler
3555    }
3556
3557    /// Whether this authority runs the `ExecutionScheduler` rather than the
3558    /// `TransactionManager`.
3559    pub fn uses_execution_scheduler(&self) -> bool {
3560        self.execution_scheduler.uses_execution_scheduler()
3561    }
3562
3563    fn create_owner_index_if_empty(
3564        &self,
3565        genesis_objects: &[Object],
3566        epoch_store: &Arc<AuthorityPerEpochStore>,
3567    ) -> IotaResult {
3568        let Some(index_store) = &self.indexes else {
3569            return Ok(());
3570        };
3571        if !index_store.is_empty() {
3572            return Ok(());
3573        }
3574
3575        let mut new_owners = vec![];
3576        let mut new_dynamic_fields = vec![];
3577        let mut layout_resolver = epoch_store
3578            .executor()
3579            .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()));
3580        for o in genesis_objects.iter() {
3581            match o.owner {
3582                Owner::Address(addr) => {
3583                    new_owners.push(((addr, o.id()), ObjectInfo::new(&o.object_ref(), o)))
3584                }
3585                Owner::Object(object_id) => {
3586                    let id = o.id();
3587                    let info = match self.try_create_dynamic_field_info(
3588                        o,
3589                        &BTreeMap::new(),
3590                        layout_resolver.as_mut(),
3591                    ) {
3592                        Ok(Some(info)) => info,
3593                        Ok(None) => continue,
3594                        Err(IotaError::UserInput {
3595                            error:
3596                                UserInputError::ObjectNotFound {
3597                                    object_id: not_found_id,
3598                                    version,
3599                                },
3600                        }) => {
3601                            warn!(
3602                                ?not_found_id,
3603                                ?version,
3604                                object_owner=?object_id,
3605                                field=?id,
3606                                "Skipping dynamic field: referenced genesis object not found"
3607                            );
3608                            continue;
3609                        }
3610                        Err(e) => return Err(e),
3611                    };
3612                    new_dynamic_fields.push(((object_id, id), info));
3613                }
3614                _ => {}
3615            }
3616        }
3617
3618        index_store.insert_genesis_objects(ObjectIndexChanges {
3619            deleted_owners: vec![],
3620            deleted_dynamic_fields: vec![],
3621            new_owners,
3622            new_dynamic_fields,
3623        })
3624    }
3625
3626    /// Attempts to acquire execution lock for an executable transaction.
3627    /// Returns the lock if the transaction is matching current executed epoch
3628    /// Returns None otherwise
3629    pub fn execution_lock_for_executable_transaction(
3630        &self,
3631        transaction: &VerifiedExecutableTransaction,
3632    ) -> IotaResult<ExecutionLockReadGuard<'_>> {
3633        let lock = self
3634            .execution_lock
3635            .try_read()
3636            .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)?;
3637        if *lock == transaction.auth_sig().epoch() {
3638            Ok(lock)
3639        } else {
3640            Err(IotaError::WrongEpoch {
3641                expected_epoch: *lock,
3642                actual_epoch: transaction.auth_sig().epoch(),
3643            })
3644        }
3645    }
3646
3647    /// Acquires the execution lock for the duration of a transaction signing
3648    /// request. This prevents reconfiguration from starting until we are
3649    /// finished handling the signing request. Otherwise, in-memory lock
3650    /// state could be cleared (by `ObjectLocks::clear_cached_locks`)
3651    /// while we are attempting to acquire locks for the transaction.
3652    pub fn execution_lock_for_signing(&self) -> IotaResult<ExecutionLockReadGuard<'_>> {
3653        self.execution_lock
3654            .try_read()
3655            .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)
3656    }
3657
3658    pub async fn execution_lock_for_reconfiguration(&self) -> ExecutionLockWriteGuard<'_> {
3659        self.execution_lock.write().await
3660    }
3661
3662    /// Reports a mirror that diverged from the object at the epoch boundary,
3663    /// where the two must agree. Reporting is the remedy: reconfiguration
3664    /// re-seeds the mirror from the object, so failing here would only pin
3665    /// the node to the diverged state. A missing object is fatal instead.
3666    /// Objects cannot be deleted, so the local store lost it and there is
3667    /// nothing to re-seed from. Nodes outside the closing committee are
3668    /// exempt. So is an epoch this node's consensus did not close. A
3669    /// checkpoint catch-up leaves the mirror legitimately behind until the
3670    /// re-seed.
3671    pub(crate) fn check_transaction_deny_rules_consistency(
3672        &self,
3673        cur_epoch_store: &AuthorityPerEpochStore,
3674        epoch_start_configuration: &EpochStartConfiguration,
3675    ) {
3676        if self.is_fullnode(cur_epoch_store) {
3677            return;
3678        }
3679        let Some(walked_deny_rules) = epoch_start_configuration.transaction_deny_rules_state()
3680        else {
3681            if cur_epoch_store
3682                .epoch_start_config()
3683                .transaction_deny_rules_obj_initial_shared_version()
3684                .is_some()
3685            {
3686                fatal!(
3687                    "TransactionDenyRules object existed in epoch {} but is missing from the \
3688                     state walked for the next epoch — the local store is corrupted; restore or \
3689                     state-sync before rejoining",
3690                    cur_epoch_store.epoch(),
3691                );
3692            }
3693            return;
3694        };
3695        // RejectAllTx proves this node's consensus processed every commit of
3696        // the epoch, so the mirror is complete. Otherwise the tail came from
3697        // synced checkpoints and the mirror's lag carries no signal.
3698        if cur_epoch_store
3699            .get_reconfig_state_read_lock_guard()
3700            .should_accept_tx()
3701        {
3702            info!(
3703                "skipping the deny-rule mirror comparison: consensus did not close epoch {} on \
3704                 this node",
3705                cur_epoch_store.epoch(),
3706            );
3707            return;
3708        }
3709        let mirrored_deny_rules = cur_epoch_store.get_mirrored_transaction_deny_rules();
3710        if *walked_deny_rules != *mirrored_deny_rules {
3711            debug_fatal!(
3712                "TransactionDenyRules object diverged from the mirrored state at the end of \
3713                 epoch {}; continuing from the object (walked: {walked_deny_rules:?}, mirrored: \
3714                 {mirrored_deny_rules:?})",
3715                cur_epoch_store.epoch(),
3716            );
3717            cur_epoch_store.metrics.deny_rule_mirror_divergence.set(1);
3718        }
3719    }
3720
3721    /// Reports a `TransactionDenyRulesUpdate` whose execution failed — an
3722    /// invariant violation, the update is built to exclude every expected
3723    /// failure. The object misses the delta until the epoch boundary re-seeds
3724    /// the mirror. Identification is by kind, so the report needs no tracking
3725    /// state and holds across restarts and replays.
3726    ///
3727    /// `expected_effects_digest` is `Some` when these effects were handed to
3728    /// this node with the transaction, which is the case while executing a
3729    /// certified checkpoint: the failure is then part of agreed history, so it
3730    /// is reported without asserting. Effects the node derived itself assert,
3731    /// because only then is the broken invariant its own.
3732    pub(crate) fn report_failed_deny_rule_update_execution(
3733        &self,
3734        transaction: &VerifiedExecutableTransaction,
3735        effects: &TransactionEffects,
3736        expected_effects_digest: Option<TransactionEffectsDigest>,
3737        epoch_store: &AuthorityPerEpochStore,
3738    ) {
3739        if !matches!(
3740            transaction.transaction().kind(),
3741            TransactionKind::TransactionDenyRulesUpdate(_)
3742        ) || effects.status().is_success()
3743        {
3744            return;
3745        }
3746        epoch_store
3747            .metrics
3748            .deny_rule_update_execution_failures
3749            .inc();
3750        if expected_effects_digest.is_some() {
3751            error!(
3752                digest = ?transaction.digest(),
3753                status = ?effects.status(),
3754                "TransactionDenyRulesUpdate failed execution; the object misses its delta until \
3755                 the epoch boundary re-seeds the mirror"
3756            );
3757            return;
3758        }
3759        debug_fatal!(
3760            "TransactionDenyRulesUpdate failed execution; the object misses its delta until the \
3761             epoch boundary re-seeds the mirror (digest: {:?}, status: {:?})",
3762            transaction.digest(),
3763            effects.status(),
3764        );
3765    }
3766
3767    #[instrument(level = "error", skip_all)]
3768    pub async fn reconfigure(
3769        &self,
3770        cur_epoch_store: &AuthorityPerEpochStore,
3771        supported_protocol_versions: SupportedProtocolVersions,
3772        new_committee: Committee,
3773        epoch_start_configuration: EpochStartConfiguration,
3774        state_hasher: Arc<GlobalStateHasher>,
3775        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3776        epoch_supply_change: i64,
3777        epoch_last_checkpoint: CheckpointSequenceNumber,
3778    ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
3779        Self::check_protocol_version(
3780            supported_protocol_versions,
3781            epoch_start_configuration
3782                .epoch_start_state()
3783                .protocol_version(),
3784        );
3785        self.metrics.reset_on_reconfigure();
3786        self.committee_store.insert_new_committee(&new_committee)?;
3787
3788        // Wait until no transactions are being executed.
3789        let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3790
3791        // Terminate all epoch-specific tasks (those started with within_alive_epoch).
3792        cur_epoch_store.epoch_terminated().await;
3793
3794        let highest_locally_built_checkpoint_seq = self
3795            .checkpoint_store
3796            .get_latest_locally_computed_checkpoint()?
3797            .map(|c| c.sequence_number())
3798            .unwrap_or(0);
3799
3800        assert!(
3801            epoch_last_checkpoint >= highest_locally_built_checkpoint_seq,
3802            "expected {epoch_last_checkpoint} >= {highest_locally_built_checkpoint_seq}"
3803        );
3804
3805        // Safe to reconfigure now. No transactions are being executed,
3806        // and no epoch-specific tasks are running.
3807
3808        // TODO: revert_uncommitted_epoch_transactions will soon be unnecessary -
3809        // clear_state_end_of_epoch() can simply drop all uncommitted transactions
3810        self.revert_uncommitted_epoch_transactions(cur_epoch_store)
3811            .await?;
3812        self.get_reconfig_api()
3813            .clear_state_end_of_epoch(&execution_lock);
3814        self.check_system_consistency(
3815            cur_epoch_store,
3816            state_hasher,
3817            expensive_safety_check_config,
3818            epoch_supply_change,
3819        )?;
3820        self.check_transaction_deny_rules_consistency(cur_epoch_store, &epoch_start_configuration);
3821
3822        self.get_reconfig_api()
3823            .try_set_epoch_start_configuration(&epoch_start_configuration)?;
3824        self.hand_over_epoch_end_db_snapshot(cur_epoch_store.epoch())
3825            .await;
3826
3827        let new_epoch = new_committee.epoch;
3828        let new_epoch_store = self
3829            .reopen_epoch_db(
3830                cur_epoch_store,
3831                new_committee,
3832                epoch_start_configuration,
3833                expensive_safety_check_config,
3834                epoch_last_checkpoint,
3835            )
3836            .await?;
3837        assert_eq!(new_epoch_store.epoch(), new_epoch);
3838        match self.execution_scheduler.as_ref() {
3839            ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3840            ExecutionSchedulerWrapper::TransactionManager(tm) => {
3841                tm.reconfigure(new_epoch);
3842            }
3843        }
3844        *execution_lock = new_epoch;
3845        // drop execution_lock after epoch store was updated
3846        // see also assert in AuthorityState::process_transaction
3847        // on the epoch store and execution lock epoch match
3848        Ok(new_epoch_store)
3849    }
3850
3851    /// Advance the epoch store to the next epoch for testing only.
3852    /// This only manually sets all the places where we have the epoch number.
3853    /// It doesn't properly reconfigure the node, hence should be only used for
3854    /// testing.
3855    pub async fn reconfigure_for_testing(&self) {
3856        self.reconfigure_for_testing_impl(None).await;
3857    }
3858
3859    /// Like [`Self::reconfigure_for_testing`], but the next epoch uses the
3860    /// given protocol config.
3861    pub async fn reconfigure_for_testing_with_protocol_config(
3862        &self,
3863        protocol_config: ProtocolConfig,
3864    ) {
3865        self.reconfigure_for_testing_impl(Some(protocol_config))
3866            .await;
3867    }
3868
3869    async fn reconfigure_for_testing_impl(&self, protocol_config: Option<ProtocolConfig>) {
3870        let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3871        let epoch_store = self.epoch_store_for_testing().clone();
3872        // Default to the epoch store's config, whose override guard may have
3873        // been dropped. Read it under the lock so config and epoch store are
3874        // one snapshot.
3875        let protocol_config =
3876            protocol_config.unwrap_or_else(|| epoch_store.protocol_config().clone());
3877        let _guard =
3878            ProtocolConfig::apply_overrides_for_testing(move |_, _| protocol_config.clone());
3879        let new_epoch_store = epoch_store.new_at_next_epoch_for_testing(
3880            self.get_backing_package_store().clone(),
3881            &self.config.expensive_safety_check_config,
3882            self.checkpoint_store
3883                .get_epoch_last_checkpoint(epoch_store.epoch())
3884                .unwrap()
3885                .map(|c| c.sequence_number())
3886                .unwrap_or_default(),
3887        );
3888        let new_epoch = new_epoch_store.epoch();
3889        match self.execution_scheduler.as_ref() {
3890            ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3891            ExecutionSchedulerWrapper::TransactionManager(tm) => {
3892                tm.reconfigure(new_epoch);
3893            }
3894        }
3895        self.epoch_store.store(new_epoch_store);
3896        epoch_store.epoch_terminated().await;
3897        *execution_lock = new_epoch;
3898    }
3899
3900    #[instrument(level = "error", skip_all)]
3901    fn check_system_consistency(
3902        &self,
3903        cur_epoch_store: &AuthorityPerEpochStore,
3904        state_hasher: Arc<GlobalStateHasher>,
3905        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3906        epoch_supply_change: i64,
3907    ) -> IotaResult<()> {
3908        info!(
3909            "Performing iota conservation consistency check for epoch {}",
3910            cur_epoch_store.epoch()
3911        );
3912
3913        if cfg!(debug_assertions) {
3914            cur_epoch_store.check_all_executed_transactions_in_checkpoint();
3915        }
3916
3917        self.get_reconfig_api()
3918            .try_expensive_check_iota_conservation(cur_epoch_store, Some(epoch_supply_change))?;
3919
3920        // check for root state hash consistency with live object set
3921        if expensive_safety_check_config.enable_state_consistency_check() {
3922            info!(
3923                "Performing state consistency check for epoch {}",
3924                cur_epoch_store.epoch()
3925            );
3926            self.expensive_check_is_consistent_state(state_hasher, cur_epoch_store);
3927        }
3928
3929        if expensive_safety_check_config.enable_secondary_index_checks() {
3930            if let Some(indexes) = self.indexes.clone() {
3931                verify_indexes(self.get_global_state_hash_store().as_ref(), indexes)
3932                    .expect("secondary indexes are inconsistent");
3933            }
3934        }
3935
3936        Ok(())
3937    }
3938
3939    fn expensive_check_is_consistent_state(
3940        &self,
3941        state_hasher: Arc<GlobalStateHasher>,
3942        cur_epoch_store: &AuthorityPerEpochStore,
3943    ) {
3944        let live_object_set_hash = state_hasher.digest_live_object_set();
3945
3946        let root_state_hash: ECMHLiveObjectSetDigest = self
3947            .get_global_state_hash_store()
3948            .get_root_state_hash_for_epoch(cur_epoch_store.epoch())
3949            .expect("Retrieving root state hash cannot fail")
3950            .expect("Root state hash for epoch must exist")
3951            .1
3952            .digest()
3953            .into();
3954
3955        let is_inconsistent = root_state_hash != live_object_set_hash;
3956        if is_inconsistent {
3957            debug_fatal!(
3958                "Inconsistent state detected: root state hash: {:?}, live object set hash: {:?}",
3959                root_state_hash,
3960                live_object_set_hash
3961            );
3962        } else {
3963            info!("State consistency check passed");
3964        }
3965
3966        state_hasher.set_inconsistent_state(is_inconsistent);
3967    }
3968
3969    pub fn current_epoch_for_testing(&self) -> EpochId {
3970        self.epoch_store_for_testing().epoch()
3971    }
3972
3973    /// Lets the consumer take its database snapshot of the perpetual store as
3974    /// the epoch ends, when there is one. See
3975    /// [`EpochEndDbSnapshotHandle::hand_over`].
3976    #[instrument(level = "error", skip_all)]
3977    async fn hand_over_epoch_end_db_snapshot(&self, epoch: EpochId) {
3978        let Some(handle) = &self.epoch_end_db_snapshots else {
3979            return;
3980        };
3981        let _metrics_guard = self
3982            .metrics
3983            .epoch_end_db_snapshot_handover_latency
3984            .start_timer();
3985        if handle.hand_over(epoch).await == HandOver::Skipped {
3986            self.metrics.epoch_end_db_snapshots_skipped.inc();
3987        }
3988    }
3989
3990    /// Load the current epoch store. This can change during reconfiguration. To
3991    /// ensure that we never end up accessing different epoch stores in a
3992    /// single task, we need to make sure that this is called once per task.
3993    /// Each call needs to be carefully audited to ensure it is
3994    /// the case. This also means we should minimize the number of call-sites.
3995    /// Only call it when there is no way to obtain it from somewhere else.
3996    pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3997        self.epoch_store.load()
3998    }
3999
4000    // Load the epoch store, should be used in tests only.
4001    pub fn epoch_store_for_testing(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
4002        self.load_epoch_store_one_call_per_task()
4003    }
4004
4005    pub fn clone_committee_for_testing(&self) -> Committee {
4006        Committee::clone(self.epoch_store_for_testing().committee())
4007    }
4008
4009    #[instrument(level = "trace", skip_all)]
4010    pub fn try_get_object(&self, object_id: &ObjectId) -> IotaResult<Option<Object>> {
4011        self.get_object_store()
4012            .try_get_object(object_id)
4013            .map_err(Into::into)
4014    }
4015
4016    /// Non-fallible version of `try_get_object`.
4017    pub fn get_object(&self, object_id: &ObjectId) -> Option<Object> {
4018        self.try_get_object(object_id)
4019            .expect("storage access failed")
4020    }
4021
4022    pub fn get_iota_system_package_object_ref(&self) -> IotaResult<ObjectReference> {
4023        Ok(self
4024            .try_get_object(&ObjectId::SYSTEM)?
4025            .expect("system package should always exist")
4026            .object_ref())
4027    }
4028
4029    // This function is only used for testing.
4030    pub fn get_iota_system_state_object_for_testing(&self) -> IotaResult<IotaSystemState> {
4031        self.get_object_cache_reader()
4032            .try_get_iota_system_state_object_unsafe()
4033    }
4034
4035    #[instrument(level = "trace", skip_all)]
4036    pub fn get_checkpoint_by_sequence_number(
4037        &self,
4038        sequence_number: CheckpointSequenceNumber,
4039    ) -> IotaResult<Option<VerifiedCheckpoint>> {
4040        Ok(self
4041            .checkpoint_store
4042            .get_checkpoint_by_sequence_number(sequence_number)?)
4043    }
4044
4045    /// Wait for the given transactions to be included in a checkpoint.
4046    ///
4047    /// Returns a mapping from transaction digest to
4048    /// `(checkpoint_sequence_number, checkpoint_timestamp_ms)`.
4049    /// On timeout, returns partial results for any transactions that were
4050    /// already checkpointed.
4051    ///
4052    /// The wait survives epoch boundaries: a transaction in flight at a
4053    /// boundary may only be checkpointed in the next epoch, and still resolves
4054    /// here under the original deadline.
4055    pub async fn wait_for_checkpoint_inclusion(
4056        &self,
4057        digests: &[TransactionDigest],
4058        timeout: Duration,
4059    ) -> IotaResult<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>> {
4060        let deadline = tokio::time::Instant::now() + timeout;
4061        let mut checkpoint_timestamp_cache = HashMap::<CheckpointSequenceNumber, u64>::new();
4062        let mut results = BTreeMap::new();
4063        let mut remaining = digests.to_vec();
4064        let mut epoch_store = self.load_epoch_store_one_call_per_task().clone();
4065
4066        loop {
4067            let wait = epoch_store.wait_for_transactions_in_checkpoint_with_timeout(
4068                &remaining,
4069                deadline.saturating_duration_since(tokio::time::Instant::now()),
4070                |seq| self.checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache),
4071            );
4072            tokio::select! {
4073                wait_results = wait => {
4074                    for (digest, seq_and_ts) in remaining.iter().zip(wait_results?) {
4075                        if let Some(seq_and_ts) = seq_and_ts {
4076                            results.insert(*digest, seq_and_ts);
4077                        }
4078                    }
4079                    return Ok(results);
4080                }
4081                _ = epoch_store.wait_epoch_terminated() => {}
4082            }
4083
4084            // The epoch ended mid-wait, and this epoch store's notifications
4085            // can no longer fire: whatever is still uncheckpointed here is
4086            // checkpointed in the next epoch, on the next store. Cancelling
4087            // the wait may also have dropped notifications it had already
4088            // received, but the table write precedes each notification, so
4089            // re-reading the table recovers them.
4090            let found = match epoch_store.multi_get_transaction_checkpoint(&remaining) {
4091                Ok(found) => found,
4092                // The table handles were already released. They are released
4093                // long after the epoch's checkpoints are executed, so nothing
4094                // waited on here can still be checkpointed in the old epoch;
4095                // move on to the next store.
4096                Err(IotaError::EpochEnded(_)) => vec![None; remaining.len()],
4097                Err(err) => return Err(err),
4098            };
4099            let mut still_uncheckpointed = Vec::new();
4100            for (digest, found_seq) in remaining.iter().zip(found) {
4101                match found_seq {
4102                    Some(seq) => {
4103                        let ts = self
4104                            .checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache);
4105                        results.insert(*digest, (seq, ts));
4106                    }
4107                    None => still_uncheckpointed.push(*digest),
4108                }
4109            }
4110            remaining = still_uncheckpointed;
4111            if remaining.is_empty() {
4112                return Ok(results);
4113            }
4114
4115            match self
4116                .wait_for_next_epoch_store(epoch_store.epoch(), deadline)
4117                .await
4118            {
4119                Some(next) => epoch_store = next,
4120                None => return Ok(results),
4121            }
4122        }
4123    }
4124
4125    /// Wait for the epoch store to be swapped to an epoch later than
4126    /// `prev_epoch`, returning `None` if `deadline` passes first.
4127    async fn wait_for_next_epoch_store(
4128        &self,
4129        prev_epoch: EpochId,
4130        deadline: tokio::time::Instant,
4131    ) -> Option<Arc<AuthorityPerEpochStore>> {
4132        // There is no notification for the epoch-store swap, and termination
4133        // and swap can come in either order (`reconfigure` terminates the old
4134        // epoch first, `reconfigure_for_testing` swaps first), so the swap is
4135        // polled at this interval.
4136        const EPOCH_STORE_SWAP_POLL_INTERVAL: Duration = Duration::from_millis(100);
4137
4138        loop {
4139            // Deliberately re-loaded on each poll; the one-call-per-task rule
4140            // guards against *unaware* mixing of epoch stores within a task.
4141            let current = self.load_epoch_store_one_call_per_task().clone();
4142            if current.epoch() > prev_epoch {
4143                return Some(current);
4144            }
4145            if tokio::time::Instant::now() >= deadline {
4146                return None;
4147            }
4148            tokio::time::sleep(EPOCH_STORE_SWAP_POLL_INTERVAL).await;
4149        }
4150    }
4151
4152    /// Resolve a checkpoint's timestamp, memoizing lookups in `cache` so
4153    /// multiple transactions in the same checkpoint trigger a single
4154    /// checkpoint summary lookup.
4155    fn checkpoint_timestamp_ms_cached(
4156        &self,
4157        seq: CheckpointSequenceNumber,
4158        cache: &mut HashMap<CheckpointSequenceNumber, u64>,
4159    ) -> u64 {
4160        *cache.entry(seq).or_insert_with(|| {
4161            self.get_checkpoint_by_sequence_number(seq)
4162                .ok()
4163                .flatten()
4164                .map(|c| c.timestamp_ms)
4165                .unwrap_or(0)
4166        })
4167    }
4168
4169    #[instrument(level = "trace", skip_all)]
4170    pub fn get_transaction_checkpoint_for_tests(
4171        &self,
4172        digest: &TransactionDigest,
4173        epoch_store: &AuthorityPerEpochStore,
4174    ) -> IotaResult<Option<VerifiedCheckpoint>> {
4175        let checkpoint = epoch_store.get_transaction_checkpoint(digest)?;
4176        let Some(checkpoint) = checkpoint else {
4177            return Ok(None);
4178        };
4179        let checkpoint = self
4180            .checkpoint_store
4181            .get_checkpoint_by_sequence_number(checkpoint)?;
4182        Ok(checkpoint)
4183    }
4184
4185    #[instrument(level = "trace", skip_all)]
4186    pub fn get_object_read(&self, object_id: &ObjectId) -> IotaResult<ObjectRead> {
4187        Ok(
4188            match self
4189                .get_object_cache_reader()
4190                .try_get_latest_object_or_tombstone(*object_id)?
4191            {
4192                Some((_, ObjectOrTombstone::Object(object))) => {
4193                    let layout = self.get_object_layout(&object)?;
4194                    ObjectRead::Exists(object.object_ref(), object, layout)
4195                }
4196                Some((_, ObjectOrTombstone::Tombstone(objref))) => ObjectRead::Deleted(objref),
4197                None => ObjectRead::NotExists(*object_id),
4198            },
4199        )
4200    }
4201
4202    /// Chain Identifier is the digest of the genesis checkpoint.
4203    pub fn get_chain_identifier(&self) -> ChainIdentifier {
4204        self.chain_identifier
4205    }
4206
4207    #[instrument(level = "trace", skip_all)]
4208    pub fn get_move_object<T>(&self, object_id: &ObjectId) -> IotaResult<T>
4209    where
4210        T: DeserializeOwned,
4211    {
4212        let o = self.get_object_read(object_id)?.into_object()?;
4213        if let Some(move_object) = o.data.as_opt_struct() {
4214            Ok(bcs::from_bytes(move_object.contents()).map_err(|e| {
4215                IotaError::ObjectDeserialization {
4216                    error: format!("{e}"),
4217                }
4218            })?)
4219        } else {
4220            Err(IotaError::ObjectDeserialization {
4221                error: format!("Provided object : [{object_id}] is not a Move object."),
4222            })
4223        }
4224    }
4225
4226    /// This function aims to serve rpc reads on past objects and
4227    /// we don't expect it to be called for other purposes.
4228    /// Depending on the object pruning policies that will be enforced in the
4229    /// future there is no software-level guarantee/SLA to retrieve an object
4230    /// with an old version even if it exists/existed.
4231    #[instrument(level = "trace", skip_all)]
4232    pub fn get_past_object_read(
4233        &self,
4234        object_id: &ObjectId,
4235        version: Version,
4236    ) -> IotaResult<PastObjectRead> {
4237        // Firstly we see if the object ever existed by getting its latest data
4238        let Some(obj_ref) = self
4239            .get_object_cache_reader()
4240            .try_get_latest_object_ref_or_tombstone(*object_id)?
4241        else {
4242            return Ok(PastObjectRead::ObjectNotExists(*object_id));
4243        };
4244
4245        if version > obj_ref.version {
4246            return Ok(PastObjectRead::VersionTooHigh {
4247                object_id: *object_id,
4248                asked_version: version,
4249                latest_version: obj_ref.version,
4250            });
4251        }
4252
4253        if version < obj_ref.version {
4254            // Read past objects
4255            return Ok(match self.read_object_at_version(object_id, version)? {
4256                Some((object, layout)) => {
4257                    let obj_ref = object.object_ref();
4258                    PastObjectRead::VersionFound(obj_ref, object, layout)
4259                }
4260
4261                None => PastObjectRead::VersionNotFound(*object_id, version),
4262            });
4263        }
4264
4265        if !obj_ref.digest.is_alive() {
4266            return Ok(PastObjectRead::ObjectDeleted(obj_ref));
4267        }
4268
4269        match self.read_object_at_version(object_id, obj_ref.version)? {
4270            Some((object, layout)) => Ok(PastObjectRead::VersionFound(obj_ref, object, layout)),
4271            None => {
4272                debug_fatal!(
4273                    "Object with in parent_entry is missing from object store, datastore is \
4274                     inconsistent",
4275                );
4276                Err(UserInputError::ObjectNotFound {
4277                    object_id: *object_id,
4278                    version: Some(obj_ref.version),
4279                }
4280                .into())
4281            }
4282        }
4283    }
4284
4285    #[instrument(level = "trace", skip_all)]
4286    fn read_object_at_version(
4287        &self,
4288        object_id: &ObjectId,
4289        version: Version,
4290    ) -> IotaResult<Option<(Object, Option<MoveStructLayout>)>> {
4291        let Some(object) = self
4292            .get_object_cache_reader()
4293            .try_get_object_by_key(object_id, version)?
4294        else {
4295            return Ok(None);
4296        };
4297
4298        let layout = self.get_object_layout(&object)?;
4299        Ok(Some((object, layout)))
4300    }
4301
4302    fn get_object_layout(&self, object: &Object) -> IotaResult<Option<MoveStructLayout>> {
4303        let layout = object
4304            .data
4305            .as_opt_struct()
4306            .map(|object| {
4307                into_struct_layout(
4308                    self.load_epoch_store_one_call_per_task()
4309                        .executor()
4310                        // TODO(cache) - must read through cache
4311                        .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
4312                        .get_annotated_layout(object.struct_tag())?,
4313                )
4314            })
4315            .transpose()?;
4316        Ok(layout)
4317    }
4318
4319    fn get_owner_at_version(&self, object_id: &ObjectId, version: Version) -> IotaResult<Owner> {
4320        self.get_object_store()
4321            .try_get_object_by_key(object_id, version)?
4322            .ok_or_else(|| {
4323                IotaError::from(UserInputError::ObjectNotFound {
4324                    object_id: *object_id,
4325                    version: Some(version),
4326                })
4327            })
4328            .map(|o| o.owner)
4329    }
4330
4331    #[instrument(level = "trace", skip_all)]
4332    pub fn get_owner_objects(
4333        &self,
4334        owner: Address,
4335        // If `Some`, the query will start from the next item after the specified cursor
4336        cursor: Option<ObjectId>,
4337        limit: usize,
4338        filter: Option<IotaObjectDataFilter>,
4339    ) -> IotaResult<Vec<ObjectInfo>> {
4340        if let Some(indexes) = &self.indexes {
4341            indexes.get_owner_objects(owner, cursor, limit, filter)
4342        } else {
4343            Err(IotaError::IndexStoreNotAvailable)
4344        }
4345    }
4346
4347    #[instrument(level = "trace", skip_all)]
4348    pub fn get_owned_coins_iterator_with_cursor(
4349        &self,
4350        owner: Address,
4351        // If `Some`, the query will start from the next item after the specified cursor
4352        cursor: (String, ObjectId),
4353        limit: usize,
4354        one_coin_type_only: bool,
4355    ) -> IotaResult<impl Iterator<Item = (String, ObjectId, CoinInfo)> + '_> {
4356        if let Some(indexes) = &self.indexes {
4357            indexes.get_owned_coins_iterator_with_cursor(owner, cursor, limit, one_coin_type_only)
4358        } else {
4359            Err(IotaError::IndexStoreNotAvailable)
4360        }
4361    }
4362
4363    #[instrument(level = "trace", skip_all)]
4364    pub fn get_owner_objects_iterator(
4365        &self,
4366        owner: Address,
4367        // If `Some`, the query will start from the next item after the specified cursor
4368        cursor: Option<ObjectId>,
4369        filter: Option<IotaObjectDataFilter>,
4370    ) -> IotaResult<impl Iterator<Item = ObjectInfo> + '_> {
4371        if let Some(indexes) = &self.indexes {
4372            indexes.get_owner_objects_iterator(owner, cursor, filter)
4373        } else {
4374            Err(IotaError::IndexStoreNotAvailable)
4375        }
4376    }
4377
4378    #[instrument(level = "trace", skip_all)]
4379    pub fn get_move_objects<T>(&self, owner: Address, tag: StructTag) -> IotaResult<Vec<T>>
4380    where
4381        T: DeserializeOwned,
4382    {
4383        let object_ids = self
4384            .get_owner_objects_iterator(owner, None, None)?
4385            .filter(|o| match &o.object_type {
4386                ObjectType::Struct(s) => *s == tag,
4387                ObjectType::Package => false,
4388            })
4389            .map(|info| ObjectKey(info.object_id, info.version))
4390            .collect::<Vec<_>>();
4391        let mut move_objects = vec![];
4392
4393        let objects = self
4394            .get_object_store()
4395            .try_multi_get_objects_by_key(&object_ids)?;
4396
4397        for (o, id) in objects.into_iter().zip(object_ids) {
4398            let object = o.ok_or_else(|| {
4399                IotaError::from(UserInputError::ObjectNotFound {
4400                    object_id: id.0,
4401                    version: Some(id.1),
4402                })
4403            })?;
4404            let move_object = object.data.as_opt_struct().ok_or_else(|| {
4405                IotaError::from(UserInputError::MovePackageAsObject { object_id: id.0 })
4406            })?;
4407            move_objects.push(bcs::from_bytes(move_object.contents()).map_err(|e| {
4408                IotaError::ObjectDeserialization {
4409                    error: format!("{e}"),
4410                }
4411            })?);
4412        }
4413        Ok(move_objects)
4414    }
4415
4416    #[instrument(level = "trace", skip_all)]
4417    pub fn get_dynamic_fields(
4418        &self,
4419        owner: ObjectId,
4420        // If `Some`, the query will start from the next item after the specified cursor
4421        cursor: Option<ObjectId>,
4422        limit: usize,
4423    ) -> IotaResult<Vec<(ObjectId, DynamicFieldInfo)>> {
4424        Ok(self
4425            .get_dynamic_fields_iterator(owner, cursor)?
4426            .take(limit)
4427            .collect::<Result<Vec<_>, _>>()?)
4428    }
4429
4430    fn get_dynamic_fields_iterator(
4431        &self,
4432        owner: ObjectId,
4433        // If `Some`, the query will start from the next item after the specified cursor
4434        cursor: Option<ObjectId>,
4435    ) -> IotaResult<impl Iterator<Item = Result<(ObjectId, DynamicFieldInfo), TypedStoreError>> + '_>
4436    {
4437        if let Some(indexes) = &self.indexes {
4438            indexes.get_dynamic_fields_iterator(owner, cursor)
4439        } else {
4440            Err(IotaError::IndexStoreNotAvailable)
4441        }
4442    }
4443
4444    #[instrument(level = "trace", skip_all)]
4445    pub fn get_dynamic_field_object_id(
4446        &self,
4447        owner: ObjectId,
4448        name_type: TypeTag,
4449        name_bcs_bytes: &[u8],
4450    ) -> IotaResult<Option<ObjectId>> {
4451        if let Some(indexes) = &self.indexes {
4452            indexes.get_dynamic_field_object_id(owner, name_type, name_bcs_bytes)
4453        } else {
4454            Err(IotaError::IndexStoreNotAvailable)
4455        }
4456    }
4457
4458    #[instrument(level = "trace", skip_all)]
4459    pub fn get_total_transaction_blocks(&self) -> IotaResult<u64> {
4460        Ok(self.get_indexes()?.next_sequence_number())
4461    }
4462
4463    #[instrument(level = "trace", skip_all)]
4464    pub async fn get_executed_transaction_and_effects(
4465        &self,
4466        digest: TransactionDigest,
4467        kv_store: Arc<TransactionKeyValueStore>,
4468    ) -> IotaResult<(TransactionEnvelope, TransactionEffects)> {
4469        let transaction = kv_store.get_tx(digest).await?;
4470        let effects = kv_store.get_fx_by_tx_digest(digest).await?;
4471        Ok((transaction, effects))
4472    }
4473
4474    #[instrument(level = "trace", skip_all)]
4475    pub fn multi_get_checkpoint_by_sequence_number(
4476        &self,
4477        sequence_numbers: &[CheckpointSequenceNumber],
4478    ) -> IotaResult<Vec<Option<VerifiedCheckpoint>>> {
4479        Ok(self
4480            .checkpoint_store
4481            .multi_get_checkpoint_by_sequence_number(sequence_numbers)?)
4482    }
4483
4484    #[instrument(level = "trace", skip_all)]
4485    pub fn get_transaction_events(
4486        &self,
4487        digest: &TransactionDigest,
4488    ) -> IotaResult<TransactionEvents> {
4489        self.get_transaction_cache_reader()
4490            .try_get_events(digest)?
4491            .ok_or(IotaError::TransactionEventsNotFound { digest: *digest })
4492    }
4493
4494    pub fn get_transaction_input_objects(
4495        &self,
4496        effects: &TransactionEffects,
4497    ) -> anyhow::Result<Vec<Object>> {
4498        iota_types::storage::get_transaction_input_objects(self.get_object_store(), effects)
4499            .map_err(Into::into)
4500    }
4501
4502    pub fn get_transaction_output_objects(
4503        &self,
4504        effects: &TransactionEffects,
4505    ) -> anyhow::Result<Vec<Object>> {
4506        iota_types::storage::get_transaction_output_objects(self.get_object_store(), effects)
4507            .map_err(Into::into)
4508    }
4509
4510    fn get_indexes(&self) -> IotaResult<Arc<IndexStore>> {
4511        match &self.indexes {
4512            Some(i) => Ok(i.clone()),
4513            None => Err(IotaError::UnsupportedFeature {
4514                error: "extended object indexing is not enabled on this server".into(),
4515            }),
4516        }
4517    }
4518
4519    pub async fn get_transactions_for_tests(
4520        self: &Arc<Self>,
4521        filter: Option<TransactionFilter>,
4522        cursor: Option<TransactionDigest>,
4523        limit: Option<usize>,
4524        reverse: bool,
4525    ) -> IotaResult<Vec<TransactionDigest>> {
4526        let metrics = KeyValueStoreMetrics::new_for_tests();
4527        let kv_store = Arc::new(TransactionKeyValueStore::new(
4528            "rocksdb",
4529            metrics,
4530            self.clone(),
4531        ));
4532        self.get_transactions(&kv_store, filter, cursor, limit, reverse)
4533            .await
4534    }
4535
4536    #[instrument(level = "trace", skip_all)]
4537    pub async fn get_transactions(
4538        &self,
4539        kv_store: &Arc<TransactionKeyValueStore>,
4540        filter: Option<TransactionFilter>,
4541        // If `Some`, the query will start from the next item after the specified cursor
4542        cursor: Option<TransactionDigest>,
4543        limit: Option<usize>,
4544        reverse: bool,
4545    ) -> IotaResult<Vec<TransactionDigest>> {
4546        if let Some(TransactionFilter::Checkpoint(sequence_number)) = filter {
4547            let checkpoint_contents = kv_store.get_checkpoint_contents(sequence_number).await?;
4548            let iter = checkpoint_contents.iter().map(|c| c.transaction);
4549            if reverse {
4550                let iter = iter
4551                    .rev()
4552                    .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4553                    .skip(usize::from(cursor.is_some()));
4554                return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4555            } else {
4556                let iter = iter
4557                    .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4558                    .skip(usize::from(cursor.is_some()));
4559                return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4560            }
4561        }
4562        self.get_indexes()?
4563            .get_transactions(filter, cursor, limit, reverse)
4564    }
4565
4566    pub fn get_checkpoint_store(&self) -> &Arc<CheckpointStore> {
4567        &self.checkpoint_store
4568    }
4569
4570    /// The store pruner; the checkpoint executor uses it to nudge the pruner
4571    /// after each checkpoint.
4572    pub fn pruner(&self) -> &AuthorityStorePruner {
4573        &self.pruner
4574    }
4575
4576    /// Keeps the object versions that transactions in the highest executed
4577    /// checkpoint, and in every later one, supersede readable until the
4578    /// returned guard is dropped. Take it before submitting a transaction whose
4579    /// input or output objects are read from the store once it is
4580    /// checkpointed.
4581    pub fn retain_objects(&self) -> ObjectRetentionGuard {
4582        self.pruner.retain_objects()
4583    }
4584
4585    pub fn get_latest_checkpoint_sequence_number(&self) -> IotaResult<CheckpointSequenceNumber> {
4586        self.get_checkpoint_store()
4587            .get_highest_executed_checkpoint_seq_number()?
4588            .ok_or(IotaError::UserInput {
4589                error: UserInputError::LatestCheckpointSequenceNumberNotFound,
4590            })
4591    }
4592
4593    #[cfg(msim)]
4594    pub fn get_highest_pruned_checkpoint_for_testing(
4595        &self,
4596    ) -> IotaResult<CheckpointSequenceNumber> {
4597        self.database_for_testing()
4598            .perpetual_tables
4599            .get_highest_pruned_checkpoint()
4600            .map(|c| c.unwrap_or(0))
4601            .map_err(Into::into)
4602    }
4603
4604    #[instrument(level = "trace", skip_all)]
4605    pub fn get_checkpoint_summary_by_sequence_number(
4606        &self,
4607        sequence_number: CheckpointSequenceNumber,
4608    ) -> IotaResult<CheckpointSummary> {
4609        let verified_checkpoint = self
4610            .get_checkpoint_store()
4611            .get_checkpoint_by_sequence_number(sequence_number)?;
4612        match verified_checkpoint {
4613            Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4614            None => Err(IotaError::UserInput {
4615                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4616            }),
4617        }
4618    }
4619
4620    #[instrument(level = "trace", skip_all)]
4621    pub fn get_checkpoint_summary_by_digest(
4622        &self,
4623        digest: CheckpointDigest,
4624    ) -> IotaResult<CheckpointSummary> {
4625        let verified_checkpoint = self
4626            .get_checkpoint_store()
4627            .get_checkpoint_by_digest(&digest)?;
4628        match verified_checkpoint {
4629            Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4630            None => Err(IotaError::UserInput {
4631                error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4632            }),
4633        }
4634    }
4635
4636    #[instrument(level = "trace", skip_all)]
4637    pub fn find_publish_txn_digest(&self, package_id: ObjectId) -> IotaResult<TransactionDigest> {
4638        if package_id.is_system_package() {
4639            return self.find_genesis_txn_digest();
4640        }
4641        Ok(self
4642            .get_object_read(&package_id)?
4643            .into_object()?
4644            .previous_transaction)
4645    }
4646
4647    #[instrument(level = "trace", skip_all)]
4648    pub fn find_genesis_txn_digest(&self) -> IotaResult<TransactionDigest> {
4649        let summary = self
4650            .get_verified_checkpoint_by_sequence_number(0)?
4651            .into_message();
4652        let content = self.get_checkpoint_contents(summary.contents_digest)?;
4653        let genesis_transaction = content.enumerate_transactions(&summary).next();
4654        Ok(genesis_transaction
4655            .ok_or(IotaError::UserInput {
4656                error: UserInputError::GenesisTransactionNotFound,
4657            })?
4658            .1
4659            .transaction)
4660    }
4661
4662    #[instrument(level = "trace", skip_all)]
4663    pub fn get_verified_checkpoint_by_sequence_number(
4664        &self,
4665        sequence_number: CheckpointSequenceNumber,
4666    ) -> IotaResult<VerifiedCheckpoint> {
4667        let verified_checkpoint = self
4668            .get_checkpoint_store()
4669            .get_checkpoint_by_sequence_number(sequence_number)?;
4670        match verified_checkpoint {
4671            Some(verified_checkpoint) => Ok(verified_checkpoint),
4672            None => Err(IotaError::UserInput {
4673                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4674            }),
4675        }
4676    }
4677
4678    #[instrument(level = "trace", skip_all)]
4679    pub fn get_verified_checkpoint_summary_by_digest(
4680        &self,
4681        digest: CheckpointDigest,
4682    ) -> IotaResult<VerifiedCheckpoint> {
4683        let verified_checkpoint = self
4684            .get_checkpoint_store()
4685            .get_checkpoint_by_digest(&digest)?;
4686        match verified_checkpoint {
4687            Some(verified_checkpoint) => Ok(verified_checkpoint),
4688            None => Err(IotaError::UserInput {
4689                error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4690            }),
4691        }
4692    }
4693
4694    #[instrument(level = "trace", skip_all)]
4695    pub fn get_checkpoint_contents(
4696        &self,
4697        digest: CheckpointContentsDigest,
4698    ) -> IotaResult<CheckpointContents> {
4699        self.get_checkpoint_store()
4700            .get_checkpoint_contents(&digest)?
4701            .ok_or(IotaError::UserInput {
4702                error: UserInputError::CheckpointContentsNotFound(digest),
4703            })
4704    }
4705
4706    #[instrument(level = "trace", skip_all)]
4707    pub fn get_checkpoint_contents_by_sequence_number(
4708        &self,
4709        sequence_number: CheckpointSequenceNumber,
4710    ) -> IotaResult<CheckpointContents> {
4711        let verified_checkpoint = self
4712            .get_checkpoint_store()
4713            .get_checkpoint_by_sequence_number(sequence_number)?;
4714        match verified_checkpoint {
4715            Some(verified_checkpoint) => {
4716                let contents_digest = verified_checkpoint.into_inner().contents_digest;
4717                self.get_checkpoint_contents(contents_digest)
4718            }
4719            None => Err(IotaError::UserInput {
4720                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4721            }),
4722        }
4723    }
4724
4725    #[instrument(level = "trace", skip_all)]
4726    pub async fn query_events(
4727        &self,
4728        kv_store: &Arc<TransactionKeyValueStore>,
4729        query: EventFilter,
4730        // If `Some`, the query will start from the next item after the specified cursor
4731        cursor: Option<EventID>,
4732        limit: usize,
4733        descending: bool,
4734    ) -> IotaResult<Vec<IotaEvent>> {
4735        let index_store = self.get_indexes()?;
4736
4737        // Get the tx_num from tx_digest
4738        let (tx_num, event_num) = if let Some(cursor) = cursor.as_ref() {
4739            let tx_seq = index_store.get_transaction_seq(&cursor.tx_digest)?.ok_or(
4740                IotaError::TransactionNotFound {
4741                    digest: cursor.tx_digest,
4742                },
4743            )?;
4744            (tx_seq, cursor.event_seq as usize)
4745        } else if descending {
4746            (u64::MAX, usize::MAX)
4747        } else {
4748            (0, 0)
4749        };
4750
4751        let limit = limit + 1;
4752        let mut event_keys = match query {
4753            EventFilter::All(filters) => {
4754                if filters.is_empty() {
4755                    index_store.all_events(tx_num, event_num, limit, descending)?
4756                } else {
4757                    return Err(IotaError::UserInput {
4758                        error: UserInputError::Unsupported(
4759                            "This query type does not currently support filter combinations"
4760                                .to_string(),
4761                        ),
4762                    });
4763                }
4764            }
4765            EventFilter::Transaction(digest) => {
4766                index_store.events_by_transaction(&digest, tx_num, event_num, limit, descending)?
4767            }
4768            EventFilter::MoveModule { package, module } => {
4769                let module_id = ModuleId::new(
4770                    AccountAddress::new(package.into_bytes()),
4771                    move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4772                );
4773                index_store.events_by_module_id(&module_id, tx_num, event_num, limit, descending)?
4774            }
4775            EventFilter::MoveEventType(struct_name) => index_store
4776                .events_by_move_event_struct_name(
4777                    &struct_name,
4778                    tx_num,
4779                    event_num,
4780                    limit,
4781                    descending,
4782                )?,
4783            EventFilter::Sender(sender) => {
4784                index_store.events_by_sender(&sender, tx_num, event_num, limit, descending)?
4785            }
4786            EventFilter::TimeRange {
4787                start_time,
4788                end_time,
4789            } => index_store
4790                .event_iterator(start_time, end_time, tx_num, event_num, limit, descending)?,
4791            EventFilter::MoveEventModule { package, module } => index_store
4792                .events_by_move_event_module(
4793                    &ModuleId::new(
4794                        AccountAddress::new(package.into_bytes()),
4795                        move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4796                    ),
4797                    tx_num,
4798                    event_num,
4799                    limit,
4800                    descending,
4801                )?,
4802            // not using "_ =>" because we want to make sure we remember to add new variants here
4803            EventFilter::Package(_)
4804            | EventFilter::MoveEventField { .. }
4805            | EventFilter::Any(_)
4806            | EventFilter::And(_, _)
4807            | EventFilter::Or(_, _) => {
4808                return Err(IotaError::UserInput {
4809                    error: UserInputError::Unsupported(
4810                        "This query type is not supported by the full node.".to_string(),
4811                    ),
4812                });
4813            }
4814        };
4815
4816        // skip one event if exclusive cursor is provided,
4817        // otherwise truncate to the original limit.
4818        if cursor.is_some() {
4819            if !event_keys.is_empty() {
4820                event_keys.remove(0);
4821            }
4822        } else {
4823            event_keys.truncate(limit - 1);
4824        }
4825
4826        // get the unique set of digests from the event_keys
4827        let transaction_digests = event_keys
4828            .iter()
4829            .map(|(_, digest, _, _)| *digest)
4830            .collect::<HashSet<_>>()
4831            .into_iter()
4832            .collect::<Vec<_>>();
4833
4834        let events = kv_store
4835            .multi_get_events_by_tx_digests(&transaction_digests)
4836            .await?;
4837
4838        let events_map: HashMap<_, _> =
4839            transaction_digests.iter().zip(events.into_iter()).collect();
4840
4841        let stored_events = event_keys
4842            .into_iter()
4843            .map(|k| {
4844                (
4845                    k,
4846                    events_map
4847                        .get(&k.1)
4848                        .expect("fetched digest is missing")
4849                        .clone()
4850                        .and_then(|e| e.get(k.2).cloned()),
4851                )
4852            })
4853            .map(
4854                |((_event_digest, tx_digest, event_seq, timestamp), event)| {
4855                    event
4856                        .map(|e| (e, tx_digest, event_seq, timestamp))
4857                        .ok_or(IotaError::TransactionEventsNotFound { digest: tx_digest })
4858                },
4859            )
4860            .collect::<Result<Vec<_>, _>>()?;
4861
4862        let epoch_store = self.load_epoch_store_one_call_per_task();
4863        let backing_store = self.get_backing_package_store().as_ref();
4864        let mut layout_resolver = epoch_store
4865            .executor()
4866            .type_layout_resolver(Box::new(backing_store));
4867        let mut events = vec![];
4868        for (e, tx_digest, event_seq, timestamp) in stored_events.into_iter() {
4869            events.push(IotaEvent::try_from(
4870                e.clone(),
4871                tx_digest,
4872                event_seq as u64,
4873                Some(timestamp),
4874                layout_resolver.get_annotated_layout(&e.struct_tag)?,
4875            )?)
4876        }
4877        Ok(events)
4878    }
4879
4880    pub fn insert_genesis_object(&self, object: Object) {
4881        self.get_reconfig_api()
4882            .try_insert_genesis_object(object)
4883            .expect("Cannot insert genesis object")
4884    }
4885
4886    pub fn insert_genesis_objects(&self, objects: &[Object]) {
4887        for o in objects {
4888            self.insert_genesis_object(o.clone());
4889        }
4890    }
4891
4892    /// Make a status response for a transaction
4893    #[instrument(level = "trace", skip_all)]
4894    pub fn get_transaction_status(
4895        &self,
4896        transaction_digest: &TransactionDigest,
4897        epoch_store: &Arc<AuthorityPerEpochStore>,
4898    ) -> IotaResult<Option<(SenderSignedTransaction, TransactionStatus)>> {
4899        // TODO: In the case of read path, we should not have to re-sign the effects.
4900        if let Some(effects) =
4901            self.get_signed_effects_and_maybe_resign(transaction_digest, epoch_store)?
4902        {
4903            if let Some(transaction) = self
4904                .get_transaction_cache_reader()
4905                .try_get_transaction_block(transaction_digest)?
4906            {
4907                let cert_sig = epoch_store.get_transaction_cert_sig(transaction_digest)?;
4908                let events = if effects.events_digest().is_some() {
4909                    self.get_transaction_events(effects.transaction_digest())?
4910                } else {
4911                    TransactionEvents::default()
4912                };
4913                return Ok(Some((
4914                    (*transaction).clone().into_message(),
4915                    TransactionStatus::Executed(cert_sig, effects.into_inner(), events),
4916                )));
4917            } else {
4918                // The read of effects and read of transaction are not atomic. It's possible
4919                // that we reverted the transaction (during epoch change) in
4920                // between the above two reads, and we end up having effects but
4921                // not transaction. In this case, we just fall through.
4922                debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
4923            }
4924        }
4925        if let Some(signed) = epoch_store.get_signed_transaction(transaction_digest)? {
4926            self.metrics.tx_already_processed.inc();
4927            let (transaction, sig) = signed.into_inner().into_data_and_sig();
4928            Ok(Some((transaction, TransactionStatus::Signed(sig))))
4929        } else {
4930            Ok(None)
4931        }
4932    }
4933
4934    /// Get the signed effects of the given transaction. If the effects was
4935    /// signed in a previous epoch, re-sign it so that the caller is able to
4936    /// form a cert of the effects in the current epoch.
4937    #[instrument(level = "trace", skip_all)]
4938    pub fn get_signed_effects_and_maybe_resign(
4939        &self,
4940        transaction_digest: &TransactionDigest,
4941        epoch_store: &Arc<AuthorityPerEpochStore>,
4942    ) -> IotaResult<Option<VerifiedSignedTransactionEffects>> {
4943        let effects = self
4944            .get_transaction_cache_reader()
4945            .try_get_executed_effects(transaction_digest)?;
4946        match effects {
4947            Some(effects) => {
4948                // If the transaction was executed in previous epochs, the validator will
4949                // re-sign the effects with new current epoch so that a client is always able to
4950                // obtain an effects certificate at the current epoch.
4951                //
4952                // Why is this necessary? Consider the following case:
4953                // - assume there are 4 validators
4954                // - Quorum driver gets 2 signed effects before reconfig halt
4955                // - The tx makes it into final checkpoint.
4956                // - 2 validators go away and are replaced in the new epoch.
4957                // - The new epoch begins.
4958                // - The quorum driver cannot complete the partial effects cert from the previous
4959                //   epoch, because it may not be able to reach either of the 2 former validators.
4960                // - But, if the 2 validators that stayed are willing to re-sign the effects in the
4961                //   new epoch, the QD can make a new effects cert and return it to the client.
4962                //
4963                // This is a considered a short-term workaround. Eventually, Quorum Driver
4964                // should be able to return either an effects certificate, -or-
4965                // a proof of inclusion in a checkpoint. In the case above, the
4966                // Quorum Driver would return a proof of inclusion in the final
4967                // checkpoint, and this code would no longer be necessary.
4968                if effects.epoch() != epoch_store.epoch() {
4969                    debug!(
4970                        tx_digest=?transaction_digest,
4971                        effects_epoch=?effects.epoch(),
4972                        epoch=?epoch_store.epoch(),
4973                        "Re-signing the effects with the current epoch"
4974                    );
4975                }
4976                Ok(Some(self.sign_effects(effects, epoch_store)?))
4977            }
4978            None => Ok(None),
4979        }
4980    }
4981
4982    /// A client aggregating effects signatures towards a quorum assumes
4983    /// finality once it collects 2f+1 of them, so within an epoch this
4984    /// validator must never assert two different effects for the same
4985    /// transaction on any RPC surface, signed or unsigned. Executed effects
4986    /// can change across a restart if an uncommitted transaction is
4987    /// re-executed with divergent results (e.g. by a new binary), so every
4988    /// effects-reporting path calls this before returning effects, and
4989    /// refuses to contradict a signature that may already be in a client's
4990    /// hands.
4991    pub fn check_effects_against_previously_signed(
4992        &self,
4993        epoch_store: &AuthorityPerEpochStore,
4994        tx_digest: &TransactionDigest,
4995        effects_digest: &TransactionEffectsDigest,
4996        surface: &'static str,
4997    ) -> IotaResult<()> {
4998        if let Some(previously_signed_digest) = epoch_store.get_signed_effects_digest(tx_digest)? {
4999            if previously_signed_digest != *effects_digest {
5000                self.metrics
5001                    .signed_effects_equivocation_prevented
5002                    .with_label_values(&[surface])
5003                    .inc();
5004                error!(
5005                    ?tx_digest,
5006                    ?previously_signed_digest,
5007                    executed_digest = ?effects_digest,
5008                    surface,
5009                    "refusing to report effects that differ from previously signed effects"
5010                );
5011                return Err(IotaError::GenericAuthority {
5012                    error: format!(
5013                        "Refusing to report effects for transaction {tx_digest}: effects digest \
5014                         {effects_digest} differs from previously signed effects digest \
5015                         {previously_signed_digest}"
5016                    ),
5017                });
5018            }
5019        }
5020        Ok(())
5021    }
5022
5023    #[instrument(level = "trace", skip_all)]
5024    pub(crate) fn sign_effects(
5025        &self,
5026        effects: TransactionEffects,
5027        epoch_store: &Arc<AuthorityPerEpochStore>,
5028    ) -> IotaResult<VerifiedSignedTransactionEffects> {
5029        let tx_digest = *effects.transaction_digest();
5030
5031        self.check_effects_against_previously_signed(
5032            epoch_store,
5033            &tx_digest,
5034            &effects.digest(),
5035            "sign_effects",
5036        )?;
5037
5038        let signed_effects = match epoch_store.get_effects_signature(&tx_digest)? {
5039            Some(sig) => {
5040                debug_assert!(sig.epoch == epoch_store.epoch());
5041                SignedTransactionEffects::new_from_data_and_sig(effects, sig)
5042            }
5043            _ => {
5044                let sig = AuthoritySignInfo::new(
5045                    epoch_store.epoch(),
5046                    &effects,
5047                    Intent::iota_app(IntentScope::TransactionEffects),
5048                    self.name,
5049                    &*self.secret,
5050                );
5051
5052                let effects = SignedTransactionEffects::new_from_data_and_sig(effects, sig.clone());
5053
5054                epoch_store.insert_effects_digest_and_signature(
5055                    &tx_digest,
5056                    effects.digest(),
5057                    &sig,
5058                )?;
5059
5060                effects
5061            }
5062        };
5063
5064        Ok(VerifiedSignedTransactionEffects::new_unchecked(
5065            signed_effects,
5066        ))
5067    }
5068
5069    // Returns coin objects for indexing for fullnode if indexing is enabled.
5070    #[instrument(level = "trace", skip_all)]
5071    fn fullnode_only_get_tx_coins_for_indexing(
5072        &self,
5073        effects: &TransactionEffects,
5074        inner_temporary_store: &InnerTemporaryStore,
5075        epoch_store: &Arc<AuthorityPerEpochStore>,
5076    ) -> Option<TxCoins> {
5077        if self.indexes.is_none() || self.is_committee_validator(epoch_store) {
5078            return None;
5079        }
5080        let written_coin_objects = inner_temporary_store
5081            .written
5082            .iter()
5083            .filter_map(|(k, v)| {
5084                if v.is_coin() {
5085                    Some((*k, v.clone()))
5086                } else {
5087                    None
5088                }
5089            })
5090            .collect();
5091        let mut input_coin_objects = inner_temporary_store
5092            .input_objects
5093            .iter()
5094            .filter_map(|(k, v)| {
5095                if v.is_coin() {
5096                    Some((*k, v.clone()))
5097                } else {
5098                    None
5099                }
5100            })
5101            .collect::<ObjectMap>();
5102
5103        // Check for receiving objects that were actually used and modified during
5104        // execution. Their updated version will already showup in
5105        // "written_coins" but their input isn't included in the set of input
5106        // objects in a inner_temporary_store.
5107        for modified in effects.modified_at_versions() {
5108            let (object_id, version) = (*modified.object_id(), modified.version());
5109            if inner_temporary_store
5110                .loaded_runtime_objects
5111                .contains_key(&object_id)
5112            {
5113                if let Some(object) = self
5114                    .get_object_store()
5115                    .get_object_by_key(&object_id, version)
5116                {
5117                    if object.is_coin() {
5118                        input_coin_objects.insert(object_id, object);
5119                    }
5120                }
5121            }
5122        }
5123
5124        Some((input_coin_objects, written_coin_objects))
5125    }
5126
5127    /// Get the transaction envelope that currently locks the given object, if
5128    /// any. Since object locks are only valid for one epoch, we also need
5129    /// the epoch_id in the query. Returns UserInputError::ObjectNotFound if
5130    /// no lock records for the given object can be found.
5131    /// Returns UserInputError::ObjectVersionUnavailableForConsumption if the
5132    /// object record is at a different version.
5133    /// Returns Some(VerifiedEnvelope) if the given ObjectReference is locked by
5134    /// a certain transaction. Returns None if the a lock record is
5135    /// initialized for the given ObjectReference but not yet locked by any
5136    /// transaction,     or cannot find the transaction in transaction
5137    /// table, because of data race etc.
5138    #[instrument(level = "trace", skip_all)]
5139    pub fn get_transaction_lock(
5140        &self,
5141        object_ref: &ObjectReference,
5142        epoch_store: &AuthorityPerEpochStore,
5143    ) -> IotaResult<Option<VerifiedSignedTransaction>> {
5144        let lock_info = self
5145            .get_object_cache_reader()
5146            .try_get_lock(*object_ref, epoch_store)?;
5147        let lock_info = match lock_info {
5148            ObjectLockStatus::LockedAtDifferentVersion { locked_ref } => {
5149                return Err(UserInputError::ObjectVersionUnavailableForConsumption {
5150                    provided_obj_ref: *object_ref,
5151                    current_version: locked_ref.version,
5152                }
5153                .into());
5154            }
5155            ObjectLockStatus::Initialized => {
5156                return Ok(None);
5157            }
5158            ObjectLockStatus::LockedToTx { locked_by_tx } => locked_by_tx,
5159        };
5160
5161        epoch_store.get_signed_transaction(&lock_info)
5162    }
5163
5164    pub fn try_get_objects(&self, objects: &[ObjectId]) -> IotaResult<Vec<Option<Object>>> {
5165        self.get_object_cache_reader().try_get_objects(objects)
5166    }
5167
5168    /// Non-fallible version of `try_get_objects`.
5169    pub fn get_objects(&self, objects: &[ObjectId]) -> Vec<Option<Object>> {
5170        self.try_get_objects(objects)
5171            .expect("storage access failed")
5172    }
5173
5174    pub fn try_get_object_or_tombstone(
5175        &self,
5176        object_id: ObjectId,
5177    ) -> IotaResult<Option<ObjectReference>> {
5178        self.get_object_cache_reader()
5179            .try_get_latest_object_ref_or_tombstone(object_id)
5180    }
5181
5182    /// Non-fallible version of `try_get_object_or_tombstone`.
5183    pub fn get_object_or_tombstone(&self, object_id: ObjectId) -> Option<ObjectReference> {
5184        self.try_get_object_or_tombstone(object_id)
5185            .expect("storage access failed")
5186    }
5187
5188    /// Ordinarily, protocol upgrades occur when 2f + 1 + (f *
5189    /// ProtocolConfig::buffer_stake_for_protocol_upgrade_bps) vote for the
5190    /// upgrade.
5191    ///
5192    /// This method can be used to dynamic adjust the amount of buffer. If set
5193    /// to 0, the upgrade will go through with only 2f+1 votes.
5194    ///
5195    /// IMPORTANT: If this is used, it must be used on >=2f+1 validators (all
5196    /// should have the same value), or you risk halting the chain.
5197    pub fn set_override_protocol_upgrade_buffer_stake(
5198        &self,
5199        expected_epoch: EpochId,
5200        buffer_stake_bps: u64,
5201    ) -> IotaResult {
5202        let epoch_store = self.load_epoch_store_one_call_per_task();
5203        let actual_epoch = epoch_store.epoch();
5204        if actual_epoch != expected_epoch {
5205            return Err(IotaError::WrongEpoch {
5206                expected_epoch,
5207                actual_epoch,
5208            });
5209        }
5210
5211        epoch_store.set_override_protocol_upgrade_buffer_stake(buffer_stake_bps)
5212    }
5213
5214    pub fn clear_override_protocol_upgrade_buffer_stake(
5215        &self,
5216        expected_epoch: EpochId,
5217    ) -> IotaResult {
5218        let epoch_store = self.load_epoch_store_one_call_per_task();
5219        let actual_epoch = epoch_store.epoch();
5220        if actual_epoch != expected_epoch {
5221            return Err(IotaError::WrongEpoch {
5222                expected_epoch,
5223                actual_epoch,
5224            });
5225        }
5226
5227        epoch_store.clear_override_protocol_upgrade_buffer_stake()
5228    }
5229
5230    /// Get the set of system packages that are compiled in to this build, if
5231    /// those packages are compatible with the current versions of those
5232    /// packages on-chain.
5233    pub async fn get_available_system_packages(
5234        &self,
5235        protocol_config: &ProtocolConfig,
5236    ) -> Vec<ObjectReference> {
5237        let mut results = vec![];
5238
5239        let system_packages = BuiltInFramework::iter_system_packages();
5240
5241        // Add extra framework packages during simtest
5242        #[cfg(msim)]
5243        let extra_packages = framework_injection::get_extra_packages(self.name);
5244        #[cfg(msim)]
5245        let system_packages = {
5246            let mut packages: Vec<_> = system_packages.collect();
5247            packages.extend(extra_packages.iter());
5248            packages
5249        };
5250
5251        for system_package in system_packages {
5252            let modules = system_package.modules().to_vec();
5253            // In simtests, we could override the current built-in framework packages.
5254            #[cfg(msim)]
5255            let modules = framework_injection::get_override_modules(&system_package.id, self.name)
5256                .unwrap_or(modules);
5257
5258            let Some(obj_ref) = iota_framework::compare_system_package(
5259                &self.get_object_store(),
5260                &system_package.id,
5261                &modules,
5262                system_package.dependencies.to_vec(),
5263                protocol_config,
5264            )
5265            .await
5266            else {
5267                return vec![];
5268            };
5269            results.push(obj_ref);
5270        }
5271
5272        results
5273    }
5274
5275    /// Return the new versions, module bytes, and dependencies for the packages
5276    /// that have been committed to for a framework upgrade, in
5277    /// `system_packages`.  Loads the module contents from the binary, and
5278    /// performs the following checks:
5279    ///
5280    /// - Whether its contents matches what is on-chain already, in which case no upgrade is
5281    ///   required, and its contents are omitted from the output.
5282    /// - Whether the contents in the binary can form a package whose digest matches the input,
5283    ///   meaning the framework will be upgraded, and this authority can satisfy that upgrade, in
5284    ///   which case the contents are included in the output.
5285    ///
5286    /// If a needed version of the framework can't be loaded, the binary does
5287    /// not contain the bytes for that framework ID, or the resulting
5288    /// package fails the digest check, `None` is returned indicating that
5289    /// this authority cannot run the upgrade that the network voted on.
5290    ///
5291    /// All object lookups are pinned to the versions in `system_packages`
5292    /// instead of using the latest versions, so that the result is
5293    /// deterministic even if the change epoch transaction that performs the
5294    /// upgrade has already been executed locally (e.g. via state sync). In
5295    /// that case the reconstructed change epoch transaction is byte-identical
5296    /// to the executed one, and the caller detects it as already executed.
5297    async fn get_system_package_bytes(
5298        &self,
5299        system_packages: Vec<ObjectReference>,
5300        binary_config: &BinaryConfig,
5301    ) -> Option<Vec<SystemPackage>> {
5302        let object_store = self.get_object_cache_reader();
5303
5304        let mut res = Vec::with_capacity(system_packages.len());
5305        for system_package_ref in system_packages {
5306            if object_store
5307                .get_object_by_key(&system_package_ref.object_id, system_package_ref.version)
5308                .is_some_and(|object| object.object_ref() == system_package_ref)
5309            {
5310                // Skip this one because it doesn't need to be upgraded.
5311                info!(
5312                    "Framework {} does not need updating",
5313                    system_package_ref.object_id
5314                );
5315                continue;
5316            }
5317
5318            // The digest in `system_package_ref` commits to a package built on top of the
5319            // predecessor version's `previous_transaction` (see `compare_system_package`),
5320            // so it must be re-derived from that version. A ref at
5321            // `Version::OBJECT_START` is a freshly created package with no predecessor.
5322            let prev_transaction = if system_package_ref.version == Version::OBJECT_START {
5323                TransactionDigest::GENESIS_MARKER
5324            } else {
5325                let prev_version = system_package_ref
5326                    .version
5327                    .previous()
5328                    .expect("version is greater than Version::OBJECT_START");
5329                let Some(prev_object) =
5330                    object_store.get_object_by_key(&system_package_ref.object_id, prev_version)
5331                else {
5332                    error!(
5333                        "Framework {} not available locally at version {prev_version:?}, cannot \
5334                         derive upgrade to {system_package_ref:?}",
5335                        system_package_ref.object_id
5336                    );
5337                    return None;
5338                };
5339                prev_object.previous_transaction
5340            };
5341
5342            #[cfg(msim)]
5343            let FrameworkSystemPackage {
5344                id: _,
5345                bytes,
5346                dependencies,
5347            } = framework_injection::get_override_system_package(
5348                &system_package_ref.object_id,
5349                self.name,
5350            )
5351            .unwrap_or_else(|| {
5352                BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone()
5353            });
5354
5355            #[cfg(not(msim))]
5356            let FrameworkSystemPackage {
5357                id: _,
5358                bytes,
5359                dependencies,
5360            } = BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone();
5361
5362            let modules: Vec<_> = bytes
5363                .iter()
5364                .map(|m| CompiledModule::deserialize_with_config(m, binary_config).unwrap())
5365                .collect();
5366
5367            let new_object = Object::new_system_package(
5368                &modules,
5369                system_package_ref.version,
5370                dependencies.clone(),
5371                prev_transaction,
5372            );
5373
5374            let new_ref = new_object.object_ref();
5375            if new_ref != system_package_ref {
5376                debug_fatal!(
5377                    "Framework mismatch -- binary: {new_ref:?}\n  upgrade: {system_package_ref:?}"
5378                );
5379                return None;
5380            }
5381
5382            res.push(SystemPackage {
5383                version: system_package_ref.version,
5384                modules: bytes,
5385                dependencies,
5386            });
5387        }
5388
5389        Some(res)
5390    }
5391
5392    /// Returns the new protocol version and system packages that the network
5393    /// has voted to upgrade to. If the proposed protocol version is not
5394    /// supported, None is returned.
5395    fn is_protocol_version_supported_v1(
5396        proposed_protocol_version: ProtocolVersion,
5397        committee: &Committee,
5398        capabilities: Vec<AuthorityCapabilitiesV1>,
5399        mut buffer_stake_bps: u64,
5400    ) -> Option<(ProtocolVersion, Digest, Vec<ObjectReference>)> {
5401        if buffer_stake_bps > 10000 {
5402            warn!("clamping buffer_stake_bps to 10000");
5403            buffer_stake_bps = 10000;
5404        }
5405
5406        // For each validator, gather the protocol version and system packages that it
5407        // would like to upgrade to in the next epoch.
5408        let mut desired_upgrades: Vec<_> = capabilities
5409            .into_iter()
5410            .filter_map(|mut cap| {
5411                // A validator that lists no packages is voting against any change at all.
5412                if cap.available_system_packages.is_empty() {
5413                    return None;
5414                }
5415
5416                cap.available_system_packages.sort();
5417
5418                info!(
5419                    "validator {:?} supports {:?} with system packages: {:?}",
5420                    cap.authority.concise(),
5421                    cap.supported_protocol_versions,
5422                    cap.available_system_packages,
5423                );
5424
5425                // A validator that only supports the current protocol version is also voting
5426                // against any change, because framework upgrades always require a protocol
5427                // version bump.
5428                cap.supported_protocol_versions
5429                    .get_version_digest(proposed_protocol_version)
5430                    .map(|digest| (digest, cap.available_system_packages, cap.authority))
5431            })
5432            .collect();
5433
5434        // There can only be one set of votes that have a majority, find one if it
5435        // exists.
5436        desired_upgrades.sort();
5437        desired_upgrades
5438            .into_iter()
5439            .chunk_by(|(digest, packages, _authority)| (*digest, packages.clone()))
5440            .into_iter()
5441            .find_map(|((digest, packages), group)| {
5442                // should have been filtered out earlier.
5443                assert!(!packages.is_empty());
5444
5445                let mut stake_aggregator: StakeAggregator<(), true> =
5446                    StakeAggregator::new(Arc::new(committee.clone()));
5447
5448                for (_, _, authority) in group {
5449                    stake_aggregator.insert_generic(authority, ());
5450                }
5451
5452                let total_votes = stake_aggregator.total_votes();
5453                let quorum_threshold = committee.quorum_threshold();
5454                let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5455
5456                info!(
5457                    protocol_config_digest = ?digest,
5458                    ?total_votes,
5459                    ?quorum_threshold,
5460                    ?buffer_stake_bps,
5461                    ?effective_threshold,
5462                    ?proposed_protocol_version,
5463                    ?packages,
5464                    "support for upgrade"
5465                );
5466
5467                let has_support = total_votes >= effective_threshold;
5468                has_support.then_some((proposed_protocol_version, digest, packages))
5469            })
5470    }
5471
5472    /// Selects the highest supported protocol version and system packages that
5473    /// the network has voted to upgrade to. If no upgrade is supported,
5474    /// returns the current protocol version and system packages.
5475    fn choose_protocol_version_and_system_packages_v1(
5476        current_protocol_version: ProtocolVersion,
5477        current_protocol_digest: Digest,
5478        committee: &Committee,
5479        capabilities: Vec<AuthorityCapabilitiesV1>,
5480        buffer_stake_bps: u64,
5481    ) -> (ProtocolVersion, Digest, Vec<ObjectReference>) {
5482        let mut next_protocol_version = current_protocol_version;
5483        let mut system_packages = vec![];
5484        let mut protocol_version_digest = current_protocol_digest;
5485
5486        // Finds the highest supported protocol version and system packages by
5487        // incrementing the proposed protocol version by one until no further
5488        // upgrades are supported.
5489        while let Some((version, digest, packages)) = Self::is_protocol_version_supported_v1(
5490            next_protocol_version + 1,
5491            committee,
5492            capabilities.clone(),
5493            buffer_stake_bps,
5494        ) {
5495            next_protocol_version = version;
5496            protocol_version_digest = digest;
5497            system_packages = packages;
5498        }
5499
5500        (
5501            next_protocol_version,
5502            protocol_version_digest,
5503            system_packages,
5504        )
5505    }
5506
5507    /// Returns the indices of validators that support the given protocol
5508    /// version and digest. This includes both committee and non-committee
5509    /// validators based on their capabilities. Uses active validators
5510    /// instead of committee indices.
5511    fn get_validators_supporting_protocol_version(
5512        target_protocol_version: ProtocolVersion,
5513        target_digest: Digest,
5514        active_validators: &[AggregateAuthorityPublicKey],
5515        capabilities: &[AuthorityCapabilitiesV1],
5516    ) -> Vec<u64> {
5517        let mut eligible_validators = Vec::new();
5518
5519        for capability in capabilities {
5520            // Check if this validator supports the target protocol version and digest
5521            if let Some(digest) = capability
5522                .supported_protocol_versions
5523                .get_version_digest(target_protocol_version)
5524            {
5525                if digest == target_digest {
5526                    // Find the validator's index in the active validators list
5527                    if let Some(index) = active_validators
5528                        .iter()
5529                        .position(|name| AuthorityName::from(name) == capability.authority)
5530                    {
5531                        eligible_validators.push(index as u64);
5532                    }
5533                }
5534            }
5535        }
5536
5537        // Sort indices for deterministic behavior
5538        eligible_validators.sort();
5539        eligible_validators
5540    }
5541
5542    /// Calculates the sum of weights for eligible validators that are part of
5543    /// the committee. Takes the indices from
5544    /// get_validators_supporting_protocol_version and maps them back
5545    /// to committee members to get their weights.
5546    fn calculate_eligible_validators_weight(
5547        eligible_validator_indices: &[u64],
5548        active_validators: &[AggregateAuthorityPublicKey],
5549        committee: &Committee,
5550    ) -> u64 {
5551        let mut total_weight = 0u64;
5552
5553        for &index in eligible_validator_indices {
5554            let authority_pubkey = &active_validators[index as usize];
5555            // Check if this validator is in the committee and get their weight
5556            if let Some((_, weight)) = committee
5557                .members()
5558                .find(|(name, _)| *name == AuthorityName::from(authority_pubkey))
5559            {
5560                total_weight += weight;
5561            }
5562        }
5563
5564        total_weight
5565    }
5566
5567    /// Creates and execute the advance epoch transaction to effects without
5568    /// committing it to the database. The effects of the change epoch tx
5569    /// are only written to the database after a certified checkpoint has been
5570    /// formed and executed by CheckpointExecutor.
5571    ///
5572    /// When a framework upgraded has been decided on, but the validator does
5573    /// not have the new versions of the packages locally, the validator
5574    /// cannot form the ChangeEpochTx. In this case it returns Err,
5575    /// indicating that the checkpoint builder should give up trying to make the
5576    /// final checkpoint. As long as the network is able to create a certified
5577    /// checkpoint (which should be ensured by the capabilities vote), it
5578    /// will arrive via state sync and be executed by CheckpointExecutor.
5579    #[instrument(level = "error", skip_all)]
5580    pub async fn create_and_execute_advance_epoch_tx(
5581        &self,
5582        epoch_store: &Arc<AuthorityPerEpochStore>,
5583        gas_cost_summary: &GasCostSummary,
5584        checkpoint: CheckpointSequenceNumber,
5585        epoch_start_timestamp_ms: CheckpointTimestamp,
5586        scores: Vec<u64>,
5587    ) -> CheckpointBuilderResult<(
5588        IotaSystemState,
5589        Option<SystemEpochInfoEvent>,
5590        TransactionEffects,
5591    )> {
5592        let mut txns = Vec::new();
5593
5594        // Create the TransactionDenyRules object once: the epoch-start
5595        // configuration is identical on every validator, so the whole
5596        // committee injects (or skips) the kind together. If this epoch
5597        // change falls into safe mode the creation is dropped with it, the
5598        // object stays absent, and the next epoch end injects it again.
5599        if epoch_store.protocol_config().enable_pcool_flow()
5600            && epoch_store
5601                .epoch_start_config()
5602                .transaction_deny_rules_obj_initial_shared_version()
5603                .is_none()
5604        {
5605            txns.push(EndOfEpochTransactionKind::TransactionDenyRulesCreate);
5606        }
5607
5608        let next_epoch = epoch_store.epoch() + 1;
5609
5610        let buffer_stake_bps = epoch_store.get_effective_buffer_stake_bps();
5611        let authority_capabilities = epoch_store
5612            .get_capabilities_v1()
5613            .expect("read capabilities from db cannot fail");
5614        let (next_epoch_protocol_version, next_epoch_protocol_digest, next_epoch_system_packages) =
5615            Self::choose_protocol_version_and_system_packages_v1(
5616                epoch_store.protocol_version(),
5617                SupportedProtocolVersionsWithHashes::protocol_config_digest(
5618                    epoch_store.protocol_config(),
5619                ),
5620                epoch_store.committee(),
5621                authority_capabilities.clone(),
5622                buffer_stake_bps,
5623            );
5624
5625        // since system packages are created during the current epoch, they should abide
5626        // by the rules of the current epoch, including the current epoch's max
5627        // Move binary format version
5628        let config = epoch_store.protocol_config();
5629        let binary_config = to_binary_config(config, None);
5630        let Some(next_epoch_system_package_bytes) = self
5631            .get_system_package_bytes(next_epoch_system_packages.clone(), &binary_config)
5632            .await
5633        else {
5634            debug_fatal!(
5635                "upgraded system packages {:?} are not locally available, cannot create \
5636                ChangeEpochTx. validator binary must be upgraded to the correct version!",
5637                next_epoch_system_packages
5638            );
5639            // the checkpoint builder will keep retrying forever when it hits this error.
5640            // Eventually, one of two things will happen:
5641            // - The operator will upgrade this binary to one that has the new packages locally, and
5642            //   this function will succeed.
5643            // - The final checkpoint will be certified by other validators, we will receive it via
5644            //   state sync, and execute it. This will upgrade the framework packages, reconfigure,
5645            //   and most likely shut down in the new epoch (this validator likely doesn't support
5646            //   the new protocol version, or else it should have had the packages.)
5647            return Err(CheckpointBuilderError::SystemPackagesMissing);
5648        };
5649
5650        // Use ChangeEpochV3 or ChangeEpochV4 when the feature flags are enabled and
5651        // ChangeEpochV2 requirements are met
5652        if config.select_committee_from_eligible_validators() {
5653            // Get the list of eligible validators that support the target protocol version
5654            let active_validators = epoch_store.epoch_start_state().get_active_validators();
5655
5656            let mut eligible_active_validators = (0..active_validators.len() as u64).collect();
5657
5658            // Use validators supporting the target protocol version as eligible validators
5659            // in the next version if select_committee_supporting_next_epoch_version feature
5660            // flag is set to true.
5661            if config.select_committee_supporting_next_epoch_version() {
5662                eligible_active_validators = Self::get_validators_supporting_protocol_version(
5663                    next_epoch_protocol_version,
5664                    next_epoch_protocol_digest,
5665                    &active_validators,
5666                    &authority_capabilities,
5667                );
5668
5669                // Calculate the total weight of eligible validators in the committee
5670                let eligible_validators_weight = Self::calculate_eligible_validators_weight(
5671                    &eligible_active_validators,
5672                    &active_validators,
5673                    epoch_store.committee(),
5674                );
5675
5676                // Safety check: ensure eligible validators have enough stake
5677                // Use the same effective threshold calculation that was used to decide the
5678                // protocol version
5679                let committee = epoch_store.committee();
5680                let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5681
5682                if eligible_validators_weight < effective_threshold {
5683                    error!(
5684                        "Eligible validators weight {eligible_validators_weight} is less than effective threshold {effective_threshold}. \
5685                        This could indicate a bug in validator selection logic or inconsistency with protocol version decision.",
5686                    );
5687                    // Pass all active validator indices as eligible validators
5688                    // to perform selection among all of them.
5689                    eligible_active_validators = (0..active_validators.len() as u64).collect();
5690                }
5691            }
5692
5693            // Use ChangeEpochV4 when the pass_validator_scores_to_advance_epoch feature
5694            // flag is enabled.
5695            if config.pass_validator_scores_to_advance_epoch() {
5696                txns.push(EndOfEpochTransactionKind::new_change_epoch_v4(
5697                    next_epoch,
5698                    next_epoch_protocol_version.as_u64(),
5699                    gas_cost_summary.storage_cost,
5700                    gas_cost_summary.computation_cost,
5701                    gas_cost_summary.computation_cost_burned,
5702                    gas_cost_summary.storage_rebate,
5703                    gas_cost_summary.non_refundable_storage_fee,
5704                    epoch_start_timestamp_ms,
5705                    next_epoch_system_package_bytes,
5706                    eligible_active_validators,
5707                    scores,
5708                    config.adjust_rewards_by_score(),
5709                ));
5710            } else {
5711                txns.push(EndOfEpochTransactionKind::new_change_epoch_v3(
5712                    next_epoch,
5713                    next_epoch_protocol_version.as_u64(),
5714                    gas_cost_summary.storage_cost,
5715                    gas_cost_summary.computation_cost,
5716                    gas_cost_summary.computation_cost_burned,
5717                    gas_cost_summary.storage_rebate,
5718                    gas_cost_summary.non_refundable_storage_fee,
5719                    epoch_start_timestamp_ms,
5720                    next_epoch_system_package_bytes,
5721                    eligible_active_validators,
5722                ));
5723            }
5724        } else if config.protocol_defined_base_fee()
5725            && config.max_committee_members_count_as_option().is_some()
5726        {
5727            txns.push(EndOfEpochTransactionKind::new_change_epoch_v2(
5728                next_epoch,
5729                next_epoch_protocol_version.as_u64(),
5730                gas_cost_summary.storage_cost,
5731                gas_cost_summary.computation_cost,
5732                gas_cost_summary.computation_cost_burned,
5733                gas_cost_summary.storage_rebate,
5734                gas_cost_summary.non_refundable_storage_fee,
5735                epoch_start_timestamp_ms,
5736                next_epoch_system_package_bytes,
5737            ));
5738        } else {
5739            txns.push(EndOfEpochTransactionKind::new_change_epoch(
5740                next_epoch,
5741                next_epoch_protocol_version.as_u64(),
5742                gas_cost_summary.storage_cost,
5743                gas_cost_summary.computation_cost,
5744                gas_cost_summary.storage_rebate,
5745                gas_cost_summary.non_refundable_storage_fee,
5746                epoch_start_timestamp_ms,
5747                next_epoch_system_package_bytes,
5748            ));
5749        }
5750
5751        let tx = VerifiedTransaction::new_end_of_epoch_transaction(txns);
5752
5753        let executable_tx = VerifiedExecutableTransaction::new_from_checkpoint(
5754            tx.clone(),
5755            epoch_store.epoch(),
5756            checkpoint,
5757        );
5758
5759        let tx_digest = executable_tx.digest();
5760
5761        info!(
5762            ?next_epoch,
5763            ?next_epoch_protocol_version,
5764            ?next_epoch_system_packages,
5765            computation_cost=?gas_cost_summary.computation_cost,
5766            computation_cost_burned=?gas_cost_summary.computation_cost_burned,
5767            storage_cost=?gas_cost_summary.storage_cost,
5768            storage_rebate=?gas_cost_summary.storage_rebate,
5769            non_refundable_storage_fee=?gas_cost_summary.non_refundable_storage_fee,
5770            ?tx_digest,
5771            "Creating advance epoch transaction"
5772        );
5773
5774        fail_point_async!("change_epoch_tx_delay");
5775        let tx_lock = epoch_store.acquire_tx_lock(tx_digest);
5776
5777        // The tx could have been executed by state sync already - if so simply return
5778        // an error. The checkpoint builder will shortly be terminated by
5779        // reconfiguration anyway.
5780        if self
5781            .get_transaction_cache_reader()
5782            .try_is_tx_already_executed(tx_digest)?
5783        {
5784            warn!("change epoch tx has already been executed via state sync");
5785            return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
5786        }
5787
5788        let execution_guard = self.execution_lock_for_executable_transaction(&executable_tx)?;
5789
5790        // We must manually assign the shared object versions to the transaction before
5791        // executing it. This is because we do not sequence end-of-epoch
5792        // transactions through consensus.
5793        let assigned_versions = epoch_store.assign_shared_object_versions_idempotent(
5794            self.get_object_cache_reader().as_ref(),
5795            std::iter::once(&Schedulable::Transaction(&executable_tx)),
5796        )?;
5797
5798        assert_eq!(assigned_versions.0.len(), 1);
5799        let assigned_versions = assigned_versions.0.into_iter().next().unwrap().1;
5800
5801        let (input_objects, _) = self.read_objects_for_execution(
5802            &tx_lock,
5803            &executable_tx,
5804            assigned_versions,
5805            epoch_store,
5806        )?;
5807
5808        let (temporary_store, effects, _execution_error_opt) = self.execute_transaction(
5809            &execution_guard,
5810            &executable_tx,
5811            input_objects,
5812            vec![],
5813            epoch_store,
5814        )?;
5815        let system_obj = get_iota_system_state(&temporary_store.written)
5816            .expect("change epoch tx must write to system object");
5817        // Find the SystemEpochInfoEvent emitted by the advance_epoch transaction.
5818        let system_epoch_info_event = temporary_store
5819            .events
5820            .0
5821            .into_iter()
5822            .find(|event| event.is_system_epoch_info_event())
5823            .map(SystemEpochInfoEvent::from);
5824        // The system epoch info event can be `None` in case if the `advance_epoch`
5825        // Move function call failed and was executed in the safe mode.
5826        assert!(system_epoch_info_event.is_some() || system_obj.safe_mode());
5827
5828        // We must write tx and effects to the state sync tables so that state sync is
5829        // able to deliver to the transaction to CheckpointExecutor after it is
5830        // included in a certified checkpoint.
5831        self.get_state_sync_store()
5832            .try_insert_transaction_and_effects(&tx, &effects)?;
5833
5834        info!(
5835            "Effects summary of the change epoch transaction: {:?}",
5836            effects.summary_for_debug()
5837        );
5838        epoch_store.record_checkpoint_builder_is_safe_mode_metric(system_obj.safe_mode());
5839        // The change epoch transaction cannot fail to execute.
5840        assert!(effects.status().is_success());
5841        Ok((system_obj, system_epoch_info_event, effects))
5842    }
5843
5844    /// This function is called at the very end of the epoch.
5845    /// This step is required before updating new epoch in the db and calling
5846    /// reopen_epoch_db.
5847    #[instrument(level = "error", skip_all)]
5848    async fn revert_uncommitted_epoch_transactions(
5849        &self,
5850        epoch_store: &AuthorityPerEpochStore,
5851    ) -> IotaResult {
5852        {
5853            let state = epoch_store.get_reconfig_state_write_lock_guard();
5854            if state.should_accept_user_certs() {
5855                // Need to change this so that consensus adapter do not accept certificates from
5856                // user. This can happen if our local validator did not initiate
5857                // epoch change locally, but 2f+1 nodes already concluded the
5858                // epoch.
5859                //
5860                // This lock is essentially a barrier (in the certificate mode only) for
5861                // `epoch_store.pending_consensus_certificates` table we are reading on the line
5862                // after this block
5863                epoch_store.close_user_certs(state);
5864            }
5865            // lock is dropped here
5866        }
5867
5868        // In the P-COOL flow, the list of pending consensus certificates is
5869        // always empty, so the reverting below is only for the certificate mode.
5870        if !epoch_store.protocol_config().enable_pcool_flow() {
5871            let pending_certificates = epoch_store.pending_consensus_certificates();
5872            info!(
5873                "Reverting {} locally executed transactions that was not included in the epoch: \
5874                    {:?}",
5875                pending_certificates.len(),
5876                pending_certificates,
5877            );
5878            for digest in pending_certificates {
5879                if epoch_store.is_transaction_executed_in_checkpoint(&digest)? {
5880                    info!(
5881                        "Not reverting pending consensus transaction {:?} - it was included in \
5882                            checkpoint",
5883                        digest
5884                    );
5885                    continue;
5886                }
5887                info!("Reverting {:?} at the end of epoch", digest);
5888                epoch_store.revert_executed_transaction(&digest)?;
5889                self.get_reconfig_api().try_revert_state_update(&digest)?;
5890            }
5891            info!("All uncommitted local transactions reverted");
5892        } else {
5893            info!("P-COOL mode: skipping revert of uncommitted epoch transactions");
5894        }
5895
5896        Ok(())
5897    }
5898
5899    #[instrument(level = "error", skip_all)]
5900    async fn reopen_epoch_db(
5901        &self,
5902        cur_epoch_store: &AuthorityPerEpochStore,
5903        new_committee: Committee,
5904        epoch_start_configuration: EpochStartConfiguration,
5905        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
5906        epoch_last_checkpoint: CheckpointSequenceNumber,
5907    ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
5908        let new_epoch = new_committee.epoch;
5909        info!(new_epoch = ?new_epoch, "re-opening AuthorityEpochTables for new epoch");
5910        assert_eq!(
5911            epoch_start_configuration.epoch_start_state().epoch(),
5912            new_committee.epoch
5913        );
5914        fail_point!("before-open-new-epoch-store");
5915        let new_epoch_store = cur_epoch_store.new_at_next_epoch(
5916            self.name,
5917            new_committee,
5918            epoch_start_configuration,
5919            self.get_backing_package_store().clone(),
5920            expensive_safety_check_config,
5921            epoch_last_checkpoint,
5922        )?;
5923        self.epoch_store.store(new_epoch_store.clone());
5924        Ok(new_epoch_store)
5925    }
5926
5927    /// Resolves the account's `AuthenticatorFunctionRef` on the execution path,
5928    /// where the certificate has already passed validation before consensus.
5929    ///
5930    /// A deleted or cancelled account object is not an error here: its version
5931    /// is returned so execution can proceed and surface the proper effect
5932    /// (e.g. `InputObjectDeleted` or a shared-object congestion cancellation).
5933    ///
5934    /// # Errors
5935    ///
5936    /// Any failure the check finds with the transaction, as the error the
5937    /// transaction fails with, with the original error as the source:
5938    /// [`ExecutionErrorKind::AuthenticatorFunctionNotFound`] when the account
5939    /// has no authenticator function field or the field cannot be read, and
5940    /// [`ExecutionErrorKind::AccountNotSharedObject`] when the account is not a
5941    /// shared object.
5942    ///
5943    /// # Panics
5944    ///
5945    /// When the store cannot be read: that says nothing about the transaction,
5946    /// so nobody can be charged for it, and effects written here would differ
5947    /// from the other validators'.
5948    fn check_move_account_for_execution(
5949        &self,
5950        auth_account_object_id: ObjectId,
5951        auth_account_object_seq_number: Option<Version>,
5952        auth_account_object_digest: Option<ObjectDigest>,
5953        account_object: ObjectReadResult,
5954        signer: &Address,
5955        protocol_config: &ProtocolConfig,
5956    ) -> Result<AuthenticatorFunctionRefForExecution, ExecutionError> {
5957        match self.check_move_account(
5958            auth_account_object_id,
5959            auth_account_object_seq_number,
5960            auth_account_object_digest,
5961            account_object,
5962            signer,
5963            true,
5964            protocol_config,
5965        ) {
5966            Ok(function_ref) => Ok(function_ref),
5967            Err(MoveAccountCheckError::Input(input_error)) => {
5968                let status = match &input_error {
5969                    UserInputError::MoveAuthenticatorNotFound {
5970                        account_object_id, ..
5971                    }
5972                    | UserInputError::InvalidAuthenticatorFunctionRefField { account_object_id } => {
5973                        ExecutionErrorKind::AuthenticatorFunctionNotFound {
5974                            object_id: *account_object_id,
5975                        }
5976                    }
5977                    // Since protocol version 36, only a shared account named with
5978                    // an immutable or owned reference reaches the digest
5979                    // comparison. The fix is the same as for the other two: name
5980                    // the account as a shared object.
5981                    UserInputError::AccountObjectNotSupported { object_id }
5982                    | UserInputError::ImmutableAccountObjectNotSupported { object_id }
5983                    | UserInputError::InvalidAccountObjectDigest { object_id, .. } => {
5984                        ExecutionErrorKind::AccountNotSharedObject {
5985                            object_id: *object_id,
5986                        }
5987                    }
5988                    // The check produces nothing else today. A failure added to
5989                    // it gets this status until it is given one of its own.
5990                    _ => ExecutionErrorKind::FunctionNotFound,
5991                };
5992                Err(ExecutionError::new_with_source(status, input_error))
5993            }
5994            Err(MoveAccountCheckError::Storage(storage_error)) => {
5995                panic!("failed to read the store while checking a Move account: {storage_error}")
5996            }
5997        }
5998    }
5999
6000    /// Resolves the account's `AuthenticatorFunctionRef` on the validation
6001    /// (signing) path, rejecting the transaction when the account object was
6002    /// deleted or belongs to a cancelled transaction.
6003    fn check_move_account_for_validation(
6004        &self,
6005        auth_account_object_id: ObjectId,
6006        auth_account_object_seq_number: Option<Version>,
6007        auth_account_object_digest: Option<ObjectDigest>,
6008        account_object: ObjectReadResult,
6009        signer: &Address,
6010        protocol_config: &ProtocolConfig,
6011    ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
6012        self.check_move_account(
6013            auth_account_object_id,
6014            auth_account_object_seq_number,
6015            auth_account_object_digest,
6016            account_object,
6017            signer,
6018            false,
6019            protocol_config,
6020        )
6021        .map_err(IotaError::from)
6022    }
6023
6024    /// Checks whether `authenticator` unlocks a valid Move account and returns
6025    /// the account-related `AuthenticatorFunctionRef`. Where the protocol
6026    /// config requires it, the account object must be shared, so that a
6027    /// transaction carrying a `MoveAuthenticator` always has a shared input
6028    /// and is ordered by consensus. When `is_execution` is
6029    /// set, a deleted or cancelled account object yields its version instead of
6030    /// an error, so execution can proceed to the proper effect. Prefer the
6031    /// `check_move_account_for_execution` / `check_move_account_for_validation`
6032    /// wrappers over calling this directly.
6033    ///
6034    /// # Errors
6035    ///
6036    /// [`MoveAccountCheckError::Input`] when the account fails a check, and
6037    /// [`MoveAccountCheckError::Storage`] when the store cannot be read. The
6038    /// error type is what lets the execution path distinguish the two, so a
6039    /// new kind of failure here has to be added to it.
6040    fn check_move_account(
6041        &self,
6042        auth_account_object_id: ObjectId,
6043        auth_account_object_seq_number: Option<Version>,
6044        auth_account_object_digest: Option<ObjectDigest>,
6045        account_object: ObjectReadResult,
6046        signer: &Address,
6047        is_execution: bool,
6048        protocol_config: &ProtocolConfig,
6049    ) -> Result<AuthenticatorFunctionRefForExecution, MoveAccountCheckError> {
6050        let auth_account_object_seq_number = match (&account_object.object, is_execution) {
6051            // In any case, if the account object is loaded, we can check its version and digest.
6052            // Then we return the version of the account object to be used for reading the
6053            // authenticator function ref dynamic field.
6054            (ObjectReadResultKind::Object(object), _) => {
6055                let account_object_addr = Address::from(auth_account_object_id);
6056                fp_ensure!(
6057                    signer == &account_object_addr,
6058                    UserInputError::IncorrectUserSignature {
6059                        error: format!("Move authenticator is trying to unlock {account_object_addr:?}, but given signer address is {signer:?}")
6060                    }
6061                    .into()
6062                );
6063
6064                if protocol_config.reject_immutable_account_objects() {
6065                    fp_ensure!(
6066                        !object.is_immutable(),
6067                        UserInputError::ImmutableAccountObjectNotSupported {
6068                            object_id: auth_account_object_id
6069                        }
6070                        .into()
6071                    );
6072                }
6073
6074                fp_ensure!(
6075                    object.is_shared() || object.is_immutable(),
6076                    UserInputError::AccountObjectNotSupported {
6077                        object_id: auth_account_object_id
6078                    }
6079                    .into()
6080                );
6081
6082                let auth_account_object_seq_number =
6083                    if let Some(expected_version) = auth_account_object_seq_number {
6084                        let account_object_version = object.version();
6085
6086                        fp_ensure!(
6087                            account_object_version == expected_version,
6088                            UserInputError::AccountObjectVersionMismatch {
6089                                object_id: auth_account_object_id,
6090                                expected_version,
6091                                actual_version: account_object_version,
6092                            }
6093                            .into()
6094                        );
6095
6096                        expected_version
6097                    } else {
6098                        object.version()
6099                    };
6100
6101                if let Some(expected_digest) = auth_account_object_digest {
6102                    let account_object_digest = object.digest();
6103                    fp_ensure!(
6104                        account_object_digest == expected_digest,
6105                        UserInputError::InvalidAccountObjectDigest {
6106                            object_id: auth_account_object_id,
6107                            expected_digest,
6108                            actual_digest: account_object_digest,
6109                        }
6110                        .into()
6111                    );
6112                }
6113
6114                Ok(auth_account_object_seq_number)
6115            }
6116            // If the account object is not loaded because it was deleted, we return the error in
6117            // the case in which we are not executing the transaction right after.
6118            (ObjectReadResultKind::DeletedSharedObject(version, digest), false) => {
6119                Err(UserInputError::AccountObjectDeleted {
6120                    account_id: account_object.id(),
6121                    account_version: *version,
6122                    transaction_digest: *digest,
6123                })
6124            }
6125            // If the account object is not loaded because the transaction was canceled, we return
6126            // the error in the case in which we are not executing the transaction right
6127            // after.
6128            (ObjectReadResultKind::CancelledTransactionObject(version), false) => {
6129                Err(UserInputError::AccountObjectInCanceledTransaction {
6130                    account_id: account_object.id(),
6131                    account_version: *version,
6132                })
6133            }
6134            // If the account object is not loaded because it was deleted, we return the version in
6135            // the case in which we are executing the transaction right after.
6136            // This version is used to read the authenticator function ref dynamic field because it
6137            // is greater than the version of the child dynamic field.
6138            (ObjectReadResultKind::DeletedSharedObject(version, _), true) => Ok(*version),
6139            // If the account object is not loaded because the transaction was canceled, we return
6140            // the version in the case in which we are executing the transaction right
6141            // after. This version is used to read the authenticator function ref
6142            // dynamic field because it is greater than the version of the child dynamic
6143            // field.
6144            (ObjectReadResultKind::CancelledTransactionObject(version), true) => Ok(*version),
6145            // A transaction validated post-consensus at a commit leaves its account
6146            // to execution, which reads it, so no check gets an unread account.
6147            (ObjectReadResultKind::UnreadSharedObject, _) => unreachable!(
6148                "only post-consensus validation at a commit lists an unread shared object, and \
6149                    it leaves the account to execution"
6150            ),
6151        }?;
6152
6153        let authenticator_function_ref_field_id =
6154            derive_authenticator_function_ref_v1_dynamic_field_id(auth_account_object_id)?;
6155
6156        let authenticator_function_ref_field = self
6157            .get_object_cache_reader()
6158            .try_find_object_lt_or_eq_version(
6159                authenticator_function_ref_field_id,
6160                auth_account_object_seq_number,
6161            )
6162            .map_err(MoveAccountCheckError::Storage)?;
6163
6164        if let Some(authenticator_function_ref_field_obj) = authenticator_function_ref_field {
6165            Ok(authenticator_function_ref_v1_from_dynamic_field_object(
6166                auth_account_object_id,
6167                &authenticator_function_ref_field_obj,
6168            )?)
6169        } else {
6170            Err(UserInputError::MoveAuthenticatorNotFound {
6171                authenticator_function_ref_id: authenticator_function_ref_field_id,
6172                account_object_id: auth_account_object_id,
6173                account_object_version: auth_account_object_seq_number,
6174            }
6175            .into())
6176        }
6177    }
6178
6179    #[allow(clippy::type_complexity)]
6180    fn read_objects_for_validation(
6181        &self,
6182        transaction: &VerifiedTransaction,
6183        epoch: u64,
6184    ) -> IotaResult<(
6185        InputObjects,
6186        ReceivingObjects,
6187        Vec<(InputObjects, ObjectReadResult)>,
6188    )> {
6189        let (input_objects, tx_receiving_objects) = self.input_loader.read_objects_for_signing(
6190            Some(transaction.digest()),
6191            &transaction.collect_all_input_object_kind_for_reading()?,
6192            &transaction.data().transaction().receiving_objects(),
6193            epoch,
6194        )?;
6195
6196        transaction
6197            .split_input_objects_into_groups_for_reading(input_objects)
6198            .map(|(tx_input_objects, per_authenticator_inputs)| {
6199                (
6200                    tx_input_objects,
6201                    tx_receiving_objects,
6202                    per_authenticator_inputs,
6203                )
6204            })
6205    }
6206
6207    /// Like [`Self::read_objects_for_validation`], but for post-consensus
6208    /// validation at the commit `reader` was built for. Every input and every
6209    /// receiving object comes from the commit-indexed reader, the inputs
6210    /// first, so the first of them that decides is reported as at admission.
6211    fn read_objects_for_validation_at_commit(
6212        &self,
6213        reader: &CommitIndexedReader,
6214        transaction: &VerifiedTransaction,
6215    ) -> IotaResult<ValidationInputsAtCommit> {
6216        let input_objects = match self.input_loader.read_objects_at_commit(
6217            reader,
6218            &transaction.collect_all_input_object_kind_for_reading()?,
6219        )? {
6220            InputResolution::Loaded(input_objects) => input_objects,
6221            InputResolution::Drop(kind, reason) => {
6222                return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6223            }
6224            InputResolution::Missing(kind, reason) => {
6225                return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6226            }
6227        };
6228        let tx_receiving_objects = match self.input_loader.read_receiving_objects_at_commit(
6229            reader,
6230            &transaction.data().transaction().receiving_objects(),
6231        )? {
6232            ReceivingObjectsResolution::Loaded(receiving_objects) => receiving_objects,
6233            ReceivingObjectsResolution::Drop(kind, reason) => {
6234                return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6235            }
6236            ReceivingObjectsResolution::Missing(kind, reason) => {
6237                return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6238            }
6239        };
6240
6241        let (tx_input_objects, per_authenticator_inputs) =
6242            transaction.split_input_objects_into_groups_for_reading(input_objects)?;
6243        Ok(ValidationInputsAtCommit::Loaded {
6244            tx_input_objects,
6245            tx_receiving_objects,
6246            per_authenticator_inputs,
6247        })
6248    }
6249
6250    #[allow(clippy::type_complexity)]
6251    fn check_transaction_inputs_for_validation(
6252        &self,
6253        protocol_config: &ProtocolConfig,
6254        reference_gas_price: u64,
6255        tx: &Transaction,
6256        tx_input_objects: InputObjects,
6257        tx_receiving_objects: &ReceivingObjects,
6258        move_authenticators: &Vec<&MoveAuthenticator>,
6259        per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6260        verifier_limits_source: VerifierLimitsSource<'_>,
6261    ) -> IotaResult<(
6262        IotaGasStatus,
6263        CheckedInputObjects,
6264        Vec<(CheckedInputObjects, AuthenticatorFunctionRef)>,
6265    )> {
6266        let authenticator_gas_budget = if move_authenticators.is_empty() {
6267            0
6268        } else {
6269            // `max_auth_gas` is used here as a Move authenticator gas budget until it is
6270            // not a part of the transaction data.
6271            protocol_config.max_auth_gas()
6272        };
6273
6274        debug_assert_eq!(
6275            move_authenticators.len(),
6276            per_authenticator_inputs.len(),
6277            "Move authenticators amount must match the number of authenticator inputs"
6278        );
6279
6280        let per_authenticator_checked_inputs = move_authenticators
6281            .iter()
6282            .zip(per_authenticator_inputs)
6283            .map(
6284                |(move_authenticator, (authenticator_input_objects, account_object))| {
6285                    // Check basic `object_to_authenticate` preconditions and get its components.
6286                    let (
6287                        auth_account_object_id,
6288                        auth_account_object_seq_number,
6289                        auth_account_object_digest,
6290                    ) = move_authenticator.object_to_authenticate_components()?;
6291
6292                    let signer = move_authenticator.address();
6293
6294                    // Make sure the signer is a Move account.
6295                    let AuthenticatorFunctionRefForExecution {
6296                        authenticator_function_ref,
6297                        ..
6298                    } = self.check_move_account_for_validation(
6299                        auth_account_object_id,
6300                        auth_account_object_seq_number,
6301                        auth_account_object_digest,
6302                        account_object,
6303                        &signer,
6304                        protocol_config,
6305                    )?;
6306
6307                    // Check the MoveAuthenticator input objects.
6308                    let authenticator_checked_input_objects =
6309                        iota_transaction_checks::check_move_authenticator_input_for_validation(
6310                            authenticator_input_objects,
6311                        )?;
6312
6313                    Ok((
6314                        authenticator_checked_input_objects,
6315                        authenticator_function_ref,
6316                    ))
6317                },
6318            )
6319            .collect::<IotaResult<Vec<_>>>()?;
6320
6321        // Check the transaction inputs.
6322        let (gas_status, tx_checked_input_objects) =
6323            iota_transaction_checks::check_transaction_input(
6324                protocol_config,
6325                reference_gas_price,
6326                tx,
6327                tx_input_objects,
6328                tx_receiving_objects,
6329                &self.metrics.bytecode_verifier_metrics,
6330                verifier_limits_source,
6331                authenticator_gas_budget,
6332            )?;
6333
6334        Ok((
6335            gas_status,
6336            tx_checked_input_objects,
6337            per_authenticator_checked_inputs,
6338        ))
6339    }
6340
6341    /// Like [`Self::check_transaction_inputs_for_validation`], but for
6342    /// post-consensus validation at a commit. One difference: the Move
6343    /// account is not resolved here, only the authenticator's inputs are
6344    /// checked, so no function reference comes back. The receiving objects,
6345    /// read through the commit-indexed reader, get the same checks as at
6346    /// admission.
6347    fn check_transaction_inputs_at_commit(
6348        &self,
6349        protocol_config: &ProtocolConfig,
6350        reference_gas_price: u64,
6351        tx: &Transaction,
6352        tx_input_objects: InputObjects,
6353        tx_receiving_objects: &ReceivingObjects,
6354        move_authenticators: &[&MoveAuthenticator],
6355        per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6356        verifier_limits_source: VerifierLimitsSource<'_>,
6357    ) -> IotaResult<CheckedValidationInputs> {
6358        let authenticator_gas_budget = if move_authenticators.is_empty() {
6359            0
6360        } else {
6361            protocol_config.max_auth_gas()
6362        };
6363
6364        debug_assert_eq!(
6365            move_authenticators.len(),
6366            per_authenticator_inputs.len(),
6367            "Move authenticators amount must match the number of authenticator inputs"
6368        );
6369
6370        // The account object is among the authenticator's inputs. An account
6371        // named as a shared object was decided by the reader from its rows,
6372        // which drop the transaction when the object was not created shared.
6373        // An account named as an immutable-or-owned input was read at the
6374        // version the transaction names, and this check rejects one owned by
6375        // an address or by another object. An immutable account is not
6376        // rejected here. Looking up the account's authenticator function is
6377        // left to execution.
6378        let per_authenticator_checked_inputs = per_authenticator_inputs
6379            .into_iter()
6380            .map(|(authenticator_input_objects, _account_object)| {
6381                iota_transaction_checks::check_move_authenticator_input_for_validation(
6382                    authenticator_input_objects,
6383                )
6384            })
6385            .collect::<IotaResult<Vec<_>>>()?;
6386
6387        // The gas status only meters an authenticator run, which does not happen here.
6388        let (_gas_status, tx_checked_input_objects) =
6389            iota_transaction_checks::check_transaction_input(
6390                protocol_config,
6391                reference_gas_price,
6392                tx,
6393                tx_input_objects,
6394                tx_receiving_objects,
6395                &self.metrics.bytecode_verifier_metrics,
6396                verifier_limits_source,
6397                authenticator_gas_budget,
6398            )?;
6399
6400        Ok((tx_checked_input_objects, per_authenticator_checked_inputs))
6401    }
6402
6403    #[cfg(test)]
6404    pub(crate) fn iter_live_object_set_for_testing(
6405        &self,
6406    ) -> impl Iterator<Item = authority_store_tables::LiveObject> + '_ {
6407        self.get_global_state_hash_store()
6408            .iter_cached_live_object_set_for_testing()
6409    }
6410
6411    #[cfg(test)]
6412    pub(crate) fn shutdown_execution_for_test(&self) {
6413        self.tx_execution_shutdown
6414            .lock()
6415            .take()
6416            .unwrap()
6417            .send(())
6418            .unwrap();
6419    }
6420
6421    /// NOTE: this function is only to be used for fuzzing and testing. Never
6422    /// use in prod
6423    pub async fn insert_objects_unsafe_for_testing_only(&self, objects: &[Object]) {
6424        self.get_reconfig_api().bulk_insert_genesis_objects(objects);
6425        self.get_object_cache_reader()
6426            .force_reload_system_packages(&BuiltInFramework::all_package_ids());
6427        self.get_reconfig_api()
6428            .clear_state_end_of_epoch(&self.execution_lock_for_reconfiguration().await);
6429    }
6430}
6431
6432pub struct RandomnessRoundReceiver {
6433    authority_state: Arc<AuthorityState>,
6434    randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6435}
6436
6437impl RandomnessRoundReceiver {
6438    pub fn spawn(
6439        authority_state: Arc<AuthorityState>,
6440        randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6441    ) -> JoinHandle<()> {
6442        let rrr = RandomnessRoundReceiver {
6443            authority_state,
6444            randomness_rx,
6445        };
6446        spawn_monitored_task!(rrr.run())
6447    }
6448
6449    async fn run(mut self) {
6450        info!("RandomnessRoundReceiver event loop started");
6451
6452        loop {
6453            tokio::select! {
6454                maybe_recv = self.randomness_rx.recv() => {
6455                    if let Some((epoch, round, bytes)) = maybe_recv {
6456                        self.handle_new_randomness(epoch, round, bytes).await;
6457                    } else {
6458                        break;
6459                    }
6460                },
6461            }
6462        }
6463
6464        info!("RandomnessRoundReceiver event loop ended");
6465    }
6466
6467    #[instrument(level = "debug", skip_all, fields(?epoch, ?round))]
6468    async fn handle_new_randomness(&self, epoch: EpochId, round: RandomnessRound, bytes: Vec<u8>) {
6469        fail_point_async!("randomness-delay");
6470
6471        let epoch_store = self.authority_state.load_epoch_store_one_call_per_task();
6472        if epoch_store.epoch() != epoch {
6473            warn!(
6474                "dropping randomness for epoch {epoch}, round {round}, because we are in epoch {}",
6475                epoch_store.epoch()
6476            );
6477            return;
6478        }
6479        let key = TransactionKey::RandomnessRound(epoch, round);
6480        let transaction = VerifiedTransaction::new_randomness_state_update(
6481            epoch,
6482            round,
6483            bytes,
6484            epoch_store
6485                .epoch_start_config()
6486                .randomness_obj_initial_shared_version(),
6487        );
6488        debug!(
6489            "created randomness state update transaction with digest: {:?}",
6490            transaction.digest()
6491        );
6492        let transaction = VerifiedExecutableTransaction::new_system(transaction, epoch);
6493        let digest = *transaction.digest();
6494
6495        // Randomness state updates contain the full bls signature for the random round,
6496        // which cannot necessarily be reconstructed again later. Therefore we must
6497        // immediately persist this transaction. If we crash before its outputs
6498        // are committed, this ensures we will be able to re-execute it.
6499        self.authority_state
6500            .get_cache_commit()
6501            .persist_transaction(&transaction);
6502
6503        // Notify the scheduler that the transaction key now has a known digest
6504        if epoch_store.insert_tx_key(key, digest).is_err() {
6505            warn!("epoch ended while handling new randomness");
6506        }
6507
6508        // TODO: delete this when transaction manager is deleted
6509        match self.authority_state.execution_scheduler().as_ref() {
6510            ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
6511            ExecutionSchedulerWrapper::TransactionManager(manager) => {
6512                // Notifies transaction manager about transaction and output objects
6513                // committed. This provides necessary information to transaction manager
6514                // to start executing additional ready transactions.
6515                manager.notify_transaction_key(&epoch_store, key, digest);
6516            }
6517        }
6518
6519        let authority_state = self.authority_state.clone();
6520        spawn_monitored_task!(async move {
6521            // Wait for transaction execution in a separate task, to avoid deadlock in case
6522            // of out-of-order randomness generation. (Each
6523            // RandomnessStateUpdate depends on the output of the
6524            // RandomnessStateUpdate from the previous round.)
6525            //
6526            // We set a very long timeout so that in case this gets stuck for some reason,
6527            // the validator will eventually crash rather than continuing in a
6528            // zombie mode.
6529            const RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT: Duration = Duration::from_secs(300);
6530            let result = tokio::time::timeout(
6531                RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT,
6532                authority_state
6533                    .get_transaction_cache_reader()
6534                    .try_notify_read_executed_effects(
6535                        "RandomnessRoundReceiver::notify_read_executed_effects_first",
6536                        &[digest],
6537                    ),
6538            )
6539            .await;
6540            let result = match result {
6541                Ok(result) => result,
6542                Err(_) => {
6543                    if cfg!(debug_assertions) {
6544                        // Crash on randomness update execution timeout in debug builds.
6545                        panic!(
6546                            "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6547                        );
6548                    }
6549                    warn!(
6550                        "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6551                    );
6552                    // Continue waiting as long as necessary in non-debug builds.
6553                    authority_state
6554                        .get_transaction_cache_reader()
6555                        .try_notify_read_executed_effects(
6556                            "RandomnessRoundReceiver::notify_read_executed_effects_second",
6557                            &[digest],
6558                        )
6559                        .await
6560                }
6561            };
6562
6563            let mut effects = result.unwrap_or_else(|_| panic!("failed to get effects for randomness state update transaction at epoch {epoch}, round {round}"));
6564            let effects = effects.pop().expect("should return effects");
6565            if *effects.status() != ExecutionStatus::Success {
6566                fatal!(
6567                    "failed to execute randomness state update transaction at epoch {epoch}, round {round}: {effects:?}"
6568                );
6569            }
6570            debug!(
6571                "successfully executed randomness state update transaction at epoch {epoch}, round {round}"
6572            );
6573        });
6574    }
6575}
6576
6577#[async_trait]
6578impl TransactionKeyValueStoreTrait for AuthorityState {
6579    async fn multi_get(
6580        &self,
6581        transaction_keys: &[TransactionDigest],
6582        effects_keys: &[TransactionDigest],
6583    ) -> IotaResult<KVStoreTransactionData> {
6584        let txns = if !transaction_keys.is_empty() {
6585            self.get_transaction_cache_reader()
6586                .try_multi_get_transaction_blocks(transaction_keys)?
6587                .into_iter()
6588                .map(|t| t.map(|t| (*t).clone().into_inner()))
6589                .collect()
6590        } else {
6591            vec![]
6592        };
6593
6594        let fx = if !effects_keys.is_empty() {
6595            self.get_transaction_cache_reader()
6596                .try_multi_get_executed_effects(effects_keys)?
6597        } else {
6598            vec![]
6599        };
6600
6601        Ok((txns, fx))
6602    }
6603
6604    async fn multi_get_checkpoints(
6605        &self,
6606        checkpoint_summaries: &[CheckpointSequenceNumber],
6607        checkpoint_contents: &[CheckpointSequenceNumber],
6608        checkpoint_summaries_by_digest: &[CheckpointDigest],
6609    ) -> IotaResult<(
6610        Vec<Option<CertifiedCheckpointSummary>>,
6611        Vec<Option<CheckpointContents>>,
6612        Vec<Option<CertifiedCheckpointSummary>>,
6613    )> {
6614        // TODO: use multi-get methods if it ever becomes important (unlikely)
6615        let mut summaries = Vec::with_capacity(checkpoint_summaries.len());
6616        let store = self.get_checkpoint_store();
6617        for seq in checkpoint_summaries {
6618            let checkpoint = store
6619                .get_checkpoint_by_sequence_number(*seq)?
6620                .map(|c| c.into_inner());
6621
6622            summaries.push(checkpoint);
6623        }
6624
6625        let mut contents = Vec::with_capacity(checkpoint_contents.len());
6626        for seq in checkpoint_contents {
6627            let checkpoint = store
6628                .get_checkpoint_by_sequence_number(*seq)?
6629                .and_then(|summary| {
6630                    store
6631                        .get_checkpoint_contents(&summary.contents_digest)
6632                        .expect("db read cannot fail")
6633                });
6634            contents.push(checkpoint);
6635        }
6636
6637        let mut summaries_by_digest = Vec::with_capacity(checkpoint_summaries_by_digest.len());
6638        for digest in checkpoint_summaries_by_digest {
6639            let checkpoint = store
6640                .get_checkpoint_by_digest(digest)?
6641                .map(|c| c.into_inner());
6642            summaries_by_digest.push(checkpoint);
6643        }
6644
6645        Ok((summaries, contents, summaries_by_digest))
6646    }
6647
6648    async fn get_transaction_perpetual_checkpoint(
6649        &self,
6650        digest: TransactionDigest,
6651    ) -> IotaResult<Option<CheckpointSequenceNumber>> {
6652        self.get_checkpoint_cache()
6653            .try_get_transaction_perpetual_checkpoint(&digest)
6654            .map(|res| res.map(|(_epoch, checkpoint)| checkpoint))
6655    }
6656
6657    async fn get_object(
6658        &self,
6659        object_id: ObjectId,
6660        version: VersionNumber,
6661    ) -> IotaResult<Option<Object>> {
6662        self.get_object_cache_reader()
6663            .try_get_object_by_key(&object_id, version)
6664    }
6665
6666    #[instrument(skip_all)]
6667    async fn multi_get_objects(
6668        &self,
6669        object_keys: &[ObjectKey],
6670    ) -> IotaResult<Vec<Option<Object>>> {
6671        Ok(self
6672            .get_object_cache_reader()
6673            .multi_get_objects_by_key(object_keys))
6674    }
6675
6676    async fn multi_get_transactions_perpetual_checkpoints(
6677        &self,
6678        digests: &[TransactionDigest],
6679    ) -> IotaResult<Vec<Option<CheckpointSequenceNumber>>> {
6680        let res = self
6681            .get_checkpoint_cache()
6682            .try_multi_get_transactions_perpetual_checkpoints(digests)?;
6683
6684        Ok(res
6685            .into_iter()
6686            .map(|maybe| maybe.map(|(_epoch, checkpoint)| checkpoint))
6687            .collect())
6688    }
6689
6690    #[instrument(skip(self, digests), fields(digests = digests.iter().map(|d| d.to_string()).collect::<Vec<String>>().join(", ")))]
6691    async fn multi_get_events_by_tx_digests(
6692        &self,
6693        digests: &[TransactionDigest],
6694    ) -> IotaResult<Vec<Option<TransactionEvents>>> {
6695        if digests.is_empty() {
6696            return Ok(vec![]);
6697        }
6698
6699        Ok(self
6700            .get_transaction_cache_reader()
6701            .multi_get_events(digests))
6702    }
6703}
6704
6705#[cfg(msim)]
6706pub mod framework_injection {
6707    use std::{
6708        cell::RefCell,
6709        collections::{BTreeMap, BTreeSet},
6710    };
6711
6712    use iota_framework::{BuiltInFramework, SystemPackage};
6713    use iota_sdk_types::ObjectId;
6714    use iota_types::base_types::AuthorityName;
6715    use move_binary_format::CompiledModule;
6716
6717    type FrameworkOverrideConfig = BTreeMap<ObjectId, PackageOverrideConfig>;
6718
6719    // Thread local cache because all simtests run in a single unique thread.
6720    thread_local! {
6721        static OVERRIDE: RefCell<FrameworkOverrideConfig> = RefCell::new(FrameworkOverrideConfig::default());
6722    }
6723
6724    type Framework = Vec<CompiledModule>;
6725
6726    pub type PackageUpgradeCallback =
6727        Box<dyn Fn(AuthorityName) -> Option<Framework> + Send + Sync + 'static>;
6728
6729    enum PackageOverrideConfig {
6730        Global(Framework),
6731        PerValidator(PackageUpgradeCallback),
6732    }
6733
6734    fn compiled_modules_to_bytes(modules: &[CompiledModule]) -> Vec<Vec<u8>> {
6735        modules
6736            .iter()
6737            .map(|m| {
6738                let mut buf = Vec::new();
6739                m.serialize_with_version(m.version, &mut buf).unwrap();
6740                buf
6741            })
6742            .collect()
6743    }
6744
6745    pub fn set_override(package_id: ObjectId, modules: Vec<CompiledModule>) {
6746        OVERRIDE.with(|bs| {
6747            bs.borrow_mut()
6748                .insert(package_id, PackageOverrideConfig::Global(modules))
6749        });
6750    }
6751
6752    pub fn set_override_cb(package_id: ObjectId, func: PackageUpgradeCallback) {
6753        OVERRIDE.with(|bs| {
6754            bs.borrow_mut()
6755                .insert(package_id, PackageOverrideConfig::PerValidator(func))
6756        });
6757    }
6758
6759    pub fn get_override_bytes(package_id: &ObjectId, name: AuthorityName) -> Option<Vec<Vec<u8>>> {
6760        OVERRIDE.with(|cfg| {
6761            cfg.borrow().get(package_id).and_then(|entry| match entry {
6762                PackageOverrideConfig::Global(framework) => {
6763                    Some(compiled_modules_to_bytes(framework))
6764                }
6765                PackageOverrideConfig::PerValidator(func) => {
6766                    func(name).map(|fw| compiled_modules_to_bytes(&fw))
6767                }
6768            })
6769        })
6770    }
6771
6772    pub fn get_override_modules(
6773        package_id: &ObjectId,
6774        name: AuthorityName,
6775    ) -> Option<Vec<CompiledModule>> {
6776        OVERRIDE.with(|cfg| {
6777            cfg.borrow().get(package_id).and_then(|entry| match entry {
6778                PackageOverrideConfig::Global(framework) => Some(framework.clone()),
6779                PackageOverrideConfig::PerValidator(func) => func(name),
6780            })
6781        })
6782    }
6783
6784    pub fn get_override_system_package(
6785        package_id: &ObjectId,
6786        name: AuthorityName,
6787    ) -> Option<SystemPackage> {
6788        let bytes = get_override_bytes(package_id, name)?;
6789        // A built-in package keeps the dependencies it declares. Anything else is a
6790        // package being added -- including one at a system address that is not built in
6791        // yet -- and is assumed to depend on all existing system packages.
6792        let dependencies = BuiltInFramework::try_get_package_by_id(package_id)
6793            .map_or_else(BuiltInFramework::all_package_ids, |package| {
6794                package.dependencies.to_vec()
6795            });
6796        Some(SystemPackage {
6797            id: *package_id,
6798            bytes,
6799            dependencies,
6800        })
6801    }
6802
6803    pub fn get_extra_packages(name: AuthorityName) -> Vec<SystemPackage> {
6804        let built_in = BTreeSet::from_iter(BuiltInFramework::all_package_ids());
6805        let extra: Vec<ObjectId> = OVERRIDE.with(|cfg| {
6806            cfg.borrow()
6807                .keys()
6808                .filter_map(|package| (!built_in.contains(package)).then_some(*package))
6809                .collect()
6810        });
6811
6812        extra
6813            .into_iter()
6814            .map(|package| SystemPackage {
6815                id: package,
6816                bytes: get_override_bytes(&package, name).unwrap(),
6817                dependencies: BuiltInFramework::all_package_ids(),
6818            })
6819            .collect()
6820    }
6821}
6822
6823#[derive(Debug, Serialize, Deserialize, Clone)]
6824pub struct ObjDumpFormat {
6825    pub id: ObjectId,
6826    pub version: VersionNumber,
6827    pub digest: ObjectDigest,
6828    pub object: Object,
6829}
6830
6831impl ObjDumpFormat {
6832    fn new(object: Object) -> Self {
6833        let oref = object.object_ref();
6834        Self {
6835            id: oref.object_id,
6836            version: oref.version,
6837            digest: oref.digest,
6838            object,
6839        }
6840    }
6841}
6842
6843#[derive(Debug, Serialize, Deserialize, Clone)]
6844pub struct NodeStateDump {
6845    pub tx_digest: TransactionDigest,
6846    pub sender_signed_data: SenderSignedTransaction,
6847    pub executed_epoch: u64,
6848    pub reference_gas_price: u64,
6849    pub protocol_version: u64,
6850    pub epoch_start_timestamp_ms: u64,
6851    pub computed_effects: TransactionEffects,
6852    pub expected_effects_digest: TransactionEffectsDigest,
6853    pub relevant_system_packages: Vec<ObjDumpFormat>,
6854    pub shared_objects: Vec<ObjDumpFormat>,
6855    pub loaded_child_objects: Vec<ObjDumpFormat>,
6856    pub modified_at_versions: Vec<ObjDumpFormat>,
6857    pub runtime_reads: Vec<ObjDumpFormat>,
6858    pub input_objects: Vec<ObjDumpFormat>,
6859}
6860
6861impl NodeStateDump {
6862    pub fn new(
6863        tx_digest: &TransactionDigest,
6864        effects: &TransactionEffects,
6865        expected_effects_digest: TransactionEffectsDigest,
6866        object_store: &dyn ObjectStore,
6867        epoch_store: &Arc<AuthorityPerEpochStore>,
6868        inner_temporary_store: &InnerTemporaryStore,
6869        transaction: &VerifiedExecutableTransaction,
6870    ) -> IotaResult<Self> {
6871        // Epoch info
6872        let executed_epoch = epoch_store.epoch();
6873        let reference_gas_price = epoch_store.reference_gas_price();
6874        let epoch_start_config = epoch_store.epoch_start_config();
6875        let protocol_version = epoch_store.protocol_version().as_u64();
6876        let epoch_start_timestamp_ms = epoch_start_config.epoch_data().epoch_start_timestamp();
6877
6878        // Record all system packages at this version
6879        let mut relevant_system_packages = Vec::new();
6880        for sys_package_id in BuiltInFramework::all_package_ids() {
6881            if let Some(w) = object_store.try_get_object(&sys_package_id)? {
6882                relevant_system_packages.push(ObjDumpFormat::new(w))
6883            }
6884        }
6885
6886        // Record all the shared objects
6887        let mut shared_objects = Vec::new();
6888        for kind in effects.input_shared_objects() {
6889            match kind {
6890                InputSharedObject::Mutate(obj_ref) | InputSharedObject::ReadOnly(obj_ref) => {
6891                    if let Some(w) =
6892                        object_store.try_get_object_by_key(&obj_ref.object_id, obj_ref.version)?
6893                    {
6894                        shared_objects.push(ObjDumpFormat::new(w))
6895                    }
6896                }
6897                InputSharedObject::ReadDeleted(..)
6898                | InputSharedObject::MutateDeleted(..)
6899                // TODO: consider record congested objects.
6900                | InputSharedObject::Canceled(..) => (),
6901                _ => unimplemented!(
6902                    "a new InputSharedObject enum variant was added and needs to be handled"
6903                ),
6904            }
6905        }
6906
6907        // Record all loaded child objects
6908        // Child objects which are read but not mutated are not tracked anywhere else
6909        let mut loaded_child_objects = Vec::new();
6910        for (id, meta) in &inner_temporary_store.loaded_runtime_objects {
6911            if let Some(w) = object_store.try_get_object_by_key(id, meta.version)? {
6912                loaded_child_objects.push(ObjDumpFormat::new(w))
6913            }
6914        }
6915
6916        // Record all modified objects
6917        let mut modified_at_versions = Vec::new();
6918        for modified in effects.modified_at_versions() {
6919            let (id, ver) = (modified.object_id(), modified.version());
6920            if let Some(w) = object_store.try_get_object_by_key(id, ver)? {
6921                modified_at_versions.push(ObjDumpFormat::new(w))
6922            }
6923        }
6924
6925        // Packages read at runtime, which were not previously loaded into the temoorary
6926        // store Some packages may be fetched at runtime and wont show up in
6927        // input objects
6928        let mut runtime_reads = Vec::new();
6929        for obj in inner_temporary_store
6930            .runtime_packages_loaded_from_db
6931            .values()
6932        {
6933            runtime_reads.push(ObjDumpFormat::new(obj.object().clone()));
6934        }
6935
6936        // All other input objects should already be in `inner_temporary_store.objects`
6937
6938        Ok(Self {
6939            tx_digest: *tx_digest,
6940            executed_epoch,
6941            reference_gas_price,
6942            epoch_start_timestamp_ms,
6943            protocol_version,
6944            relevant_system_packages,
6945            shared_objects,
6946            loaded_child_objects,
6947            modified_at_versions,
6948            runtime_reads,
6949            sender_signed_data: transaction.clone().into_message(),
6950            input_objects: inner_temporary_store
6951                .input_objects
6952                .values()
6953                .map(|o| ObjDumpFormat::new(o.clone()))
6954                .collect(),
6955            computed_effects: effects.clone(),
6956            expected_effects_digest,
6957        })
6958    }
6959
6960    pub fn all_objects(&self) -> Vec<ObjDumpFormat> {
6961        let mut objects = Vec::new();
6962        objects.extend(self.relevant_system_packages.clone());
6963        objects.extend(self.shared_objects.clone());
6964        objects.extend(self.loaded_child_objects.clone());
6965        objects.extend(self.modified_at_versions.clone());
6966        objects.extend(self.runtime_reads.clone());
6967        objects.extend(self.input_objects.clone());
6968        objects
6969    }
6970
6971    pub fn write_to_file(&self, path: &Path) -> Result<PathBuf, anyhow::Error> {
6972        let file_name = format!(
6973            "{}_{}_NODE_DUMP.json",
6974            self.tx_digest,
6975            AuthorityState::unixtime_now_ms()
6976        );
6977        let mut path = path.to_path_buf();
6978        path.push(&file_name);
6979        let mut file = File::create(path.clone())?;
6980        file.write_all(serde_json::to_string_pretty(self)?.as_bytes())?;
6981        Ok(path)
6982    }
6983
6984    pub fn read_from_file(path: &PathBuf) -> Result<Self, anyhow::Error> {
6985        let file = File::open(path)?;
6986        serde_json::from_reader(file).map_err(|e| anyhow::anyhow!(e))
6987    }
6988}
6989
6990/// The reason [`AuthorityState::check_move_account`] failed.
6991/// Execution treats the two cases differently, because only
6992/// the first one is about the transaction.
6993enum MoveAccountCheckError {
6994    /// The account fails a check.
6995    Input(UserInputError),
6996
6997    /// This validator failed to read its store.
6998    Storage(IotaError),
6999}
7000
7001impl From<UserInputError> for MoveAccountCheckError {
7002    fn from(error: UserInputError) -> Self {
7003        Self::Input(error)
7004    }
7005}
7006
7007impl From<MoveAccountCheckError> for IotaError {
7008    fn from(error: MoveAccountCheckError) -> Self {
7009        match error {
7010            MoveAccountCheckError::Input(error) => IotaError::UserInput { error },
7011            MoveAccountCheckError::Storage(error) => error,
7012        }
7013    }
7014}
7015
7016/// Returns the [`MoveAuthenticator`]s to execute during the pre-consensus
7017/// phase.
7018///
7019/// When `pre_consensus_sponsor_only_move_authentication` is enabled:
7020/// - For sponsored transactions: only the sponsor's [`MoveAuthenticator`] is returned (empty if the
7021///   sponsor does not use one).
7022/// - For non-sponsored transactions: all [`MoveAuthenticator`]s are returned (currently only the
7023///   sender's).
7024///
7025/// When the flag is not set, all [`MoveAuthenticator`]s are returned for
7026/// compatibility.
7027fn pre_consensus_move_authenticators<'a>(
7028    tx: &'a VerifiedTransaction,
7029    protocol_config: &ProtocolConfig,
7030) -> Vec<&'a MoveAuthenticator> {
7031    if protocol_config.pre_consensus_sponsor_only_move_authentication() {
7032        if tx.transaction().is_sponsored_tx() {
7033            if let Some(sponsor_move_authenticator) = tx.sponsor_move_authenticator() {
7034                vec![sponsor_move_authenticator]
7035            } else {
7036                vec![]
7037            }
7038        } else {
7039            tx.move_authenticators()
7040        }
7041    } else {
7042        tx.move_authenticators()
7043    }
7044}