Skip to main content

iota_core/
authority.rs

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