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