Skip to main content

sui_core/
authority.rs

1// Copyright (c) 2021, Facebook, Inc. and its affiliates
2// Copyright (c) Mysten Labs, Inc.
3// SPDX-License-Identifier: Apache-2.0
4
5use crate::accumulators::coin_reservations::CachingCoinReservationResolver;
6use crate::accumulators::funds_read::AccountFundsRead;
7use crate::accumulators::object_funds_checker::ObjectFundsCheckerDEPRECATED;
8use crate::accumulators::object_funds_checker::metrics::ObjectFundsCheckerMetrics;
9use crate::accumulators::transaction_rewriting::rewrite_transaction_for_coin_reservations;
10use crate::accumulators::unsettled_object_withdrawals::UnsettledObjectWithdrawals;
11use crate::accumulators::{self, AccumulatorSettlementTxBuilder};
12use crate::checkpoints::CheckpointBuilderError;
13use crate::checkpoints::CheckpointBuilderResult;
14use crate::congestion_tracker::CongestionTracker;
15use crate::execution_cache::ExecutionCacheTraitPointers;
16use crate::execution_cache::TransactionCacheRead;
17use crate::execution_cache::writeback_cache::WritebackCache;
18use crate::execution_scheduler::ExecutionScheduler;
19use crate::execution_scheduler::funds_withdraw_scheduler::FundsSettlement;
20use crate::gasless_rate_limiter::ConsensusGaslessCounter;
21use crate::traffic_controller::TrafficController;
22use crate::traffic_controller::metrics::TrafficControllerMetrics;
23use crate::transaction_deny_config_manager::TransactionDenyConfigManager;
24use crate::transaction_outputs::TransactionOutputs;
25use arc_swap::{ArcSwap, ArcSwapOption, Guard};
26use authority_per_epoch_store::CertLockGuard;
27use fastcrypto::encoding::Base58;
28use fastcrypto::encoding::Encoding;
29use fastcrypto::hash::MultisetHash;
30use itertools::Itertools;
31use move_binary_format::CompiledModule;
32use move_binary_format::binary_config::BinaryConfig;
33use move_core_types::annotated_value::MoveStructLayout;
34use move_core_types::language_storage::ModuleId;
35use mysten_common::ZipDebugEqIteratorExt;
36use mysten_common::{assert_reachable, fatal};
37use parking_lot::Mutex;
38use prometheus::{
39    Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, Registry,
40    register_histogram_vec_with_registry, register_histogram_with_registry,
41    register_int_counter_vec_with_registry, register_int_counter_with_registry,
42    register_int_gauge_vec_with_registry, register_int_gauge_with_registry,
43};
44use serde::{Deserialize, Serialize};
45use shared_object_version_manager::AssignedVersions;
46use shared_object_version_manager::Schedulable;
47use std::collections::BTreeMap;
48use std::collections::BTreeSet;
49use std::fs::File;
50use std::io::Write;
51use std::path::{Path, PathBuf};
52use std::sync::atomic::Ordering;
53use std::time::Duration;
54use std::time::Instant;
55use std::time::SystemTime;
56use std::time::UNIX_EPOCH;
57use std::{
58    collections::{HashMap, HashSet},
59    fs,
60    pin::Pin,
61    str::FromStr,
62    sync::Arc,
63    vec,
64};
65use sui_config::NodeConfig;
66use sui_config::node::{AuthorityOverloadConfig, StateDebugDumpConfig};
67use sui_config::transaction_deny_config::TransactionDenyConfig;
68use sui_execution::Executor;
69use sui_protocol_config::PerObjectCongestionControlMode;
70use sui_protocol_config::assert_reachable_gated;
71use sui_types::accumulator_root::AccumulatorObjId;
72use sui_types::accumulator_root::UnsettledObjectFundsRead;
73use sui_types::base_types::SystemObjectVersions;
74use sui_types::execution::ExecutionOutput;
75use sui_types::execution::ExecutionTimeObservationKey;
76use sui_types::execution::ExecutionTiming;
77use sui_types::execution_params::ExecutionOrEarlyError;
78use sui_types::execution_params::FundsWithdrawStatus;
79use sui_types::execution_params::get_early_execution_error;
80use sui_types::layout_resolver::into_struct_layout;
81use sui_types::messages_consensus::AuthorityCapabilitiesV2;
82use sui_types::node_role::NodeRole;
83use sui_types::storage::InputKey;
84use sui_types::storage::RuntimeObjectResolver;
85use sui_types::storage::TrackingBackingStore;
86use sui_types::traffic_control::{
87    PolicyConfig, RemoteFirewallConfig, TrafficControlReconfigParams,
88};
89use sui_types::transaction_executor::SimulateTransactionResult;
90use sui_types::transaction_executor::TransactionChecks;
91use sui_types::{SUI_ACCUMULATOR_ROOT_OBJECT_ID, accumulator_metadata};
92use tap::TapFallible;
93use tokio::sync::RwLock;
94use tokio::sync::mpsc::unbounded_channel;
95use tokio::sync::oneshot;
96use tokio::sync::watch::error::RecvError;
97use tokio::time::timeout;
98use tracing::{debug, error, info, instrument, warn};
99
100use self::authority_store::ExecutionLockWriteGuard;
101use self::authority_store_pruner::{AuthorityStorePruningMetrics, PrunerWatermarks};
102pub use authority_store::{AuthorityStore, ResolverWrapper};
103use mysten_metrics::{monitored_scope, spawn_monitored_task};
104
105use mysten_common::debug_fatal;
106use shared_crypto::intent::{Intent, IntentScope};
107use sui_config::genesis::Genesis;
108use sui_config::node::{DBCheckpointConfig, ExpensiveSafetyCheckConfig};
109use sui_framework::{BuiltInFramework, SystemPackage};
110use sui_macros::{fail_point, fail_point_arg, fail_point_async, fail_point_if};
111use sui_rpc_store::Store as RpcStore;
112use sui_types::authenticator_state::get_authenticator_state;
113use sui_types::coin_reservation::CoinReservationResolverTrait;
114use sui_types::committee::{EpochId, ProtocolVersion};
115use sui_types::crypto::{AuthoritySignInfo, Signer};
116use sui_types::deny_list_v1::check_coin_deny_list_v1;
117use sui_types::digests::ChainIdentifier;
118use sui_types::effects::{
119    InputConsensusObject, SignedTransactionEffects, TransactionEffects, TransactionEffectsAPI,
120    TransactionEvents, VerifiedSignedTransactionEffects,
121};
122use sui_types::error::{ExecutionError, SuiErrorKind, UserInputError};
123use sui_types::executable_transaction::VerifiedExecutableTransaction;
124use sui_types::execution_status::ExecutionStatus;
125use sui_types::gas::{GasCostSummary, SuiGasStatus};
126use sui_types::inner_temporary_store::InnerTemporaryStore;
127use sui_types::message_envelope::Message;
128use sui_types::messages_checkpoint::{
129    CheckpointCommitment, CheckpointContents, CheckpointContentsDigest, CheckpointDigest,
130    CheckpointRequest, CheckpointRequestV2, CheckpointResponse, CheckpointResponseV2,
131    CheckpointSequenceNumber, CheckpointSummary, CheckpointSummaryResponse, CheckpointTimestamp,
132    ECMHLiveObjectSetDigest, VerifiedCheckpoint,
133};
134use sui_types::messages_grpc::{
135    LayoutGenerationOption, ObjectInfoRequest, ObjectInfoRequestKind, ObjectInfoResponse,
136    TransactionInfoRequest, TransactionInfoResponse, TransactionStatus,
137};
138use sui_types::metrics::{BytecodeVerifierMetrics, ExecutionMetrics};
139#[cfg(test)]
140use sui_types::object::MoveObject;
141use sui_types::object::{OBJECT_START_VERSION, Owner, PastObjectRead};
142use sui_types::signature::GenericSignature;
143use sui_types::storage::{
144    BackingPackageStore, BackingStore, ObjectKey, ObjectOrTombstone, ObjectStore,
145};
146use sui_types::sui_system_state::SuiSystemStateTrait;
147use sui_types::sui_system_state::epoch_start_sui_system_state::EpochStartSystemStateTrait;
148use sui_types::sui_system_state::{SuiSystemState, get_sui_system_state};
149use sui_types::supported_protocol_versions::{ProtocolConfig, SupportedProtocolVersions};
150use sui_types::{
151    SUI_SYSTEM_ADDRESS,
152    base_types::*,
153    committee::Committee,
154    crypto::AuthoritySignature,
155    error::{SuiError, SuiResult},
156    object::{Object, ObjectRead},
157    transaction::*,
158};
159use sui_types::{TypeTag, is_system_package};
160use typed_store::TypedStoreError;
161
162use crate::authority::authority_per_epoch_store::{AuthorityPerEpochStore, CertTxGuard};
163use crate::authority::authority_per_epoch_store_pruner::AuthorityPerEpochStorePruner;
164use crate::authority::authority_store::ExecutionLockReadGuard;
165use crate::authority::authority_store_pruner::{
166    AuthorityStorePruner, EPOCH_DURATION_MS_FOR_TESTING,
167};
168use crate::authority::epoch_start_configuration::EpochStartConfigTrait;
169use crate::authority::epoch_start_configuration::EpochStartConfiguration;
170use crate::checkpoints::CheckpointStore;
171use crate::epoch::committee_store::CommitteeStore;
172use crate::execution_cache::{
173    CheckpointCache, ExecutionCacheCommit, ExecutionCacheReconfigAPI, ExecutionCacheWrite,
174    ObjectCacheRead, StateSyncAPI,
175};
176use crate::execution_driver::execution_process;
177use crate::global_state_hasher::{GlobalStateHashStore, GlobalStateHasher, WrappedObject};
178use crate::metrics::LatencyObserver;
179use crate::metrics::RateTracker;
180use crate::module_cache_metrics::ResolverMetrics;
181use crate::overload_monitor::{AuthorityOverloadInfo, overload_monitor_accept_tx};
182use crate::stake_aggregator::StakeAggregator;
183use crate::transaction_input_loader::TransactionInputLoader;
184
185#[cfg(msim)]
186pub use crate::checkpoints::checkpoint_executor::utils::{
187    CheckpointTimeoutConfig, init_checkpoint_timeout_config,
188};
189
190#[cfg(msim)]
191use sui_types::committee::CommitteeTrait;
192use sui_types::deny_list_v2::check_coin_deny_list_v2_during_signing;
193
194#[cfg(test)]
195#[path = "unit_tests/authority_tests.rs"]
196pub mod authority_tests;
197
198#[cfg(test)]
199#[path = "unit_tests/transaction_tests.rs"]
200pub mod transaction_tests;
201
202#[cfg(test)]
203#[path = "unit_tests/batch_transaction_tests.rs"]
204mod batch_transaction_tests;
205
206#[cfg(test)]
207#[path = "unit_tests/move_integration_tests.rs"]
208pub mod move_integration_tests;
209
210#[cfg(test)]
211#[path = "unit_tests/gas_tests.rs"]
212mod gas_tests;
213
214#[cfg(test)]
215#[path = "unit_tests/gas_data_tests.rs"]
216mod gas_data_tests;
217
218#[cfg(test)]
219#[path = "unit_tests/batch_verification_tests.rs"]
220mod batch_verification_tests;
221
222#[cfg(test)]
223#[path = "unit_tests/coin_deny_list_tests.rs"]
224mod coin_deny_list_tests;
225
226#[cfg(test)]
227#[path = "unit_tests/auth_unit_test_utils.rs"]
228pub mod auth_unit_test_utils;
229
230pub mod authority_test_utils;
231
232pub mod authority_per_epoch_store;
233pub mod authority_per_epoch_store_pruner;
234
235pub mod authority_store_pruner;
236pub mod authority_store_tables;
237pub mod authority_store_types;
238pub mod congestion_log;
239pub mod consensus_tx_status_cache;
240pub(crate) mod epoch_marker_key;
241pub mod epoch_start_configuration;
242pub mod execution_time_estimator;
243pub mod finalized_transactions_cache;
244pub mod shared_object_congestion_tracker;
245pub mod shared_object_version_manager;
246pub mod submitted_transaction_cache;
247pub mod test_authority_builder;
248pub mod transaction_deferral;
249pub mod transaction_reject_reason_cache;
250mod weighted_moving_average;
251
252pub(crate) mod authority_store;
253pub mod backpressure;
254
255/// Prometheus metrics which can be displayed in Grafana, queried and alerted on
256pub struct AuthorityMetrics {
257    tx_orders: IntCounter,
258    total_certs: IntCounter,
259    total_effects: IntCounter,
260    // TODO: this tracks consensus object tx, not just shared. Consider renaming.
261    pub shared_obj_tx: IntCounter,
262    sponsored_tx: IntCounter,
263    num_input_objs: Histogram,
264    // TODO: this tracks consensus object count, not just shared. Consider renaming.
265    num_shared_objects: Histogram,
266    batch_size: Histogram,
267
268    authority_state_handle_vote_transaction_latency: Histogram,
269
270    internal_execution_latency: Histogram,
271    /// Number of times the validator refused to report effects (signed or unsigned, labeled by
272    /// RPC surface) because it had previously signed different effects for the same transaction.
273    signed_effects_equivocation_prevented: IntCounterVec,
274    execution_load_input_objects_latency: Histogram,
275    prepare_certificate_latency: Histogram,
276    commit_certificate_latency: Histogram,
277    db_checkpoint_latency: Histogram,
278
279    // TODO: Rename these metrics.
280    pub(crate) transaction_manager_num_enqueued_certificates: IntCounterVec,
281    pub(crate) transaction_manager_num_pending_certificates: IntGauge,
282    pub(crate) transaction_manager_num_executing_certificates: IntGauge,
283    pub(crate) transaction_manager_transaction_queue_age_s: Histogram,
284
285    pub(crate) execution_driver_executed_transactions: IntCounter,
286    pub(crate) execution_driver_paused_transactions: IntCounter,
287    pub(crate) execution_driver_dispatch_queue: IntGauge,
288    pub(crate) execution_queueing_delay_s: Histogram,
289    pub(crate) prepare_cert_gas_latency_ratio: Histogram,
290    pub(crate) execution_gas_latency_ratio: Histogram,
291
292    pub(crate) skipped_consensus_txns: IntCounter,
293    pub(crate) skipped_consensus_txns_cache_hit: IntCounter,
294    pub(crate) consensus_handler_duplicate_tx_count: Histogram,
295
296    pub(crate) authority_overload_status: IntGauge,
297    pub(crate) authority_load_shedding_percentage: IntGauge,
298
299    pub(crate) transaction_overload_sources: IntCounterVec,
300
301    /// Post processing metrics
302    /// Consensus commit and transaction handler metrics
303    pub consensus_handler_processed: IntCounterVec,
304    pub consensus_handler_processed_user_transactions: IntCounterVec,
305    pub consensus_handler_transaction_sizes: HistogramVec,
306    pub consensus_handler_max_transaction_size: IntGaugeVec,
307    pub consensus_handler_deferred_transactions: IntCounter,
308    pub consensus_handler_congested_transactions: IntCounter,
309    pub consensus_handler_unpaid_amplification_deferrals: IntCounter,
310    pub consensus_handler_double_spend_deferrals: IntCounter,
311    pub consensus_handler_double_spend_conflict_count: HistogramVec,
312    pub consensus_handler_double_spend_conflicting_authority: IntCounterVec,
313    pub consensus_handler_cancelled_transactions: IntCounter,
314    pub consensus_handler_dropped_transactions: IntCounterVec,
315    pub consensus_handler_max_object_costs: IntGaugeVec,
316    pub consensus_committed_subdags: IntCounterVec,
317    pub accumulator_deposits: IntCounter,
318    pub accumulator_withdrawals: IntCounter,
319    pub consensus_committed_messages: IntGaugeVec,
320    pub consensus_committed_user_transactions: IntGaugeVec,
321    pub consensus_finalized_user_transactions: IntGaugeVec,
322    pub consensus_rejected_user_transactions: IntGaugeVec,
323    pub consensus_dropped_user_transactions: IntGaugeVec,
324    pub consensus_calculated_throughput: IntGauge,
325    pub consensus_calculated_throughput_profile: IntGauge,
326    pub consensus_block_handler_block_processed: IntCounter,
327    pub consensus_block_handler_txn_processed: IntCounterVec,
328    pub consensus_block_handler_fastpath_executions: IntCounter,
329    pub consensus_timestamp_bias: Histogram,
330
331    pub execution_metrics: Arc<ExecutionMetrics>,
332
333    /// bytecode verifier metrics for tracking timeouts
334    pub bytecode_verifier_metrics: Arc<BytecodeVerifierMetrics>,
335
336    /// Count of zklogin signatures
337    pub zklogin_sig_count: IntCounter,
338    /// Count of multisig signatures
339    pub multisig_sig_count: IntCounter,
340
341    // Tracks recent average txn queueing delay between when it is ready for execution
342    // until it starts executing.
343    pub execution_queueing_latency: LatencyObserver,
344
345    // Tracks the rate of transactions become ready for execution in transaction manager.
346    // The need for the Mutex is that the tracker is updated in transaction manager and read
347    // in the overload_monitor. There should be low mutex contention because
348    // transaction manager is single threaded and the read rate in overload_monitor is
349    // low. In the case where transaction manager becomes multi-threaded, we can
350    // create one rate tracker per thread.
351    pub txn_ready_rate_tracker: Arc<Mutex<RateTracker>>,
352
353    // Tracks the rate of transactions starts execution in execution driver.
354    // Similar reason for using a Mutex here as to `txn_ready_rate_tracker`.
355    pub execution_rate_tracker: Arc<Mutex<RateTracker>>,
356}
357
358// Override default Prom buckets for positive numbers in 0-10M range
359const POSITIVE_INT_BUCKETS: &[f64] = &[
360    1., 2., 5., 7., 10., 20., 50., 70., 100., 200., 500., 700., 1000., 2000., 5000., 7000., 10000.,
361    20000., 50000., 70000., 100000., 200000., 500000., 700000., 1000000., 2000000., 5000000.,
362    7000000., 10000000.,
363];
364
365const CONSENSUS_TRANSACTION_SIZE_BUCKETS: &[f64] = &[
366    1., 2., 5., 7., 10., 20., 50., 70., 100., 200., 500., 700., 1000., 2000., 5000., 7000., 10000.,
367    20000., 50000., 70000., 100000., 150000., 200000., 250000., 300000., 500000., 700000.,
368    1000000., 2000000., 5000000., 7000000., 10000000.,
369];
370
371const LATENCY_SEC_BUCKETS: &[f64] = &[
372    0.0005, 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1., 2., 3., 4., 5., 6., 7., 8., 9.,
373    10., 20., 30., 60., 90.,
374];
375
376// Buckets for low latency samples. Starts from 10us.
377const LOW_LATENCY_SEC_BUCKETS: &[f64] = &[
378    0.00001, 0.00002, 0.00005, 0.0001, 0.0002, 0.0005, 0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1,
379    0.2, 0.5, 1., 2., 5., 10., 20., 50., 100.,
380];
381
382// Buckets for consensus timestamp bias in seconds.
383// We expect 200-300ms, so we cluster the buckets more tightly in that range.
384const TIMESTAMP_BIAS_SEC_BUCKETS: &[f64] = &[
385    -2.0, 0.0, 0.2, 0.22, 0.24, 0.26, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.45, 0.50, 0.80,
386    2.0, 10.0, 30.0,
387];
388
389const GAS_LATENCY_RATIO_BUCKETS: &[f64] = &[
390    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,
391    3000.0, 4000.0, 5000.0, 6000.0, 7000.0, 8000.0, 9000.0, 10000.0, 50000.0, 100000.0, 1000000.0,
392];
393
394pub const DEV_INSPECT_GAS_COIN_VALUE: u64 = 1_000_000_000_000_000_000;
395
396// Transaction author should have observed the input objects as finalized output,
397// so usually the wait does not need to be long.
398// When submitted by TransactionDriver, it will retry quickly if there is no return from this validator too.
399pub const WAIT_FOR_FASTPATH_INPUT_TIMEOUT: Duration = Duration::from_secs(2);
400
401impl AuthorityMetrics {
402    pub fn new(registry: &prometheus::Registry) -> AuthorityMetrics {
403        Self {
404            tx_orders: register_int_counter_with_registry!(
405                "total_transaction_orders",
406                "Total number of transaction orders",
407                registry,
408            )
409            .unwrap(),
410            total_certs: register_int_counter_with_registry!(
411                "total_transaction_certificates",
412                "Total number of transaction certificates handled",
413                registry,
414            )
415            .unwrap(),
416            // total_effects == total transactions finished
417            total_effects: register_int_counter_with_registry!(
418                "total_transaction_effects",
419                "Total number of transaction effects produced",
420                registry,
421            )
422            .unwrap(),
423
424            shared_obj_tx: register_int_counter_with_registry!(
425                "num_shared_obj_tx",
426                "Number of transactions involving shared objects",
427                registry,
428            )
429            .unwrap(),
430
431            sponsored_tx: register_int_counter_with_registry!(
432                "num_sponsored_tx",
433                "Number of sponsored transactions",
434                registry,
435            )
436            .unwrap(),
437
438            num_input_objs: register_histogram_with_registry!(
439                "num_input_objects",
440                "Distribution of number of input TX objects per TX",
441                POSITIVE_INT_BUCKETS.to_vec(),
442                registry,
443            )
444            .unwrap(),
445            num_shared_objects: register_histogram_with_registry!(
446                "num_shared_objects",
447                "Number of shared input objects per TX",
448                POSITIVE_INT_BUCKETS.to_vec(),
449                registry,
450            )
451            .unwrap(),
452            batch_size: register_histogram_with_registry!(
453                "batch_size",
454                "Distribution of size of transaction batch",
455                POSITIVE_INT_BUCKETS.to_vec(),
456                registry,
457            )
458            .unwrap(),
459            authority_state_handle_vote_transaction_latency: register_histogram_with_registry!(
460                "authority_state_handle_vote_transaction_latency",
461                "Latency of voting on transactions without signing",
462                LATENCY_SEC_BUCKETS.to_vec(),
463                registry,
464            )
465            .unwrap(),
466            internal_execution_latency: register_histogram_with_registry!(
467                "authority_state_internal_execution_latency",
468                "Latency of actual certificate executions",
469                LATENCY_SEC_BUCKETS.to_vec(),
470                registry,
471            )
472            .unwrap(),
473            signed_effects_equivocation_prevented: register_int_counter_vec_with_registry!(
474                "authority_state_signed_effects_equivocation_prevented",
475                "Number of times the validator refused to report effects that differ from previously signed effects for the same transaction, by RPC surface",
476                &["surface"],
477                registry,
478            )
479            .unwrap(),
480            execution_load_input_objects_latency: register_histogram_with_registry!(
481                "authority_state_execution_load_input_objects_latency",
482                "Latency of loading input objects for execution",
483                LOW_LATENCY_SEC_BUCKETS.to_vec(),
484                registry,
485            )
486            .unwrap(),
487            prepare_certificate_latency: register_histogram_with_registry!(
488                "authority_state_prepare_certificate_latency",
489                "Latency of executing certificates, before committing the results",
490                LATENCY_SEC_BUCKETS.to_vec(),
491                registry,
492            )
493            .unwrap(),
494            commit_certificate_latency: register_histogram_with_registry!(
495                "authority_state_commit_certificate_latency",
496                "Latency of committing certificate execution results",
497                LATENCY_SEC_BUCKETS.to_vec(),
498                registry,
499            )
500            .unwrap(),
501            db_checkpoint_latency: register_histogram_with_registry!(
502                "db_checkpoint_latency",
503                "Latency of checkpointing dbs",
504                LATENCY_SEC_BUCKETS.to_vec(),
505                registry,
506            ).unwrap(),
507            transaction_manager_num_enqueued_certificates: register_int_counter_vec_with_registry!(
508                "transaction_manager_num_enqueued_certificates",
509                "Current number of certificates enqueued to ExecutionScheduler",
510                &["result"],
511                registry,
512            )
513            .unwrap(),
514            transaction_manager_num_pending_certificates: register_int_gauge_with_registry!(
515                "transaction_manager_num_pending_certificates",
516                "Number of certificates pending in ExecutionScheduler, with at least 1 missing input object",
517                registry,
518            )
519            .unwrap(),
520            transaction_manager_num_executing_certificates: register_int_gauge_with_registry!(
521                "transaction_manager_num_executing_certificates",
522                "Number of executing certificates, including queued and actually running certificates",
523                registry,
524            )
525            .unwrap(),
526            authority_overload_status: register_int_gauge_with_registry!(
527                "authority_overload_status",
528                "Whether authority is current experiencing overload and enters load shedding mode.",
529                registry)
530            .unwrap(),
531            authority_load_shedding_percentage: register_int_gauge_with_registry!(
532                "authority_load_shedding_percentage",
533                "The percentage of transactions is shed when the authority is in load shedding mode.",
534                registry)
535            .unwrap(),
536            transaction_manager_transaction_queue_age_s: register_histogram_with_registry!(
537                "transaction_manager_transaction_queue_age_s",
538                "Time spent in waiting for transaction in the queue",
539                LATENCY_SEC_BUCKETS.to_vec(),
540                registry,
541            )
542            .unwrap(),
543            transaction_overload_sources: register_int_counter_vec_with_registry!(
544                "transaction_overload_sources",
545                "Number of times each source indicates transaction overload.",
546                &["source"],
547                registry)
548            .unwrap(),
549            execution_driver_executed_transactions: register_int_counter_with_registry!(
550                "execution_driver_executed_transactions",
551                "Cumulative number of transaction executed by execution driver",
552                registry,
553            )
554            .unwrap(),
555            execution_driver_paused_transactions: register_int_counter_with_registry!(
556                "execution_driver_paused_transactions",
557                "Cumulative number of transactions paused by execution driver",
558                registry,
559            )
560            .unwrap(),
561            execution_driver_dispatch_queue: register_int_gauge_with_registry!(
562                "execution_driver_dispatch_queue",
563                "Number of transaction pending in execution driver dispatch queue",
564                registry,
565            )
566            .unwrap(),
567            execution_queueing_delay_s: register_histogram_with_registry!(
568                "execution_queueing_delay_s",
569                "Queueing delay between a transaction is ready for execution until it starts executing.",
570                LATENCY_SEC_BUCKETS.to_vec(),
571                registry
572            )
573            .unwrap(),
574            prepare_cert_gas_latency_ratio: register_histogram_with_registry!(
575                "prepare_cert_gas_latency_ratio",
576                "The ratio of computation gas divided by VM execution latency.",
577                GAS_LATENCY_RATIO_BUCKETS.to_vec(),
578                registry
579            )
580            .unwrap(),
581            execution_gas_latency_ratio: register_histogram_with_registry!(
582                "execution_gas_latency_ratio",
583                "The ratio of computation gas divided by certificate execution latency, include committing certificate.",
584                GAS_LATENCY_RATIO_BUCKETS.to_vec(),
585                registry
586            )
587            .unwrap(),
588            skipped_consensus_txns: register_int_counter_with_registry!(
589                "skipped_consensus_txns",
590                "Total number of consensus transactions skipped",
591                registry,
592            )
593            .unwrap(),
594            skipped_consensus_txns_cache_hit: register_int_counter_with_registry!(
595                "skipped_consensus_txns_cache_hit",
596                "Total number of consensus transactions skipped because of local cache hit",
597                registry,
598            )
599            .unwrap(),
600            consensus_handler_duplicate_tx_count: register_histogram_with_registry!(
601                "consensus_handler_duplicate_tx_count",
602                "Number of times each transaction appears in its first consensus commit",
603                POSITIVE_INT_BUCKETS.to_vec(),
604                registry,
605            )
606            .unwrap(),
607            consensus_handler_processed: register_int_counter_vec_with_registry!(
608                "consensus_handler_processed",
609                "Number of transactions processed by consensus handler, sliced by class and commit outcome (accepted/rejected)",
610                &["class", "outcome"],
611                registry
612            ).unwrap(),
613            consensus_handler_processed_user_transactions: register_int_counter_vec_with_registry!(
614                "consensus_handler_processed_user_transactions",
615                "Number of user transactions processed by consensus handler, sliced by commit outcome (accepted/rejected) and block author",
616                &["outcome", "authority"],
617                registry
618            ).unwrap(),
619            consensus_handler_transaction_sizes: register_histogram_vec_with_registry!(
620                "consensus_handler_transaction_sizes",
621                "Sizes of each type of transactions processed by consensus handler, sliced by class and commit outcome (accepted/rejected)",
622                &["class", "outcome"],
623                CONSENSUS_TRANSACTION_SIZE_BUCKETS.to_vec(),
624                registry
625            ).unwrap(),
626            consensus_handler_max_transaction_size: register_int_gauge_vec_with_registry!(
627                "consensus_handler_max_transaction_size",
628                "Maximum transaction size in bytes received by the consensus handler for each class",
629                &["class"],
630                registry,
631            ).unwrap(),
632            consensus_handler_deferred_transactions: register_int_counter_with_registry!(
633                "consensus_handler_deferred_transactions",
634                "Number of transactions deferred by consensus handler",
635                registry,
636            ).unwrap(),
637            consensus_handler_congested_transactions: register_int_counter_with_registry!(
638                "consensus_handler_congested_transactions",
639                "Number of transactions deferred by consensus handler due to congestion",
640                registry,
641            ).unwrap(),
642            consensus_handler_unpaid_amplification_deferrals: register_int_counter_with_registry!(
643                "consensus_handler_unpaid_amplification_deferrals",
644                "Number of transactions deferred due to unpaid consensus amplification",
645                registry,
646            ).unwrap(),
647            consensus_handler_double_spend_deferrals: register_int_counter_with_registry!(
648                "consensus_handler_double_spend_deferrals",
649                "Number of transactions deferred due to owned object double-spend contention",
650                registry,
651            ).unwrap(),
652            consensus_handler_double_spend_conflict_count: register_histogram_vec_with_registry!(
653                "consensus_handler_double_spend_conflict_count",
654                "Number of conflicting transactions per double-spend winner, by object type",
655                &["object_type"],
656                POSITIVE_INT_BUCKETS.to_vec(),
657                registry,
658            ).unwrap(),
659            consensus_handler_double_spend_conflicting_authority: register_int_counter_vec_with_registry!(
660                "consensus_handler_double_spend_conflicting_authority",
661                "Number of transactions involved in owned object double-spend contention, by the \
662                 block authority that sequenced the transaction and its role in the conflict \
663                 (winner = won the lock, loser = dropped)",
664                &["authority", "role"],
665                registry,
666            ).unwrap(),
667            consensus_handler_cancelled_transactions: register_int_counter_with_registry!(
668                "consensus_handler_cancelled_transactions",
669                "Number of transactions cancelled by consensus handler",
670                registry,
671            ).unwrap(),
672            consensus_handler_dropped_transactions: register_int_counter_vec_with_registry!(
673                "consensus_handler_dropped_transactions",
674                "Number of transactions dropped by consensus handler, by drop reason",
675                &["reason"],
676                registry,
677            ).unwrap(),
678            consensus_handler_max_object_costs: register_int_gauge_vec_with_registry!(
679                "consensus_handler_max_congestion_control_object_costs",
680                "Max object costs for congestion control in the current consensus commit",
681                &["commit_type"],
682                registry,
683            ).unwrap(),
684            consensus_committed_subdags: register_int_counter_vec_with_registry!(
685                "consensus_committed_subdags",
686                "Number of committed subdags, sliced by author",
687                &["authority"],
688                registry,
689            ).unwrap(),
690            accumulator_deposits: register_int_counter_with_registry!(
691                "accumulator_deposits",
692                "Total accumulator deposit (merge) events processed in settlement",
693                registry,
694            ).unwrap(),
695            accumulator_withdrawals: register_int_counter_with_registry!(
696                "accumulator_withdrawals",
697                "Total accumulator withdrawal (split) events processed in settlement",
698                registry,
699            ).unwrap(),
700            consensus_committed_messages: register_int_gauge_vec_with_registry!(
701                "consensus_committed_messages",
702                "Total number of committed consensus messages, sliced by author",
703                &["authority"],
704                registry,
705            ).unwrap(),
706            consensus_committed_user_transactions: register_int_gauge_vec_with_registry!(
707                "consensus_committed_user_transactions",
708                "Number of certified & user transactions committed, sliced by submitter and persisted across restarts within each epoch",
709                &["authority"],
710                registry,
711            ).unwrap(),
712            consensus_finalized_user_transactions: register_int_gauge_vec_with_registry!(
713                "consensus_finalized_user_transactions",
714                "Number of user transactions finalized, sliced by submitter",
715                &["authority"],
716                registry,
717            ).unwrap(),
718            consensus_rejected_user_transactions: register_int_gauge_vec_with_registry!(
719                "consensus_rejected_user_transactions",
720                "Number of user transactions rejected, sliced by submitter",
721                &["authority"],
722                registry,
723            ).unwrap(),
724            consensus_dropped_user_transactions: register_int_gauge_vec_with_registry!(
725                "consensus_dropped_user_transactions",
726                "Number of user transactions dropped post-consensus, sliced by submitter",
727                &["authority"],
728                registry,
729            ).unwrap(),
730            execution_metrics: Arc::new(ExecutionMetrics::new(registry)),
731            bytecode_verifier_metrics: Arc::new(BytecodeVerifierMetrics::new(registry)),
732            zklogin_sig_count: register_int_counter_with_registry!(
733                "zklogin_sig_count",
734                "Count of zkLogin signatures",
735                registry,
736            )
737            .unwrap(),
738            multisig_sig_count: register_int_counter_with_registry!(
739                "multisig_sig_count",
740                "Count of zkLogin signatures",
741                registry,
742            )
743            .unwrap(),
744            consensus_calculated_throughput: register_int_gauge_with_registry!(
745                "consensus_calculated_throughput",
746                "The calculated throughput from consensus output. Result is calculated based on unique transactions.",
747                registry,
748            ).unwrap(),
749            consensus_calculated_throughput_profile: register_int_gauge_with_registry!(
750                "consensus_calculated_throughput_profile",
751                "The current active calculated throughput profile",
752                registry
753            ).unwrap(),
754            consensus_block_handler_block_processed: register_int_counter_with_registry!(
755                "consensus_block_handler_block_processed",
756                "Number of blocks processed by consensus block handler.",
757                registry
758            ).unwrap(),
759            consensus_block_handler_txn_processed: register_int_counter_vec_with_registry!(
760                "consensus_block_handler_txn_processed",
761                "Number of transactions processed by consensus block handler, by whether they are certified or rejected.",
762                &["outcome"],
763                registry
764            ).unwrap(),
765            consensus_block_handler_fastpath_executions: register_int_counter_with_registry!(
766                "consensus_block_handler_fastpath_executions",
767                "Number of fastpath transactions sent for execution by consensus transaction handler",
768                registry,
769            ).unwrap(),
770            consensus_timestamp_bias: register_histogram_with_registry!(
771                "consensus_timestamp_bias",
772                "Bias/delay from consensus timestamp to system time",
773                TIMESTAMP_BIAS_SEC_BUCKETS.to_vec(),
774                registry
775            ).unwrap(),
776            execution_queueing_latency: LatencyObserver::new(),
777            txn_ready_rate_tracker: Arc::new(Mutex::new(RateTracker::new(Duration::from_secs(10)))),
778            execution_rate_tracker: Arc::new(Mutex::new(RateTracker::new(Duration::from_secs(10)))),
779        }
780    }
781
782    pub(crate) fn observe_consensus_handler_transaction_size(
783        &self,
784        class: &str,
785        outcome: &str,
786        size: usize,
787    ) {
788        self.consensus_handler_transaction_sizes
789            .with_label_values(&[class, outcome])
790            .observe(size as f64);
791
792        let max_transaction_size = self
793            .consensus_handler_max_transaction_size
794            .with_label_values(&[class]);
795        max_transaction_size.set(max_transaction_size.get().max(size as i64));
796    }
797}
798
799/// a Trait object for `Signer` that is:
800/// - Pin, i.e. confined to one place in memory (we don't want to copy private keys).
801/// - Sync, i.e. can be safely shared between threads.
802///
803/// Typically instantiated with Box::pin(keypair) where keypair is a `KeyPair`
804///
805pub type StableSyncAuthoritySigner = Pin<Arc<dyn Signer<AuthoritySignature> + Send + Sync>>;
806
807/// The expected effects digest of a transaction, when the effects are known before execution,
808/// tagged with where the expectation came from.
809#[derive(Debug, Clone, Copy, PartialEq, Eq)]
810pub enum ExpectedEffectsDigest {
811    /// Read from the contents of the certified checkpoint at `checkpoint_seq`.
812    Certified {
813        digest: TransactionEffectsDigest,
814        checkpoint_seq: CheckpointSequenceNumber,
815    },
816    /// Known but not network-certified: this validator's own previously signed effects, or an
817    /// operator override.
818    Uncertified(TransactionEffectsDigest),
819}
820
821impl ExpectedEffectsDigest {
822    pub fn digest(&self) -> TransactionEffectsDigest {
823        match self {
824            Self::Certified { digest, .. } => *digest,
825            Self::Uncertified(digest) => *digest,
826        }
827    }
828
829    pub fn checkpoint_seq(&self) -> Option<CheckpointSequenceNumber> {
830        match self {
831            Self::Certified { checkpoint_seq, .. } => Some(*checkpoint_seq),
832            Self::Uncertified(_) => None,
833        }
834    }
835}
836
837/// Execution env contains the "environment" for the transaction to be executed in, that is,
838/// all the information necessary for execution that is not specified by the transaction itself.
839#[derive(Debug, Clone)]
840pub struct ExecutionEnv {
841    /// The assigned version of each shared object for the transaction.
842    pub assigned_versions: AssignedVersions,
843    /// The expected digest of the effects of the transaction, if executing from checkpoint or
844    /// other sources where the effects are known in advance.
845    pub expected_effects_digest: Option<ExpectedEffectsDigest>,
846    /// Status of the address funds withdraw scheduling of the transaction,
847    /// including both address and object funds withdraws.
848    pub funds_withdraw_status: FundsWithdrawStatus,
849    /// Transactions that must finish before this transaction can be executed.
850    /// Used to schedule barrier transactions after non-exclusive writes.
851    pub barrier_dependencies: Vec<TransactionDigest>,
852    /// The transaction's position in causal order, assigned by the ExecutionScheduler
853    /// at enqueue time and used by the execution driver for admission. The driver
854    /// retires the index when the transaction finishes executing or is dropped as no
855    /// longer needed. None at the driver means the transaction is admitted
856    /// unconditionally (settlement transactions - see
857    /// `execution_scheduler::causal_admission`).
858    pub(crate) causal_index: Option<u64>,
859}
860
861impl Default for ExecutionEnv {
862    fn default() -> Self {
863        Self {
864            assigned_versions: AssignedVersions::empty(),
865            expected_effects_digest: None,
866            funds_withdraw_status: FundsWithdrawStatus::MaybeSufficient,
867            barrier_dependencies: Default::default(),
868            causal_index: None,
869        }
870    }
871}
872
873impl ExecutionEnv {
874    pub fn new() -> Self {
875        Default::default()
876    }
877
878    pub fn with_expected_effects(mut self, expected: ExpectedEffectsDigest) -> Self {
879        self.expected_effects_digest = Some(expected);
880        self
881    }
882
883    pub fn with_assigned_versions(mut self, assigned_versions: AssignedVersions) -> Self {
884        self.assigned_versions = assigned_versions;
885        self
886    }
887
888    pub fn with_insufficient_funds(mut self) -> Self {
889        self.funds_withdraw_status = FundsWithdrawStatus::Insufficient;
890        self
891    }
892
893    /// For tests that drive scheduler-internal paths directly, standing in for the
894    /// index the ExecutionScheduler assigns at enqueue time.
895    #[cfg(test)]
896    pub(crate) fn with_causal_index(mut self, index: u64) -> Self {
897        self.causal_index = Some(index);
898        self
899    }
900
901    pub fn with_barrier_dependencies(
902        mut self,
903        barrier_dependencies: BTreeSet<TransactionDigest>,
904    ) -> Self {
905        self.barrier_dependencies = barrier_dependencies.into_iter().collect();
906        self
907    }
908}
909
910#[derive(Debug)]
911pub struct ForkRecoveryState {
912    /// Transaction digest to effects digest overrides
913    transaction_overrides:
914        parking_lot::RwLock<HashMap<TransactionDigest, TransactionEffectsDigest>>,
915}
916
917impl Default for ForkRecoveryState {
918    fn default() -> Self {
919        Self {
920            transaction_overrides: parking_lot::RwLock::new(HashMap::new()),
921        }
922    }
923}
924
925impl ForkRecoveryState {
926    pub fn new(config: Option<&sui_config::node::ForkRecoveryConfig>) -> Result<Self, SuiError> {
927        let Some(config) = config else {
928            return Ok(Self::default());
929        };
930
931        let mut transaction_overrides = HashMap::new();
932        for (tx_digest_str, effects_digest_str) in &config.transaction_overrides {
933            let tx_digest = TransactionDigest::from_str(tx_digest_str).map_err(|_| {
934                SuiErrorKind::Unknown(format!("Invalid transaction digest: {}", tx_digest_str))
935            })?;
936            let effects_digest =
937                TransactionEffectsDigest::from_str(effects_digest_str).map_err(|_| {
938                    SuiErrorKind::Unknown(format!("Invalid effects digest: {}", effects_digest_str))
939                })?;
940            transaction_overrides.insert(tx_digest, effects_digest);
941        }
942
943        Ok(Self {
944            transaction_overrides: parking_lot::RwLock::new(transaction_overrides),
945        })
946    }
947
948    pub fn get_transaction_override(
949        &self,
950        tx_digest: &TransactionDigest,
951    ) -> Option<TransactionEffectsDigest> {
952        self.transaction_overrides.read().get(tx_digest).copied()
953    }
954}
955
956pub struct AuthorityState {
957    // Fixed size, static, identity of the authority
958    /// The name of this authority.
959    pub name: AuthorityName,
960    /// The signature key of the authority.
961    pub secret: StableSyncAuthoritySigner,
962
963    /// The database
964    input_loader: TransactionInputLoader,
965    execution_cache_trait_pointers: ExecutionCacheTraitPointers,
966    coin_reservation_resolver: Arc<CachingCoinReservationResolver>,
967
968    epoch_store: ArcSwap<AuthorityPerEpochStore>,
969
970    /// This lock denotes current 'execution epoch'.
971    /// Execution acquires read lock, checks certificate epoch and holds it until all writes are complete.
972    /// Reconfiguration acquires write lock, changes the epoch and revert all transactions
973    /// from previous epoch that are executed but did not make into checkpoint.
974    execution_lock: RwLock<EpochId>,
975
976    pub checkpoint_store: Arc<CheckpointStore>,
977
978    committee_store: Arc<CommitteeStore>,
979
980    /// Schedules transaction execution.
981    execution_scheduler: Arc<ExecutionScheduler>,
982
983    /// Shuts down the execution task. Used only in testing.
984    #[allow(unused)]
985    tx_execution_shutdown: Mutex<Option<oneshot::Sender<()>>>,
986
987    pub metrics: Arc<AuthorityMetrics>,
988    _pruner: AuthorityStorePruner,
989    _authority_per_epoch_pruner: AuthorityPerEpochStorePruner,
990
991    /// Take db checkpoints of different dbs
992    db_checkpoint_config: DBCheckpointConfig,
993
994    pub config: NodeConfig,
995
996    /// Current overload status in this authority. Updated periodically.
997    pub overload_info: AuthorityOverloadInfo,
998
999    /// The chain identifier is derived from the digest of the genesis checkpoint.
1000    chain_identifier: ChainIdentifier,
1001
1002    pub(crate) congestion_tracker: Arc<CongestionTracker>,
1003
1004    /// Consumed by gasless tx rate limiter.
1005    pub(crate) consensus_gasless_counter: Arc<ConsensusGaslessCounter>,
1006
1007    /// Traffic controller for the validator service.
1008    pub traffic_controller: Option<Arc<TrafficController>>,
1009
1010    /// Fork recovery state for handling equivocation after forks
1011    fork_recovery_state: Option<ForkRecoveryState>,
1012
1013    /// Notification channel for reconfiguration
1014    notify_epoch: tokio::sync::watch::Sender<EpochId>,
1015
1016    pub(crate) object_funds_checker: ArcSwapOption<ObjectFundsCheckerDEPRECATED>,
1017    object_funds_checker_metrics: Arc<ObjectFundsCheckerMetrics>,
1018    pub(crate) unsettled_object_withdrawals: Arc<UnsettledObjectWithdrawals>,
1019
1020    /// Created once per process, then re-attached to each new `AuthorityPerEpochStore`
1021    /// at reconfiguration.
1022    transaction_deny_config_manager: Arc<TransactionDenyConfigManager>,
1023}
1024
1025/// The authority state encapsulates all state, drives execution, and ensures safety.
1026///
1027/// Note the authority operations can be accessed through a read ref (&) and do not
1028/// require &mut. Internally a database is synchronized through a mutex lock.
1029///
1030/// Repeating valid commands should produce no changes and return no error.
1031impl AuthorityState {
1032    pub fn node_role(&self, epoch_store: &AuthorityPerEpochStore) -> NodeRole {
1033        epoch_store.node_role()
1034    }
1035
1036    pub fn is_validator(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1037        epoch_store.node_role().is_validator()
1038    }
1039
1040    pub fn is_fullnode(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1041        epoch_store.node_role().is_fullnode()
1042    }
1043
1044    pub fn committee_store(&self) -> &Arc<CommitteeStore> {
1045        &self.committee_store
1046    }
1047
1048    pub fn clone_committee_store(&self) -> Arc<CommitteeStore> {
1049        self.committee_store.clone()
1050    }
1051
1052    pub fn overload_config(&self) -> &AuthorityOverloadConfig {
1053        &self.config.authority_overload_config
1054    }
1055
1056    pub fn get_epoch_state_commitments(
1057        &self,
1058        epoch: EpochId,
1059    ) -> SuiResult<Option<Vec<CheckpointCommitment>>> {
1060        self.checkpoint_store.get_epoch_state_commitments(epoch)
1061    }
1062
1063    fn handle_transaction_deny_checks(
1064        &self,
1065        transaction: &VerifiedTransaction,
1066        epoch_store: &Arc<AuthorityPerEpochStore>,
1067    ) -> SuiResult<CheckedInputObjects> {
1068        let tx_digest = transaction.digest();
1069        let tx_data = transaction.data().transaction_data();
1070
1071        let input_object_kinds = tx_data.input_objects()?;
1072        let receiving_objects_refs = tx_data.receiving_objects();
1073
1074        let transaction_deny_config = self
1075            .transaction_deny_config_manager
1076            .effective_config()
1077            .load();
1078        pre_object_load_checks(
1079            tx_data,
1080            transaction.tx_signatures(),
1081            &input_object_kinds,
1082            &receiving_objects_refs,
1083            epoch_store.protocol_config(),
1084            transaction_deny_config.as_ref(),
1085            self.get_backing_package_store().as_ref(),
1086            self.chain_identifier,
1087            self.coin_reservation_resolver.as_ref(),
1088            self.get_account_funds_read().as_ref(),
1089        )?;
1090
1091        let (input_objects, receiving_objects) = self.input_loader.read_objects_for_signing(
1092            Some(tx_digest),
1093            &input_object_kinds,
1094            &receiving_objects_refs,
1095            epoch_store.epoch(),
1096        )?;
1097
1098        let (_gas_status, checked_input_objects) = sui_transaction_checks::check_transaction_input(
1099            epoch_store.protocol_config(),
1100            epoch_store.reference_gas_price(),
1101            tx_data,
1102            input_objects,
1103            &receiving_objects,
1104            &self.metrics.bytecode_verifier_metrics,
1105            &self.config.verifier_signing_config,
1106        )?;
1107
1108        self.handle_coin_deny_list_checks(
1109            tx_data,
1110            &checked_input_objects,
1111            &receiving_objects,
1112            epoch_store,
1113        )?;
1114
1115        Ok(checked_input_objects)
1116    }
1117
1118    fn handle_coin_deny_list_checks(
1119        &self,
1120        tx_data: &TransactionData,
1121        checked_input_objects: &CheckedInputObjects,
1122        receiving_objects: &ReceivingObjects,
1123        epoch_store: &Arc<AuthorityPerEpochStore>,
1124    ) -> SuiResult<()> {
1125        use sui_types::balance::Balance;
1126
1127        let declared_withdrawals = tx_data.process_funds_withdrawals_for_signing(
1128            self.chain_identifier,
1129            self.coin_reservation_resolver.as_ref(),
1130        )?;
1131
1132        let funds_withdrawals = declared_withdrawals
1133            .values()
1134            .filter_map(|(_, type_tag, funder)| {
1135                Balance::maybe_get_balance_type_param(type_tag)
1136                    .map(|ty| (*funder, ty.to_canonical_string(false)))
1137            })
1138            .collect::<BTreeSet<_>>();
1139
1140        if epoch_store.coin_deny_list_v1_enabled() {
1141            check_coin_deny_list_v1(
1142                tx_data.sender(),
1143                checked_input_objects,
1144                receiving_objects,
1145                funds_withdrawals.clone(),
1146                &self.get_object_store(),
1147            )?;
1148        }
1149
1150        if epoch_store.protocol_config().enable_coin_deny_list_v2() {
1151            check_coin_deny_list_v2_during_signing(
1152                tx_data.sender(),
1153                checked_input_objects,
1154                receiving_objects,
1155                funds_withdrawals,
1156                &self.get_object_store(),
1157            )?;
1158        }
1159
1160        Ok(())
1161    }
1162
1163    /// Vote for a transaction, either when validator receives a submit_transaction request,
1164    /// or sees a transaction from consensus. Performs the same types of checks as
1165    /// transaction signing, but does not explicitly sign the transaction.
1166    /// Note that if the transaction has been executed, we still go through the
1167    /// same checks. If the transaction has only been executed through mysticeti fastpath,
1168    /// but not yet finalized, the signing will still work since the objects are still available.
1169    /// But if the transaction has been finalized, the signing will fail.
1170    /// TODO(mysticeti-fastpath): Assess whether we want to optimize the case when the transaction
1171    /// has already been finalized executed.
1172    #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1173    pub fn handle_vote_transaction(
1174        &self,
1175        epoch_store: &Arc<AuthorityPerEpochStore>,
1176        transaction: VerifiedTransaction,
1177    ) -> SuiResult<()> {
1178        debug!("handle_vote_transaction");
1179
1180        let _metrics_guard = self
1181            .metrics
1182            .authority_state_handle_vote_transaction_latency
1183            .start_timer();
1184        self.metrics.tx_orders.inc();
1185
1186        // The should_accept_user_certs check here is best effort, because
1187        // between a validator signs a tx and a cert is formed, the validator
1188        // could close the window.
1189        if !epoch_store
1190            .get_reconfig_state_read_lock_guard()
1191            .should_accept_user_certs()
1192        {
1193            return Err(SuiErrorKind::ValidatorHaltedAtEpochEnd.into());
1194        }
1195
1196        // Accept finalized transactions, instead of voting to reject them.
1197        // Checking executed transactions is limited to the current epoch.
1198        // Otherwise there can be a race where the transaction is accepted because it has executed,
1199        // but the executed effects are pruned post consensus, leading to failures.
1200        let tx_digest = *transaction.digest();
1201        if epoch_store.is_recently_finalized(&tx_digest)
1202            || epoch_store.transactions_executed_in_cur_epoch(&[tx_digest])[0]
1203        {
1204            assert_reachable!("transaction recently executed");
1205            return Ok(());
1206        }
1207
1208        if self
1209            .get_transaction_cache_reader()
1210            .transaction_executed_in_last_epoch(transaction.digest(), epoch_store.epoch())
1211        {
1212            return Err(SuiErrorKind::TransactionAlreadyExecuted {
1213                digest: (*transaction.digest()),
1214            }
1215            .into());
1216        }
1217
1218        // Ensure that validator cannot reconfigure while we are validating the transaction.
1219        let _execution_lock = self.execution_lock_for_validation()?;
1220
1221        let checked_input_objects =
1222            self.handle_transaction_deny_checks(&transaction, epoch_store)?;
1223
1224        let owned_objects = checked_input_objects.inner().filter_owned_objects();
1225
1226        // Validate owned object versions without acquiring locks. Locking happens post-consensus
1227        // in the consensus handler. Validation still runs to prevent spam transactions with
1228        // invalid object versions, and is necessary to handle recently created objects.
1229        self.get_cache_writer()
1230            .validate_owned_object_versions(&owned_objects)
1231    }
1232
1233    /// Used for early client validation check for transactions before submission to server.
1234    /// Performs the same validation checks as handle_vote_transaction without acquiring locks.
1235    /// This allows for fast failure feedback to clients for non-retriable errors.
1236    ///
1237    /// The key addition is checking that owned object versions match live object versions.
1238    /// This is necessary because handle_transaction_deny_checks fetches objects at their
1239    /// requested version (which may exist in storage as historical versions), whereas
1240    /// validators check against the live/current version during locking (verify_live_object).
1241    pub fn check_transaction_validity(
1242        &self,
1243        epoch_store: &Arc<AuthorityPerEpochStore>,
1244        transaction: &VerifiedTransaction,
1245        enforce_live_input_objects: bool,
1246    ) -> SuiResult<()> {
1247        if !epoch_store
1248            .get_reconfig_state_read_lock_guard()
1249            .should_accept_user_certs()
1250        {
1251            return Err(SuiErrorKind::ValidatorHaltedAtEpochEnd.into());
1252        }
1253
1254        transaction.validity_check(&epoch_store.tx_validity_check_context())?;
1255
1256        let checked_input_objects =
1257            self.handle_transaction_deny_checks(transaction, epoch_store)?;
1258
1259        // Check that owned object versions match live objects
1260        let owned_objects = checked_input_objects.inner().filter_owned_objects();
1261        let cache_reader = self.get_object_cache_reader();
1262
1263        for obj_ref in &owned_objects {
1264            if let Some(live_object) = cache_reader.get_object(&obj_ref.0) {
1265                // Only reject if transaction references an old version. Allow newer
1266                // versions that may exist on validators but not yet synced to fullnode.
1267                if obj_ref.1 < live_object.version() {
1268                    return Err(SuiErrorKind::UserInputError {
1269                        error: UserInputError::ObjectVersionUnavailableForConsumption {
1270                            provided_obj_ref: *obj_ref,
1271                            current_version: live_object.version(),
1272                        },
1273                    }
1274                    .into());
1275                }
1276
1277                if enforce_live_input_objects && live_object.version() < obj_ref.1 {
1278                    // Returns a non-retriable error when the input object version is required to be live.
1279                    return Err(SuiErrorKind::UserInputError {
1280                        error: UserInputError::ObjectVersionUnavailableForConsumption {
1281                            provided_obj_ref: *obj_ref,
1282                            current_version: live_object.version(),
1283                        },
1284                    }
1285                    .into());
1286                }
1287
1288                // If version matches, verify digest also matches
1289                if obj_ref.1 == live_object.version() && obj_ref.2 != live_object.digest() {
1290                    return Err(SuiErrorKind::UserInputError {
1291                        error: UserInputError::InvalidObjectDigest {
1292                            object_id: obj_ref.0,
1293                            expected_digest: live_object.digest(),
1294                        },
1295                    }
1296                    .into());
1297                }
1298            }
1299        }
1300
1301        Ok(())
1302    }
1303
1304    pub fn check_system_overload_at_signing(&self) -> bool {
1305        self.config
1306            .authority_overload_config
1307            .check_system_overload_at_signing
1308    }
1309
1310    pub(crate) fn check_system_overload(
1311        &self,
1312        tx_data: &SenderSignedData,
1313        do_authority_overload_check: bool,
1314    ) -> SuiResult {
1315        if do_authority_overload_check {
1316            self.check_authority_overload(tx_data).tap_err(|_| {
1317                self.update_overload_metrics("execution_queue");
1318            })?;
1319        }
1320        self.execution_scheduler
1321            .check_execution_overload(self.overload_config(), tx_data)
1322            .tap_err(|_| {
1323                self.update_overload_metrics("execution_pending");
1324            })?;
1325        // Consensus overload is handled by the admission queue in authority_server.rs.
1326
1327        let pending_tx_count = self
1328            .get_cache_commit()
1329            .approximate_pending_transaction_count();
1330        if pending_tx_count > self.config.execution_cache.backpressure_threshold_for_rpc() {
1331            return Err(SuiErrorKind::ValidatorOverloadedRetryAfter {
1332                retry_after_secs: 10,
1333            }
1334            .into());
1335        }
1336
1337        Ok(())
1338    }
1339
1340    fn check_authority_overload(&self, tx_data: &SenderSignedData) -> SuiResult {
1341        if !self.overload_info.is_overload.load(Ordering::Relaxed) {
1342            return Ok(());
1343        }
1344
1345        let load_shedding_percentage = self
1346            .overload_info
1347            .load_shedding_percentage
1348            .load(Ordering::Relaxed);
1349        overload_monitor_accept_tx(load_shedding_percentage, tx_data.digest())
1350    }
1351
1352    pub(crate) fn update_overload_metrics(&self, source: &str) {
1353        self.metrics
1354            .transaction_overload_sources
1355            .with_label_values(&[source])
1356            .inc();
1357    }
1358
1359    /// Waits for fastpath (owned, package) dependency objects to become available.
1360    /// Returns true if a chosen set of fastpath dependency objects are available,
1361    /// returns false otherwise after an internal timeout.
1362    pub(crate) async fn wait_for_fastpath_dependency_objects(
1363        &self,
1364        transaction: &VerifiedTransaction,
1365        epoch: EpochId,
1366    ) -> SuiResult<bool> {
1367        let txn_data = transaction.data().transaction_data();
1368        let (move_objects, packages, receiving_objects) = txn_data.fastpath_dependency_objects()?;
1369
1370        // Gather and filter input objects to wait for.
1371        let fastpath_dependency_objects: Vec<_> = move_objects
1372            .into_iter()
1373            .filter_map(|obj_ref| self.should_wait_for_dependency_object(obj_ref))
1374            .chain(
1375                packages
1376                    .into_iter()
1377                    .map(|package_id| InputKey::Package { id: package_id }),
1378            )
1379            .collect();
1380        let receiving_keys: HashSet<_> = receiving_objects
1381            .into_iter()
1382            .filter_map(|receiving_obj_ref| {
1383                self.should_wait_for_dependency_object(receiving_obj_ref)
1384            })
1385            .collect();
1386        if fastpath_dependency_objects.is_empty() && receiving_keys.is_empty() {
1387            return Ok(true);
1388        }
1389
1390        // Use shorter wait timeout in simtests to exercise server-side error paths and
1391        // client-side retry logic.
1392        let max_wait = if cfg!(msim) {
1393            Duration::from_millis(200)
1394        } else {
1395            WAIT_FOR_FASTPATH_INPUT_TIMEOUT
1396        };
1397
1398        match timeout(
1399            max_wait,
1400            self.get_object_cache_reader().notify_read_input_objects(
1401                &fastpath_dependency_objects,
1402                &receiving_keys,
1403                epoch,
1404            ),
1405        )
1406        .await
1407        {
1408            Ok(()) => Ok(true),
1409            // Maybe return an error for unavailable input objects,
1410            // and allow the caller to skip the rest of input checks?
1411            Err(_) => Ok(false),
1412        }
1413    }
1414
1415    /// Returns Some(inputKey) if the object reference should be waited on until it is
1416    /// finalized, before proceeding to input checks.
1417    ///
1418    /// Incorrect decisions here should only affect user experience, not safety:
1419    /// - Waiting unnecessarily adds latency to transaction signing and submission.
1420    /// - Not waiting when needed may cause the transaction to be rejected because input object is unavailable.
1421    fn should_wait_for_dependency_object(&self, obj_ref: ObjectRef) -> Option<InputKey> {
1422        let (obj_id, cur_version, _digest) = obj_ref;
1423        let Some(latest_obj_ref) = self
1424            .get_object_cache_reader()
1425            .get_latest_object_ref_or_tombstone(obj_id)
1426        else {
1427            // Object might not have been created.
1428            return Some(InputKey::VersionedObject {
1429                id: FullObjectID::new(obj_id, None),
1430                version: cur_version,
1431            });
1432        };
1433        let latest_digest = latest_obj_ref.2;
1434        if latest_digest == ObjectDigest::OBJECT_DIGEST_DELETED {
1435            // Do not wait for deleted object and rely on input check instead.
1436            return None;
1437        }
1438        let latest_version = latest_obj_ref.1;
1439        if cur_version <= latest_version {
1440            // Do not wait for version that already exists or has been consumed.
1441            // Let the input check to handle them and return the proper error.
1442            return None;
1443        }
1444        // Wait for the object version to become available.
1445        Some(InputKey::VersionedObject {
1446            id: FullObjectID::new(obj_id, None),
1447            version: cur_version,
1448        })
1449    }
1450
1451    /// Wait for a transaction to be executed. Transactions need to be sequenced by consensus
1452    /// before being enqueued for execution.
1453    ///
1454    /// Only use this in tests.
1455    #[instrument(level = "trace", skip_all)]
1456    pub async fn wait_for_transaction_execution_for_testing(
1457        &self,
1458        transaction: &VerifiedExecutableTransaction,
1459    ) -> TransactionEffects {
1460        self.notify_read_effects_for_testing(
1461            "AuthorityState::wait_for_transaction_execution_for_testing",
1462            *transaction.digest(),
1463        )
1464        .await
1465    }
1466
1467    /// Internal logic to execute a certificate.
1468    ///
1469    /// Guarantees that
1470    /// - If input objects are available, return no permanent failure.
1471    /// - Execution and output commit are atomic. i.e. outputs are only written to storage,
1472    /// on successful execution; crashed execution has no observable effect and can be retried.
1473    ///
1474    /// It is caller's responsibility to ensure input objects are available and locks are set.
1475    /// If this cannot be satisfied by the caller, execute_certificate() should be called instead.
1476    ///
1477    /// Should only be called within sui-core.
1478    #[instrument(level = "trace", skip_all)]
1479    pub fn try_execute_immediately(
1480        &self,
1481        certificate: &VerifiedExecutableTransaction,
1482        mut execution_env: ExecutionEnv,
1483        epoch_store: &Arc<AuthorityPerEpochStore>,
1484    ) -> ExecutionOutput<(TransactionEffects, Option<ExecutionError>)> {
1485        let _scope = monitored_scope("Execution::try_execute_immediately");
1486        let _metrics_guard = self.metrics.internal_execution_latency.start_timer();
1487
1488        let tx_digest = certificate.digest();
1489
1490        if let Some(fork_recovery) = &self.fork_recovery_state
1491            && let Some(override_digest) = fork_recovery.get_transaction_override(tx_digest)
1492        {
1493            warn!(
1494                ?tx_digest,
1495                original_digest = ?execution_env.expected_effects_digest,
1496                override_digest = ?override_digest,
1497                "Applying fork recovery override for transaction effects digest"
1498            );
1499            execution_env.expected_effects_digest =
1500                Some(ExpectedEffectsDigest::Uncertified(override_digest));
1501        }
1502
1503        // prevent concurrent executions of the same tx.
1504        let tx_guard = epoch_store.acquire_tx_guard(certificate);
1505
1506        let tx_cache_reader = self.get_transaction_cache_reader();
1507        if let Some(effects) = tx_cache_reader.get_executed_effects(tx_digest) {
1508            if let Some(expected_effects_digest) = execution_env.expected_effects_digest {
1509                assert_eq!(
1510                    effects.digest(),
1511                    expected_effects_digest.digest(),
1512                    "Unexpected effects digest for transaction {:?}",
1513                    tx_digest
1514                );
1515            }
1516            tx_guard.release();
1517            return ExecutionOutput::Success((effects, None));
1518        }
1519
1520        let execution_start_time = Instant::now();
1521
1522        // Any caller that verifies the signatures on the certificate will have already checked the
1523        // epoch. But paths that don't verify sigs (e.g. execution from checkpoint, reading from db)
1524        // present the possibility of an epoch mismatch. If this cert is not finalzied in previous
1525        // epoch, then it's invalid.
1526        let Some(execution_guard) = self.execution_lock_for_executable_transaction(certificate)
1527        else {
1528            tx_guard.release();
1529            return ExecutionOutput::EpochEnded;
1530        };
1531        // Since we obtain a reference to the epoch store before taking the execution lock, it's
1532        // possible that reconfiguration has happened and they no longer match.
1533        // TODO: We may not need the following check anymore since the scheduler
1534        // should have checked that the certificate is from the same epoch as epoch_store.
1535        if *execution_guard != epoch_store.epoch() {
1536            tx_guard.release();
1537            info!("The epoch of the execution_guard doesn't match the epoch store");
1538            return ExecutionOutput::EpochEnded;
1539        }
1540
1541        let accumulator_version = execution_env.assigned_versions.accumulator_version();
1542
1543        let (transaction_outputs, timings, execution_error_opt) = match self.process_certificate(
1544            &tx_guard,
1545            &execution_guard,
1546            certificate,
1547            execution_env,
1548            epoch_store,
1549        ) {
1550            ExecutionOutput::Success(result) => result,
1551            output => return output.unwrap_err(),
1552        };
1553        let transaction_outputs = Arc::new(transaction_outputs);
1554
1555        fail_point!("crash");
1556
1557        let effects = transaction_outputs.effects.clone();
1558        debug!(
1559            ?tx_digest,
1560            fx_digest=?effects.digest(),
1561            "process_certificate succeeded in {:.3}ms",
1562            (execution_start_time.elapsed().as_micros() as f64) / 1000.0
1563        );
1564
1565        self.commit_certificate(certificate, transaction_outputs, epoch_store);
1566
1567        if let TransactionKind::AuthenticatorStateUpdate(auth_state) =
1568            certificate.data().transaction_data().kind()
1569        {
1570            if let Some(err) = &execution_error_opt {
1571                debug_fatal!("Authenticator state update failed: {:?}", err);
1572            }
1573            epoch_store.update_authenticator_state(auth_state);
1574
1575            // double check that the signature verifier always matches the authenticator state
1576            if cfg!(debug_assertions) {
1577                let authenticator_state = get_authenticator_state(self.get_object_store())
1578                    .expect("Read cannot fail")
1579                    .expect("Authenticator state must exist");
1580
1581                let mut sys_jwks: Vec<_> = authenticator_state
1582                    .active_jwks
1583                    .into_iter()
1584                    .map(|jwk| (jwk.jwk_id, jwk.jwk))
1585                    .collect();
1586                let mut active_jwks: Vec<_> = epoch_store
1587                    .signature_verifier
1588                    .get_jwks()
1589                    .into_iter()
1590                    .collect();
1591                sys_jwks.sort();
1592                active_jwks.sort();
1593
1594                assert_eq!(sys_jwks, active_jwks);
1595            }
1596        }
1597
1598        if certificate
1599            .transaction_data()
1600            .kind()
1601            .is_accumulator_barrier_settle_tx()
1602        {
1603            let object_funds_checker = self.object_funds_checker.load();
1604            if let Some(object_funds_checker) = object_funds_checker.as_ref() {
1605                // unwrap safe because we assign accumulator version for every transaction
1606                // when accumulator is enabled.
1607                let next_accumulator_version = accumulator_version.unwrap().next();
1608                object_funds_checker.settle_accumulator_version(next_accumulator_version);
1609            }
1610        }
1611
1612        tx_guard.commit_tx();
1613
1614        let elapsed = execution_start_time.elapsed();
1615        epoch_store.record_local_execution_time(
1616            certificate.data().transaction_data(),
1617            &effects,
1618            timings,
1619            elapsed,
1620        );
1621
1622        let elapsed_us = elapsed.as_micros() as f64;
1623        if elapsed_us > 0.0 {
1624            self.metrics
1625                .execution_gas_latency_ratio
1626                .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed_us);
1627        };
1628        ExecutionOutput::Success((effects, execution_error_opt))
1629    }
1630
1631    pub fn read_objects_for_execution(
1632        &self,
1633        tx_lock: &CertLockGuard,
1634        certificate: &VerifiedExecutableTransaction,
1635        assigned_shared_object_versions: &AssignedVersions,
1636        epoch_store: &Arc<AuthorityPerEpochStore>,
1637    ) -> SuiResult<InputObjects> {
1638        let _scope = monitored_scope("Execution::load_input_objects");
1639        let _metrics_guard = self
1640            .metrics
1641            .execution_load_input_objects_latency
1642            .start_timer();
1643        let input_objects = &certificate.data().transaction_data().input_objects()?;
1644        self.input_loader.read_objects_for_execution(
1645            &certificate.key(),
1646            tx_lock,
1647            input_objects,
1648            assigned_shared_object_versions,
1649            epoch_store.epoch(),
1650        )
1651    }
1652
1653    pub async fn try_execute_executable_for_test(
1654        &self,
1655        executable: &VerifiedExecutableTransaction,
1656        execution_env: ExecutionEnv,
1657    ) -> (VerifiedSignedTransactionEffects, Option<ExecutionError>) {
1658        let epoch_store = self.epoch_store_for_testing();
1659        let (effects, execution_error_opt) = self
1660            .try_execute_immediately(executable, execution_env, &epoch_store)
1661            .unwrap();
1662        let signed_effects = self.sign_effects(effects, &epoch_store).unwrap();
1663        (signed_effects, execution_error_opt)
1664    }
1665
1666    /// Wait until the effects of the given transaction are available and return them.
1667    /// Panics if the effects are not found.
1668    ///
1669    /// Only use this in tests where effects are expected to exist.
1670    pub async fn notify_read_effects_for_testing(
1671        &self,
1672        task_name: &'static str,
1673        digest: TransactionDigest,
1674    ) -> TransactionEffects {
1675        self.get_transaction_cache_reader()
1676            .notify_read_executed_effects(task_name, &[digest])
1677            .await
1678            .pop()
1679            .expect("must return correct number of effects")
1680    }
1681
1682    /// This function captures the required state to debug a forked transaction.
1683    /// The dump is written to a file in dir `path`, with name prefixed by the transaction digest.
1684    /// NOTE: Since this info escapes the validator context,
1685    /// make sure not to leak any private info here
1686    pub(crate) fn debug_dump_transaction_state(
1687        &self,
1688        tx_digest: &TransactionDigest,
1689        effects: &TransactionEffects,
1690        expected_effects_digest: TransactionEffectsDigest,
1691        inner_temporary_store: &InnerTemporaryStore,
1692        certificate: &VerifiedExecutableTransaction,
1693        debug_dump_config: &StateDebugDumpConfig,
1694    ) -> SuiResult<PathBuf> {
1695        let dump_dir = debug_dump_config
1696            .dump_file_directory
1697            .as_ref()
1698            .cloned()
1699            .unwrap_or(std::env::temp_dir());
1700        let epoch_store = self.load_epoch_store_one_call_per_task();
1701
1702        NodeStateDump::new(
1703            tx_digest,
1704            effects,
1705            expected_effects_digest,
1706            self.get_object_store().as_ref(),
1707            &epoch_store,
1708            inner_temporary_store,
1709            certificate,
1710        )?
1711        .write_to_file(&dump_dir)
1712        .map_err(|e| SuiErrorKind::FileIOError(e.to_string()).into())
1713    }
1714
1715    #[instrument(level = "trace", skip_all)]
1716    pub(crate) fn process_certificate(
1717        &self,
1718        tx_guard: &CertTxGuard,
1719        execution_guard: &ExecutionLockReadGuard<'_>,
1720        certificate: &VerifiedExecutableTransaction,
1721        execution_env: ExecutionEnv,
1722        epoch_store: &Arc<AuthorityPerEpochStore>,
1723    ) -> ExecutionOutput<(
1724        TransactionOutputs,
1725        Vec<ExecutionTiming>,
1726        Option<ExecutionError>,
1727    )> {
1728        let _scope = monitored_scope("Execution::process_certificate");
1729
1730        let input_objects = match self.read_objects_for_execution(
1731            tx_guard.as_lock_guard(),
1732            certificate,
1733            &execution_env.assigned_versions,
1734            epoch_store,
1735        ) {
1736            Ok(objects) => objects,
1737            Err(e) => return ExecutionOutput::Fatal(e),
1738        };
1739
1740        let expected_effects_digest = execution_env.expected_effects_digest;
1741
1742        fail_point_if!("correlated-crash-process-certificate", || {
1743            if sui_simulator::random::deterministic_probability_once(certificate.digest(), 0.01) {
1744                sui_simulator::task::kill_current_node(None);
1745            }
1746        });
1747
1748        // Errors originating from prepare_certificate may be transient (failure to read locks) or
1749        // non-transient (transaction input is invalid, move vm errors). However, all errors from
1750        // this function occur before we have written anything to the db, so we commit the tx
1751        // guard and rely on the client to retry the tx (if it was transient).
1752        self.execute_certificate(
1753            execution_guard,
1754            certificate,
1755            input_objects,
1756            expected_effects_digest,
1757            execution_env,
1758            epoch_store,
1759        )
1760    }
1761
1762    pub async fn reconfigure_traffic_control(
1763        &self,
1764        params: TrafficControlReconfigParams,
1765    ) -> Result<TrafficControlReconfigParams, SuiError> {
1766        if let Some(traffic_controller) = self.traffic_controller.as_ref() {
1767            traffic_controller.admin_reconfigure(params).await
1768        } else {
1769            Err(SuiErrorKind::InvalidAdminRequest(
1770                "Traffic controller is not configured on this node".to_string(),
1771            )
1772            .into())
1773        }
1774    }
1775
1776    #[instrument(level = "trace", skip_all)]
1777    fn commit_certificate(
1778        &self,
1779        certificate: &VerifiedExecutableTransaction,
1780        transaction_outputs: Arc<TransactionOutputs>,
1781        epoch_store: &Arc<AuthorityPerEpochStore>,
1782    ) {
1783        let _scope: Option<mysten_metrics::MonitoredScopeGuard> =
1784            monitored_scope("Execution::commit_certificate");
1785        let _metrics_guard = self.metrics.commit_certificate_latency.start_timer();
1786
1787        let tx_digest = certificate.digest();
1788
1789        // The insertion to epoch_store is not atomic with the insertion to the perpetual store. This is OK because
1790        // we insert to the epoch store first. And during lookups we always look up in the perpetual store first.
1791        epoch_store.insert_executed_in_epoch(tx_digest);
1792        let key = certificate.key();
1793        if !matches!(key, TransactionKey::Digest(_)) {
1794            epoch_store.insert_tx_key(key, *tx_digest);
1795        }
1796
1797        // Allow testing what happens if we crash here.
1798        fail_point!("crash");
1799
1800        self.get_cache_writer()
1801            .write_transaction_outputs(epoch_store.epoch(), transaction_outputs);
1802
1803        // Fire an in-memory-only notification so the scheduler can detect that this
1804        // barrier transaction has been executed (e.g. by the checkpoint executor) and
1805        // stop waiting for the checkpoint builder.  We intentionally do NOT persist
1806        // this to the DB to avoid stale entries surviving a crash while effects may not.
1807        if let Some(settlement_key) = certificate
1808            .transaction_data()
1809            .kind()
1810            .accumulator_barrier_settlement_key()
1811        {
1812            epoch_store.notify_barrier_executed(settlement_key, *tx_digest);
1813        }
1814
1815        if certificate.transaction_data().is_end_of_epoch_tx() {
1816            // At the end of epoch, since system packages may have been upgraded, force
1817            // reload them in the cache.
1818            self.get_object_cache_reader()
1819                .force_reload_system_packages(&BuiltInFramework::all_package_ids());
1820        }
1821    }
1822
1823    fn update_metrics(
1824        &self,
1825        certificate: &VerifiedExecutableTransaction,
1826        inner_temporary_store: &InnerTemporaryStore,
1827        effects: &TransactionEffects,
1828    ) {
1829        // count signature by scheme, for zklogin and multisig
1830        if certificate.has_zklogin_sig() {
1831            self.metrics.zklogin_sig_count.inc();
1832        } else if certificate.has_upgraded_multisig() {
1833            self.metrics.multisig_sig_count.inc();
1834        }
1835
1836        self.metrics.total_effects.inc();
1837        self.metrics.total_certs.inc();
1838
1839        let consensus_object_count = effects.accessed_consensus_objects().len();
1840        if consensus_object_count > 0 {
1841            self.metrics.shared_obj_tx.inc();
1842        }
1843
1844        if certificate.is_sponsored_tx() {
1845            self.metrics.sponsored_tx.inc();
1846        }
1847
1848        let input_object_count = inner_temporary_store.input_objects.len();
1849        self.metrics
1850            .num_input_objs
1851            .observe(input_object_count as f64);
1852        self.metrics
1853            .num_shared_objects
1854            .observe(consensus_object_count as f64);
1855        self.metrics.batch_size.observe(
1856            certificate
1857                .data()
1858                .intent_message()
1859                .value
1860                .kind()
1861                .num_commands() as f64,
1862        );
1863    }
1864
1865    /// Runs the executor on an already-prepared transaction; the caller is responsible for any
1866    /// coin reservation rewriting.
1867    fn execute_transaction_to_effects(
1868        &self,
1869        executor: &dyn Executor,
1870        store: &dyn BackingStore,
1871        protocol_config: &ProtocolConfig,
1872        enable_expensive_checks: bool,
1873        execution_params: ExecutionOrEarlyError,
1874        epoch_id: &EpochId,
1875        epoch_timestamp_ms: u64,
1876        input_objects: CheckedInputObjects,
1877        system_object_versions: SystemObjectVersions,
1878        unsettled_object_funds: &dyn UnsettledObjectFundsRead,
1879        gas_data: GasData,
1880        gas_status: SuiGasStatus,
1881        kind: TransactionKind,
1882        rewritten_inputs: Option<Vec<bool>>,
1883        signer: SuiAddress,
1884        tx_digest: TransactionDigest,
1885    ) -> (
1886        InnerTemporaryStore,
1887        SuiGasStatus,
1888        TransactionEffects,
1889        Vec<ExecutionTiming>,
1890        Result<(), ExecutionError>,
1891    ) {
1892        let (inner_temp_store, gas_status, effects, timings, execution_error) = executor
1893            // TODO only run this function on FullNodes, use `execute_transaction_to_effects` on validators.
1894            .execute_transaction_to_effects_and_execution_error(
1895                store,
1896                protocol_config,
1897                self.metrics.execution_metrics.clone(),
1898                enable_expensive_checks,
1899                execution_params,
1900                epoch_id,
1901                epoch_timestamp_ms,
1902                input_objects,
1903                system_object_versions,
1904                unsettled_object_funds,
1905                gas_data,
1906                gas_status,
1907                kind,
1908                rewritten_inputs,
1909                signer,
1910                tx_digest,
1911                &mut None,
1912            );
1913
1914        (
1915            inner_temp_store,
1916            gas_status,
1917            effects,
1918            timings,
1919            execution_error,
1920        )
1921    }
1922
1923    /// execute_certificate validates the transaction input, and executes the certificate,
1924    /// returning transaction outputs.
1925    ///
1926    /// It reads state from the db (both owned and shared locks), but it has no side effects.
1927    ///
1928    /// Executes a certificate and returns an ExecutionOutput.
1929    /// The function can fail with Fatal errors (e.g., the transaction input is invalid,
1930    /// locks are not held correctly, etc.) or transient errors (e.g., db read errors).
1931    #[instrument(level = "trace", skip_all)]
1932    fn execute_certificate(
1933        &self,
1934        _execution_guard: &ExecutionLockReadGuard<'_>,
1935        certificate: &VerifiedExecutableTransaction,
1936        input_objects: InputObjects,
1937        expected_effects_digest: Option<ExpectedEffectsDigest>,
1938        execution_env: ExecutionEnv,
1939        epoch_store: &Arc<AuthorityPerEpochStore>,
1940    ) -> ExecutionOutput<(
1941        TransactionOutputs,
1942        Vec<ExecutionTiming>,
1943        Option<ExecutionError>,
1944    )> {
1945        let _scope = monitored_scope("Execution::prepare_certificate");
1946        let _metrics_guard = self.metrics.prepare_certificate_latency.start_timer();
1947        let prepare_certificate_start_time = tokio::time::Instant::now();
1948
1949        // TODO: We need to move this to a more appropriate place to avoid redundant checks.
1950        let tx_data = certificate.data().transaction_data();
1951
1952        if let Err(e) = tx_data.validity_check(&epoch_store.tx_validity_check_context()) {
1953            return ExecutionOutput::Fatal(e);
1954        }
1955
1956        // The cost of partially re-auditing a transaction before execution is tolerated.
1957        // This step is required for correctness because, for example, ConsensusAddressOwner
1958        // object owner may have changed between signing and execution.
1959        let (gas_status, input_objects) = match sui_transaction_checks::check_certificate_input(
1960            certificate,
1961            input_objects,
1962            epoch_store.protocol_config(),
1963            epoch_store.reference_gas_price(),
1964        ) {
1965            Ok(result) => result,
1966            Err(e) => return ExecutionOutput::Fatal(e),
1967        };
1968
1969        let tx_digest = *certificate.digest();
1970        let protocol_config = epoch_store.protocol_config();
1971        let transaction_data = &certificate.data().intent_message().value;
1972        let sender = transaction_data.sender();
1973        let (mut kind, signer, gas_data) = transaction_data.execution_parts();
1974        let early_execution_error = get_early_execution_error(
1975            &tx_digest,
1976            &input_objects,
1977            self.config.certificate_deny_config.certificate_deny_set(),
1978            &execution_env.funds_withdraw_status,
1979        );
1980        let system_object_versions = execution_env.assigned_versions.system_object_versions;
1981        let accumulator_version = execution_env.assigned_versions.accumulator_version();
1982        let execution_params = match early_execution_error {
1983            None => ExecutionOrEarlyError::ok(accumulator_version),
1984            Some(errors) => ExecutionOrEarlyError::failed(errors, accumulator_version),
1985        };
1986
1987        // Skip on early error: the tx will fail anyway and rewriting may fail if the accumulator
1988        // was deleted.
1989        let rewritten_inputs = if execution_params.is_ok() {
1990            rewrite_transaction_for_coin_reservations(
1991                self.chain_identifier,
1992                &*self.coin_reservation_resolver,
1993                sender,
1994                &mut kind,
1995                execution_env.assigned_versions.accumulator_version(),
1996            )
1997            .expect("rewriting must succeed for a certified transaction")
1998        } else {
1999            None
2000        };
2001
2002        let tracking_store = TrackingBackingStore::new(self.get_backing_store().as_ref());
2003
2004        let unsettled_object_funds =
2005            self.unsettled_object_withdrawals.as_ref() as &dyn UnsettledObjectFundsRead;
2006
2007        #[allow(unused_mut)]
2008        let (inner_temp_store, _, mut effects, timings, execution_error_opt) = self
2009            .execute_transaction_to_effects(
2010                &**epoch_store.executor(),
2011                &tracking_store,
2012                protocol_config,
2013                // TODO: would be nice to pass the whole NodeConfig here, but it creates a
2014                // cyclic dependency w/ sui-adapter
2015                self.config
2016                    .expensive_safety_check_config
2017                    .enable_deep_per_tx_sui_conservation_check(),
2018                execution_params,
2019                &epoch_store.epoch_start_config().epoch_data().epoch_id(),
2020                epoch_store
2021                    .epoch_start_config()
2022                    .epoch_data()
2023                    .epoch_start_timestamp(),
2024                input_objects,
2025                system_object_versions,
2026                unsettled_object_funds,
2027                gas_data,
2028                gas_status,
2029                kind,
2030                rewritten_inputs,
2031                signer,
2032                tx_digest,
2033            );
2034
2035        if !protocol_config.check_object_funds_withdraw_in_execution() {
2036            // TODO: Move the object funds checker to the executor so that it can eventually be
2037            // removed from the active code path.
2038            let object_funds_checker = self.object_funds_checker.load();
2039            if let Some(object_funds_checker) = object_funds_checker.as_ref()
2040                && !object_funds_checker.should_commit_object_funds_withdraws(
2041                    certificate,
2042                    &effects,
2043                    &inner_temp_store.accumulator_running_max_withdraws,
2044                    &execution_env,
2045                    self.get_account_funds_read(),
2046                    &self.execution_scheduler,
2047                    epoch_store,
2048                )
2049            {
2050                assert_reachable_gated!("retry object withdraw later", |pc| !pc
2051                    .check_object_funds_withdraw_in_execution());
2052                return ExecutionOutput::RetryLater;
2053            }
2054        } else {
2055            match effects.status() {
2056                ExecutionStatus::Success => {
2057                    if let Some(accumulator_version) =
2058                        execution_env.assigned_versions.accumulator_version()
2059                    {
2060                        self.unsettled_object_withdrawals
2061                            .record_object_funds_withdraws(
2062                                certificate.transaction_data(),
2063                                &effects,
2064                                &inner_temp_store.accumulator_running_max_withdraws,
2065                                accumulator_version,
2066                                self.chain_identifier,
2067                            );
2068                    }
2069                }
2070                ExecutionStatus::Failure(failure) => {
2071                    if sui_types::funds_accumulator::is_object_funds_insufficient_abort(
2072                        &failure.error,
2073                    ) {
2074                        assert_reachable_gated!("object funds insufficient in execution", |pc| pc
2075                            .check_object_funds_withdraw_in_execution());
2076                        self.object_funds_checker_metrics
2077                            .in_execution_check_result
2078                            .with_label_values(&["insufficient"])
2079                            .inc();
2080                    }
2081                }
2082            }
2083        }
2084
2085        // (test-only) Inject a fork before the effects-digest check below. Placed here so that a
2086        // forked validator executing a *certified* checkpoint (expected_effects_digest is set, i.e.
2087        // the checkpoint-executor path) trips the transaction-fork check. On the builder path
2088        // (expected_effects_digest is None) the check is skipped, so this still produces a checkpoint
2089        // fork as before.
2090        fail_point_arg!("simulate_fork_during_execution", |(
2091            forked_validators,
2092            full_halt,
2093            effects_overrides,
2094            fork_probability,
2095            executor_path_only,
2096        ): (
2097            std::sync::Arc<
2098                std::sync::Mutex<std::collections::HashSet<sui_types::base_types::AuthorityName>>,
2099            >,
2100            bool,
2101            std::sync::Arc<std::sync::Mutex<std::collections::BTreeMap<String, String>>>,
2102            f32,
2103            bool,
2104        )| {
2105            #[cfg(msim)]
2106            // When `executor_path_only` is set, fork only while executing a certified checkpoint
2107            // (expected_effects_digest is set) so the divergence trips the transaction-fork check
2108            // below; otherwise fork on any path (the builder path yields a checkpoint fork).
2109            if !executor_path_only || expected_effects_digest.is_some() {
2110                self.simulate_fork_during_execution(
2111                    certificate,
2112                    epoch_store,
2113                    &mut effects,
2114                    forked_validators,
2115                    full_halt,
2116                    effects_overrides,
2117                    fork_probability,
2118                );
2119            }
2120        });
2121
2122        if let Some(expected) = expected_effects_digest
2123            && effects.digest() != expected.digest()
2124        {
2125            let expected_effects_digest = expected.digest();
2126            // We dont want to mask the original error, so we log it and continue.
2127            match self.debug_dump_transaction_state(
2128                &tx_digest,
2129                &effects,
2130                expected_effects_digest,
2131                &inner_temp_store,
2132                certificate,
2133                &self.config.state_debug_dump_config,
2134            ) {
2135                Ok(out_path) => {
2136                    info!(
2137                        "Dumped node state for transaction {} to {}",
2138                        tx_digest,
2139                        out_path.as_path().display().to_string()
2140                    );
2141                }
2142                Err(e) => {
2143                    error!("Error dumping state for transaction {}: {e}", tx_digest);
2144                }
2145            }
2146            let expected_effects = self
2147                .get_transaction_cache_reader()
2148                .get_effects(&expected_effects_digest);
2149            error!(
2150                ?tx_digest,
2151                ?expected,
2152                actual_effects = ?effects,
2153                expected_effects = ?expected_effects,
2154                "fork detected!"
2155            );
2156            if let Err(e) = self.checkpoint_store.record_transaction_fork_detected(
2157                tx_digest,
2158                expected_effects_digest,
2159                effects.digest(),
2160                expected.checkpoint_seq(),
2161            ) {
2162                error!("Failed to record transaction fork: {e}");
2163            }
2164
2165            fail_point_if!("kill_transaction_fork_node", || {
2166                #[cfg(msim)]
2167                {
2168                    tracing::error!(
2169                        fatal = true,
2170                        "Fork recovery test: killing node due to transaction effects fork for digest: {}",
2171                        tx_digest
2172                    );
2173                    sui_simulator::task::shutdown_current_node();
2174                }
2175            });
2176
2177            fatal!(
2178                "Transaction {} is expected to have effects digest {}, but got {}!",
2179                tx_digest,
2180                expected_effects_digest,
2181                effects.digest()
2182            );
2183        }
2184
2185        let unchanged_loaded_runtime_objects =
2186            crate::transaction_outputs::unchanged_loaded_runtime_objects(
2187                certificate.transaction_data(),
2188                &effects,
2189                &tracking_store.into_read_objects(),
2190            );
2191
2192        self.update_metrics(certificate, &inner_temp_store, &effects);
2193
2194        let transaction_outputs = TransactionOutputs::build_transaction_outputs(
2195            certificate.clone().into_unsigned(),
2196            effects,
2197            inner_temp_store,
2198            unchanged_loaded_runtime_objects,
2199        );
2200
2201        let elapsed = prepare_certificate_start_time.elapsed().as_micros() as f64;
2202        if elapsed > 0.0 {
2203            self.metrics.prepare_cert_gas_latency_ratio.observe(
2204                transaction_outputs
2205                    .effects
2206                    .gas_cost_summary()
2207                    .computation_cost as f64
2208                    / elapsed,
2209            );
2210        }
2211
2212        ExecutionOutput::Success((transaction_outputs, timings, execution_error_opt.err()))
2213    }
2214
2215    pub fn prepare_certificate_for_benchmark(
2216        &self,
2217        certificate: &VerifiedExecutableTransaction,
2218        input_objects: InputObjects,
2219        epoch_store: &Arc<AuthorityPerEpochStore>,
2220    ) -> SuiResult<(TransactionOutputs, Option<ExecutionError>)> {
2221        let lock = RwLock::new(epoch_store.epoch());
2222        let execution_guard = lock.try_read().unwrap();
2223
2224        let (transaction_outputs, _timings, execution_error_opt) = self
2225            .execute_certificate(
2226                &execution_guard,
2227                certificate,
2228                input_objects,
2229                None,
2230                ExecutionEnv::default(),
2231                epoch_store,
2232            )
2233            .unwrap();
2234        Ok((transaction_outputs, execution_error_opt))
2235    }
2236
2237    pub fn simulate_transaction(
2238        &self,
2239        transaction: TransactionData,
2240        checks: TransactionChecks,
2241        allow_mock_gas_coin: bool,
2242    ) -> SuiResult<SimulateTransactionResult> {
2243        if transaction.kind().is_system_tx() {
2244            return Err(SuiErrorKind::UnsupportedFeatureError {
2245                error: "simulate does not support system transactions".to_string(),
2246            }
2247            .into());
2248        }
2249
2250        let epoch_store = self.load_epoch_store_one_call_per_task();
2251        if !self.is_fullnode(&epoch_store) {
2252            return Err(SuiErrorKind::UnsupportedFeatureError {
2253                error: "simulate is only supported on fullnodes".to_string(),
2254            }
2255            .into());
2256        }
2257
2258        if checks.disabled() && self.config.dev_inspect_disabled {
2259            return Err(SuiErrorKind::UnsupportedFeatureError {
2260                error: "simulate with checks disabled is not allowed on this node".to_string(),
2261            }
2262            .into());
2263        }
2264
2265        let transaction_deny_config = self
2266            .transaction_deny_config_manager
2267            .effective_config()
2268            .load();
2269        let epoch_data = epoch_store.epoch_start_config().epoch_data();
2270        let suggested_gas_price = self
2271            .congestion_tracker
2272            .get_suggested_gas_prices(&transaction);
2273
2274        crate::transaction_simulation::simulate_transaction(
2275            transaction,
2276            checks,
2277            allow_mock_gas_coin,
2278            suggested_gas_price,
2279            epoch_store.tx_validity_check_context(),
2280            epoch_data.epoch_id(),
2281            epoch_data.epoch_start_timestamp(),
2282            self.chain_identifier,
2283            transaction_deny_config.as_ref(),
2284            self.config.certificate_deny_config.certificate_deny_set(),
2285            &self.input_loader,
2286            self.get_backing_store().as_ref(),
2287            self.get_backing_package_store().as_ref(),
2288            epoch_store.simulate_executor().as_ref(),
2289            self.coin_reservation_resolver.as_ref(),
2290            self.get_account_funds_read().as_ref(),
2291            &self.config.verifier_signing_config,
2292            &self.metrics.bytecode_verifier_metrics,
2293            &self.metrics.execution_metrics,
2294        )
2295    }
2296
2297    // Only used for testing because of how epoch store is loaded.
2298    pub fn reference_gas_price_for_testing(&self) -> Result<u64, anyhow::Error> {
2299        let epoch_store = self.epoch_store_for_testing();
2300        Ok(epoch_store.reference_gas_price())
2301    }
2302
2303    pub fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
2304        self.get_transaction_cache_reader()
2305            .is_tx_already_executed(digest)
2306    }
2307
2308    #[cfg(msim)]
2309    fn simulate_fork_during_execution(
2310        &self,
2311        certificate: &VerifiedExecutableTransaction,
2312        epoch_store: &Arc<AuthorityPerEpochStore>,
2313        effects: &mut TransactionEffects,
2314        forked_validators: std::sync::Arc<
2315            std::sync::Mutex<std::collections::HashSet<sui_types::base_types::AuthorityName>>,
2316        >,
2317        full_halt: bool,
2318        effects_overrides: std::sync::Arc<
2319            std::sync::Mutex<std::collections::BTreeMap<String, String>>,
2320        >,
2321        fork_probability: f32,
2322    ) {
2323        static TOTAL_FAILING_STAKE: std::sync::Mutex<u64> = std::sync::Mutex::new(0);
2324        if !certificate.data().intent_message().value.is_system_tx() {
2325            let committee = epoch_store.committee();
2326            let cur_stake = (**committee).weight(&self.name);
2327            if cur_stake > 0 {
2328                {
2329                    let mut total_stake = TOTAL_FAILING_STAKE.lock().unwrap();
2330                    let total_stake = &mut *total_stake;
2331                    let already_forked = forked_validators
2332                        .lock()
2333                        .ok()
2334                        .map(|set| set.contains(&self.name))
2335                        .unwrap_or(false);
2336
2337                    if !already_forked {
2338                        let should_fork = if full_halt {
2339                            // For full halt, fork enough nodes to reach validity threshold
2340                            *total_stake <= committee.validity_threshold()
2341                        } else {
2342                            // For partial fork, stay strictly below validity threshold
2343                            *total_stake + cur_stake < committee.validity_threshold()
2344                        };
2345
2346                        if should_fork {
2347                            *total_stake += cur_stake;
2348
2349                            if let Ok(mut external_set) = forked_validators.lock() {
2350                                external_set.insert(self.name);
2351                                info!("forked_validators: {:?}", external_set);
2352                            }
2353                        }
2354                    }
2355
2356                    if let Ok(external_set) = forked_validators.lock() {
2357                        if external_set.contains(&self.name) {
2358                            // If effects_overrides is empty, deterministically select a tx_digest to fork with 1/100 probability.
2359                            // Fork this transaction and record the digest and the original effects to original_effects.
2360                            // If original_effects is nonempty and contains a key matching this transaction digest (i.e.
2361                            // the transaction was forked on a different validator), fork this txn as well.
2362
2363                            let tx_digest = certificate.digest().to_string();
2364                            if let Ok(mut overrides) = effects_overrides.lock() {
2365                                if overrides.contains_key(&tx_digest)
2366                                    || overrides.is_empty()
2367                                        && sui_simulator::random::deterministic_probability(
2368                                            &tx_digest,
2369                                            fork_probability,
2370                                        )
2371                                {
2372                                    let original_effects_digest = effects.digest().to_string();
2373                                    overrides
2374                                        .insert(tx_digest.clone(), original_effects_digest.clone());
2375                                    info!(
2376                                        ?tx_digest,
2377                                        ?original_effects_digest,
2378                                        "Captured forked effects digest for transaction"
2379                                    );
2380                                    effects.gas_cost_summary_mut_for_testing().computation_cost +=
2381                                        1;
2382                                }
2383                            }
2384                        }
2385                    }
2386                }
2387            }
2388        }
2389    }
2390
2391    pub fn unixtime_now_ms() -> u64 {
2392        let now = SystemTime::now()
2393            .duration_since(UNIX_EPOCH)
2394            .expect("Time went backwards")
2395            .as_millis();
2396        u64::try_from(now).expect("Travelling in time machine")
2397    }
2398
2399    // TODO(fastpath): update this handler for Mysticeti fastpath.
2400    // There will no longer be validator quorum signed transactions or effects.
2401    // The proof of finality needs to come from checkpoints.
2402    #[instrument(level = "trace", skip_all)]
2403    pub async fn handle_transaction_info_request(
2404        &self,
2405        request: TransactionInfoRequest,
2406    ) -> SuiResult<TransactionInfoResponse> {
2407        let epoch_store = self.load_epoch_store_one_call_per_task();
2408        let (transaction, status) = self
2409            .get_transaction_status(&request.transaction_digest, &epoch_store)?
2410            .ok_or(SuiErrorKind::TransactionNotFound {
2411                digest: request.transaction_digest,
2412            })?;
2413        Ok(TransactionInfoResponse {
2414            transaction,
2415            status,
2416        })
2417    }
2418
2419    #[instrument(level = "trace", skip_all)]
2420    pub async fn handle_object_info_request(
2421        &self,
2422        request: ObjectInfoRequest,
2423    ) -> SuiResult<ObjectInfoResponse> {
2424        let requested_object_seq = match request.request_kind {
2425            ObjectInfoRequestKind::LatestObjectInfo => {
2426                let (_, seq, _) =
2427                    self.get_object_or_tombstone(request.object_id)
2428                        .ok_or_else(|| {
2429                            SuiError::from(UserInputError::ObjectNotFound {
2430                                object_id: request.object_id,
2431                                version: None,
2432                            })
2433                        })?;
2434                seq
2435            }
2436            ObjectInfoRequestKind::PastObjectInfoDebug(seq) => seq,
2437        };
2438
2439        let object = self
2440            .get_object_store()
2441            .get_object_by_key(&request.object_id, requested_object_seq)
2442            .ok_or_else(|| {
2443                SuiError::from(UserInputError::ObjectNotFound {
2444                    object_id: request.object_id,
2445                    version: Some(requested_object_seq),
2446                })
2447            })?;
2448
2449        let layout = if let (LayoutGenerationOption::Generate, Some(move_obj)) =
2450            (request.generate_layout, object.data.try_as_move())
2451        {
2452            let epoch_store = self.load_epoch_store_one_call_per_task();
2453            Some(into_struct_layout(
2454                epoch_store
2455                    .executor()
2456                    .type_layout_resolver(
2457                        epoch_store.protocol_config(),
2458                        Box::new(self.get_backing_package_store().as_ref()),
2459                    )
2460                    .get_annotated_layout(&move_obj.type_().clone().into())?,
2461            )?)
2462        } else {
2463            None
2464        };
2465
2466        Ok(ObjectInfoResponse {
2467            object,
2468            layout,
2469            // Validators no longer store signed transactions, so the locking
2470            // transaction cannot be returned.
2471            lock_for_debugging: None,
2472        })
2473    }
2474
2475    #[instrument(level = "trace", skip_all)]
2476    pub fn handle_checkpoint_request(
2477        &self,
2478        request: &CheckpointRequest,
2479    ) -> SuiResult<CheckpointResponse> {
2480        let summary = match request.sequence_number {
2481            Some(seq) => self
2482                .checkpoint_store
2483                .get_checkpoint_by_sequence_number(seq)?,
2484            None => self.checkpoint_store.get_latest_certified_checkpoint()?,
2485        }
2486        .map(|v| v.into_inner());
2487        let contents = match &summary {
2488            Some(s) => self
2489                .checkpoint_store
2490                .get_checkpoint_contents(&s.content_digest)?,
2491            None => None,
2492        };
2493        Ok(CheckpointResponse {
2494            checkpoint: summary,
2495            contents,
2496        })
2497    }
2498
2499    #[instrument(level = "trace", skip_all)]
2500    pub fn handle_checkpoint_request_v2(
2501        &self,
2502        request: &CheckpointRequestV2,
2503    ) -> SuiResult<CheckpointResponseV2> {
2504        let summary = if request.certified {
2505            let summary = match request.sequence_number {
2506                Some(seq) => self
2507                    .checkpoint_store
2508                    .get_checkpoint_by_sequence_number(seq)?,
2509                None => self.checkpoint_store.get_latest_certified_checkpoint()?,
2510            }
2511            .map(|v| v.into_inner());
2512            summary.map(CheckpointSummaryResponse::Certified)
2513        } else {
2514            let summary = match request.sequence_number {
2515                Some(seq) => self.checkpoint_store.get_locally_computed_checkpoint(seq)?,
2516                None => self
2517                    .checkpoint_store
2518                    .get_latest_locally_computed_checkpoint()?,
2519            };
2520            summary.map(CheckpointSummaryResponse::Pending)
2521        };
2522        let contents = match &summary {
2523            Some(s) => self
2524                .checkpoint_store
2525                .get_checkpoint_contents(&s.content_digest())?,
2526            None => None,
2527        };
2528        Ok(CheckpointResponseV2 {
2529            checkpoint: summary,
2530            contents,
2531        })
2532    }
2533
2534    fn check_protocol_version(
2535        supported_protocol_versions: SupportedProtocolVersions,
2536        current_version: ProtocolVersion,
2537    ) {
2538        info!("current protocol version is now {:?}", current_version);
2539        info!("supported versions are: {:?}", supported_protocol_versions);
2540        if !supported_protocol_versions.is_version_supported(current_version) {
2541            let msg = format!(
2542                "Unsupported protocol version. The network is at {:?}, but this SuiNode only supports: {:?}. Shutting down.",
2543                current_version, supported_protocol_versions,
2544            );
2545
2546            error!("{}", msg);
2547            eprintln!("{}", msg);
2548
2549            #[cfg(not(msim))]
2550            std::process::exit(1);
2551
2552            #[cfg(msim)]
2553            sui_simulator::task::shutdown_current_node();
2554        }
2555    }
2556
2557    #[allow(clippy::disallowed_methods)] // allow unbounded_channel()
2558    #[allow(clippy::too_many_arguments)]
2559    pub async fn new(
2560        name: AuthorityName,
2561        secret: StableSyncAuthoritySigner,
2562        supported_protocol_versions: SupportedProtocolVersions,
2563        store: Arc<AuthorityStore>,
2564        execution_cache_trait_pointers: ExecutionCacheTraitPointers,
2565        epoch_store: Arc<AuthorityPerEpochStore>,
2566        committee_store: Arc<CommitteeStore>,
2567        rpc_store: Option<RpcStore>,
2568        checkpoint_store: Arc<CheckpointStore>,
2569        prometheus_registry: &Registry,
2570        db_checkpoint_config: &DBCheckpointConfig,
2571        config: NodeConfig,
2572        chain_identifier: ChainIdentifier,
2573        policy_config: Option<PolicyConfig>,
2574        firewall_config: Option<RemoteFirewallConfig>,
2575        pruner_watermarks: Arc<PrunerWatermarks>,
2576    ) -> Arc<Self> {
2577        Self::check_protocol_version(supported_protocol_versions, epoch_store.protocol_version());
2578
2579        let metrics = Arc::new(AuthorityMetrics::new(prometheus_registry));
2580        let (tx_ready_certificates, rx_ready_certificates) = unbounded_channel();
2581        let execution_scheduler = Arc::new(ExecutionScheduler::new(
2582            execution_cache_trait_pointers.object_cache_reader.clone(),
2583            execution_cache_trait_pointers.account_funds_read.clone(),
2584            execution_cache_trait_pointers
2585                .transaction_cache_reader
2586                .clone(),
2587            tx_ready_certificates,
2588            &epoch_store,
2589            config.funds_withdraw_scheduler_type,
2590            metrics.clone(),
2591            prometheus_registry,
2592        ));
2593        let (tx_execution_shutdown, rx_execution_shutdown) = oneshot::channel();
2594
2595        let _authority_per_epoch_pruner = AuthorityPerEpochStorePruner::new(
2596            epoch_store.get_parent_path(),
2597            &config.authority_store_pruning_config,
2598        );
2599        let _pruner = AuthorityStorePruner::new(
2600            store.perpetual_tables.clone(),
2601            checkpoint_store.clone(),
2602            rpc_store,
2603            config.authority_store_pruning_config.clone(),
2604            epoch_store.committee().authority_exists(&name),
2605            epoch_store.epoch_start_state().epoch_duration_ms(),
2606            prometheus_registry,
2607            pruner_watermarks,
2608        );
2609        let input_loader =
2610            TransactionInputLoader::new(execution_cache_trait_pointers.object_cache_reader.clone());
2611        let epoch = epoch_store.epoch();
2612        let traffic_controller_metrics =
2613            Arc::new(TrafficControllerMetrics::new(prometheus_registry));
2614        let traffic_controller = if let Some(policy_config) = policy_config {
2615            Some(Arc::new(
2616                TrafficController::init(
2617                    policy_config,
2618                    traffic_controller_metrics,
2619                    firewall_config.clone(),
2620                )
2621                .await,
2622            ))
2623        } else {
2624            None
2625        };
2626
2627        let fork_recovery_state = config.fork_recovery.as_ref().map(|fork_config| {
2628            ForkRecoveryState::new(Some(fork_config))
2629                .expect("Failed to initialize fork recovery state")
2630        });
2631
2632        let coin_reservation_resolver = Arc::new(CachingCoinReservationResolver::new(
2633            execution_cache_trait_pointers
2634                .runtime_object_resolver
2635                .clone(),
2636        ));
2637
2638        let object_funds_checker_metrics =
2639            Arc::new(ObjectFundsCheckerMetrics::new(prometheus_registry));
2640
2641        let transaction_deny_config_manager = TransactionDenyConfigManager::new(
2642            name,
2643            config.transaction_deny_config.clone(),
2644            config.peer_deny_sync_config.clone(),
2645            epoch_store.committee().clone(),
2646            store.perpetual_tables.clone(),
2647            prometheus_registry,
2648        )
2649        .expect("Failed to initialize TransactionDenyConfigManager");
2650        // Drop any cached entries from peers no longer in the active committee.
2651        if let Err(e) =
2652            transaction_deny_config_manager.update_for_committee(epoch_store.committee().clone())
2653        {
2654            warn!(
2655                "Initial update_for_committee failed during AuthorityState init: {:?}",
2656                e
2657            );
2658        }
2659
2660        let state = Arc::new(AuthorityState {
2661            name,
2662            secret,
2663            execution_lock: RwLock::new(epoch),
2664            epoch_store: ArcSwap::new(epoch_store.clone()),
2665            input_loader,
2666            execution_cache_trait_pointers,
2667            coin_reservation_resolver,
2668            checkpoint_store,
2669            committee_store,
2670            execution_scheduler,
2671            tx_execution_shutdown: Mutex::new(Some(tx_execution_shutdown)),
2672            metrics,
2673            _pruner,
2674            _authority_per_epoch_pruner,
2675            db_checkpoint_config: db_checkpoint_config.clone(),
2676            config,
2677            overload_info: AuthorityOverloadInfo::default(),
2678            chain_identifier,
2679            congestion_tracker: Arc::new(CongestionTracker::new()),
2680            consensus_gasless_counter: Arc::new(ConsensusGaslessCounter::default()),
2681            traffic_controller,
2682            fork_recovery_state,
2683            notify_epoch: tokio::sync::watch::channel(epoch).0,
2684            object_funds_checker: ArcSwapOption::empty(),
2685            // unsettled_object_withdrawals needs to be initialized unconditionally, even on fullnodes.
2686            // Once we enable object funds checking during execution, fullnodes will need it to track
2687            // unsettled object withdraws as well similar to validators.
2688            unsettled_object_withdrawals: Arc::new(UnsettledObjectWithdrawals::new(
2689                object_funds_checker_metrics.clone(),
2690            )),
2691            object_funds_checker_metrics,
2692            transaction_deny_config_manager,
2693        });
2694        state.init_object_funds_checker().await;
2695
2696        // Start a task to execute ready certificates.
2697        let authority_state = Arc::downgrade(&state);
2698        let causal_admission = state.execution_scheduler.causal_admission().clone();
2699        spawn_monitored_task!(execution_process(
2700            authority_state,
2701            rx_ready_certificates,
2702            rx_execution_shutdown,
2703            causal_admission,
2704        ));
2705        if epoch_store
2706            .protocol_config()
2707            .enable_multi_epoch_transaction_expiration()
2708            && epoch_store.epoch() > 0
2709        {
2710            use typed_store::Map;
2711            let previous_epoch = epoch_store.epoch() - 1;
2712            let start_key = (previous_epoch, TransactionDigest::ZERO);
2713            let end_key = (previous_epoch + 1, TransactionDigest::ZERO);
2714            let has_previous_epoch_data = store
2715                .perpetual_tables
2716                .executed_transaction_digests
2717                .safe_range_iter(start_key..end_key)
2718                .next()
2719                .is_some();
2720
2721            if !has_previous_epoch_data {
2722                panic!(
2723                    "enable_multi_epoch_transaction_expiration is enabled but no transaction data found for previous epoch {}. \
2724                    This indicates the node was restored using an old version of sui-tool that does not backfill the table. \
2725                    Please restore from a snapshot using the latest version of sui-tool.",
2726                    previous_epoch
2727                );
2728            }
2729        }
2730
2731        state
2732    }
2733
2734    async fn init_object_funds_checker(&self) {
2735        let epoch_store = self.epoch_store.load();
2736        // TODO: Once we enable object funds checking during execution, we will no longer need to initialize the object funds checker here.
2737        if self.node_role(&epoch_store).runs_consensus()
2738            && epoch_store.protocol_config().enable_object_funds_withdraw()
2739        {
2740            if self.object_funds_checker.load().is_none() {
2741                let inner = self.get_object(&SUI_ACCUMULATOR_ROOT_OBJECT_ID).map(|o| {
2742                    Arc::new(ObjectFundsCheckerDEPRECATED::new(
2743                        o.version(),
2744                        self.unsettled_object_withdrawals.clone(),
2745                        self.object_funds_checker_metrics.clone(),
2746                    ))
2747                });
2748                self.object_funds_checker.store(inner);
2749            }
2750        } else {
2751            self.object_funds_checker.store(None);
2752        }
2753    }
2754
2755    // TODO: Consolidate our traits to reduce the number of methods here.
2756    pub fn get_object_cache_reader(&self) -> &Arc<dyn ObjectCacheRead> {
2757        &self.execution_cache_trait_pointers.object_cache_reader
2758    }
2759
2760    pub fn get_transaction_cache_reader(&self) -> &Arc<dyn TransactionCacheRead> {
2761        &self.execution_cache_trait_pointers.transaction_cache_reader
2762    }
2763
2764    pub fn get_cache_writer(&self) -> &Arc<dyn ExecutionCacheWrite> {
2765        &self.execution_cache_trait_pointers.cache_writer
2766    }
2767
2768    pub fn get_backing_store(&self) -> &Arc<dyn BackingStore + Send + Sync> {
2769        &self.execution_cache_trait_pointers.backing_store
2770    }
2771
2772    pub fn get_runtime_object_resolver(&self) -> &Arc<dyn RuntimeObjectResolver + Send + Sync> {
2773        &self.execution_cache_trait_pointers.runtime_object_resolver
2774    }
2775
2776    pub(crate) fn get_account_funds_read(&self) -> &Arc<dyn AccountFundsRead> {
2777        &self.execution_cache_trait_pointers.account_funds_read
2778    }
2779
2780    pub fn get_backing_package_store(&self) -> &Arc<dyn BackingPackageStore + Send + Sync> {
2781        &self.execution_cache_trait_pointers.backing_package_store
2782    }
2783
2784    pub fn get_object_store(&self) -> &Arc<dyn ObjectStore + Send + Sync> {
2785        &self.execution_cache_trait_pointers.object_store
2786    }
2787
2788    pub fn get_reconfig_api(&self) -> &Arc<dyn ExecutionCacheReconfigAPI> {
2789        &self.execution_cache_trait_pointers.reconfig_api
2790    }
2791
2792    pub fn get_global_state_hash_store(&self) -> &Arc<dyn GlobalStateHashStore> {
2793        &self.execution_cache_trait_pointers.global_state_hash_store
2794    }
2795
2796    pub fn get_checkpoint_cache(&self) -> &Arc<dyn CheckpointCache> {
2797        &self.execution_cache_trait_pointers.checkpoint_cache
2798    }
2799
2800    pub fn get_state_sync_store(&self) -> &Arc<dyn StateSyncAPI> {
2801        &self.execution_cache_trait_pointers.state_sync_store
2802    }
2803
2804    pub fn get_cache_commit(&self) -> &Arc<dyn ExecutionCacheCommit> {
2805        &self.execution_cache_trait_pointers.cache_commit
2806    }
2807
2808    pub fn database_for_testing(&self) -> Arc<AuthorityStore> {
2809        self.execution_cache_trait_pointers
2810            .testing_api
2811            .database_for_testing()
2812    }
2813
2814    /// Access to the underlying authority store for diagnostic tooling (db-shell).
2815    ///
2816    /// Goes through `testing_api` deliberately: db-shell is read-only diagnostics
2817    /// that bypasses the writeback cache, and we want the execution path to have
2818    /// no other route to the raw `AuthorityStore`. Using the testing API here
2819    /// keeps that invariant visible — diagnostic code is the only non-test caller.
2820    pub fn authority_store(&self) -> Arc<AuthorityStore> {
2821        self.execution_cache_trait_pointers
2822            .testing_api
2823            .database_for_testing()
2824    }
2825
2826    pub fn cache_for_testing(&self) -> &WritebackCache {
2827        self.execution_cache_trait_pointers
2828            .testing_api
2829            .cache_for_testing()
2830    }
2831
2832    pub async fn prune_checkpoints_for_eligible_epochs_for_testing(
2833        &self,
2834        config: NodeConfig,
2835        metrics: Arc<AuthorityStorePruningMetrics>,
2836    ) -> anyhow::Result<()> {
2837        use crate::authority::authority_store_pruner::PrunerWatermarks;
2838        let watermarks = Arc::new(PrunerWatermarks::default());
2839        AuthorityStorePruner::prune_checkpoints_for_eligible_epochs(
2840            &self.database_for_testing().perpetual_tables,
2841            &self.checkpoint_store,
2842            None,
2843            config.authority_store_pruning_config,
2844            metrics,
2845            EPOCH_DURATION_MS_FOR_TESTING,
2846            &watermarks,
2847        )
2848        .await
2849    }
2850
2851    pub fn execution_scheduler(&self) -> &Arc<ExecutionScheduler> {
2852        &self.execution_scheduler
2853    }
2854
2855    /// Attempts to acquire execution lock for an executable transaction.
2856    /// Returns Some(lock) if the transaction is matching current executed epoch.
2857    /// Returns None if validator is halted at epoch end or epoch mismatch.
2858    pub fn execution_lock_for_executable_transaction(
2859        &self,
2860        transaction: &VerifiedExecutableTransaction,
2861    ) -> Option<ExecutionLockReadGuard<'_>> {
2862        let lock = self.execution_lock.try_read().ok()?;
2863        if *lock == transaction.auth_sig().epoch() {
2864            Some(lock)
2865        } else {
2866            // TODO: Can this still happen?
2867            None
2868        }
2869    }
2870
2871    /// Acquires the execution lock for the duration of transaction validation.
2872    /// This prevents reconfiguration from starting until we are finished validating the transaction.
2873    fn execution_lock_for_validation(&self) -> SuiResult<ExecutionLockReadGuard<'_>> {
2874        self.execution_lock
2875            .try_read()
2876            .map_err(|_| SuiErrorKind::ValidatorHaltedAtEpochEnd.into())
2877    }
2878
2879    pub async fn execution_lock_for_reconfiguration(&self) -> ExecutionLockWriteGuard<'_> {
2880        self.execution_lock.write().await
2881    }
2882
2883    #[instrument(level = "error", skip_all)]
2884    pub async fn reconfigure(
2885        &self,
2886        cur_epoch_store: &AuthorityPerEpochStore,
2887        supported_protocol_versions: SupportedProtocolVersions,
2888        new_committee: Committee,
2889        epoch_start_configuration: EpochStartConfiguration,
2890        state_hasher: Arc<GlobalStateHasher>,
2891        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
2892        epoch_last_checkpoint: CheckpointSequenceNumber,
2893    ) -> SuiResult<Arc<AuthorityPerEpochStore>> {
2894        Self::check_protocol_version(
2895            supported_protocol_versions,
2896            epoch_start_configuration
2897                .epoch_start_state()
2898                .protocol_version(),
2899        );
2900
2901        self.committee_store.insert_new_committee(&new_committee)?;
2902
2903        // Wait until no transactions are being executed.
2904        let mut execution_lock = self.execution_lock_for_reconfiguration().await;
2905
2906        // Terminate all epoch-specific tasks (those started with within_alive_epoch).
2907        cur_epoch_store.epoch_terminated().await;
2908
2909        // Record metrics in case the node has not observed epoch close in consensus.
2910        cur_epoch_store.record_epoch_close_time_once();
2911
2912        // Safe to begin reconfiguration now. No transactions are being executed,
2913        // and no epoch-specific tasks are running.
2914
2915        self.get_reconfig_api()
2916            .clear_state_end_of_epoch(&execution_lock);
2917        self.check_system_consistency(cur_epoch_store, state_hasher, expensive_safety_check_config);
2918        self.maybe_reaccumulate_state_hash(
2919            cur_epoch_store,
2920            epoch_start_configuration
2921                .epoch_start_state()
2922                .protocol_version(),
2923        );
2924        self.get_reconfig_api()
2925            .set_epoch_start_configuration(&epoch_start_configuration);
2926        if let Some(checkpoint_path) = &self.db_checkpoint_config.checkpoint_path
2927            && self
2928                .db_checkpoint_config
2929                .perform_db_checkpoints_at_epoch_end
2930        {
2931            let current_epoch = cur_epoch_store.epoch();
2932            let epoch_checkpoint_path = checkpoint_path.join(format!("epoch_{}", current_epoch));
2933            self.checkpoint_all_dbs(&epoch_checkpoint_path, cur_epoch_store)?;
2934        }
2935
2936        self.get_reconfig_api()
2937            .reconfigure_cache(&epoch_start_configuration)
2938            .await;
2939
2940        let new_epoch = new_committee.epoch;
2941        let new_epoch_store = self
2942            .reopen_epoch_db(
2943                cur_epoch_store,
2944                new_committee,
2945                epoch_start_configuration,
2946                expensive_safety_check_config,
2947                epoch_last_checkpoint,
2948            )
2949            .await?;
2950        assert_eq!(new_epoch_store.epoch(), new_epoch);
2951        self.execution_scheduler
2952            .reconfigure(&new_epoch_store, self.get_account_funds_read());
2953        self.init_object_funds_checker().await;
2954
2955        // Update the committee and drop entries for peers no longer in it before tx
2956        // processing resumes for the new epoch.
2957        if let Err(e) = self
2958            .transaction_deny_config_manager
2959            .update_for_committee(new_epoch_store.committee().clone())
2960        {
2961            warn!(
2962                "TransactionDenyConfigManager update_for_committee failed at reconfigure: {:?}",
2963                e
2964            );
2965        }
2966
2967        *execution_lock = new_epoch;
2968
2969        self.notify_epoch(new_epoch);
2970        // drop execution_lock after epoch store was updated
2971        // see also assert in AuthorityState::process_certificate
2972        // on the epoch store and execution lock epoch match
2973        Ok(new_epoch_store)
2974    }
2975
2976    fn notify_epoch(&self, new_epoch: EpochId) {
2977        self.notify_epoch.send_modify(|epoch| *epoch = new_epoch);
2978    }
2979
2980    pub async fn wait_for_epoch(&self, target_epoch: EpochId) -> Result<EpochId, RecvError> {
2981        let mut rx = self.notify_epoch.subscribe();
2982        loop {
2983            let epoch = *rx.borrow();
2984            if epoch >= target_epoch {
2985                return Ok(epoch);
2986            }
2987            rx.changed().await?;
2988        }
2989    }
2990
2991    /// The accumulator root version a transaction executed right now would read, or
2992    /// None when accumulators are not enabled. Test paths that execute directly attach
2993    /// this to their assigned versions: the test version-assignment helper assigns no
2994    /// root version, but execution reads the root implicitly for object funds withdraws.
2995    pub fn accumulator_version_for_testing(
2996        &self,
2997    ) -> Option<sui_types::base_types::ConsensusObjectVersion> {
2998        let initial_shared_version = self
2999            .epoch_store_for_testing()
3000            .epoch_start_config()
3001            .accumulator_root_obj_initial_shared_version()?;
3002        let version = self.get_object(&SUI_ACCUMULATOR_ROOT_OBJECT_ID)?.version();
3003        Some(sui_types::base_types::ConsensusObjectVersion {
3004            initial_shared_version,
3005            version,
3006        })
3007    }
3008
3009    /// Executes accumulator settlement for testing purposes.
3010    /// Returns a list of (transaction, execution_env) pairs that can be replayed on another
3011    /// AuthorityState (e.g., a fullnode) using `replay_settlement_for_testing`.
3012    pub async fn settle_accumulator_for_testing(
3013        &self,
3014        effects: &[TransactionEffects],
3015        checkpoint_seq: Option<u64>,
3016    ) -> Vec<(VerifiedExecutableTransaction, ExecutionEnv)> {
3017        let accumulator_version = self
3018            .get_object(&SUI_ACCUMULATOR_ROOT_OBJECT_ID)
3019            .unwrap()
3020            .version();
3021        // Use provided checkpoint sequence, or fall back to accumulator version.
3022        let ckpt_seq = checkpoint_seq.unwrap_or_else(|| accumulator_version.value());
3023        let builder = AccumulatorSettlementTxBuilder::new(
3024            Some(self.get_transaction_cache_reader().as_ref()),
3025            effects,
3026            ckpt_seq,
3027            0,
3028        );
3029        let balance_changes = builder.collect_funds_changes();
3030        let epoch_store = self.epoch_store_for_testing();
3031        let epoch = epoch_store.epoch();
3032        let accumulator_root_obj_initial_shared_version = epoch_store
3033            .epoch_start_config()
3034            .accumulator_root_obj_initial_shared_version()
3035            .unwrap();
3036        let settlements = builder.build_tx(
3037            epoch_store.protocol_config(),
3038            epoch,
3039            accumulator_root_obj_initial_shared_version,
3040            ckpt_seq,
3041            ckpt_seq,
3042        );
3043
3044        let settlements: Vec<_> = settlements
3045            .into_iter()
3046            .map(|tx| {
3047                VerifiedExecutableTransaction::new_system(
3048                    VerifiedTransaction::new_system_transaction(tx),
3049                    epoch,
3050                )
3051            })
3052            .collect();
3053
3054        // The test version-assignment helper assigns no accumulator root version, and
3055        // the barrier settles object funds at the version it writes.
3056        let root_version = sui_types::base_types::ConsensusObjectVersion {
3057            initial_shared_version: accumulator_root_obj_initial_shared_version,
3058            version: accumulator_version,
3059        };
3060        let with_root_version = |assigned: shared_object_version_manager::AssignedVersions| {
3061            assigned.with_accumulator_version_for_testing(root_version)
3062        };
3063
3064        let assigned_versions = epoch_store
3065            .assign_shared_object_versions_for_tests(
3066                self.get_object_cache_reader().as_ref(),
3067                &settlements,
3068            )
3069            .unwrap();
3070        let version_map = assigned_versions.into_map();
3071
3072        let mut replay_txns = Vec::new();
3073        let mut settlement_effects = Vec::with_capacity(settlements.len());
3074        for tx in settlements {
3075            let assigned = with_root_version(version_map.get(&tx.key()).unwrap().clone());
3076            let env = ExecutionEnv::new().with_assigned_versions(assigned);
3077            let (effects, _) = self
3078                .try_execute_immediately(&tx.clone(), env.clone(), &epoch_store)
3079                .unwrap();
3080            assert!(effects.status().is_ok());
3081            replay_txns.push((tx, env));
3082            settlement_effects.push(effects);
3083        }
3084
3085        let barrier = accumulators::build_accumulator_barrier_tx(
3086            epoch,
3087            accumulator_root_obj_initial_shared_version,
3088            ckpt_seq,
3089            &settlement_effects,
3090        );
3091        let barrier = VerifiedExecutableTransaction::new_system(
3092            VerifiedTransaction::new_system_transaction(barrier),
3093            epoch,
3094        );
3095
3096        let assigned_versions = epoch_store
3097            .assign_shared_object_versions_for_tests(
3098                self.get_object_cache_reader().as_ref(),
3099                std::slice::from_ref(&barrier),
3100            )
3101            .unwrap();
3102        let version_map = assigned_versions.into_map();
3103
3104        let barrier_assigned = with_root_version(version_map.get(&barrier.key()).unwrap().clone());
3105        let env = ExecutionEnv::new().with_assigned_versions(barrier_assigned);
3106        let (effects, _) = self
3107            .try_execute_immediately(&barrier.clone(), env.clone(), &epoch_store)
3108            .unwrap();
3109        assert!(effects.status().is_ok());
3110        replay_txns.push((barrier, env));
3111
3112        let next_accumulator_version = accumulator_version.next();
3113        self.execution_scheduler
3114            .settle_address_funds(FundsSettlement {
3115                funds_changes: balance_changes,
3116                next_accumulator_version,
3117            });
3118        // object funds are settled while executing the barrier transaction
3119
3120        replay_txns
3121    }
3122
3123    /// Replays settlement transactions on this AuthorityState.
3124    /// Used to sync a fullnode with settlement transactions executed on a validator.
3125    pub async fn replay_settlement_for_testing(
3126        &self,
3127        txns: &[(VerifiedExecutableTransaction, ExecutionEnv)],
3128    ) {
3129        let epoch_store = self.epoch_store_for_testing();
3130        for (tx, env) in txns {
3131            let (effects, _) = self
3132                .try_execute_immediately(tx, env.clone(), &epoch_store)
3133                .unwrap();
3134            assert!(effects.status().is_ok());
3135        }
3136    }
3137
3138    /// Advance the epoch store to the next epoch for testing only.
3139    /// This only manually sets all the places where we have the epoch number.
3140    /// It doesn't properly reconfigure the node, hence should be only used for testing.
3141    pub async fn reconfigure_for_testing(&self) {
3142        let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3143        let epoch_store = self.epoch_store_for_testing().clone();
3144        let protocol_config = epoch_store.protocol_config().clone();
3145        // The current protocol config used in the epoch store may have been overridden and diverged from
3146        // the protocol config definitions. That override may have now been dropped when the initial guard was dropped.
3147        // We reapply the override before creating the new epoch store, to make sure that
3148        // the new epoch store has the same protocol config as the current one.
3149        // Since this is for testing only, we mostly like to keep the protocol config the same
3150        // across epochs.
3151        let _guard =
3152            ProtocolConfig::apply_overrides_for_testing(move |_, _| protocol_config.clone());
3153        let new_epoch_store = epoch_store.new_at_next_epoch_for_testing(
3154            self.get_backing_package_store().clone(),
3155            self.get_object_store().clone(),
3156            &self.config.expensive_safety_check_config,
3157            self.checkpoint_store
3158                .get_epoch_last_checkpoint(epoch_store.epoch())
3159                .unwrap()
3160                .map(|c| *c.sequence_number())
3161                .unwrap_or_default(),
3162        );
3163        self.execution_scheduler
3164            .reconfigure(&new_epoch_store, self.get_account_funds_read());
3165        let new_epoch = new_epoch_store.epoch();
3166        self.epoch_store.store(new_epoch_store);
3167        epoch_store.epoch_terminated().await;
3168
3169        *execution_lock = new_epoch;
3170    }
3171
3172    /// This is a temporary method to be used when we enable simplified_unwrap_then_delete.
3173    /// It re-accumulates state hash for the new epoch if simplified_unwrap_then_delete is enabled.
3174    #[instrument(level = "error", skip_all)]
3175    fn maybe_reaccumulate_state_hash(
3176        &self,
3177        cur_epoch_store: &AuthorityPerEpochStore,
3178        new_protocol_version: ProtocolVersion,
3179    ) {
3180        self.get_reconfig_api()
3181            .maybe_reaccumulate_state_hash(cur_epoch_store, new_protocol_version);
3182    }
3183
3184    #[instrument(level = "error", skip_all)]
3185    fn check_system_consistency(
3186        &self,
3187        cur_epoch_store: &AuthorityPerEpochStore,
3188        state_hasher: Arc<GlobalStateHasher>,
3189        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3190    ) {
3191        info!(
3192            "Performing sui conservation consistency check for epoch {}",
3193            cur_epoch_store.epoch()
3194        );
3195
3196        if let Err(err) = self
3197            .get_reconfig_api()
3198            .expensive_check_sui_conservation(cur_epoch_store)
3199        {
3200            if cfg!(debug_assertions) {
3201                panic!("{}", err);
3202            } else {
3203                // We cannot panic in production yet because it is known that there are some
3204                // inconsistencies in testnet. We will enable this once we make it balanced again in testnet.
3205                warn!("Sui conservation consistency check failed: {}", err);
3206            }
3207        } else {
3208            info!("Sui conservation consistency check passed");
3209        }
3210
3211        // check for root state hash consistency with live object set
3212        if expensive_safety_check_config.enable_state_consistency_check() {
3213            info!(
3214                "Performing state consistency check for epoch {}",
3215                cur_epoch_store.epoch()
3216            );
3217            self.expensive_check_is_consistent_state(state_hasher, cur_epoch_store);
3218        }
3219    }
3220
3221    fn expensive_check_is_consistent_state(
3222        &self,
3223        state_hasher: Arc<GlobalStateHasher>,
3224        cur_epoch_store: &AuthorityPerEpochStore,
3225    ) {
3226        let live_object_set_hash = state_hasher.digest_live_object_set(
3227            !cur_epoch_store
3228                .protocol_config()
3229                .simplified_unwrap_then_delete(),
3230        );
3231
3232        let root_state_hash: ECMHLiveObjectSetDigest = self
3233            .get_global_state_hash_store()
3234            .get_root_state_hash_for_epoch(cur_epoch_store.epoch())
3235            .expect("Retrieving root state hash cannot fail")
3236            .expect("Root state hash for epoch must exist")
3237            .1
3238            .digest()
3239            .into();
3240
3241        let is_inconsistent = root_state_hash != live_object_set_hash;
3242        if is_inconsistent {
3243            debug_fatal!(
3244                "Inconsistent state detected: root state hash: {:?}, live object set hash: {:?}",
3245                root_state_hash,
3246                live_object_set_hash
3247            );
3248        } else {
3249            info!("State consistency check passed");
3250        }
3251
3252        state_hasher.set_inconsistent_state(is_inconsistent);
3253    }
3254
3255    pub fn current_epoch_for_testing(&self) -> EpochId {
3256        self.epoch_store_for_testing().epoch()
3257    }
3258
3259    #[instrument(level = "error", skip_all)]
3260    pub fn checkpoint_all_dbs(
3261        &self,
3262        checkpoint_path: &Path,
3263        cur_epoch_store: &AuthorityPerEpochStore,
3264    ) -> SuiResult {
3265        let _metrics_guard = self.metrics.db_checkpoint_latency.start_timer();
3266        let current_epoch = cur_epoch_store.epoch();
3267
3268        if checkpoint_path.exists() {
3269            info!("Skipping db checkpoint as it already exists for epoch: {current_epoch}");
3270            return Ok(());
3271        }
3272
3273        let checkpoint_path_tmp = checkpoint_path.with_extension("tmp");
3274        let store_checkpoint_path_tmp = checkpoint_path_tmp.join("store");
3275
3276        if checkpoint_path_tmp.exists() {
3277            fs::remove_dir_all(&checkpoint_path_tmp)
3278                .map_err(|e| SuiErrorKind::FileIOError(e.to_string()))?;
3279        }
3280
3281        fs::create_dir_all(&checkpoint_path_tmp)
3282            .map_err(|e| SuiErrorKind::FileIOError(e.to_string()))?;
3283        fs::create_dir(&store_checkpoint_path_tmp)
3284            .map_err(|e| SuiErrorKind::FileIOError(e.to_string()))?;
3285
3286        // NOTE: Do not change the order of invoking these checkpoint calls
3287        // We want to snapshot checkpoint db first to not race with state sync
3288        self.checkpoint_store
3289            .checkpoint_db(&checkpoint_path_tmp.join("checkpoints"))?;
3290
3291        self.get_reconfig_api()
3292            .checkpoint_db(&store_checkpoint_path_tmp.join("perpetual"))?;
3293
3294        self.committee_store
3295            .checkpoint_db(&checkpoint_path_tmp.join("epochs"))?;
3296
3297        fs::rename(checkpoint_path_tmp, checkpoint_path)
3298            .map_err(|e| SuiErrorKind::FileIOError(e.to_string()))?;
3299        Ok(())
3300    }
3301
3302    /// Load the current epoch store. This can change during reconfiguration. To ensure that
3303    /// we never end up accessing different epoch stores in a single task, we need to make sure
3304    /// that this is called once per task. Each call needs to be carefully audited to ensure it is
3305    /// the case. This also means we should minimize the number of call-sites. Only call it when
3306    /// there is no way to obtain it from somewhere else.
3307    pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3308        self.epoch_store.load()
3309    }
3310
3311    // Load the epoch store, should be used in tests only.
3312    pub fn epoch_store_for_testing(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3313        self.load_epoch_store_one_call_per_task()
3314    }
3315
3316    pub fn transaction_deny_config_manager(&self) -> &Arc<TransactionDenyConfigManager> {
3317        &self.transaction_deny_config_manager
3318    }
3319
3320    /// The operator-configured local `TransactionDenyConfig` (before any peer
3321    /// recommendations are merged).
3322    pub fn local_transaction_deny_config(&self) -> &Arc<TransactionDenyConfig> {
3323        self.transaction_deny_config_manager.local()
3324    }
3325
3326    pub fn clone_committee_for_testing(&self) -> Committee {
3327        Committee::clone(self.epoch_store_for_testing().committee())
3328    }
3329
3330    #[instrument(level = "trace", skip_all)]
3331    pub fn get_object(&self, object_id: &ObjectID) -> Option<Object> {
3332        self.get_object_store().get_object(object_id)
3333    }
3334
3335    pub fn get_sui_system_package_object_ref(&self) -> SuiResult<ObjectRef> {
3336        Ok(self
3337            .get_object(&SUI_SYSTEM_ADDRESS.into())
3338            .expect("framework object should always exist")
3339            .compute_object_reference())
3340    }
3341
3342    // This function is only used for testing.
3343    pub fn get_sui_system_state_object_for_testing(&self) -> SuiResult<SuiSystemState> {
3344        self.get_object_cache_reader()
3345            .get_sui_system_state_object_unsafe()
3346    }
3347
3348    #[instrument(level = "trace", skip_all)]
3349    fn get_transaction_checkpoint_sequence(
3350        &self,
3351        digest: &TransactionDigest,
3352        epoch_store: &AuthorityPerEpochStore,
3353    ) -> SuiResult<Option<CheckpointSequenceNumber>> {
3354        epoch_store.get_transaction_checkpoint(digest)
3355    }
3356
3357    #[instrument(level = "trace", skip_all)]
3358    pub fn get_checkpoint_by_sequence_number(
3359        &self,
3360        sequence_number: CheckpointSequenceNumber,
3361    ) -> SuiResult<Option<VerifiedCheckpoint>> {
3362        Ok(self
3363            .checkpoint_store
3364            .get_checkpoint_by_sequence_number(sequence_number)?)
3365    }
3366
3367    #[instrument(level = "trace", skip_all)]
3368    pub fn get_transaction_checkpoint_for_tests(
3369        &self,
3370        digest: &TransactionDigest,
3371        epoch_store: &AuthorityPerEpochStore,
3372    ) -> SuiResult<Option<VerifiedCheckpoint>> {
3373        let checkpoint = self.get_transaction_checkpoint_sequence(digest, epoch_store)?;
3374        let Some(checkpoint) = checkpoint else {
3375            return Ok(None);
3376        };
3377        let checkpoint = self
3378            .checkpoint_store
3379            .get_checkpoint_by_sequence_number(checkpoint)?;
3380        Ok(checkpoint)
3381    }
3382
3383    #[instrument(level = "trace", skip_all)]
3384    pub fn get_object_read(&self, object_id: &ObjectID) -> SuiResult<ObjectRead> {
3385        Ok(
3386            match self
3387                .get_object_cache_reader()
3388                .get_latest_object_or_tombstone(*object_id)
3389            {
3390                Some((_, ObjectOrTombstone::Object(object))) => {
3391                    let layout = self.get_object_layout(&object)?;
3392                    ObjectRead::Exists(object.compute_object_reference(), object, layout)
3393                }
3394                Some((_, ObjectOrTombstone::Tombstone(objref))) => ObjectRead::Deleted(objref),
3395                None => ObjectRead::NotExists(*object_id),
3396            },
3397        )
3398    }
3399
3400    /// Chain Identifier is the digest of the genesis checkpoint.
3401    pub fn get_chain_identifier(&self) -> ChainIdentifier {
3402        self.chain_identifier
3403    }
3404
3405    /// This function aims to serve rpc reads on past objects and
3406    /// we don't expect it to be called for other purposes.
3407    /// Depending on the object pruning policies that will be enforced in the
3408    /// future there is no software-level guarantee/SLA to retrieve an object
3409    /// with an old version even if it exists/existed.
3410    #[instrument(level = "trace", skip_all)]
3411    pub fn get_past_object_read(
3412        &self,
3413        object_id: &ObjectID,
3414        version: SequenceNumber,
3415    ) -> SuiResult<PastObjectRead> {
3416        // Firstly we see if the object ever existed by getting its latest data
3417        let Some(obj_ref) = self
3418            .get_object_cache_reader()
3419            .get_latest_object_ref_or_tombstone(*object_id)
3420        else {
3421            return Ok(PastObjectRead::ObjectNotExists(*object_id));
3422        };
3423
3424        if version > obj_ref.1 {
3425            return Ok(PastObjectRead::VersionTooHigh {
3426                object_id: *object_id,
3427                asked_version: version,
3428                latest_version: obj_ref.1,
3429            });
3430        }
3431
3432        if version < obj_ref.1 {
3433            // Read past objects
3434            return Ok(match self.read_object_at_version(object_id, version)? {
3435                Some((object, layout)) => {
3436                    let obj_ref = object.compute_object_reference();
3437                    PastObjectRead::VersionFound(obj_ref, object, layout)
3438                }
3439
3440                None => PastObjectRead::VersionNotFound(*object_id, version),
3441            });
3442        }
3443
3444        if !obj_ref.2.is_alive() {
3445            return Ok(PastObjectRead::ObjectDeleted(obj_ref));
3446        }
3447
3448        match self.read_object_at_version(object_id, obj_ref.1)? {
3449            Some((object, layout)) => Ok(PastObjectRead::VersionFound(obj_ref, object, layout)),
3450            None => {
3451                debug_fatal!(
3452                    "Object with in parent_entry is missing from object store, datastore is \
3453                     inconsistent"
3454                );
3455                Err(UserInputError::ObjectNotFound {
3456                    object_id: *object_id,
3457                    version: Some(obj_ref.1),
3458                }
3459                .into())
3460            }
3461        }
3462    }
3463
3464    #[instrument(level = "trace", skip_all)]
3465    fn read_object_at_version(
3466        &self,
3467        object_id: &ObjectID,
3468        version: SequenceNumber,
3469    ) -> SuiResult<Option<(Object, Option<MoveStructLayout>)>> {
3470        let Some(object) = self
3471            .get_object_cache_reader()
3472            .get_object_by_key(object_id, version)
3473        else {
3474            return Ok(None);
3475        };
3476
3477        let layout = self.get_object_layout(&object)?;
3478        Ok(Some((object, layout)))
3479    }
3480
3481    pub fn get_object_layout(&self, object: &Object) -> SuiResult<Option<MoveStructLayout>> {
3482        let layout = object
3483            .data
3484            .try_as_move()
3485            .map(|object| {
3486                let epoch_store = self.load_epoch_store_one_call_per_task();
3487                into_struct_layout(
3488                    epoch_store
3489                        .executor()
3490                        // TODO(cache) - must read through cache
3491                        .type_layout_resolver(
3492                            epoch_store.protocol_config(),
3493                            Box::new(self.get_backing_package_store().as_ref()),
3494                        )
3495                        .get_annotated_layout(&object.type_().clone().into())?,
3496                )
3497            })
3498            .transpose()?;
3499        Ok(layout)
3500    }
3501
3502    #[instrument(level = "trace", skip_all)]
3503    pub fn get_executed_transaction_and_effects(
3504        &self,
3505        digest: TransactionDigest,
3506    ) -> SuiResult<(Transaction, TransactionEffects)> {
3507        let transaction = self
3508            .get_transaction_cache_reader()
3509            .get_transaction_block(&digest)
3510            .ok_or(SuiErrorKind::TransactionNotFound { digest })?;
3511        let effects = self
3512            .get_transaction_cache_reader()
3513            .get_executed_effects(&digest)
3514            .ok_or(SuiErrorKind::TransactionNotFound { digest })?;
3515        Ok(((*transaction).clone().into_inner(), effects))
3516    }
3517
3518    #[instrument(level = "trace", skip_all)]
3519    pub fn multi_get_checkpoint_by_sequence_number(
3520        &self,
3521        sequence_numbers: &[CheckpointSequenceNumber],
3522    ) -> SuiResult<Vec<Option<VerifiedCheckpoint>>> {
3523        Ok(self
3524            .checkpoint_store
3525            .multi_get_checkpoint_by_sequence_number(sequence_numbers)?)
3526    }
3527
3528    #[instrument(level = "trace", skip_all)]
3529    pub fn get_transaction_events(
3530        &self,
3531        digest: &TransactionDigest,
3532    ) -> SuiResult<TransactionEvents> {
3533        self.get_transaction_cache_reader()
3534            .get_events(digest)
3535            .ok_or(SuiErrorKind::TransactionEventsNotFound { digest: *digest }.into())
3536    }
3537
3538    pub fn get_transaction_input_objects(
3539        &self,
3540        effects: &TransactionEffects,
3541    ) -> SuiResult<Vec<Object>> {
3542        sui_types::storage::get_transaction_input_objects(self.get_object_store(), effects)
3543            .map_err(Into::into)
3544    }
3545
3546    pub fn get_transaction_output_objects(
3547        &self,
3548        effects: &TransactionEffects,
3549    ) -> SuiResult<Vec<Object>> {
3550        sui_types::storage::get_transaction_output_objects(self.get_object_store(), effects)
3551            .map_err(Into::into)
3552    }
3553
3554    pub fn get_checkpoint_store(&self) -> &Arc<CheckpointStore> {
3555        &self.checkpoint_store
3556    }
3557
3558    pub fn get_latest_checkpoint_sequence_number(&self) -> SuiResult<CheckpointSequenceNumber> {
3559        self.get_checkpoint_store()
3560            .get_highest_executed_checkpoint_seq_number()?
3561            .ok_or(
3562                SuiErrorKind::UserInputError {
3563                    error: UserInputError::LatestCheckpointSequenceNumberNotFound,
3564                }
3565                .into(),
3566            )
3567    }
3568
3569    #[cfg(msim)]
3570    pub fn get_highest_pruned_checkpoint_for_testing(&self) -> SuiResult<CheckpointSequenceNumber> {
3571        self.database_for_testing()
3572            .perpetual_tables
3573            .get_highest_pruned_checkpoint()
3574            .map(|c| c.unwrap_or(0))
3575            .map_err(Into::into)
3576    }
3577
3578    #[instrument(level = "trace", skip_all)]
3579    pub fn get_checkpoint_summary_by_sequence_number(
3580        &self,
3581        sequence_number: CheckpointSequenceNumber,
3582    ) -> SuiResult<CheckpointSummary> {
3583        let verified_checkpoint = self
3584            .get_checkpoint_store()
3585            .get_checkpoint_by_sequence_number(sequence_number)?;
3586        match verified_checkpoint {
3587            Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
3588            None => Err(SuiErrorKind::UserInputError {
3589                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
3590            }
3591            .into()),
3592        }
3593    }
3594
3595    #[instrument(level = "trace", skip_all)]
3596    pub fn get_checkpoint_summary_by_digest(
3597        &self,
3598        digest: CheckpointDigest,
3599    ) -> SuiResult<CheckpointSummary> {
3600        let verified_checkpoint = self
3601            .get_checkpoint_store()
3602            .get_checkpoint_by_digest(&digest)?;
3603        match verified_checkpoint {
3604            Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
3605            None => Err(SuiErrorKind::UserInputError {
3606                error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
3607            }
3608            .into()),
3609        }
3610    }
3611
3612    #[instrument(level = "trace", skip_all)]
3613    pub fn find_publish_txn_digest(&self, package_id: ObjectID) -> SuiResult<TransactionDigest> {
3614        if is_system_package(package_id) {
3615            return self.find_genesis_txn_digest();
3616        }
3617        Ok(self
3618            .get_object_read(&package_id)?
3619            .into_object()?
3620            .previous_transaction)
3621    }
3622
3623    #[instrument(level = "trace", skip_all)]
3624    pub fn find_genesis_txn_digest(&self) -> SuiResult<TransactionDigest> {
3625        let summary = self
3626            .get_verified_checkpoint_by_sequence_number(0)?
3627            .into_message();
3628        let content = self.get_checkpoint_contents(summary.content_digest)?;
3629        let genesis_transaction = content.enumerate_transactions(&summary).next();
3630        Ok(genesis_transaction
3631            .ok_or(SuiErrorKind::UserInputError {
3632                error: UserInputError::GenesisTransactionNotFound,
3633            })?
3634            .1
3635            .transaction)
3636    }
3637
3638    #[instrument(level = "trace", skip_all)]
3639    pub fn get_verified_checkpoint_by_sequence_number(
3640        &self,
3641        sequence_number: CheckpointSequenceNumber,
3642    ) -> SuiResult<VerifiedCheckpoint> {
3643        let verified_checkpoint = self
3644            .get_checkpoint_store()
3645            .get_checkpoint_by_sequence_number(sequence_number)?;
3646        match verified_checkpoint {
3647            Some(verified_checkpoint) => Ok(verified_checkpoint),
3648            None => Err(SuiErrorKind::UserInputError {
3649                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
3650            }
3651            .into()),
3652        }
3653    }
3654
3655    #[instrument(level = "trace", skip_all)]
3656    pub fn get_verified_checkpoint_summary_by_digest(
3657        &self,
3658        digest: CheckpointDigest,
3659    ) -> SuiResult<VerifiedCheckpoint> {
3660        let verified_checkpoint = self
3661            .get_checkpoint_store()
3662            .get_checkpoint_by_digest(&digest)?;
3663        match verified_checkpoint {
3664            Some(verified_checkpoint) => Ok(verified_checkpoint),
3665            None => Err(SuiErrorKind::UserInputError {
3666                error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
3667            }
3668            .into()),
3669        }
3670    }
3671
3672    #[instrument(level = "trace", skip_all)]
3673    pub fn get_checkpoint_contents(
3674        &self,
3675        digest: CheckpointContentsDigest,
3676    ) -> SuiResult<CheckpointContents> {
3677        self.get_checkpoint_store()
3678            .get_checkpoint_contents(&digest)?
3679            .ok_or(
3680                SuiErrorKind::UserInputError {
3681                    error: UserInputError::CheckpointContentsNotFound(digest),
3682                }
3683                .into(),
3684            )
3685    }
3686
3687    #[instrument(level = "trace", skip_all)]
3688    pub fn get_checkpoint_contents_by_sequence_number(
3689        &self,
3690        sequence_number: CheckpointSequenceNumber,
3691    ) -> SuiResult<CheckpointContents> {
3692        let verified_checkpoint = self
3693            .get_checkpoint_store()
3694            .get_checkpoint_by_sequence_number(sequence_number)?;
3695        match verified_checkpoint {
3696            Some(verified_checkpoint) => {
3697                let content_digest = verified_checkpoint.into_inner().content_digest;
3698                self.get_checkpoint_contents(content_digest)
3699            }
3700            None => Err(SuiErrorKind::UserInputError {
3701                error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
3702            }
3703            .into()),
3704        }
3705    }
3706
3707    pub fn insert_genesis_object(&self, object: Object) {
3708        self.get_reconfig_api().insert_genesis_object(object);
3709    }
3710
3711    pub fn insert_genesis_objects(&self, objects: &[Object]) {
3712        for o in objects {
3713            self.insert_genesis_object(o.clone());
3714        }
3715    }
3716
3717    /// Make a status response for a transaction
3718    #[instrument(level = "trace", skip_all)]
3719    pub fn get_transaction_status(
3720        &self,
3721        transaction_digest: &TransactionDigest,
3722        epoch_store: &Arc<AuthorityPerEpochStore>,
3723    ) -> SuiResult<Option<(SenderSignedData, TransactionStatus)>> {
3724        // TODO: In the case of read path, we should not have to re-sign the effects.
3725        if let Some(effects) =
3726            self.get_signed_effects_and_maybe_resign(transaction_digest, epoch_store)?
3727        {
3728            if let Some(transaction) = self
3729                .get_transaction_cache_reader()
3730                .get_transaction_block(transaction_digest)
3731            {
3732                let events = if effects.events_digest().is_some() {
3733                    self.get_transaction_events(effects.transaction_digest())?
3734                } else {
3735                    TransactionEvents::default()
3736                };
3737                // The cert_sig slot is permanently None: validators no longer aggregate or
3738                // persist per-transaction quorum signatures.
3739                return Ok(Some((
3740                    (*transaction).clone().into_message(),
3741                    TransactionStatus::Executed(None, effects.into_inner(), events),
3742                )));
3743            } else {
3744                // The read of effects and read of transaction are not atomic. It's possible that we reverted
3745                // the transaction (during epoch change) in between the above two reads, and we end up
3746                // having effects but not transaction. In this case, we just fall through.
3747                debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
3748            }
3749        }
3750        // Validators no longer sign transactions before execution, so there is no
3751        // TransactionStatus::Signed state to report.
3752        Ok(None)
3753    }
3754
3755    /// Get the signed effects of the given transaction. If the effects was signed in a previous
3756    /// epoch, re-sign it so that the caller is able to form a cert of the effects in the current
3757    /// epoch.
3758    #[instrument(level = "trace", skip_all)]
3759    pub fn get_signed_effects_and_maybe_resign(
3760        &self,
3761        transaction_digest: &TransactionDigest,
3762        epoch_store: &Arc<AuthorityPerEpochStore>,
3763    ) -> SuiResult<Option<VerifiedSignedTransactionEffects>> {
3764        let effects = self
3765            .get_transaction_cache_reader()
3766            .get_executed_effects(transaction_digest);
3767        match effects {
3768            Some(effects) => {
3769                // If the transaction was executed in previous epochs, the validator will
3770                // re-sign the effects with new current epoch so that a client is always able to
3771                // obtain an effects certificate at the current epoch.
3772                //
3773                // Why is this necessary? Consider the following case:
3774                // - assume there are 4 validators
3775                // - Quorum driver gets 2 signed effects before reconfig halt
3776                // - The tx makes it into final checkpoint.
3777                // - 2 validators go away and are replaced in the new epoch.
3778                // - The new epoch begins.
3779                // - The quorum driver cannot complete the partial effects cert from the previous epoch,
3780                //   because it may not be able to reach either of the 2 former validators.
3781                // - But, if the 2 validators that stayed are willing to re-sign the effects in the new
3782                //   epoch, the QD can make a new effects cert and return it to the client.
3783                //
3784                // This is a considered a short-term workaround. Eventually, Quorum Driver should be able
3785                // to return either an effects certificate, -or- a proof of inclusion in a checkpoint. In
3786                // the case above, the Quorum Driver would return a proof of inclusion in the final
3787                // checkpoint, and this code would no longer be necessary.
3788                if effects.executed_epoch() != epoch_store.epoch() {
3789                    debug!(
3790                        tx_digest=?transaction_digest,
3791                        effects_epoch=?effects.executed_epoch(),
3792                        epoch=?epoch_store.epoch(),
3793                        "Re-signing the effects with the current epoch"
3794                    );
3795                }
3796                Ok(Some(self.sign_effects(effects, epoch_store)?))
3797            }
3798            None => Ok(None),
3799        }
3800    }
3801
3802    /// A client aggregating effects signatures towards a quorum assumes finality once it
3803    /// collects 2f+1 of them, so within an epoch this validator must never assert two
3804    /// different effects for the same transaction on any RPC surface, signed or unsigned.
3805    /// Executed effects can change across a restart if an uncommitted transaction is
3806    /// re-executed with divergent results (e.g. by a new binary), so every effects-reporting
3807    /// path calls this before returning effects, and refuses to contradict a signature that
3808    /// may already be in a client's hands.
3809    pub fn check_effects_against_previously_signed(
3810        &self,
3811        epoch_store: &AuthorityPerEpochStore,
3812        tx_digest: &TransactionDigest,
3813        effects_digest: &TransactionEffectsDigest,
3814        surface: &'static str,
3815    ) -> SuiResult<()> {
3816        if let Some(previously_signed_digest) = epoch_store.get_signed_effects_digest(tx_digest)?
3817            && previously_signed_digest != *effects_digest
3818        {
3819            self.metrics
3820                .signed_effects_equivocation_prevented
3821                .with_label_values(&[surface])
3822                .inc();
3823            error!(
3824                ?tx_digest,
3825                ?previously_signed_digest,
3826                executed_digest = ?effects_digest,
3827                surface,
3828                "refusing to report effects that differ from previously signed effects"
3829            );
3830            return Err(SuiErrorKind::GenericAuthorityError {
3831                error: format!(
3832                    "Refusing to report effects for transaction {tx_digest}: effects digest \
3833                     {effects_digest} differs from previously signed effects digest \
3834                     {previously_signed_digest}"
3835                ),
3836            }
3837            .into());
3838        }
3839        Ok(())
3840    }
3841
3842    #[instrument(level = "trace", skip_all)]
3843    pub(crate) fn sign_effects(
3844        &self,
3845        effects: TransactionEffects,
3846        epoch_store: &Arc<AuthorityPerEpochStore>,
3847    ) -> SuiResult<VerifiedSignedTransactionEffects> {
3848        let tx_digest = *effects.transaction_digest();
3849
3850        self.check_effects_against_previously_signed(
3851            epoch_store,
3852            &tx_digest,
3853            &effects.digest(),
3854            "sign_effects",
3855        )?;
3856
3857        let signed_effects = match epoch_store.get_effects_signature(&tx_digest)? {
3858            Some(sig) => {
3859                debug_assert!(sig.epoch == epoch_store.epoch());
3860                SignedTransactionEffects::new_from_data_and_sig(effects, sig)
3861            }
3862            _ => {
3863                let sig = AuthoritySignInfo::new(
3864                    epoch_store.epoch(),
3865                    &effects,
3866                    Intent::sui_app(IntentScope::TransactionEffects),
3867                    self.name,
3868                    &*self.secret,
3869                );
3870
3871                let effects = SignedTransactionEffects::new_from_data_and_sig(effects, sig.clone());
3872
3873                epoch_store.insert_effects_digest_and_signature(
3874                    &tx_digest,
3875                    effects.digest(),
3876                    &sig,
3877                )?;
3878
3879                effects
3880            }
3881        };
3882
3883        Ok(VerifiedSignedTransactionEffects::new_unchecked(
3884            signed_effects,
3885        ))
3886    }
3887
3888    pub fn get_objects(&self, objects: &[ObjectID]) -> Vec<Option<Object>> {
3889        self.get_object_cache_reader().get_objects(objects)
3890    }
3891
3892    pub fn get_object_or_tombstone(&self, object_id: ObjectID) -> Option<ObjectRef> {
3893        self.get_object_cache_reader()
3894            .get_latest_object_ref_or_tombstone(object_id)
3895    }
3896
3897    /// Ordinarily, protocol upgrades occur when 2f + 1 + (f *
3898    /// ProtocolConfig::buffer_stake_for_protocol_upgrade_bps) vote for the upgrade.
3899    ///
3900    /// This method can be used to dynamic adjust the amount of buffer. If set to 0, the upgrade
3901    /// will go through with only 2f+1 votes.
3902    ///
3903    /// IMPORTANT: If this is used, it must be used on >=2f+1 validators (all should have the same
3904    /// value), or you risk halting the chain.
3905    pub fn set_override_protocol_upgrade_buffer_stake(
3906        &self,
3907        expected_epoch: EpochId,
3908        buffer_stake_bps: u64,
3909    ) -> SuiResult {
3910        let epoch_store = self.load_epoch_store_one_call_per_task();
3911        let actual_epoch = epoch_store.epoch();
3912        if actual_epoch != expected_epoch {
3913            return Err(SuiErrorKind::WrongEpoch {
3914                expected_epoch,
3915                actual_epoch,
3916            }
3917            .into());
3918        }
3919
3920        epoch_store.set_override_protocol_upgrade_buffer_stake(buffer_stake_bps)
3921    }
3922
3923    pub fn clear_override_protocol_upgrade_buffer_stake(
3924        &self,
3925        expected_epoch: EpochId,
3926    ) -> SuiResult {
3927        let epoch_store = self.load_epoch_store_one_call_per_task();
3928        let actual_epoch = epoch_store.epoch();
3929        if actual_epoch != expected_epoch {
3930            return Err(SuiErrorKind::WrongEpoch {
3931                expected_epoch,
3932                actual_epoch,
3933            }
3934            .into());
3935        }
3936
3937        epoch_store.clear_override_protocol_upgrade_buffer_stake()
3938    }
3939
3940    /// Get the set of system packages that are compiled in to this build, if those packages are
3941    /// compatible with the current versions of those packages on-chain.
3942    pub async fn get_available_system_packages(
3943        &self,
3944        binary_config: &BinaryConfig,
3945    ) -> Vec<ObjectRef> {
3946        let mut results = vec![];
3947
3948        let system_packages = BuiltInFramework::iter_system_packages();
3949
3950        // Add extra framework packages during simtest
3951        #[cfg(msim)]
3952        let extra_packages = framework_injection::get_extra_packages(self.name);
3953        #[cfg(msim)]
3954        let system_packages = system_packages.map(|p| p).chain(extra_packages.iter());
3955
3956        for system_package in system_packages {
3957            let modules = system_package.modules().to_vec();
3958            // In simtests, we could override the current built-in framework packages.
3959            #[cfg(msim)]
3960            let modules =
3961                match framework_injection::get_override_modules(&system_package.id, self.name) {
3962                    Some(overrides) if overrides.is_empty() => continue,
3963                    Some(overrides) => overrides,
3964                    None => modules,
3965                };
3966
3967            let Some(obj_ref) = sui_framework::compare_system_package(
3968                &self.get_object_store(),
3969                &system_package.id,
3970                &modules,
3971                system_package.dependencies.to_vec(),
3972                binary_config,
3973            )
3974            .await
3975            else {
3976                return vec![];
3977            };
3978            results.push(obj_ref);
3979        }
3980
3981        results
3982    }
3983
3984    /// Return the new versions, module bytes, and dependencies for the packages that have been
3985    /// committed to for a framework upgrade, in `system_packages`.  Loads the module contents from
3986    /// the binary, and performs the following checks:
3987    ///
3988    /// - Whether its contents matches what is on-chain already, in which case no upgrade is
3989    ///   required, and its contents are omitted from the output.
3990    /// - Whether the contents in the binary can form a package whose digest matches the input,
3991    ///   meaning the framework will be upgraded, and this authority can satisfy that upgrade, in
3992    ///   which case the contents are included in the output.
3993    ///
3994    /// If a needed version of the framework can't be loaded, the binary does not contain the
3995    /// bytes for that framework ID, or the resulting package fails the digest check, `None` is
3996    /// returned indicating that this authority cannot run the upgrade that the network voted on.
3997    ///
3998    /// All object lookups are pinned to the versions in `system_packages` instead of using the
3999    /// latest versions, so that the result is deterministic even if the change epoch transaction
4000    /// that performs the upgrade has already been executed locally (e.g. via state sync). In that
4001    /// case the reconstructed change epoch transaction is byte-identical to the executed one, and
4002    /// the caller detects it as already executed.
4003    async fn get_system_package_bytes(
4004        &self,
4005        system_packages: Vec<ObjectRef>,
4006        binary_config: &BinaryConfig,
4007    ) -> Option<Vec<(SequenceNumber, Vec<Vec<u8>>, Vec<ObjectID>)>> {
4008        let object_store = self.get_object_cache_reader();
4009
4010        let mut res = Vec::with_capacity(system_packages.len());
4011        for system_package_ref in system_packages {
4012            if let Some(object) =
4013                object_store.get_object_by_key(&system_package_ref.0, system_package_ref.1)
4014                && object.compute_object_reference() == system_package_ref
4015            {
4016                // Skip this one because it doesn't need to be upgraded.
4017                info!("Framework {} does not need updating", system_package_ref.0);
4018                continue;
4019            }
4020
4021            // The digest in `system_package_ref` commits to a package built on top of the
4022            // predecessor version's `previous_transaction` (see `compare_system_package`), so it
4023            // must be re-derived from that version. A ref at `OBJECT_START_VERSION` is a freshly
4024            // created package with no predecessor.
4025            let prev_transaction = if system_package_ref.1 == OBJECT_START_VERSION {
4026                TransactionDigest::genesis_marker()
4027            } else {
4028                let prev_version = system_package_ref
4029                    .1
4030                    .one_before()
4031                    .expect("version is greater than OBJECT_START_VERSION");
4032                let Some(prev_object) =
4033                    object_store.get_object_by_key(&system_package_ref.0, prev_version)
4034                else {
4035                    error!(
4036                        "Framework {} not available locally at version {:?}, cannot derive \
4037                        upgrade to {system_package_ref:?}",
4038                        system_package_ref.0, prev_version
4039                    );
4040                    return None;
4041                };
4042                prev_object.previous_transaction
4043            };
4044
4045            #[cfg(msim)]
4046            let SystemPackage {
4047                id: _,
4048                bytes,
4049                dependencies,
4050            } = framework_injection::get_override_system_package(&system_package_ref.0, self.name)
4051                .unwrap_or_else(|| {
4052                    BuiltInFramework::get_package_by_id(&system_package_ref.0).clone()
4053                });
4054
4055            #[cfg(not(msim))]
4056            let SystemPackage {
4057                id: _,
4058                bytes,
4059                dependencies,
4060            } = BuiltInFramework::get_package_by_id(&system_package_ref.0).clone();
4061
4062            let modules: Vec<_> = bytes
4063                .iter()
4064                .map(|m| CompiledModule::deserialize_with_config(m, binary_config).unwrap())
4065                .collect();
4066
4067            let new_object = Object::new_system_package(
4068                &modules,
4069                system_package_ref.1,
4070                dependencies.clone(),
4071                prev_transaction,
4072            );
4073
4074            let new_ref = new_object.compute_object_reference();
4075            if new_ref != system_package_ref {
4076                if cfg!(msim) {
4077                    // debug_fatal required here for test_framework_upgrade_conflicting_versions to pass
4078                    debug_fatal!(
4079                        "Framework mismatch -- binary: {new_ref:?}\n  upgrade: {system_package_ref:?}"
4080                    );
4081                } else {
4082                    error!(
4083                        "Framework mismatch -- binary: {new_ref:?}\n  upgrade: {system_package_ref:?}"
4084                    );
4085                }
4086                return None;
4087            }
4088
4089            res.push((system_package_ref.1, bytes, dependencies));
4090        }
4091
4092        Some(res)
4093    }
4094
4095    fn is_protocol_version_supported_v2(
4096        current_protocol_version: ProtocolVersion,
4097        proposed_protocol_version: ProtocolVersion,
4098        protocol_config: &ProtocolConfig,
4099        committee: &Committee,
4100        capabilities: Vec<AuthorityCapabilitiesV2>,
4101        mut buffer_stake_bps: u64,
4102    ) -> Option<(ProtocolVersion, Vec<ObjectRef>)> {
4103        if proposed_protocol_version > current_protocol_version + 1
4104            && !protocol_config.advance_to_highest_supported_protocol_version()
4105        {
4106            return None;
4107        }
4108
4109        if buffer_stake_bps > 10000 {
4110            warn!("clamping buffer_stake_bps to 10000");
4111            buffer_stake_bps = 10000;
4112        }
4113
4114        // For each validator, gather the protocol version and system packages that it would like
4115        // to upgrade to in the next epoch.
4116        let mut desired_upgrades: Vec<_> = capabilities
4117            .into_iter()
4118            .filter_map(|mut cap| {
4119                // A validator that lists no packages is voting against any change at all.
4120                if cap.available_system_packages.is_empty() {
4121                    return None;
4122                }
4123
4124                cap.available_system_packages.sort();
4125
4126                info!(
4127                    "validator {:?} supports {:?} with system packages: {:?}",
4128                    cap.authority.concise(),
4129                    cap.supported_protocol_versions,
4130                    cap.available_system_packages,
4131                );
4132
4133                // A validator that only supports the current protocol version is also voting
4134                // against any change, because framework upgrades always require a protocol version
4135                // bump.
4136                cap.supported_protocol_versions
4137                    .get_version_digest(proposed_protocol_version)
4138                    .map(|digest| (digest, cap.available_system_packages, cap.authority))
4139            })
4140            .collect();
4141
4142        // There can only be one set of votes that have a majority, find one if it exists.
4143        desired_upgrades.sort();
4144        desired_upgrades
4145            .into_iter()
4146            .chunk_by(|(digest, packages, _authority)| (*digest, packages.clone()))
4147            .into_iter()
4148            .find_map(|((digest, packages), group)| {
4149                // should have been filtered out earlier.
4150                assert!(!packages.is_empty());
4151
4152                let mut stake_aggregator: StakeAggregator<(), true> =
4153                    StakeAggregator::new(Arc::new(committee.clone()));
4154
4155                for (_, _, authority) in group {
4156                    stake_aggregator.insert_generic(authority, ());
4157                }
4158
4159                let total_votes = stake_aggregator.total_votes();
4160                let quorum_threshold = committee.quorum_threshold();
4161                let f = committee.total_votes() - committee.quorum_threshold();
4162
4163                // multiple by buffer_stake_bps / 10000, rounded up.
4164                let buffer_stake = (f * buffer_stake_bps).div_ceil(10000);
4165                let effective_threshold = quorum_threshold + buffer_stake;
4166
4167                info!(
4168                    protocol_config_digest = ?digest,
4169                    ?total_votes,
4170                    ?quorum_threshold,
4171                    ?buffer_stake_bps,
4172                    ?effective_threshold,
4173                    ?proposed_protocol_version,
4174                    ?packages,
4175                    "support for upgrade"
4176                );
4177
4178                let has_support = total_votes >= effective_threshold;
4179                has_support.then_some((proposed_protocol_version, packages))
4180            })
4181    }
4182
4183    fn choose_protocol_version_and_system_packages_v2(
4184        current_protocol_version: ProtocolVersion,
4185        protocol_config: &ProtocolConfig,
4186        committee: &Committee,
4187        capabilities: Vec<AuthorityCapabilitiesV2>,
4188        buffer_stake_bps: u64,
4189    ) -> (ProtocolVersion, Vec<ObjectRef>) {
4190        assert!(protocol_config.authority_capabilities_v2());
4191        let mut next_protocol_version = current_protocol_version;
4192        let mut system_packages = vec![];
4193
4194        while let Some((version, packages)) = Self::is_protocol_version_supported_v2(
4195            current_protocol_version,
4196            next_protocol_version + 1,
4197            protocol_config,
4198            committee,
4199            capabilities.clone(),
4200            buffer_stake_bps,
4201        ) {
4202            next_protocol_version = version;
4203            system_packages = packages;
4204        }
4205
4206        (next_protocol_version, system_packages)
4207    }
4208
4209    #[instrument(level = "debug", skip_all)]
4210    fn create_authenticator_state_tx(
4211        &self,
4212        epoch_store: &Arc<AuthorityPerEpochStore>,
4213    ) -> Option<EndOfEpochTransactionKind> {
4214        if !epoch_store.protocol_config().enable_jwk_consensus_updates() {
4215            info!("authenticator state transactions not enabled");
4216            return None;
4217        }
4218
4219        let authenticator_state_exists = epoch_store.authenticator_state_exists();
4220        let tx = if authenticator_state_exists {
4221            let next_epoch = epoch_store.epoch().checked_add(1).expect("epoch overflow");
4222            let min_epoch =
4223                next_epoch.saturating_sub(epoch_store.protocol_config().max_age_of_jwk_in_epochs());
4224            let authenticator_obj_initial_shared_version = epoch_store
4225                .epoch_start_config()
4226                .authenticator_obj_initial_shared_version()
4227                .expect("initial version must exist");
4228
4229            let tx = EndOfEpochTransactionKind::new_authenticator_state_expire(
4230                min_epoch,
4231                authenticator_obj_initial_shared_version,
4232            );
4233
4234            info!(?min_epoch, "Creating AuthenticatorStateExpire tx",);
4235
4236            tx
4237        } else {
4238            let tx = EndOfEpochTransactionKind::new_authenticator_state_create();
4239            info!("Creating AuthenticatorStateCreate tx");
4240            tx
4241        };
4242        Some(tx)
4243    }
4244
4245    #[instrument(level = "debug", skip_all)]
4246    fn create_randomness_state_tx(
4247        &self,
4248        epoch_store: &Arc<AuthorityPerEpochStore>,
4249    ) -> Option<EndOfEpochTransactionKind> {
4250        if !epoch_store.protocol_config().random_beacon() {
4251            info!("randomness state transactions not enabled");
4252            return None;
4253        }
4254
4255        if epoch_store.randomness_state_exists() {
4256            return None;
4257        }
4258
4259        let tx = EndOfEpochTransactionKind::new_randomness_state_create();
4260        info!("Creating RandomnessStateCreate tx");
4261        Some(tx)
4262    }
4263
4264    #[instrument(level = "debug", skip_all)]
4265    fn create_accumulator_root_tx(
4266        &self,
4267        epoch_store: &Arc<AuthorityPerEpochStore>,
4268    ) -> Option<EndOfEpochTransactionKind> {
4269        if !epoch_store
4270            .protocol_config()
4271            .create_root_accumulator_object()
4272        {
4273            info!("accumulator root creation not enabled");
4274            return None;
4275        }
4276
4277        if epoch_store.accumulator_root_exists() {
4278            return None;
4279        }
4280
4281        let tx = EndOfEpochTransactionKind::new_accumulator_root_create();
4282        info!("Creating AccumulatorRootCreate tx");
4283        Some(tx)
4284    }
4285
4286    #[instrument(level = "debug", skip_all)]
4287    fn create_write_accumulator_storage_cost_tx(
4288        &self,
4289        epoch_store: &Arc<AuthorityPerEpochStore>,
4290    ) -> Option<EndOfEpochTransactionKind> {
4291        if !epoch_store.accumulator_root_exists() {
4292            info!("accumulator root does not exist yet");
4293            return None;
4294        }
4295        if !epoch_store.protocol_config().enable_accumulators() {
4296            info!("accumulators not enabled");
4297            return None;
4298        }
4299
4300        let object_store = self.get_object_store();
4301        let object_count =
4302            match accumulator_metadata::get_accumulator_object_count(object_store.as_ref()) {
4303                Ok(Some(count)) => count,
4304                Ok(None) => return None,
4305                Err(e) => {
4306                    fatal!("failed to read accumulator object count: {e}");
4307                }
4308            };
4309
4310        let storage_cost = object_count.saturating_mul(
4311            epoch_store
4312                .protocol_config()
4313                .accumulator_object_storage_cost(),
4314        );
4315
4316        let tx = EndOfEpochTransactionKind::new_write_accumulator_storage_cost(storage_cost);
4317        info!(
4318            object_count,
4319            storage_cost, "Creating WriteAccumulatorStorageCost tx"
4320        );
4321        Some(tx)
4322    }
4323
4324    #[instrument(level = "debug", skip_all)]
4325    fn create_coin_registry_tx(
4326        &self,
4327        epoch_store: &Arc<AuthorityPerEpochStore>,
4328    ) -> Option<EndOfEpochTransactionKind> {
4329        if !epoch_store.protocol_config().enable_coin_registry() {
4330            info!("coin registry not enabled");
4331            return None;
4332        }
4333
4334        if epoch_store.coin_registry_exists() {
4335            return None;
4336        }
4337
4338        let tx = EndOfEpochTransactionKind::new_coin_registry_create();
4339        info!("Creating CoinRegistryCreate tx");
4340        Some(tx)
4341    }
4342
4343    #[instrument(level = "debug", skip_all)]
4344    fn create_display_registry_tx(
4345        &self,
4346        epoch_store: &Arc<AuthorityPerEpochStore>,
4347    ) -> Option<EndOfEpochTransactionKind> {
4348        if !epoch_store.protocol_config().enable_display_registry() {
4349            info!("display registry not enabled");
4350            return None;
4351        }
4352
4353        if epoch_store.display_registry_exists() {
4354            return None;
4355        }
4356
4357        let tx = EndOfEpochTransactionKind::new_display_registry_create();
4358        info!("Creating DisplayRegistryCreate tx");
4359        Some(tx)
4360    }
4361
4362    #[instrument(level = "debug", skip_all)]
4363    fn create_bridge_tx(
4364        &self,
4365        epoch_store: &Arc<AuthorityPerEpochStore>,
4366    ) -> Option<EndOfEpochTransactionKind> {
4367        if !epoch_store.protocol_config().bridge() {
4368            info!("bridge not enabled");
4369            return None;
4370        }
4371        if epoch_store.bridge_exists() {
4372            return None;
4373        }
4374        let tx = EndOfEpochTransactionKind::new_bridge_create(epoch_store.get_chain_identifier());
4375        info!("Creating Bridge Create tx");
4376        Some(tx)
4377    }
4378
4379    #[instrument(level = "debug", skip_all)]
4380    fn init_bridge_committee_tx(
4381        &self,
4382        epoch_store: &Arc<AuthorityPerEpochStore>,
4383    ) -> Option<EndOfEpochTransactionKind> {
4384        if !epoch_store.protocol_config().bridge() {
4385            info!("bridge not enabled");
4386            return None;
4387        }
4388        if !epoch_store
4389            .protocol_config()
4390            .should_try_to_finalize_bridge_committee()
4391        {
4392            info!("should not try to finalize bridge committee yet");
4393            return None;
4394        }
4395        // Only create this transaction if bridge exists
4396        if !epoch_store.bridge_exists() {
4397            return None;
4398        }
4399
4400        if epoch_store.bridge_committee_initiated() {
4401            return None;
4402        }
4403
4404        let bridge_initial_shared_version = epoch_store
4405            .epoch_start_config()
4406            .bridge_obj_initial_shared_version()
4407            .expect("initial version must exist");
4408        let tx = EndOfEpochTransactionKind::init_bridge_committee(bridge_initial_shared_version);
4409        info!("Init Bridge committee tx");
4410        Some(tx)
4411    }
4412
4413    #[instrument(level = "debug", skip_all)]
4414    fn create_deny_list_state_tx(
4415        &self,
4416        epoch_store: &Arc<AuthorityPerEpochStore>,
4417    ) -> Option<EndOfEpochTransactionKind> {
4418        if !epoch_store.protocol_config().enable_coin_deny_list() {
4419            return None;
4420        }
4421
4422        if epoch_store.coin_deny_list_state_exists() {
4423            return None;
4424        }
4425
4426        let tx = EndOfEpochTransactionKind::new_deny_list_state_create();
4427        info!("Creating DenyListStateCreate tx");
4428        Some(tx)
4429    }
4430
4431    #[instrument(level = "debug", skip_all)]
4432    fn create_address_alias_state_tx(
4433        &self,
4434        epoch_store: &Arc<AuthorityPerEpochStore>,
4435    ) -> Option<EndOfEpochTransactionKind> {
4436        if !epoch_store.protocol_config().address_aliases() {
4437            info!("address aliases not enabled");
4438            return None;
4439        }
4440
4441        if epoch_store.address_alias_state_exists() {
4442            return None;
4443        }
4444
4445        let tx = EndOfEpochTransactionKind::new_address_alias_state_create();
4446        info!("Creating AddressAliasStateCreate tx");
4447        Some(tx)
4448    }
4449
4450    #[instrument(level = "debug", skip_all)]
4451    fn create_forwarding_address_registry_tx(
4452        &self,
4453        epoch_store: &Arc<AuthorityPerEpochStore>,
4454    ) -> Option<EndOfEpochTransactionKind> {
4455        if !epoch_store
4456            .protocol_config()
4457            .create_forwarding_address_registry()
4458        {
4459            info!("forwarding address registry creation not enabled");
4460            return None;
4461        }
4462
4463        if epoch_store.forwarding_address_registry_exists() {
4464            return None;
4465        }
4466
4467        let tx = EndOfEpochTransactionKind::new_forwarding_address_registry_create();
4468        info!("Creating ForwardingAddressRegistryCreate tx");
4469        Some(tx)
4470    }
4471
4472    #[instrument(level = "debug", skip_all)]
4473    fn create_execution_time_observations_tx(
4474        &self,
4475        epoch_store: &Arc<AuthorityPerEpochStore>,
4476        end_of_epoch_observation_keys: Vec<ExecutionTimeObservationKey>,
4477        last_checkpoint_before_end_of_epoch: CheckpointSequenceNumber,
4478    ) -> Option<EndOfEpochTransactionKind> {
4479        let PerObjectCongestionControlMode::ExecutionTimeEstimate(params) = epoch_store
4480            .protocol_config()
4481            .per_object_congestion_control_mode()
4482        else {
4483            return None;
4484        };
4485
4486        // Load tx in the last N checkpoints before end-of-epoch, and save only the
4487        // execution time observations for commands in these checkpoints.
4488        let start_checkpoint = std::cmp::max(
4489            last_checkpoint_before_end_of_epoch
4490                .saturating_sub(params.stored_observations_num_included_checkpoints - 1),
4491            // If we have <N checkpoints in the epoch, use all of them.
4492            epoch_store
4493                .epoch()
4494                .checked_sub(1)
4495                .map(|prev_epoch| {
4496                    self.checkpoint_store
4497                        .get_epoch_last_checkpoint_seq_number(prev_epoch)
4498                        .expect("typed store must not fail")
4499                        .expect(
4500                            "sequence number of last checkpoint of preceding epoch must be saved",
4501                        )
4502                        + 1
4503                })
4504                .unwrap_or(1),
4505        );
4506        info!(
4507            "reading checkpoint range {:?}..={:?}",
4508            start_checkpoint, last_checkpoint_before_end_of_epoch
4509        );
4510        let sequence_numbers =
4511            (start_checkpoint..=last_checkpoint_before_end_of_epoch).collect::<Vec<_>>();
4512        let contents_digests: Vec<_> = self
4513            .checkpoint_store
4514            .multi_get_locally_computed_checkpoints(&sequence_numbers)
4515            .expect("typed store must not fail")
4516            .into_iter()
4517            .zip_debug_eq(sequence_numbers)
4518            .map(|(maybe_checkpoint, sequence_number)| {
4519                if let Some(checkpoint) = maybe_checkpoint {
4520                    checkpoint.content_digest
4521                } else {
4522                    // If locally computed checkpoint summary was already pruned, load the
4523                    // certified checkpoint.
4524                    self.checkpoint_store
4525                        .get_checkpoint_by_sequence_number(sequence_number)
4526                        .expect("typed store must not fail")
4527                        .unwrap_or_else(|| {
4528                            fatal!("preceding checkpoints must exist by end of epoch")
4529                        })
4530                        .data()
4531                        .content_digest
4532                }
4533            })
4534            .collect();
4535        let tx_digests: Vec<_> = self
4536            .checkpoint_store
4537            .multi_get_checkpoint_content(&contents_digests)
4538            .expect("typed store must not fail")
4539            .into_iter()
4540            .flat_map(|maybe_contents| {
4541                maybe_contents
4542                    .expect("preceding checkpoint contents must exist by end of epoch")
4543                    .into_inner()
4544                    .into_iter()
4545                    .map(|digests| digests.transaction)
4546            })
4547            .collect();
4548        let included_execution_time_observations: HashSet<_> = self
4549            .get_transaction_cache_reader()
4550            .multi_get_transaction_blocks(&tx_digests)
4551            .into_iter()
4552            .flat_map(|maybe_tx| {
4553                if let TransactionKind::ProgrammableTransaction(ptb) = maybe_tx
4554                    .expect("preceding transaction must exist by end of epoch")
4555                    .transaction_data()
4556                    .kind()
4557                {
4558                    #[allow(clippy::unnecessary_to_owned)]
4559                    itertools::Either::Left(
4560                        ptb.commands
4561                            .to_owned()
4562                            .into_iter()
4563                            .map(|cmd| ExecutionTimeObservationKey::from_command(&cmd)),
4564                    )
4565                } else {
4566                    itertools::Either::Right(std::iter::empty())
4567                }
4568            })
4569            .chain(end_of_epoch_observation_keys.into_iter())
4570            .collect();
4571
4572        let tx = EndOfEpochTransactionKind::new_store_execution_time_observations(
4573            epoch_store
4574                .get_end_of_epoch_execution_time_observations()
4575                .filter_and_sort_v1(
4576                    |(key, _)| included_execution_time_observations.contains(key),
4577                    params.stored_observations_limit.try_into().unwrap(),
4578                ),
4579        );
4580        info!("Creating StoreExecutionTimeObservations tx");
4581        Some(tx)
4582    }
4583
4584    /// Creates and execute the advance epoch transaction to effects without committing it to the database.
4585    /// The effects of the change epoch tx are only written to the database after a certified checkpoint has been
4586    /// formed and executed by CheckpointExecutor.
4587    ///
4588    /// When a framework upgraded has been decided on, but the validator does not have the new
4589    /// versions of the packages locally, the validator cannot form the ChangeEpochTx. In this case
4590    /// it returns Err, indicating that the checkpoint builder should give up trying to make the
4591    /// final checkpoint. As long as the network is able to create a certified checkpoint (which
4592    /// should be ensured by the capabilities vote), it will arrive via state sync and be executed
4593    /// by CheckpointExecutor.
4594    #[instrument(level = "error", skip_all)]
4595    pub async fn create_and_execute_advance_epoch_tx(
4596        &self,
4597        epoch_store: &Arc<AuthorityPerEpochStore>,
4598        gas_cost_summary: &GasCostSummary,
4599        checkpoint: CheckpointSequenceNumber,
4600        epoch_start_timestamp_ms: CheckpointTimestamp,
4601        end_of_epoch_observation_keys: Vec<ExecutionTimeObservationKey>,
4602        // This may be less than `checkpoint - 1` if the end-of-epoch PendingCheckpoint produced
4603        // >1 checkpoint.
4604        last_checkpoint: CheckpointSequenceNumber,
4605    ) -> CheckpointBuilderResult<(SuiSystemState, TransactionEffects)> {
4606        let mut txns = Vec::new();
4607
4608        if let Some(tx) = self.create_authenticator_state_tx(epoch_store) {
4609            txns.push(tx);
4610        }
4611        if let Some(tx) = self.create_randomness_state_tx(epoch_store) {
4612            txns.push(tx);
4613        }
4614        if let Some(tx) = self.create_bridge_tx(epoch_store) {
4615            txns.push(tx);
4616        }
4617        if let Some(tx) = self.init_bridge_committee_tx(epoch_store) {
4618            txns.push(tx);
4619        }
4620        if let Some(tx) = self.create_deny_list_state_tx(epoch_store) {
4621            txns.push(tx);
4622        }
4623        if let Some(tx) = self.create_execution_time_observations_tx(
4624            epoch_store,
4625            end_of_epoch_observation_keys,
4626            last_checkpoint,
4627        ) {
4628            txns.push(tx);
4629        }
4630        if let Some(tx) = self.create_accumulator_root_tx(epoch_store) {
4631            txns.push(tx);
4632        }
4633
4634        if let Some(tx) = self.create_coin_registry_tx(epoch_store) {
4635            txns.push(tx);
4636        }
4637        if let Some(tx) = self.create_display_registry_tx(epoch_store) {
4638            txns.push(tx);
4639        }
4640        if let Some(tx) = self.create_address_alias_state_tx(epoch_store) {
4641            txns.push(tx);
4642        }
4643        if let Some(tx) = self.create_forwarding_address_registry_tx(epoch_store) {
4644            txns.push(tx);
4645        }
4646        if let Some(tx) = self.create_write_accumulator_storage_cost_tx(epoch_store) {
4647            txns.push(tx);
4648        }
4649
4650        let next_epoch = epoch_store.epoch() + 1;
4651
4652        let buffer_stake_bps = epoch_store.get_effective_buffer_stake_bps();
4653
4654        let (next_epoch_protocol_version, next_epoch_system_packages) =
4655            Self::choose_protocol_version_and_system_packages_v2(
4656                epoch_store.protocol_version(),
4657                epoch_store.protocol_config(),
4658                epoch_store.committee(),
4659                epoch_store
4660                    .get_capabilities_v2()
4661                    .expect("read capabilities from db cannot fail"),
4662                buffer_stake_bps,
4663            );
4664
4665        // since system packages are created during the current epoch, they should abide by the
4666        // rules of the current epoch, including the current epoch's max Move binary format version
4667        let config = epoch_store.protocol_config();
4668        let binary_config = config.binary_config(None);
4669        let Some(next_epoch_system_package_bytes) = self
4670            .get_system_package_bytes(next_epoch_system_packages.clone(), &binary_config)
4671            .await
4672        else {
4673            if next_epoch_protocol_version <= ProtocolVersion::MAX {
4674                // This case should only be hit if the validator supports the new protocol version,
4675                // but carries a different framework. The validator should still be able to
4676                // reconfigure, as the correct framework will be installed by the change epoch txn.
4677                debug_fatal!(
4678                    "upgraded system packages {:?} are not locally available, cannot create \
4679                    ChangeEpochTx. validator binary must be upgraded to the correct version!",
4680                    next_epoch_system_packages
4681                );
4682            } else {
4683                error!(
4684                    "validator does not support next_epoch_protocol_version {:?} - will shut down after reconfig unless upgraded",
4685                    next_epoch_protocol_version
4686                );
4687            }
4688            // the checkpoint builder will keep retrying forever when it hits this error.
4689            // Eventually, one of two things will happen:
4690            // - The operator will upgrade this binary to one that has the new packages locally,
4691            //   and this function will succeed.
4692            // - The final checkpoint will be certified by other validators, we will receive it via
4693            //   state sync, and execute it. This will upgrade the framework packages, reconfigure,
4694            //   and most likely shut down in the new epoch (this validator likely doesn't support
4695            //   the new protocol version, or else it should have had the packages.)
4696            return Err(CheckpointBuilderError::SystemPackagesMissing);
4697        };
4698
4699        let tx = if epoch_store
4700            .protocol_config()
4701            .end_of_epoch_transaction_supported()
4702        {
4703            txns.push(EndOfEpochTransactionKind::new_change_epoch(
4704                next_epoch,
4705                next_epoch_protocol_version,
4706                gas_cost_summary.storage_cost,
4707                gas_cost_summary.computation_cost,
4708                gas_cost_summary.storage_rebate,
4709                gas_cost_summary.non_refundable_storage_fee,
4710                epoch_start_timestamp_ms,
4711                next_epoch_system_package_bytes,
4712            ));
4713
4714            VerifiedTransaction::new_end_of_epoch_transaction(txns)
4715        } else {
4716            VerifiedTransaction::new_change_epoch(
4717                next_epoch,
4718                next_epoch_protocol_version,
4719                gas_cost_summary.storage_cost,
4720                gas_cost_summary.computation_cost,
4721                gas_cost_summary.storage_rebate,
4722                gas_cost_summary.non_refundable_storage_fee,
4723                epoch_start_timestamp_ms,
4724                next_epoch_system_package_bytes,
4725            )
4726        };
4727
4728        let executable_tx = VerifiedExecutableTransaction::new_from_checkpoint(
4729            tx.clone(),
4730            epoch_store.epoch(),
4731            checkpoint,
4732        );
4733
4734        let tx_digest = executable_tx.digest();
4735
4736        info!(
4737            ?next_epoch,
4738            ?next_epoch_protocol_version,
4739            ?next_epoch_system_packages,
4740            computation_cost=?gas_cost_summary.computation_cost,
4741            storage_cost=?gas_cost_summary.storage_cost,
4742            storage_rebate=?gas_cost_summary.storage_rebate,
4743            non_refundable_storage_fee=?gas_cost_summary.non_refundable_storage_fee,
4744            ?tx_digest,
4745            "Creating advance epoch transaction"
4746        );
4747
4748        fail_point_async!("change_epoch_tx_delay");
4749        let tx_lock = epoch_store.acquire_tx_lock(tx_digest);
4750
4751        // The tx could have been executed by state sync already - if so simply return an error.
4752        // The checkpoint builder will shortly be terminated by reconfiguration anyway.
4753        if self
4754            .get_transaction_cache_reader()
4755            .is_tx_already_executed(tx_digest)
4756        {
4757            warn!("change epoch tx has already been executed via state sync");
4758            return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
4759        }
4760
4761        let Some(execution_guard) = self.execution_lock_for_executable_transaction(&executable_tx)
4762        else {
4763            return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
4764        };
4765
4766        // We must manually assign the shared object versions to the transaction before executing it.
4767        // This is because we do not sequence end-of-epoch transactions through consensus.
4768        let assigned_versions = epoch_store.assign_shared_object_versions_idempotent(
4769            self.get_object_cache_reader().as_ref(),
4770            std::iter::once(&Schedulable::Transaction(&executable_tx)),
4771        )?;
4772
4773        assert_eq!(assigned_versions.0.len(), 1);
4774        let assigned_versions = assigned_versions.0.into_iter().next().unwrap().1;
4775
4776        let input_objects = self.read_objects_for_execution(
4777            &tx_lock,
4778            &executable_tx,
4779            &assigned_versions,
4780            epoch_store,
4781        )?;
4782
4783        let (transaction_outputs, _timings, _execution_error_opt) = self
4784            .execute_certificate(
4785                &execution_guard,
4786                &executable_tx,
4787                input_objects,
4788                None,
4789                ExecutionEnv::default(),
4790                epoch_store,
4791            )
4792            .unwrap();
4793        let system_obj = get_sui_system_state(&transaction_outputs.written)
4794            .expect("change epoch tx must write to system object");
4795
4796        let effects = transaction_outputs.effects;
4797        // We must write tx and effects to the state sync tables so that state sync is able to
4798        // deliver to the transaction to CheckpointExecutor after it is included in a certified
4799        // checkpoint.
4800        self.get_state_sync_store()
4801            .insert_transaction_and_effects(&tx, &effects);
4802
4803        info!(
4804            "Effects summary of the change epoch transaction: {:?}",
4805            effects.summary_for_debug()
4806        );
4807        epoch_store.record_checkpoint_builder_is_safe_mode_metric(system_obj.safe_mode());
4808        // The change epoch transaction cannot fail to execute.
4809        assert!(effects.status().is_ok());
4810        Ok((system_obj, effects))
4811    }
4812
4813    #[instrument(level = "error", skip_all)]
4814    async fn reopen_epoch_db(
4815        &self,
4816        cur_epoch_store: &AuthorityPerEpochStore,
4817        new_committee: Committee,
4818        epoch_start_configuration: EpochStartConfiguration,
4819        expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
4820        epoch_last_checkpoint: CheckpointSequenceNumber,
4821    ) -> SuiResult<Arc<AuthorityPerEpochStore>> {
4822        let new_epoch = new_committee.epoch;
4823        info!(new_epoch = ?new_epoch, "re-opening AuthorityEpochTables for new epoch");
4824        assert_eq!(
4825            epoch_start_configuration.epoch_start_state().epoch(),
4826            new_committee.epoch
4827        );
4828        fail_point!("before-open-new-epoch-store");
4829        let new_epoch_store = cur_epoch_store.new_at_next_epoch(
4830            self.name,
4831            new_committee,
4832            epoch_start_configuration,
4833            self.get_backing_package_store().clone(),
4834            self.get_object_store().clone(),
4835            expensive_safety_check_config,
4836            epoch_last_checkpoint,
4837            self.config.fullnode_sync_mode,
4838        )?;
4839        self.epoch_store.store(new_epoch_store.clone());
4840        Ok(new_epoch_store)
4841    }
4842
4843    #[cfg(test)]
4844    pub(crate) fn iter_live_object_set_for_testing(
4845        &self,
4846    ) -> impl Iterator<Item = authority_store_tables::LiveObject> + '_ {
4847        let include_wrapped_object = !self
4848            .epoch_store_for_testing()
4849            .protocol_config()
4850            .simplified_unwrap_then_delete();
4851        self.get_global_state_hash_store()
4852            .iter_cached_live_object_set_for_testing(include_wrapped_object)
4853    }
4854
4855    #[cfg(test)]
4856    pub(crate) fn shutdown_execution_for_test(&self) {
4857        self.tx_execution_shutdown
4858            .lock()
4859            .take()
4860            .unwrap()
4861            .send(())
4862            .unwrap();
4863    }
4864
4865    /// NOTE: this function is only to be used for fuzzing and testing. Never use in prod
4866    pub async fn insert_objects_unsafe_for_testing_only(&self, objects: &[Object]) -> SuiResult {
4867        self.get_reconfig_api().bulk_insert_genesis_objects(objects);
4868        self.get_object_cache_reader()
4869            .force_reload_system_packages(&BuiltInFramework::all_package_ids());
4870        self.get_reconfig_api()
4871            .clear_state_end_of_epoch(&self.execution_lock_for_reconfiguration().await);
4872        Ok(())
4873    }
4874}
4875
4876#[cfg(msim)]
4877pub mod framework_injection {
4878    use move_binary_format::CompiledModule;
4879    use std::collections::BTreeMap;
4880    use std::collections::BTreeSet;
4881    use std::sync::Mutex;
4882    use sui_framework::{BuiltInFramework, SystemPackage};
4883    use sui_types::base_types::{AuthorityName, ObjectID};
4884    use sui_types::is_system_package;
4885
4886    type FrameworkOverrideConfig = BTreeMap<ObjectID, PackageOverrideConfig>;
4887
4888    static OVERRIDE: Mutex<FrameworkOverrideConfig> = Mutex::new(BTreeMap::new());
4889
4890    type Framework = Vec<CompiledModule>;
4891
4892    pub type PackageUpgradeCallback =
4893        Box<dyn Fn(AuthorityName) -> Option<Framework> + Send + Sync + 'static>;
4894
4895    enum PackageOverrideConfig {
4896        Global(Framework),
4897        PerValidator(PackageUpgradeCallback),
4898    }
4899
4900    fn compiled_modules_to_bytes(modules: &[CompiledModule]) -> Vec<Vec<u8>> {
4901        modules
4902            .iter()
4903            .map(|m| {
4904                let mut buf = Vec::new();
4905                m.serialize_with_version(m.version, &mut buf).unwrap();
4906                buf
4907            })
4908            .collect()
4909    }
4910
4911    pub fn set_override(package_id: ObjectID, modules: Vec<CompiledModule>) {
4912        OVERRIDE
4913            .lock()
4914            .unwrap()
4915            .insert(package_id, PackageOverrideConfig::Global(modules));
4916    }
4917
4918    pub fn set_override_cb(package_id: ObjectID, func: PackageUpgradeCallback) {
4919        OVERRIDE
4920            .lock()
4921            .unwrap()
4922            .insert(package_id, PackageOverrideConfig::PerValidator(func));
4923    }
4924
4925    pub fn set_system_packages(packages: Vec<SystemPackage>) {
4926        let mut cfg = OVERRIDE.lock().unwrap();
4927        let mut new_packages_not_to_include: BTreeSet<_> =
4928            BuiltInFramework::all_package_ids().into_iter().collect();
4929        for pkg in &packages {
4930            new_packages_not_to_include.remove(&pkg.id);
4931        }
4932        for pkg in packages {
4933            cfg.insert(pkg.id, PackageOverrideConfig::Global(pkg.modules()));
4934        }
4935        for empty_pkg in new_packages_not_to_include {
4936            cfg.insert(empty_pkg, PackageOverrideConfig::Global(vec![]));
4937        }
4938    }
4939
4940    pub fn get_override_bytes(package_id: &ObjectID, name: AuthorityName) -> Option<Vec<Vec<u8>>> {
4941        OVERRIDE
4942            .lock()
4943            .unwrap()
4944            .get(package_id)
4945            .and_then(|entry| match entry {
4946                PackageOverrideConfig::Global(framework) => {
4947                    Some(compiled_modules_to_bytes(framework))
4948                }
4949                PackageOverrideConfig::PerValidator(func) => {
4950                    func(name).map(|fw| compiled_modules_to_bytes(&fw))
4951                }
4952            })
4953    }
4954
4955    pub fn get_override_modules(
4956        package_id: &ObjectID,
4957        name: AuthorityName,
4958    ) -> Option<Vec<CompiledModule>> {
4959        OVERRIDE
4960            .lock()
4961            .unwrap()
4962            .get(package_id)
4963            .and_then(|entry| match entry {
4964                PackageOverrideConfig::Global(framework) => Some(framework.clone()),
4965                PackageOverrideConfig::PerValidator(func) => func(name),
4966            })
4967    }
4968
4969    pub fn get_override_system_package(
4970        package_id: &ObjectID,
4971        name: AuthorityName,
4972    ) -> Option<SystemPackage> {
4973        let bytes = get_override_bytes(package_id, name)?;
4974        let dependencies = if is_system_package(*package_id) {
4975            BuiltInFramework::get_package_by_id(package_id)
4976                .dependencies
4977                .to_vec()
4978        } else {
4979            // Assume that entirely new injected packages depend on all existing system packages.
4980            BuiltInFramework::all_package_ids()
4981        };
4982        Some(SystemPackage {
4983            id: *package_id,
4984            bytes,
4985            dependencies,
4986        })
4987    }
4988
4989    pub fn get_extra_packages(name: AuthorityName) -> Vec<SystemPackage> {
4990        let built_in = BTreeSet::from_iter(BuiltInFramework::all_package_ids().into_iter());
4991        let extra: Vec<ObjectID> = OVERRIDE
4992            .lock()
4993            .unwrap()
4994            .keys()
4995            .filter_map(|package| (!built_in.contains(package)).then_some(*package))
4996            .collect();
4997
4998        extra
4999            .into_iter()
5000            .map(|package| SystemPackage {
5001                id: package,
5002                bytes: get_override_bytes(&package, name).unwrap(),
5003                dependencies: BuiltInFramework::all_package_ids(),
5004            })
5005            .collect()
5006    }
5007}
5008
5009#[derive(Debug, Serialize, Deserialize, Clone)]
5010pub struct ObjDumpFormat {
5011    pub id: ObjectID,
5012    pub version: VersionNumber,
5013    pub digest: ObjectDigest,
5014    pub object: Object,
5015}
5016
5017impl ObjDumpFormat {
5018    fn new(object: Object) -> Self {
5019        let oref = object.compute_object_reference();
5020        Self {
5021            id: oref.0,
5022            version: oref.1,
5023            digest: oref.2,
5024            object,
5025        }
5026    }
5027}
5028
5029#[derive(Debug, Serialize, Deserialize, Clone)]
5030pub struct NodeStateDump {
5031    pub tx_digest: TransactionDigest,
5032    pub sender_signed_data: SenderSignedData,
5033    pub executed_epoch: u64,
5034    pub reference_gas_price: u64,
5035    pub protocol_version: u64,
5036    pub epoch_start_timestamp_ms: u64,
5037    pub computed_effects: TransactionEffects,
5038    pub expected_effects_digest: TransactionEffectsDigest,
5039    pub relevant_system_packages: Vec<ObjDumpFormat>,
5040    pub shared_objects: Vec<ObjDumpFormat>,
5041    pub loaded_child_objects: Vec<ObjDumpFormat>,
5042    pub modified_at_versions: Vec<ObjDumpFormat>,
5043    pub runtime_reads: Vec<ObjDumpFormat>,
5044    pub input_objects: Vec<ObjDumpFormat>,
5045}
5046
5047impl NodeStateDump {
5048    pub fn new(
5049        tx_digest: &TransactionDigest,
5050        effects: &TransactionEffects,
5051        expected_effects_digest: TransactionEffectsDigest,
5052        object_store: &dyn ObjectStore,
5053        epoch_store: &Arc<AuthorityPerEpochStore>,
5054        inner_temporary_store: &InnerTemporaryStore,
5055        certificate: &VerifiedExecutableTransaction,
5056    ) -> SuiResult<Self> {
5057        // Epoch info
5058        let executed_epoch = epoch_store.epoch();
5059        let reference_gas_price = epoch_store.reference_gas_price();
5060        let epoch_start_config = epoch_store.epoch_start_config();
5061        let protocol_version = epoch_store.protocol_version().as_u64();
5062        let epoch_start_timestamp_ms = epoch_start_config.epoch_data().epoch_start_timestamp();
5063
5064        // Record all system packages at this version
5065        let mut relevant_system_packages = Vec::new();
5066        for sys_package_id in BuiltInFramework::all_package_ids() {
5067            if let Some(w) = object_store.get_object(&sys_package_id) {
5068                relevant_system_packages.push(ObjDumpFormat::new(w))
5069            }
5070        }
5071
5072        // Record all the shared objects
5073        let mut shared_objects = Vec::new();
5074        for kind in effects.accessed_consensus_objects() {
5075            match kind {
5076                InputConsensusObject::Mutate(obj_ref) | InputConsensusObject::ReadOnly(obj_ref) => {
5077                    if let Some(w) = object_store.get_object_by_key(&obj_ref.0, obj_ref.1) {
5078                        shared_objects.push(ObjDumpFormat::new(w))
5079                    }
5080                }
5081                InputConsensusObject::ReadConsensusStreamEnded(..)
5082                | InputConsensusObject::MutateConsensusStreamEnded(..)
5083                | InputConsensusObject::Cancelled(..) => (), // TODO: consider record congested objects.
5084            }
5085        }
5086
5087        // Record all loaded child objects
5088        // Child objects which are read but not mutated are not tracked anywhere else
5089        let mut loaded_child_objects = Vec::new();
5090        for (id, meta) in &inner_temporary_store.loaded_runtime_objects {
5091            if let Some(w) = object_store.get_object_by_key(id, meta.version) {
5092                loaded_child_objects.push(ObjDumpFormat::new(w))
5093            }
5094        }
5095
5096        // Record all modified objects
5097        let mut modified_at_versions = Vec::new();
5098        for (id, ver) in effects.modified_at_versions() {
5099            if let Some(w) = object_store.get_object_by_key(&id, ver) {
5100                modified_at_versions.push(ObjDumpFormat::new(w))
5101            }
5102        }
5103
5104        // Packages read at runtime, which were not previously loaded into the temoorary store
5105        // Some packages may be fetched at runtime and wont show up in input objects
5106        let mut runtime_reads = Vec::new();
5107        for obj in inner_temporary_store
5108            .runtime_packages_loaded_from_db
5109            .values()
5110        {
5111            runtime_reads.push(ObjDumpFormat::new(obj.object().clone()));
5112        }
5113
5114        // All other input objects should already be in `inner_temporary_store.objects`
5115
5116        Ok(Self {
5117            tx_digest: *tx_digest,
5118            executed_epoch,
5119            reference_gas_price,
5120            epoch_start_timestamp_ms,
5121            protocol_version,
5122            relevant_system_packages,
5123            shared_objects,
5124            loaded_child_objects,
5125            modified_at_versions,
5126            runtime_reads,
5127            sender_signed_data: certificate.clone().into_message(),
5128            input_objects: inner_temporary_store
5129                .input_objects
5130                .values()
5131                .map(|o| ObjDumpFormat::new(o.clone()))
5132                .collect(),
5133            computed_effects: effects.clone(),
5134            expected_effects_digest,
5135        })
5136    }
5137
5138    pub fn all_objects(&self) -> Vec<ObjDumpFormat> {
5139        let mut objects = Vec::new();
5140        objects.extend(self.relevant_system_packages.clone());
5141        objects.extend(self.shared_objects.clone());
5142        objects.extend(self.loaded_child_objects.clone());
5143        objects.extend(self.modified_at_versions.clone());
5144        objects.extend(self.runtime_reads.clone());
5145        objects.extend(self.input_objects.clone());
5146        objects
5147    }
5148
5149    pub fn write_to_file(&self, path: &Path) -> Result<PathBuf, anyhow::Error> {
5150        let file_name = format!(
5151            "{}_{}_NODE_DUMP.json",
5152            self.tx_digest,
5153            AuthorityState::unixtime_now_ms()
5154        );
5155        let mut path = path.to_path_buf();
5156        path.push(&file_name);
5157        let mut file = File::create(path.clone())?;
5158        file.write_all(serde_json::to_string_pretty(self)?.as_bytes())?;
5159        Ok(path)
5160    }
5161
5162    pub fn read_from_file(path: &PathBuf) -> Result<Self, anyhow::Error> {
5163        let file = File::open(path)?;
5164        serde_json::from_reader(file).map_err(|e| anyhow::anyhow!(e))
5165    }
5166}
5167
5168/// Run deny list checks and process funds withdrawals before loading input objects.
5169pub(crate) fn pre_object_load_checks(
5170    tx_data: &TransactionData,
5171    tx_signatures: &[GenericSignature],
5172    input_object_kinds: &[InputObjectKind],
5173    receiving_objects_refs: &[ObjectRef],
5174    protocol_config: &ProtocolConfig,
5175    transaction_deny_config: &TransactionDenyConfig,
5176    backing_package_store: &dyn BackingPackageStore,
5177    chain_identifier: ChainIdentifier,
5178    coin_reservation_resolver: &dyn CoinReservationResolverTrait,
5179    account_funds_read: &dyn AccountFundsRead,
5180) -> SuiResult<BTreeMap<AccumulatorObjId, (u64, TypeTag, SuiAddress)>> {
5181    // Note: the deny checks may do redundant package loads but:
5182    // - they only load packages when there is an active package deny map
5183    // - the loads are cached anyway
5184    sui_transaction_checks::deny::check_transaction_for_signing(
5185        tx_data,
5186        tx_signatures,
5187        input_object_kinds,
5188        receiving_objects_refs,
5189        transaction_deny_config,
5190        backing_package_store,
5191    )?;
5192
5193    let declared_withdrawals = tx_data
5194        .process_funds_withdrawals_for_signing(chain_identifier, coin_reservation_resolver)?;
5195
5196    account_funds_read.check_amounts_available(&declared_withdrawals)?;
5197
5198    if protocol_config.gasless_verify_remaining_balance() && tx_data.is_gasless_transaction() {
5199        let min_amounts = sui_types::transaction::get_gasless_allowed_token_types(protocol_config);
5200        account_funds_read
5201            .check_remaining_amounts_after_withdrawal(&declared_withdrawals, &min_amounts)?;
5202    }
5203
5204    Ok(declared_withdrawals)
5205}