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