Skip to main content

iota_core/
authority.rs

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