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