1use 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
255pub struct AuthorityMetrics {
257 tx_orders: IntCounter,
258 total_certs: IntCounter,
259 total_effects: IntCounter,
260 pub shared_obj_tx: IntCounter,
262 sponsored_tx: IntCounter,
263 num_input_objs: Histogram,
264 num_shared_objects: Histogram,
266 batch_size: Histogram,
267
268 authority_state_handle_vote_transaction_latency: Histogram,
269
270 internal_execution_latency: Histogram,
271 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 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 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 pub bytecode_verifier_metrics: Arc<BytecodeVerifierMetrics>,
335
336 pub zklogin_sig_count: IntCounter,
338 pub multisig_sig_count: IntCounter,
340
341 pub execution_queueing_latency: LatencyObserver,
344
345 pub txn_ready_rate_tracker: Arc<Mutex<RateTracker>>,
352
353 pub execution_rate_tracker: Arc<Mutex<RateTracker>>,
356}
357
358const 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
376const LOW_LATENCY_SEC_BUCKETS: &[f64] = &[
378 0.00001, 0.00002, 0.00005, 0.0001, 0.0002, 0.0005, 0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1,
379 0.2, 0.5, 1., 2., 5., 10., 20., 50., 100.,
380];
381
382const 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
396pub 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: 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
799pub type StableSyncAuthoritySigner = Pin<Arc<dyn Signer<AuthoritySignature> + Send + Sync>>;
806
807#[derive(Debug, Clone, Copy, PartialEq, Eq)]
810pub enum ExpectedEffectsDigest {
811 Certified {
813 digest: TransactionEffectsDigest,
814 checkpoint_seq: CheckpointSequenceNumber,
815 },
816 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#[derive(Debug, Clone)]
840pub struct ExecutionEnv {
841 pub assigned_versions: AssignedVersions,
843 pub expected_effects_digest: Option<ExpectedEffectsDigest>,
846 pub funds_withdraw_status: FundsWithdrawStatus,
849 pub barrier_dependencies: Vec<TransactionDigest>,
852 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 #[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_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 pub name: AuthorityName,
960 pub secret: StableSyncAuthoritySigner,
962
963 input_loader: TransactionInputLoader,
965 execution_cache_trait_pointers: ExecutionCacheTraitPointers,
966 coin_reservation_resolver: Arc<CachingCoinReservationResolver>,
967
968 epoch_store: ArcSwap<AuthorityPerEpochStore>,
969
970 execution_lock: RwLock<EpochId>,
975
976 pub checkpoint_store: Arc<CheckpointStore>,
977
978 committee_store: Arc<CommitteeStore>,
979
980 execution_scheduler: Arc<ExecutionScheduler>,
982
983 #[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 db_checkpoint_config: DBCheckpointConfig,
993
994 pub config: NodeConfig,
995
996 pub overload_info: AuthorityOverloadInfo,
998
999 chain_identifier: ChainIdentifier,
1001
1002 pub(crate) congestion_tracker: Arc<CongestionTracker>,
1003
1004 pub(crate) consensus_gasless_counter: Arc<ConsensusGaslessCounter>,
1006
1007 pub traffic_controller: Option<Arc<TrafficController>>,
1009
1010 fork_recovery_state: Option<ForkRecoveryState>,
1012
1013 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 transaction_deny_config_manager: Arc<TransactionDenyConfigManager>,
1023}
1024
1025impl 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 #[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 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 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 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 self.get_cache_writer()
1230 .validate_owned_object_versions(&owned_objects)
1231 }
1232
1233 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 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 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 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 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 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 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 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 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 Err(_) => Ok(false),
1412 }
1413 }
1414
1415 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 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 return None;
1437 }
1438 let latest_version = latest_obj_ref.1;
1439 if cur_version <= latest_version {
1440 return None;
1443 }
1444 Some(InputKey::VersionedObject {
1446 id: FullObjectID::new(obj_id, None),
1447 version: cur_version,
1448 })
1449 }
1450
1451 #[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 #[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 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 let Some(execution_guard) = self.execution_lock_for_executable_transaction(certificate)
1527 else {
1528 tx_guard.release();
1529 return ExecutionOutput::EpochEnded;
1530 };
1531 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 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 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 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 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 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 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 fail_point!("crash");
1799
1800 self.get_cache_writer()
1801 .write_transaction_outputs(epoch_store.epoch(), transaction_outputs);
1802
1803 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 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 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 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 .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 #[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 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 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 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 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 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 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 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 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 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 *total_stake <= committee.validity_threshold()
2341 } else {
2342 *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 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 #[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 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(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 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: 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 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 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 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 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 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 None
2868 }
2869 }
2870
2871 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 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
2905
2906 cur_epoch_store.epoch_terminated().await;
2908
2909 cur_epoch_store.record_epoch_close_time_once();
2911
2912 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 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 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 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 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 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 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 replay_txns
3121 }
3122
3123 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 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 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 #[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 warn!("Sui conservation consistency check failed: {}", err);
3206 }
3207 } else {
3208 info!("Sui conservation consistency check passed");
3209 }
3210
3211 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 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 pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3308 self.epoch_store.load()
3309 }
3310
3311 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 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 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 pub fn get_chain_identifier(&self) -> ChainIdentifier {
3402 self.chain_identifier
3403 }
3404
3405 #[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 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 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 .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 #[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 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 return Ok(Some((
3740 (*transaction).clone().into_message(),
3741 TransactionStatus::Executed(None, effects.into_inner(), events),
3742 )));
3743 } else {
3744 debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
3748 }
3749 }
3750 Ok(None)
3753 }
3754
3755 #[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 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 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 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 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 #[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 #[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 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 info!("Framework {} does not need updating", system_package_ref.0);
4018 continue;
4019 }
4020
4021 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!(
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 let mut desired_upgrades: Vec<_> = capabilities
4117 .into_iter()
4118 .filter_map(|mut cap| {
4119 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 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 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 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 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 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 let start_checkpoint = std::cmp::max(
4489 last_checkpoint_before_end_of_epoch
4490 .saturating_sub(params.stored_observations_num_included_checkpoints - 1),
4491 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 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 #[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 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 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 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 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 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 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 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 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 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 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 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 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 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(..) => (), }
5085 }
5086
5087 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 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 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 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
5168pub(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 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}