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