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