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