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)
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 = policy_config.map(|policy_config| {
3030 Arc::new(TrafficController::init(
3031 policy_config,
3032 traffic_controller_metrics,
3033 firewall_config.clone(),
3034 ))
3035 });
3036 let state = Arc::new(AuthorityState {
3037 name,
3038 secret,
3039 execution_lock: RwLock::new(epoch),
3040 epoch_store: ArcSwap::new(epoch_store.clone()),
3041 input_loader,
3042 execution_cache_trait_pointers,
3043 indexes,
3044 grpc_indexes_store,
3045 subscription_handler: Arc::new(SubscriptionHandler::new(prometheus_registry)),
3046 checkpoint_store,
3047 committee_store,
3048 execution_scheduler,
3049 tx_execution_shutdown: Mutex::new(Some(tx_execution_shutdown)),
3050 metrics,
3051 pruner,
3052 authority_per_epoch_pruner,
3053 checkpoint_progress_tracker,
3054 config,
3055 overload_info: AuthorityOverloadInfo::default(),
3056 validator_tx_finalizer,
3057 chain_identifier,
3058 congestion_tracker: Arc::new(CongestionTracker::new(rgp)),
3059 traffic_controller,
3060 });
3061
3062 let authority_state = Arc::downgrade(&state);
3064 spawn_monitored_task!(execution_process(
3065 authority_state,
3066 rx_ready_transactions,
3067 rx_execution_shutdown,
3068 ));
3069 state
3071 .create_owner_index_if_empty(genesis_objects, &epoch_store)
3072 .expect("Error indexing genesis objects.");
3073
3074 state
3075 }
3076
3077 pub fn epoch_db_pruner(&self) -> &AuthorityPerEpochStorePruner {
3078 &self.authority_per_epoch_pruner
3079 }
3080
3081 pub fn get_object_cache_reader(&self) -> &Arc<dyn ObjectCacheRead> {
3083 &self.execution_cache_trait_pointers.object_cache_reader
3084 }
3085
3086 pub fn get_transaction_cache_reader(&self) -> &Arc<dyn TransactionCacheRead> {
3087 &self.execution_cache_trait_pointers.transaction_cache_reader
3088 }
3089
3090 pub fn get_cache_writer(&self) -> &Arc<dyn ExecutionCacheWrite> {
3091 &self.execution_cache_trait_pointers.cache_writer
3092 }
3093
3094 pub fn get_backing_store(&self) -> &Arc<dyn BackingStore + Send + Sync> {
3095 &self.execution_cache_trait_pointers.backing_store
3096 }
3097
3098 pub fn get_backing_package_store(&self) -> &Arc<dyn BackingPackageStore + Send + Sync> {
3099 &self.execution_cache_trait_pointers.backing_package_store
3100 }
3101
3102 pub fn get_object_store(&self) -> &Arc<dyn ObjectStore + Send + Sync> {
3103 &self.execution_cache_trait_pointers.object_store
3104 }
3105
3106 pub fn get_reconfig_api(&self) -> &Arc<dyn ExecutionCacheReconfigAPI> {
3107 &self.execution_cache_trait_pointers.reconfig_api
3108 }
3109
3110 pub fn get_global_state_hash_store(&self) -> &Arc<dyn GlobalStateHashStore> {
3111 &self.execution_cache_trait_pointers.global_state_hash_store
3112 }
3113
3114 pub fn get_checkpoint_cache(&self) -> &Arc<dyn CheckpointCache> {
3115 &self.execution_cache_trait_pointers.checkpoint_cache
3116 }
3117
3118 pub fn get_state_sync_store(&self) -> &Arc<dyn StateSyncAPI> {
3119 &self.execution_cache_trait_pointers.state_sync_store
3120 }
3121
3122 pub fn get_cache_commit(&self) -> &Arc<dyn ExecutionCacheCommit> {
3123 &self.execution_cache_trait_pointers.cache_commit
3124 }
3125
3126 pub fn database_for_testing(&self) -> Arc<AuthorityStore> {
3127 self.execution_cache_trait_pointers
3128 .testing_api
3129 .database_for_testing()
3130 }
3131
3132 pub async fn prune_checkpoints_for_eligible_epochs_for_testing(
3133 &self,
3134 config: NodeConfig,
3135 metrics: Arc<AuthorityStorePruningMetrics>,
3136 ) -> anyhow::Result<()> {
3137 AuthorityStorePruner::prune_checkpoints_for_eligible_epochs(
3138 &self.database_for_testing().perpetual_tables,
3139 &self.checkpoint_store,
3140 self.grpc_indexes_store.as_deref(),
3141 None,
3142 config.authority_store_pruning_config,
3143 metrics,
3144 EPOCH_DURATION_MS_FOR_TESTING,
3145 self.checkpoint_progress_tracker.as_ref(),
3146 )
3147 .await
3148 }
3149
3150 pub(crate) fn execution_scheduler(&self) -> &Arc<ExecutionSchedulerWrapper> {
3151 &self.execution_scheduler
3152 }
3153
3154 pub fn uses_execution_scheduler(&self) -> bool {
3157 self.execution_scheduler.uses_execution_scheduler()
3158 }
3159
3160 pub fn enqueue_transactions_for_execution(
3162 &self,
3163 transactions: Vec<VerifiedExecutableTransaction>,
3164 epoch_store: &Arc<AuthorityPerEpochStore>,
3165 ) {
3166 self.execution_scheduler.enqueue(transactions, epoch_store)
3167 }
3168
3169 pub fn enqueue_certificates_for_execution(
3171 &self,
3172 certs: Vec<VerifiedCertificate>,
3173 epoch_store: &Arc<AuthorityPerEpochStore>,
3174 ) {
3175 self.execution_scheduler
3176 .enqueue_certificates(certs, epoch_store)
3177 }
3178
3179 pub fn enqueue_with_expected_effects_digest(
3180 &self,
3181 transactions: Vec<(VerifiedExecutableTransaction, TransactionEffectsDigest)>,
3182 epoch_store: &Arc<AuthorityPerEpochStore>,
3183 ) {
3184 self.execution_scheduler
3185 .enqueue_with_expected_effects_digest(transactions, epoch_store)
3186 }
3187
3188 fn create_owner_index_if_empty(
3189 &self,
3190 genesis_objects: &[Object],
3191 epoch_store: &Arc<AuthorityPerEpochStore>,
3192 ) -> IotaResult {
3193 let Some(index_store) = &self.indexes else {
3194 return Ok(());
3195 };
3196 if !index_store.is_empty() {
3197 return Ok(());
3198 }
3199
3200 let mut new_owners = vec![];
3201 let mut new_dynamic_fields = vec![];
3202 let mut layout_resolver = epoch_store
3203 .executor()
3204 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()));
3205 for o in genesis_objects.iter() {
3206 match o.owner {
3207 Owner::Address(addr) => {
3208 new_owners.push(((addr, o.id()), ObjectInfo::new(&o.object_ref(), o)))
3209 }
3210 Owner::Object(object_id) => {
3211 let id = o.id();
3212 let info = match self.try_create_dynamic_field_info(
3213 o,
3214 &BTreeMap::new(),
3215 layout_resolver.as_mut(),
3216 ) {
3217 Ok(Some(info)) => info,
3218 Ok(None) => continue,
3219 Err(IotaError::UserInput {
3220 error:
3221 UserInputError::ObjectNotFound {
3222 object_id: not_found_id,
3223 version,
3224 },
3225 }) => {
3226 warn!(
3227 ?not_found_id,
3228 ?version,
3229 object_owner=?object_id,
3230 field=?id,
3231 "Skipping dynamic field: referenced genesis object not found"
3232 );
3233 continue;
3234 }
3235 Err(e) => return Err(e),
3236 };
3237 new_dynamic_fields.push(((object_id, id), info));
3238 }
3239 _ => {}
3240 }
3241 }
3242
3243 index_store.insert_genesis_objects(ObjectIndexChanges {
3244 deleted_owners: vec![],
3245 deleted_dynamic_fields: vec![],
3246 new_owners,
3247 new_dynamic_fields,
3248 })
3249 }
3250
3251 pub fn execution_lock_for_executable_transaction(
3255 &self,
3256 transaction: &VerifiedExecutableTransaction,
3257 ) -> IotaResult<ExecutionLockReadGuard<'_>> {
3258 let lock = self
3259 .execution_lock
3260 .try_read()
3261 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)?;
3262 if *lock == transaction.auth_sig().epoch() {
3263 Ok(lock)
3264 } else {
3265 Err(IotaError::WrongEpoch {
3266 expected_epoch: *lock,
3267 actual_epoch: transaction.auth_sig().epoch(),
3268 })
3269 }
3270 }
3271
3272 pub fn execution_lock_for_signing(&self) -> IotaResult<ExecutionLockReadGuard<'_>> {
3278 self.execution_lock
3279 .try_read()
3280 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)
3281 }
3282
3283 pub async fn execution_lock_for_reconfiguration(&self) -> ExecutionLockWriteGuard<'_> {
3284 self.execution_lock.write().await
3285 }
3286
3287 pub(crate) fn check_transaction_deny_rules_consistency(
3297 &self,
3298 cur_epoch_store: &AuthorityPerEpochStore,
3299 epoch_start_configuration: &EpochStartConfiguration,
3300 ) {
3301 if self.is_fullnode(cur_epoch_store) {
3302 return;
3303 }
3304 let Some(walked_deny_rules) = epoch_start_configuration.transaction_deny_rules_state()
3305 else {
3306 if cur_epoch_store
3307 .epoch_start_config()
3308 .transaction_deny_rules_obj_initial_shared_version()
3309 .is_some()
3310 {
3311 fatal!(
3312 "TransactionDenyRules object existed in epoch {} but is missing from the \
3313 state walked for the next epoch — the local store is corrupted; restore or \
3314 state-sync before rejoining",
3315 cur_epoch_store.epoch(),
3316 );
3317 }
3318 return;
3319 };
3320 if cur_epoch_store
3324 .get_reconfig_state_read_lock_guard()
3325 .should_accept_tx()
3326 {
3327 info!(
3328 "skipping the deny-rule mirror comparison: consensus did not close epoch {} on \
3329 this node",
3330 cur_epoch_store.epoch(),
3331 );
3332 return;
3333 }
3334 let mirrored_deny_rules = cur_epoch_store.get_mirrored_transaction_deny_rules();
3335 if *walked_deny_rules != *mirrored_deny_rules {
3336 debug_fatal!(
3337 "TransactionDenyRules object diverged from the mirrored state at the end of \
3338 epoch {}; continuing from the object (walked: {walked_deny_rules:?}, mirrored: \
3339 {mirrored_deny_rules:?})",
3340 cur_epoch_store.epoch(),
3341 );
3342 cur_epoch_store.metrics.deny_rule_mirror_divergence.set(1);
3343 }
3344 }
3345
3346 pub(crate) fn report_failed_deny_rule_update_execution(
3358 &self,
3359 transaction: &VerifiedExecutableTransaction,
3360 effects: &TransactionEffects,
3361 expected_effects_digest: Option<TransactionEffectsDigest>,
3362 epoch_store: &AuthorityPerEpochStore,
3363 ) {
3364 if !matches!(
3365 transaction.transaction().kind(),
3366 TransactionKind::TransactionDenyRulesUpdate(_)
3367 ) || effects.status().is_success()
3368 {
3369 return;
3370 }
3371 epoch_store
3372 .metrics
3373 .deny_rule_update_execution_failures
3374 .inc();
3375 if expected_effects_digest.is_some() {
3376 error!(
3377 digest = ?transaction.digest(),
3378 status = ?effects.status(),
3379 "TransactionDenyRulesUpdate failed execution; the object misses its delta until \
3380 the epoch boundary re-seeds the mirror"
3381 );
3382 return;
3383 }
3384 debug_fatal!(
3385 "TransactionDenyRulesUpdate failed execution; the object misses its delta until the \
3386 epoch boundary re-seeds the mirror (digest: {:?}, status: {:?})",
3387 transaction.digest(),
3388 effects.status(),
3389 );
3390 }
3391
3392 #[instrument(level = "error", skip_all)]
3393 pub async fn reconfigure(
3394 &self,
3395 cur_epoch_store: &AuthorityPerEpochStore,
3396 supported_protocol_versions: SupportedProtocolVersions,
3397 new_committee: Committee,
3398 epoch_start_configuration: EpochStartConfiguration,
3399 state_hasher: Arc<GlobalStateHasher>,
3400 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3401 epoch_supply_change: i64,
3402 epoch_last_checkpoint: CheckpointSequenceNumber,
3403 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
3404 Self::check_protocol_version(
3405 supported_protocol_versions,
3406 epoch_start_configuration
3407 .epoch_start_state()
3408 .protocol_version(),
3409 );
3410 self.metrics.reset_on_reconfigure();
3411 self.committee_store.insert_new_committee(&new_committee)?;
3412
3413 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3415
3416 cur_epoch_store.epoch_terminated().await;
3418
3419 let highest_locally_built_checkpoint_seq = self
3420 .checkpoint_store
3421 .get_latest_locally_computed_checkpoint()?
3422 .map(|c| c.sequence_number())
3423 .unwrap_or(0);
3424
3425 assert!(
3426 epoch_last_checkpoint >= highest_locally_built_checkpoint_seq,
3427 "expected {epoch_last_checkpoint} >= {highest_locally_built_checkpoint_seq}"
3428 );
3429 if highest_locally_built_checkpoint_seq == epoch_last_checkpoint
3430 || self.is_fullnode(cur_epoch_store)
3431 {
3432 let num_shared_version_assignments = cur_epoch_store.num_shared_version_assignments();
3436 if num_shared_version_assignments > 10 {
3443 debug_fatal!(
3445 "all shared_version_assignments should have been removed \
3446 (num_shared_version_assignments: {num_shared_version_assignments})"
3447 );
3448 }
3449 }
3450
3451 self.revert_uncommitted_epoch_transactions(cur_epoch_store)
3457 .await?;
3458 self.get_reconfig_api()
3459 .clear_state_end_of_epoch(&execution_lock);
3460 self.check_system_consistency(
3461 cur_epoch_store,
3462 state_hasher,
3463 expensive_safety_check_config,
3464 epoch_supply_change,
3465 )?;
3466 self.check_transaction_deny_rules_consistency(cur_epoch_store, &epoch_start_configuration);
3467
3468 self.get_reconfig_api()
3469 .try_set_epoch_start_configuration(&epoch_start_configuration)?;
3470 if self
3474 .config
3475 .state_snapshot_write_config
3476 .object_store_config
3477 .is_some()
3478 {
3479 let current_epoch = cur_epoch_store.epoch();
3480 let epoch_checkpoint_path = self
3481 .config
3482 .db_checkpoint_path()
3483 .join(format!("epoch_{current_epoch}"));
3484 self.checkpoint_perpetual_db(&epoch_checkpoint_path, cur_epoch_store)?;
3485 }
3486
3487 let new_epoch = new_committee.epoch;
3488 let new_epoch_store = self
3489 .reopen_epoch_db(
3490 cur_epoch_store,
3491 new_committee,
3492 epoch_start_configuration,
3493 expensive_safety_check_config,
3494 epoch_last_checkpoint,
3495 )
3496 .await?;
3497 assert_eq!(new_epoch_store.epoch(), new_epoch);
3498 match self.execution_scheduler.as_ref() {
3499 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3500 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3501 tm.reconfigure(new_epoch);
3502 }
3503 }
3504 *execution_lock = new_epoch;
3505 Ok(new_epoch_store)
3509 }
3510
3511 pub async fn reconfigure_for_testing(&self) {
3516 self.reconfigure_for_testing_impl(None).await;
3517 }
3518
3519 pub async fn reconfigure_for_testing_with_protocol_config(
3522 &self,
3523 protocol_config: ProtocolConfig,
3524 ) {
3525 self.reconfigure_for_testing_impl(Some(protocol_config))
3526 .await;
3527 }
3528
3529 async fn reconfigure_for_testing_impl(&self, protocol_config: Option<ProtocolConfig>) {
3530 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3531 let epoch_store = self.epoch_store_for_testing().clone();
3532 let protocol_config =
3536 protocol_config.unwrap_or_else(|| epoch_store.protocol_config().clone());
3537 let _guard =
3538 ProtocolConfig::apply_overrides_for_testing(move |_, _| protocol_config.clone());
3539 let new_epoch_store = epoch_store.new_at_next_epoch_for_testing(
3540 self.get_backing_package_store().clone(),
3541 &self.config.expensive_safety_check_config,
3542 self.checkpoint_store
3543 .get_epoch_last_checkpoint(epoch_store.epoch())
3544 .unwrap()
3545 .map(|c| c.sequence_number())
3546 .unwrap_or_default(),
3547 );
3548 let new_epoch = new_epoch_store.epoch();
3549 match self.execution_scheduler.as_ref() {
3550 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3551 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3552 tm.reconfigure(new_epoch);
3553 }
3554 }
3555 self.epoch_store.store(new_epoch_store);
3556 epoch_store.epoch_terminated().await;
3557 *execution_lock = new_epoch;
3558 }
3559
3560 #[instrument(level = "error", skip_all)]
3561 fn check_system_consistency(
3562 &self,
3563 cur_epoch_store: &AuthorityPerEpochStore,
3564 state_hasher: Arc<GlobalStateHasher>,
3565 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3566 epoch_supply_change: i64,
3567 ) -> IotaResult<()> {
3568 info!(
3569 "Performing iota conservation consistency check for epoch {}",
3570 cur_epoch_store.epoch()
3571 );
3572
3573 if cfg!(debug_assertions) {
3574 cur_epoch_store.check_all_executed_transactions_in_checkpoint();
3575 }
3576
3577 self.get_reconfig_api()
3578 .try_expensive_check_iota_conservation(cur_epoch_store, Some(epoch_supply_change))?;
3579
3580 if expensive_safety_check_config.enable_state_consistency_check() {
3582 info!(
3583 "Performing state consistency check for epoch {}",
3584 cur_epoch_store.epoch()
3585 );
3586 self.expensive_check_is_consistent_state(state_hasher, cur_epoch_store);
3587 }
3588
3589 if expensive_safety_check_config.enable_secondary_index_checks() {
3590 if let Some(indexes) = self.indexes.clone() {
3591 verify_indexes(self.get_global_state_hash_store().as_ref(), indexes)
3592 .expect("secondary indexes are inconsistent");
3593 }
3594 }
3595
3596 Ok(())
3597 }
3598
3599 fn expensive_check_is_consistent_state(
3600 &self,
3601 state_hasher: Arc<GlobalStateHasher>,
3602 cur_epoch_store: &AuthorityPerEpochStore,
3603 ) {
3604 let live_object_set_hash = state_hasher.digest_live_object_set();
3605
3606 let root_state_hash: ECMHLiveObjectSetDigest = self
3607 .get_global_state_hash_store()
3608 .get_root_state_hash_for_epoch(cur_epoch_store.epoch())
3609 .expect("Retrieving root state hash cannot fail")
3610 .expect("Root state hash for epoch must exist")
3611 .1
3612 .digest()
3613 .into();
3614
3615 let is_inconsistent = root_state_hash != live_object_set_hash;
3616 if is_inconsistent {
3617 debug_fatal!(
3618 "Inconsistent state detected: root state hash: {:?}, live object set hash: {:?}",
3619 root_state_hash,
3620 live_object_set_hash
3621 );
3622 } else {
3623 info!("State consistency check passed");
3624 }
3625
3626 state_hasher.set_inconsistent_state(is_inconsistent);
3627 }
3628
3629 pub fn current_epoch_for_testing(&self) -> EpochId {
3630 self.epoch_store_for_testing().epoch()
3631 }
3632
3633 #[instrument(level = "error", skip_all)]
3637 fn checkpoint_perpetual_db(
3638 &self,
3639 checkpoint_path: &Path,
3640 cur_epoch_store: &AuthorityPerEpochStore,
3641 ) -> IotaResult {
3642 let _metrics_guard = self.metrics.db_checkpoint_latency.start_timer();
3643 let current_epoch = cur_epoch_store.epoch();
3644
3645 if checkpoint_path.exists() {
3646 info!("Skipping db checkpoint as it already exists for epoch: {current_epoch}");
3647 return Ok(());
3648 }
3649
3650 let checkpoint_path_tmp = checkpoint_path.with_extension("tmp");
3651 let store_checkpoint_path_tmp = checkpoint_path_tmp.join("store");
3652
3653 if checkpoint_path_tmp.exists() {
3654 fs::remove_dir_all(&checkpoint_path_tmp)
3655 .map_err(|e| IotaError::FileIO(e.to_string()))?;
3656 }
3657
3658 fs::create_dir_all(&checkpoint_path_tmp).map_err(|e| IotaError::FileIO(e.to_string()))?;
3659 fs::create_dir(&store_checkpoint_path_tmp).map_err(|e| IotaError::FileIO(e.to_string()))?;
3660
3661 self.get_reconfig_api()
3662 .try_checkpoint_db(&store_checkpoint_path_tmp.join("perpetual"))?;
3663
3664 fs::rename(checkpoint_path_tmp, checkpoint_path)
3665 .map_err(|e| IotaError::FileIO(e.to_string()))?;
3666 Ok(())
3667 }
3668
3669 pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3676 self.epoch_store.load()
3677 }
3678
3679 pub fn epoch_store_for_testing(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3681 self.load_epoch_store_one_call_per_task()
3682 }
3683
3684 pub fn clone_committee_for_testing(&self) -> Committee {
3685 Committee::clone(self.epoch_store_for_testing().committee())
3686 }
3687
3688 #[instrument(level = "trace", skip_all)]
3689 pub fn try_get_object(&self, object_id: &ObjectId) -> IotaResult<Option<Object>> {
3690 self.get_object_store()
3691 .try_get_object(object_id)
3692 .map_err(Into::into)
3693 }
3694
3695 pub fn get_object(&self, object_id: &ObjectId) -> Option<Object> {
3697 self.try_get_object(object_id)
3698 .expect("storage access failed")
3699 }
3700
3701 pub fn get_iota_system_package_object_ref(&self) -> IotaResult<ObjectReference> {
3702 Ok(self
3703 .try_get_object(&ObjectId::SYSTEM)?
3704 .expect("system package should always exist")
3705 .object_ref())
3706 }
3707
3708 pub fn get_iota_system_state_object_for_testing(&self) -> IotaResult<IotaSystemState> {
3710 self.get_object_cache_reader()
3711 .try_get_iota_system_state_object_unsafe()
3712 }
3713
3714 #[instrument(level = "trace", skip_all)]
3715 pub fn get_checkpoint_by_sequence_number(
3716 &self,
3717 sequence_number: CheckpointSequenceNumber,
3718 ) -> IotaResult<Option<VerifiedCheckpoint>> {
3719 Ok(self
3720 .checkpoint_store
3721 .get_checkpoint_by_sequence_number(sequence_number)?)
3722 }
3723
3724 pub async fn wait_for_checkpoint_inclusion(
3735 &self,
3736 digests: &[TransactionDigest],
3737 timeout: Duration,
3738 ) -> IotaResult<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>> {
3739 let deadline = tokio::time::Instant::now() + timeout;
3740 let mut checkpoint_timestamp_cache = HashMap::<CheckpointSequenceNumber, u64>::new();
3741 let mut results = BTreeMap::new();
3742 let mut remaining = digests.to_vec();
3743 let mut epoch_store = self.load_epoch_store_one_call_per_task().clone();
3744
3745 loop {
3746 let wait = epoch_store.wait_for_transactions_in_checkpoint_with_timeout(
3747 &remaining,
3748 deadline.saturating_duration_since(tokio::time::Instant::now()),
3749 |seq| self.checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache),
3750 );
3751 tokio::select! {
3752 wait_results = wait => {
3753 for (digest, seq_and_ts) in remaining.iter().zip(wait_results?) {
3754 if let Some(seq_and_ts) = seq_and_ts {
3755 results.insert(*digest, seq_and_ts);
3756 }
3757 }
3758 return Ok(results);
3759 }
3760 _ = epoch_store.wait_epoch_terminated() => {}
3761 }
3762
3763 let found = match epoch_store.multi_get_transaction_checkpoint(&remaining) {
3770 Ok(found) => found,
3771 Err(IotaError::EpochEnded(_)) => vec![None; remaining.len()],
3776 Err(err) => return Err(err),
3777 };
3778 let mut still_uncheckpointed = Vec::new();
3779 for (digest, found_seq) in remaining.iter().zip(found) {
3780 match found_seq {
3781 Some(seq) => {
3782 let ts = self
3783 .checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache);
3784 results.insert(*digest, (seq, ts));
3785 }
3786 None => still_uncheckpointed.push(*digest),
3787 }
3788 }
3789 remaining = still_uncheckpointed;
3790 if remaining.is_empty() {
3791 return Ok(results);
3792 }
3793
3794 match self
3795 .wait_for_next_epoch_store(epoch_store.epoch(), deadline)
3796 .await
3797 {
3798 Some(next) => epoch_store = next,
3799 None => return Ok(results),
3800 }
3801 }
3802 }
3803
3804 async fn wait_for_next_epoch_store(
3807 &self,
3808 prev_epoch: EpochId,
3809 deadline: tokio::time::Instant,
3810 ) -> Option<Arc<AuthorityPerEpochStore>> {
3811 const EPOCH_STORE_SWAP_POLL_INTERVAL: Duration = Duration::from_millis(100);
3816
3817 loop {
3818 let current = self.load_epoch_store_one_call_per_task().clone();
3821 if current.epoch() > prev_epoch {
3822 return Some(current);
3823 }
3824 if tokio::time::Instant::now() >= deadline {
3825 return None;
3826 }
3827 tokio::time::sleep(EPOCH_STORE_SWAP_POLL_INTERVAL).await;
3828 }
3829 }
3830
3831 fn checkpoint_timestamp_ms_cached(
3835 &self,
3836 seq: CheckpointSequenceNumber,
3837 cache: &mut HashMap<CheckpointSequenceNumber, u64>,
3838 ) -> u64 {
3839 *cache.entry(seq).or_insert_with(|| {
3840 self.get_checkpoint_by_sequence_number(seq)
3841 .ok()
3842 .flatten()
3843 .map(|c| c.timestamp_ms)
3844 .unwrap_or(0)
3845 })
3846 }
3847
3848 #[instrument(level = "trace", skip_all)]
3849 pub fn get_transaction_checkpoint_for_tests(
3850 &self,
3851 digest: &TransactionDigest,
3852 epoch_store: &AuthorityPerEpochStore,
3853 ) -> IotaResult<Option<VerifiedCheckpoint>> {
3854 let checkpoint = epoch_store.get_transaction_checkpoint(digest)?;
3855 let Some(checkpoint) = checkpoint else {
3856 return Ok(None);
3857 };
3858 let checkpoint = self
3859 .checkpoint_store
3860 .get_checkpoint_by_sequence_number(checkpoint)?;
3861 Ok(checkpoint)
3862 }
3863
3864 #[instrument(level = "trace", skip_all)]
3865 pub fn get_object_read(&self, object_id: &ObjectId) -> IotaResult<ObjectRead> {
3866 Ok(
3867 match self
3868 .get_object_cache_reader()
3869 .try_get_latest_object_or_tombstone(*object_id)?
3870 {
3871 Some((_, ObjectOrTombstone::Object(object))) => {
3872 let layout = self.get_object_layout(&object)?;
3873 ObjectRead::Exists(object.object_ref(), object, layout)
3874 }
3875 Some((_, ObjectOrTombstone::Tombstone(objref))) => ObjectRead::Deleted(objref),
3876 None => ObjectRead::NotExists(*object_id),
3877 },
3878 )
3879 }
3880
3881 pub fn get_chain_identifier(&self) -> ChainIdentifier {
3883 self.chain_identifier
3884 }
3885
3886 #[instrument(level = "trace", skip_all)]
3887 pub fn get_move_object<T>(&self, object_id: &ObjectId) -> IotaResult<T>
3888 where
3889 T: DeserializeOwned,
3890 {
3891 let o = self.get_object_read(object_id)?.into_object()?;
3892 if let Some(move_object) = o.data.as_opt_struct() {
3893 Ok(bcs::from_bytes(move_object.contents()).map_err(|e| {
3894 IotaError::ObjectDeserialization {
3895 error: format!("{e}"),
3896 }
3897 })?)
3898 } else {
3899 Err(IotaError::ObjectDeserialization {
3900 error: format!("Provided object : [{object_id}] is not a Move object."),
3901 })
3902 }
3903 }
3904
3905 #[instrument(level = "trace", skip_all)]
3911 pub fn get_past_object_read(
3912 &self,
3913 object_id: &ObjectId,
3914 version: Version,
3915 ) -> IotaResult<PastObjectRead> {
3916 let Some(obj_ref) = self
3918 .get_object_cache_reader()
3919 .try_get_latest_object_ref_or_tombstone(*object_id)?
3920 else {
3921 return Ok(PastObjectRead::ObjectNotExists(*object_id));
3922 };
3923
3924 if version > obj_ref.version {
3925 return Ok(PastObjectRead::VersionTooHigh {
3926 object_id: *object_id,
3927 asked_version: version,
3928 latest_version: obj_ref.version,
3929 });
3930 }
3931
3932 if version < obj_ref.version {
3933 return Ok(match self.read_object_at_version(object_id, version)? {
3935 Some((object, layout)) => {
3936 let obj_ref = object.object_ref();
3937 PastObjectRead::VersionFound(obj_ref, object, layout)
3938 }
3939
3940 None => PastObjectRead::VersionNotFound(*object_id, version),
3941 });
3942 }
3943
3944 if !obj_ref.digest.is_alive() {
3945 return Ok(PastObjectRead::ObjectDeleted(obj_ref));
3946 }
3947
3948 match self.read_object_at_version(object_id, obj_ref.version)? {
3949 Some((object, layout)) => Ok(PastObjectRead::VersionFound(obj_ref, object, layout)),
3950 None => {
3951 debug_fatal!(
3952 "Object with in parent_entry is missing from object store, datastore is \
3953 inconsistent",
3954 );
3955 Err(UserInputError::ObjectNotFound {
3956 object_id: *object_id,
3957 version: Some(obj_ref.version),
3958 }
3959 .into())
3960 }
3961 }
3962 }
3963
3964 #[instrument(level = "trace", skip_all)]
3965 fn read_object_at_version(
3966 &self,
3967 object_id: &ObjectId,
3968 version: Version,
3969 ) -> IotaResult<Option<(Object, Option<MoveStructLayout>)>> {
3970 let Some(object) = self
3971 .get_object_cache_reader()
3972 .try_get_object_by_key(object_id, version)?
3973 else {
3974 return Ok(None);
3975 };
3976
3977 let layout = self.get_object_layout(&object)?;
3978 Ok(Some((object, layout)))
3979 }
3980
3981 fn get_object_layout(&self, object: &Object) -> IotaResult<Option<MoveStructLayout>> {
3982 let layout = object
3983 .data
3984 .as_opt_struct()
3985 .map(|object| {
3986 into_struct_layout(
3987 self.load_epoch_store_one_call_per_task()
3988 .executor()
3989 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
3991 .get_annotated_layout(object.struct_tag())?,
3992 )
3993 })
3994 .transpose()?;
3995 Ok(layout)
3996 }
3997
3998 fn get_owner_at_version(&self, object_id: &ObjectId, version: Version) -> IotaResult<Owner> {
3999 self.get_object_store()
4000 .try_get_object_by_key(object_id, version)?
4001 .ok_or_else(|| {
4002 IotaError::from(UserInputError::ObjectNotFound {
4003 object_id: *object_id,
4004 version: Some(version),
4005 })
4006 })
4007 .map(|o| o.owner)
4008 }
4009
4010 #[instrument(level = "trace", skip_all)]
4011 pub fn get_owner_objects(
4012 &self,
4013 owner: Address,
4014 cursor: Option<ObjectId>,
4016 limit: usize,
4017 filter: Option<IotaObjectDataFilter>,
4018 ) -> IotaResult<Vec<ObjectInfo>> {
4019 if let Some(indexes) = &self.indexes {
4020 indexes.get_owner_objects(owner, cursor, limit, filter)
4021 } else {
4022 Err(IotaError::IndexStoreNotAvailable)
4023 }
4024 }
4025
4026 #[instrument(level = "trace", skip_all)]
4027 pub fn get_owned_coins_iterator_with_cursor(
4028 &self,
4029 owner: Address,
4030 cursor: (String, ObjectId),
4032 limit: usize,
4033 one_coin_type_only: bool,
4034 ) -> IotaResult<impl Iterator<Item = (String, ObjectId, CoinInfo)> + '_> {
4035 if let Some(indexes) = &self.indexes {
4036 indexes.get_owned_coins_iterator_with_cursor(owner, cursor, limit, one_coin_type_only)
4037 } else {
4038 Err(IotaError::IndexStoreNotAvailable)
4039 }
4040 }
4041
4042 #[instrument(level = "trace", skip_all)]
4043 pub fn get_owner_objects_iterator(
4044 &self,
4045 owner: Address,
4046 cursor: Option<ObjectId>,
4048 filter: Option<IotaObjectDataFilter>,
4049 ) -> IotaResult<impl Iterator<Item = ObjectInfo> + '_> {
4050 let cursor_u = cursor.unwrap_or(ObjectId::ZERO);
4051 if let Some(indexes) = &self.indexes {
4052 indexes.get_owner_objects_iterator(owner, cursor_u, filter)
4053 } else {
4054 Err(IotaError::IndexStoreNotAvailable)
4055 }
4056 }
4057
4058 #[instrument(level = "trace", skip_all)]
4059 pub fn get_move_objects<T>(&self, owner: Address, tag: StructTag) -> IotaResult<Vec<T>>
4060 where
4061 T: DeserializeOwned,
4062 {
4063 let object_ids = self
4064 .get_owner_objects_iterator(owner, None, None)?
4065 .filter(|o| match &o.object_type {
4066 ObjectType::Struct(s) => *s == tag,
4067 ObjectType::Package => false,
4068 })
4069 .map(|info| ObjectKey(info.object_id, info.version))
4070 .collect::<Vec<_>>();
4071 let mut move_objects = vec![];
4072
4073 let objects = self
4074 .get_object_store()
4075 .try_multi_get_objects_by_key(&object_ids)?;
4076
4077 for (o, id) in objects.into_iter().zip(object_ids) {
4078 let object = o.ok_or_else(|| {
4079 IotaError::from(UserInputError::ObjectNotFound {
4080 object_id: id.0,
4081 version: Some(id.1),
4082 })
4083 })?;
4084 let move_object = object.data.as_opt_struct().ok_or_else(|| {
4085 IotaError::from(UserInputError::MovePackageAsObject { object_id: id.0 })
4086 })?;
4087 move_objects.push(bcs::from_bytes(move_object.contents()).map_err(|e| {
4088 IotaError::ObjectDeserialization {
4089 error: format!("{e}"),
4090 }
4091 })?);
4092 }
4093 Ok(move_objects)
4094 }
4095
4096 #[instrument(level = "trace", skip_all)]
4097 pub fn get_dynamic_fields(
4098 &self,
4099 owner: ObjectId,
4100 cursor: Option<ObjectId>,
4102 limit: usize,
4103 ) -> IotaResult<Vec<(ObjectId, DynamicFieldInfo)>> {
4104 Ok(self
4105 .get_dynamic_fields_iterator(owner, cursor)?
4106 .take(limit)
4107 .collect::<Result<Vec<_>, _>>()?)
4108 }
4109
4110 fn get_dynamic_fields_iterator(
4111 &self,
4112 owner: ObjectId,
4113 cursor: Option<ObjectId>,
4115 ) -> IotaResult<impl Iterator<Item = Result<(ObjectId, DynamicFieldInfo), TypedStoreError>> + '_>
4116 {
4117 if let Some(indexes) = &self.indexes {
4118 indexes.get_dynamic_fields_iterator(owner, cursor)
4119 } else {
4120 Err(IotaError::IndexStoreNotAvailable)
4121 }
4122 }
4123
4124 #[instrument(level = "trace", skip_all)]
4125 pub fn get_dynamic_field_object_id(
4126 &self,
4127 owner: ObjectId,
4128 name_type: TypeTag,
4129 name_bcs_bytes: &[u8],
4130 ) -> IotaResult<Option<ObjectId>> {
4131 if let Some(indexes) = &self.indexes {
4132 indexes.get_dynamic_field_object_id(owner, name_type, name_bcs_bytes)
4133 } else {
4134 Err(IotaError::IndexStoreNotAvailable)
4135 }
4136 }
4137
4138 #[instrument(level = "trace", skip_all)]
4139 pub fn get_total_transaction_blocks(&self) -> IotaResult<u64> {
4140 Ok(self.get_indexes()?.next_sequence_number())
4141 }
4142
4143 #[instrument(level = "trace", skip_all)]
4144 pub async fn get_executed_transaction_and_effects(
4145 &self,
4146 digest: TransactionDigest,
4147 kv_store: Arc<TransactionKeyValueStore>,
4148 ) -> IotaResult<(TransactionEnvelope, TransactionEffects)> {
4149 let transaction = kv_store.get_tx(digest).await?;
4150 let effects = kv_store.get_fx_by_tx_digest(digest).await?;
4151 Ok((transaction, effects))
4152 }
4153
4154 #[instrument(level = "trace", skip_all)]
4155 pub fn multi_get_checkpoint_by_sequence_number(
4156 &self,
4157 sequence_numbers: &[CheckpointSequenceNumber],
4158 ) -> IotaResult<Vec<Option<VerifiedCheckpoint>>> {
4159 Ok(self
4160 .checkpoint_store
4161 .multi_get_checkpoint_by_sequence_number(sequence_numbers)?)
4162 }
4163
4164 #[instrument(level = "trace", skip_all)]
4165 pub fn get_transaction_events(
4166 &self,
4167 digest: &TransactionDigest,
4168 ) -> IotaResult<TransactionEvents> {
4169 self.get_transaction_cache_reader()
4170 .try_get_events(digest)?
4171 .ok_or(IotaError::TransactionEventsNotFound { digest: *digest })
4172 }
4173
4174 pub fn get_transaction_input_objects(
4175 &self,
4176 effects: &TransactionEffects,
4177 ) -> anyhow::Result<Vec<Object>> {
4178 iota_types::storage::get_transaction_input_objects(self.get_object_store(), effects)
4179 .map_err(Into::into)
4180 }
4181
4182 pub fn get_transaction_output_objects(
4183 &self,
4184 effects: &TransactionEffects,
4185 ) -> anyhow::Result<Vec<Object>> {
4186 iota_types::storage::get_transaction_output_objects(self.get_object_store(), effects)
4187 .map_err(Into::into)
4188 }
4189
4190 fn get_indexes(&self) -> IotaResult<Arc<IndexStore>> {
4191 match &self.indexes {
4192 Some(i) => Ok(i.clone()),
4193 None => Err(IotaError::UnsupportedFeature {
4194 error: "extended object indexing is not enabled on this server".into(),
4195 }),
4196 }
4197 }
4198
4199 pub async fn get_transactions_for_tests(
4200 self: &Arc<Self>,
4201 filter: Option<TransactionFilter>,
4202 cursor: Option<TransactionDigest>,
4203 limit: Option<usize>,
4204 reverse: bool,
4205 ) -> IotaResult<Vec<TransactionDigest>> {
4206 let metrics = KeyValueStoreMetrics::new_for_tests();
4207 let kv_store = Arc::new(TransactionKeyValueStore::new(
4208 "rocksdb",
4209 metrics,
4210 self.clone(),
4211 ));
4212 self.get_transactions(&kv_store, filter, cursor, limit, reverse)
4213 .await
4214 }
4215
4216 #[instrument(level = "trace", skip_all)]
4217 pub async fn get_transactions(
4218 &self,
4219 kv_store: &Arc<TransactionKeyValueStore>,
4220 filter: Option<TransactionFilter>,
4221 cursor: Option<TransactionDigest>,
4223 limit: Option<usize>,
4224 reverse: bool,
4225 ) -> IotaResult<Vec<TransactionDigest>> {
4226 if let Some(TransactionFilter::Checkpoint(sequence_number)) = filter {
4227 let checkpoint_contents = kv_store.get_checkpoint_contents(sequence_number).await?;
4228 let iter = checkpoint_contents.iter().map(|c| c.transaction);
4229 if reverse {
4230 let iter = iter
4231 .rev()
4232 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4233 .skip(usize::from(cursor.is_some()));
4234 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4235 } else {
4236 let iter = iter
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 }
4241 }
4242 self.get_indexes()?
4243 .get_transactions(filter, cursor, limit, reverse)
4244 }
4245
4246 pub fn get_checkpoint_store(&self) -> &Arc<CheckpointStore> {
4247 &self.checkpoint_store
4248 }
4249
4250 pub fn pruner(&self) -> &AuthorityStorePruner {
4253 &self.pruner
4254 }
4255
4256 pub fn get_latest_checkpoint_sequence_number(&self) -> IotaResult<CheckpointSequenceNumber> {
4257 self.get_checkpoint_store()
4258 .get_highest_executed_checkpoint_seq_number()?
4259 .ok_or(IotaError::UserInput {
4260 error: UserInputError::LatestCheckpointSequenceNumberNotFound,
4261 })
4262 }
4263
4264 #[cfg(msim)]
4265 pub fn get_highest_pruned_checkpoint_for_testing(
4266 &self,
4267 ) -> IotaResult<CheckpointSequenceNumber> {
4268 self.database_for_testing()
4269 .perpetual_tables
4270 .get_highest_pruned_checkpoint()
4271 .map(|c| c.unwrap_or(0))
4272 .map_err(Into::into)
4273 }
4274
4275 #[instrument(level = "trace", skip_all)]
4276 pub fn get_checkpoint_summary_by_sequence_number(
4277 &self,
4278 sequence_number: CheckpointSequenceNumber,
4279 ) -> IotaResult<CheckpointSummary> {
4280 let verified_checkpoint = self
4281 .get_checkpoint_store()
4282 .get_checkpoint_by_sequence_number(sequence_number)?;
4283 match verified_checkpoint {
4284 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4285 None => Err(IotaError::UserInput {
4286 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4287 }),
4288 }
4289 }
4290
4291 #[instrument(level = "trace", skip_all)]
4292 pub fn get_checkpoint_summary_by_digest(
4293 &self,
4294 digest: CheckpointDigest,
4295 ) -> IotaResult<CheckpointSummary> {
4296 let verified_checkpoint = self
4297 .get_checkpoint_store()
4298 .get_checkpoint_by_digest(&digest)?;
4299 match verified_checkpoint {
4300 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4301 None => Err(IotaError::UserInput {
4302 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4303 }),
4304 }
4305 }
4306
4307 #[instrument(level = "trace", skip_all)]
4308 pub fn find_publish_txn_digest(&self, package_id: ObjectId) -> IotaResult<TransactionDigest> {
4309 if package_id.is_system_package() {
4310 return self.find_genesis_txn_digest();
4311 }
4312 Ok(self
4313 .get_object_read(&package_id)?
4314 .into_object()?
4315 .previous_transaction)
4316 }
4317
4318 #[instrument(level = "trace", skip_all)]
4319 pub fn find_genesis_txn_digest(&self) -> IotaResult<TransactionDigest> {
4320 let summary = self
4321 .get_verified_checkpoint_by_sequence_number(0)?
4322 .into_message();
4323 let content = self.get_checkpoint_contents(summary.contents_digest)?;
4324 let genesis_transaction = content.enumerate_transactions(&summary).next();
4325 Ok(genesis_transaction
4326 .ok_or(IotaError::UserInput {
4327 error: UserInputError::GenesisTransactionNotFound,
4328 })?
4329 .1
4330 .transaction)
4331 }
4332
4333 #[instrument(level = "trace", skip_all)]
4334 pub fn get_verified_checkpoint_by_sequence_number(
4335 &self,
4336 sequence_number: CheckpointSequenceNumber,
4337 ) -> IotaResult<VerifiedCheckpoint> {
4338 let verified_checkpoint = self
4339 .get_checkpoint_store()
4340 .get_checkpoint_by_sequence_number(sequence_number)?;
4341 match verified_checkpoint {
4342 Some(verified_checkpoint) => Ok(verified_checkpoint),
4343 None => Err(IotaError::UserInput {
4344 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4345 }),
4346 }
4347 }
4348
4349 #[instrument(level = "trace", skip_all)]
4350 pub fn get_verified_checkpoint_summary_by_digest(
4351 &self,
4352 digest: CheckpointDigest,
4353 ) -> IotaResult<VerifiedCheckpoint> {
4354 let verified_checkpoint = self
4355 .get_checkpoint_store()
4356 .get_checkpoint_by_digest(&digest)?;
4357 match verified_checkpoint {
4358 Some(verified_checkpoint) => Ok(verified_checkpoint),
4359 None => Err(IotaError::UserInput {
4360 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4361 }),
4362 }
4363 }
4364
4365 #[instrument(level = "trace", skip_all)]
4366 pub fn get_checkpoint_contents(
4367 &self,
4368 digest: CheckpointContentsDigest,
4369 ) -> IotaResult<CheckpointContents> {
4370 self.get_checkpoint_store()
4371 .get_checkpoint_contents(&digest)?
4372 .ok_or(IotaError::UserInput {
4373 error: UserInputError::CheckpointContentsNotFound(digest),
4374 })
4375 }
4376
4377 #[instrument(level = "trace", skip_all)]
4378 pub fn get_checkpoint_contents_by_sequence_number(
4379 &self,
4380 sequence_number: CheckpointSequenceNumber,
4381 ) -> IotaResult<CheckpointContents> {
4382 let verified_checkpoint = self
4383 .get_checkpoint_store()
4384 .get_checkpoint_by_sequence_number(sequence_number)?;
4385 match verified_checkpoint {
4386 Some(verified_checkpoint) => {
4387 let contents_digest = verified_checkpoint.into_inner().contents_digest;
4388 self.get_checkpoint_contents(contents_digest)
4389 }
4390 None => Err(IotaError::UserInput {
4391 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4392 }),
4393 }
4394 }
4395
4396 #[instrument(level = "trace", skip_all)]
4397 pub async fn query_events(
4398 &self,
4399 kv_store: &Arc<TransactionKeyValueStore>,
4400 query: EventFilter,
4401 cursor: Option<EventID>,
4403 limit: usize,
4404 descending: bool,
4405 ) -> IotaResult<Vec<IotaEvent>> {
4406 let index_store = self.get_indexes()?;
4407
4408 let (tx_num, event_num) = if let Some(cursor) = cursor.as_ref() {
4410 let tx_seq = index_store.get_transaction_seq(&cursor.tx_digest)?.ok_or(
4411 IotaError::TransactionNotFound {
4412 digest: cursor.tx_digest,
4413 },
4414 )?;
4415 (tx_seq, cursor.event_seq as usize)
4416 } else if descending {
4417 (u64::MAX, usize::MAX)
4418 } else {
4419 (0, 0)
4420 };
4421
4422 let limit = limit + 1;
4423 let mut event_keys = match query {
4424 EventFilter::All(filters) => {
4425 if filters.is_empty() {
4426 index_store.all_events(tx_num, event_num, limit, descending)?
4427 } else {
4428 return Err(IotaError::UserInput {
4429 error: UserInputError::Unsupported(
4430 "This query type does not currently support filter combinations"
4431 .to_string(),
4432 ),
4433 });
4434 }
4435 }
4436 EventFilter::Transaction(digest) => {
4437 index_store.events_by_transaction(&digest, tx_num, event_num, limit, descending)?
4438 }
4439 EventFilter::MoveModule { package, module } => {
4440 let module_id = ModuleId::new(
4441 AccountAddress::new(package.into_bytes()),
4442 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4443 );
4444 index_store.events_by_module_id(&module_id, tx_num, event_num, limit, descending)?
4445 }
4446 EventFilter::MoveEventType(struct_name) => index_store
4447 .events_by_move_event_struct_name(
4448 &struct_name,
4449 tx_num,
4450 event_num,
4451 limit,
4452 descending,
4453 )?,
4454 EventFilter::Sender(sender) => {
4455 index_store.events_by_sender(&sender, tx_num, event_num, limit, descending)?
4456 }
4457 EventFilter::TimeRange {
4458 start_time,
4459 end_time,
4460 } => index_store
4461 .event_iterator(start_time, end_time, tx_num, event_num, limit, descending)?,
4462 EventFilter::MoveEventModule { package, module } => index_store
4463 .events_by_move_event_module(
4464 &ModuleId::new(
4465 AccountAddress::new(package.into_bytes()),
4466 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4467 ),
4468 tx_num,
4469 event_num,
4470 limit,
4471 descending,
4472 )?,
4473 EventFilter::Package(_)
4475 | EventFilter::MoveEventField { .. }
4476 | EventFilter::Any(_)
4477 | EventFilter::And(_, _)
4478 | EventFilter::Or(_, _) => {
4479 return Err(IotaError::UserInput {
4480 error: UserInputError::Unsupported(
4481 "This query type is not supported by the full node.".to_string(),
4482 ),
4483 });
4484 }
4485 };
4486
4487 if cursor.is_some() {
4490 if !event_keys.is_empty() {
4491 event_keys.remove(0);
4492 }
4493 } else {
4494 event_keys.truncate(limit - 1);
4495 }
4496
4497 let transaction_digests = event_keys
4499 .iter()
4500 .map(|(_, digest, _, _)| *digest)
4501 .collect::<HashSet<_>>()
4502 .into_iter()
4503 .collect::<Vec<_>>();
4504
4505 let events = kv_store
4506 .multi_get_events_by_tx_digests(&transaction_digests)
4507 .await?;
4508
4509 let events_map: HashMap<_, _> =
4510 transaction_digests.iter().zip(events.into_iter()).collect();
4511
4512 let stored_events = event_keys
4513 .into_iter()
4514 .map(|k| {
4515 (
4516 k,
4517 events_map
4518 .get(&k.1)
4519 .expect("fetched digest is missing")
4520 .clone()
4521 .and_then(|e| e.get(k.2).cloned()),
4522 )
4523 })
4524 .map(
4525 |((_event_digest, tx_digest, event_seq, timestamp), event)| {
4526 event
4527 .map(|e| (e, tx_digest, event_seq, timestamp))
4528 .ok_or(IotaError::TransactionEventsNotFound { digest: tx_digest })
4529 },
4530 )
4531 .collect::<Result<Vec<_>, _>>()?;
4532
4533 let epoch_store = self.load_epoch_store_one_call_per_task();
4534 let backing_store = self.get_backing_package_store().as_ref();
4535 let mut layout_resolver = epoch_store
4536 .executor()
4537 .type_layout_resolver(Box::new(backing_store));
4538 let mut events = vec![];
4539 for (e, tx_digest, event_seq, timestamp) in stored_events.into_iter() {
4540 events.push(IotaEvent::try_from(
4541 e.clone(),
4542 tx_digest,
4543 event_seq as u64,
4544 Some(timestamp),
4545 layout_resolver.get_annotated_layout(&e.struct_tag)?,
4546 )?)
4547 }
4548 Ok(events)
4549 }
4550
4551 pub fn insert_genesis_object(&self, object: Object) {
4552 self.get_reconfig_api()
4553 .try_insert_genesis_object(object)
4554 .expect("Cannot insert genesis object")
4555 }
4556
4557 pub fn insert_genesis_objects(&self, objects: &[Object]) {
4558 for o in objects {
4559 self.insert_genesis_object(o.clone());
4560 }
4561 }
4562
4563 #[instrument(level = "trace", skip_all)]
4565 pub fn get_transaction_status(
4566 &self,
4567 transaction_digest: &TransactionDigest,
4568 epoch_store: &Arc<AuthorityPerEpochStore>,
4569 ) -> IotaResult<Option<(SenderSignedTransaction, TransactionStatus)>> {
4570 if let Some(effects) =
4572 self.get_signed_effects_and_maybe_resign(transaction_digest, epoch_store)?
4573 {
4574 if let Some(transaction) = self
4575 .get_transaction_cache_reader()
4576 .try_get_transaction_block(transaction_digest)?
4577 {
4578 let cert_sig = epoch_store.get_transaction_cert_sig(transaction_digest)?;
4579 let events = if effects.events_digest().is_some() {
4580 self.get_transaction_events(effects.transaction_digest())?
4581 } else {
4582 TransactionEvents::default()
4583 };
4584 return Ok(Some((
4585 (*transaction).clone().into_message(),
4586 TransactionStatus::Executed(cert_sig, effects.into_inner(), events),
4587 )));
4588 } else {
4589 debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
4594 }
4595 }
4596 if let Some(signed) = epoch_store.get_signed_transaction(transaction_digest)? {
4597 self.metrics.tx_already_processed.inc();
4598 let (transaction, sig) = signed.into_inner().into_data_and_sig();
4599 Ok(Some((transaction, TransactionStatus::Signed(sig))))
4600 } else {
4601 Ok(None)
4602 }
4603 }
4604
4605 #[instrument(level = "trace", skip_all)]
4609 pub fn get_signed_effects_and_maybe_resign(
4610 &self,
4611 transaction_digest: &TransactionDigest,
4612 epoch_store: &Arc<AuthorityPerEpochStore>,
4613 ) -> IotaResult<Option<VerifiedSignedTransactionEffects>> {
4614 let effects = self
4615 .get_transaction_cache_reader()
4616 .try_get_executed_effects(transaction_digest)?;
4617 match effects {
4618 Some(effects) => {
4619 if effects.epoch() != epoch_store.epoch() {
4642 debug!(
4643 tx_digest=?transaction_digest,
4644 effects_epoch=?effects.epoch(),
4645 epoch=?epoch_store.epoch(),
4646 "Re-signing the effects with the current epoch"
4647 );
4648 }
4649 Ok(Some(self.sign_effects(effects, epoch_store)?))
4650 }
4651 None => Ok(None),
4652 }
4653 }
4654
4655 pub fn check_effects_against_previously_signed(
4665 &self,
4666 epoch_store: &AuthorityPerEpochStore,
4667 tx_digest: &TransactionDigest,
4668 effects_digest: &TransactionEffectsDigest,
4669 surface: &'static str,
4670 ) -> IotaResult<()> {
4671 if let Some(previously_signed_digest) = epoch_store.get_signed_effects_digest(tx_digest)? {
4672 if previously_signed_digest != *effects_digest {
4673 self.metrics
4674 .signed_effects_equivocation_prevented
4675 .with_label_values(&[surface])
4676 .inc();
4677 error!(
4678 ?tx_digest,
4679 ?previously_signed_digest,
4680 executed_digest = ?effects_digest,
4681 surface,
4682 "refusing to report effects that differ from previously signed effects"
4683 );
4684 return Err(IotaError::GenericAuthority {
4685 error: format!(
4686 "Refusing to report effects for transaction {tx_digest}: effects digest \
4687 {effects_digest} differs from previously signed effects digest \
4688 {previously_signed_digest}"
4689 ),
4690 });
4691 }
4692 }
4693 Ok(())
4694 }
4695
4696 #[instrument(level = "trace", skip_all)]
4697 pub(crate) fn sign_effects(
4698 &self,
4699 effects: TransactionEffects,
4700 epoch_store: &Arc<AuthorityPerEpochStore>,
4701 ) -> IotaResult<VerifiedSignedTransactionEffects> {
4702 let tx_digest = *effects.transaction_digest();
4703
4704 self.check_effects_against_previously_signed(
4705 epoch_store,
4706 &tx_digest,
4707 &effects.digest(),
4708 "sign_effects",
4709 )?;
4710
4711 let signed_effects = match epoch_store.get_effects_signature(&tx_digest)? {
4712 Some(sig) => {
4713 debug_assert!(sig.epoch == epoch_store.epoch());
4714 SignedTransactionEffects::new_from_data_and_sig(effects, sig)
4715 }
4716 _ => {
4717 let sig = AuthoritySignInfo::new(
4718 epoch_store.epoch(),
4719 &effects,
4720 Intent::iota_app(IntentScope::TransactionEffects),
4721 self.name,
4722 &*self.secret,
4723 );
4724
4725 let effects = SignedTransactionEffects::new_from_data_and_sig(effects, sig.clone());
4726
4727 epoch_store.insert_effects_digest_and_signature(
4728 &tx_digest,
4729 effects.digest(),
4730 &sig,
4731 )?;
4732
4733 effects
4734 }
4735 };
4736
4737 Ok(VerifiedSignedTransactionEffects::new_unchecked(
4738 signed_effects,
4739 ))
4740 }
4741
4742 #[instrument(level = "trace", skip_all)]
4744 fn fullnode_only_get_tx_coins_for_indexing(
4745 &self,
4746 effects: &TransactionEffects,
4747 inner_temporary_store: &InnerTemporaryStore,
4748 epoch_store: &Arc<AuthorityPerEpochStore>,
4749 ) -> Option<TxCoins> {
4750 if self.indexes.is_none() || self.is_committee_validator(epoch_store) {
4751 return None;
4752 }
4753 let written_coin_objects = inner_temporary_store
4754 .written
4755 .iter()
4756 .filter_map(|(k, v)| {
4757 if v.is_coin() {
4758 Some((*k, v.clone()))
4759 } else {
4760 None
4761 }
4762 })
4763 .collect();
4764 let mut input_coin_objects = inner_temporary_store
4765 .input_objects
4766 .iter()
4767 .filter_map(|(k, v)| {
4768 if v.is_coin() {
4769 Some((*k, v.clone()))
4770 } else {
4771 None
4772 }
4773 })
4774 .collect::<ObjectMap>();
4775
4776 for modified in effects.modified_at_versions() {
4781 let (object_id, version) = (modified.object_id, modified.version);
4782 if inner_temporary_store
4783 .loaded_runtime_objects
4784 .contains_key(&object_id)
4785 {
4786 if let Some(object) = self
4787 .get_object_store()
4788 .get_object_by_key(&object_id, version)
4789 {
4790 if object.is_coin() {
4791 input_coin_objects.insert(object_id, object);
4792 }
4793 }
4794 }
4795 }
4796
4797 Some((input_coin_objects, written_coin_objects))
4798 }
4799
4800 #[instrument(level = "trace", skip_all)]
4812 pub fn get_transaction_lock(
4813 &self,
4814 object_ref: &ObjectReference,
4815 epoch_store: &AuthorityPerEpochStore,
4816 ) -> IotaResult<Option<VerifiedSignedTransaction>> {
4817 let lock_info = self
4818 .get_object_cache_reader()
4819 .try_get_lock(*object_ref, epoch_store)?;
4820 let lock_info = match lock_info {
4821 ObjectLockStatus::LockedAtDifferentVersion { locked_ref } => {
4822 return Err(UserInputError::ObjectVersionUnavailableForConsumption {
4823 provided_obj_ref: *object_ref,
4824 current_version: locked_ref.version,
4825 }
4826 .into());
4827 }
4828 ObjectLockStatus::Initialized => {
4829 return Ok(None);
4830 }
4831 ObjectLockStatus::LockedToTx { locked_by_tx } => locked_by_tx,
4832 };
4833
4834 epoch_store.get_signed_transaction(&lock_info)
4835 }
4836
4837 pub fn try_get_objects(&self, objects: &[ObjectId]) -> IotaResult<Vec<Option<Object>>> {
4838 self.get_object_cache_reader().try_get_objects(objects)
4839 }
4840
4841 pub fn get_objects(&self, objects: &[ObjectId]) -> Vec<Option<Object>> {
4843 self.try_get_objects(objects)
4844 .expect("storage access failed")
4845 }
4846
4847 pub fn try_get_object_or_tombstone(
4848 &self,
4849 object_id: ObjectId,
4850 ) -> IotaResult<Option<ObjectReference>> {
4851 self.get_object_cache_reader()
4852 .try_get_latest_object_ref_or_tombstone(object_id)
4853 }
4854
4855 pub fn get_object_or_tombstone(&self, object_id: ObjectId) -> Option<ObjectReference> {
4857 self.try_get_object_or_tombstone(object_id)
4858 .expect("storage access failed")
4859 }
4860
4861 pub fn set_override_protocol_upgrade_buffer_stake(
4871 &self,
4872 expected_epoch: EpochId,
4873 buffer_stake_bps: u64,
4874 ) -> IotaResult {
4875 let epoch_store = self.load_epoch_store_one_call_per_task();
4876 let actual_epoch = epoch_store.epoch();
4877 if actual_epoch != expected_epoch {
4878 return Err(IotaError::WrongEpoch {
4879 expected_epoch,
4880 actual_epoch,
4881 });
4882 }
4883
4884 epoch_store.set_override_protocol_upgrade_buffer_stake(buffer_stake_bps)
4885 }
4886
4887 pub fn clear_override_protocol_upgrade_buffer_stake(
4888 &self,
4889 expected_epoch: EpochId,
4890 ) -> IotaResult {
4891 let epoch_store = self.load_epoch_store_one_call_per_task();
4892 let actual_epoch = epoch_store.epoch();
4893 if actual_epoch != expected_epoch {
4894 return Err(IotaError::WrongEpoch {
4895 expected_epoch,
4896 actual_epoch,
4897 });
4898 }
4899
4900 epoch_store.clear_override_protocol_upgrade_buffer_stake()
4901 }
4902
4903 pub async fn get_available_system_packages(
4907 &self,
4908 binary_config: &BinaryConfig,
4909 ) -> Vec<ObjectReference> {
4910 let mut results = vec![];
4911
4912 let system_packages = BuiltInFramework::iter_system_packages();
4913
4914 #[cfg(msim)]
4916 let extra_packages = framework_injection::get_extra_packages(self.name);
4917 #[cfg(msim)]
4918 let system_packages = {
4919 let mut packages: Vec<_> = system_packages.collect();
4920 packages.extend(extra_packages.iter());
4921 packages
4922 };
4923
4924 for system_package in system_packages {
4925 let modules = system_package.modules().to_vec();
4926 #[cfg(msim)]
4928 let modules = framework_injection::get_override_modules(&system_package.id, self.name)
4929 .unwrap_or(modules);
4930
4931 let Some(obj_ref) = iota_framework::compare_system_package(
4932 &self.get_object_store(),
4933 &system_package.id,
4934 &modules,
4935 system_package.dependencies.to_vec(),
4936 binary_config,
4937 )
4938 .await
4939 else {
4940 return vec![];
4941 };
4942 results.push(obj_ref);
4943 }
4944
4945 results
4946 }
4947
4948 async fn get_system_package_bytes(
4972 &self,
4973 system_packages: Vec<ObjectReference>,
4974 binary_config: &BinaryConfig,
4975 ) -> Option<Vec<SystemPackage>> {
4976 let object_store = self.get_object_cache_reader();
4977
4978 let mut res = Vec::with_capacity(system_packages.len());
4979 for system_package_ref in system_packages {
4980 if object_store
4981 .get_object_by_key(&system_package_ref.object_id, system_package_ref.version)
4982 .is_some_and(|object| object.object_ref() == system_package_ref)
4983 {
4984 info!(
4986 "Framework {} does not need updating",
4987 system_package_ref.object_id
4988 );
4989 continue;
4990 }
4991
4992 let prev_transaction = if system_package_ref.version == Version::OBJECT_START {
4997 TransactionDigest::GENESIS_MARKER
4998 } else {
4999 let prev_version = system_package_ref
5000 .version
5001 .previous()
5002 .expect("version is greater than Version::OBJECT_START");
5003 let Some(prev_object) =
5004 object_store.get_object_by_key(&system_package_ref.object_id, prev_version)
5005 else {
5006 error!(
5007 "Framework {} not available locally at version {prev_version:?}, cannot \
5008 derive upgrade to {system_package_ref:?}",
5009 system_package_ref.object_id
5010 );
5011 return None;
5012 };
5013 prev_object.previous_transaction
5014 };
5015
5016 #[cfg(msim)]
5017 let FrameworkSystemPackage {
5018 id: _,
5019 bytes,
5020 dependencies,
5021 } = framework_injection::get_override_system_package(
5022 &system_package_ref.object_id,
5023 self.name,
5024 )
5025 .unwrap_or_else(|| {
5026 BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone()
5027 });
5028
5029 #[cfg(not(msim))]
5030 let FrameworkSystemPackage {
5031 id: _,
5032 bytes,
5033 dependencies,
5034 } = BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone();
5035
5036 let modules: Vec<_> = bytes
5037 .iter()
5038 .map(|m| CompiledModule::deserialize_with_config(m, binary_config).unwrap())
5039 .collect();
5040
5041 let new_object = Object::new_system_package(
5042 &modules,
5043 system_package_ref.version,
5044 dependencies.clone(),
5045 prev_transaction,
5046 );
5047
5048 let new_ref = new_object.object_ref();
5049 if new_ref != system_package_ref {
5050 debug_fatal!(
5051 "Framework mismatch -- binary: {new_ref:?}\n upgrade: {system_package_ref:?}"
5052 );
5053 return None;
5054 }
5055
5056 res.push(SystemPackage {
5057 version: system_package_ref.version,
5058 modules: bytes,
5059 dependencies,
5060 });
5061 }
5062
5063 Some(res)
5064 }
5065
5066 fn is_protocol_version_supported_v1(
5070 proposed_protocol_version: ProtocolVersion,
5071 committee: &Committee,
5072 capabilities: Vec<AuthorityCapabilitiesV1>,
5073 mut buffer_stake_bps: u64,
5074 ) -> Option<(ProtocolVersion, Digest, Vec<ObjectReference>)> {
5075 if buffer_stake_bps > 10000 {
5076 warn!("clamping buffer_stake_bps to 10000");
5077 buffer_stake_bps = 10000;
5078 }
5079
5080 let mut desired_upgrades: Vec<_> = capabilities
5083 .into_iter()
5084 .filter_map(|mut cap| {
5085 if cap.available_system_packages.is_empty() {
5087 return None;
5088 }
5089
5090 cap.available_system_packages.sort();
5091
5092 info!(
5093 "validator {:?} supports {:?} with system packages: {:?}",
5094 cap.authority.concise(),
5095 cap.supported_protocol_versions,
5096 cap.available_system_packages,
5097 );
5098
5099 cap.supported_protocol_versions
5103 .get_version_digest(proposed_protocol_version)
5104 .map(|digest| (digest, cap.available_system_packages, cap.authority))
5105 })
5106 .collect();
5107
5108 desired_upgrades.sort();
5111 desired_upgrades
5112 .into_iter()
5113 .chunk_by(|(digest, packages, _authority)| (*digest, packages.clone()))
5114 .into_iter()
5115 .find_map(|((digest, packages), group)| {
5116 assert!(!packages.is_empty());
5118
5119 let mut stake_aggregator: StakeAggregator<(), true> =
5120 StakeAggregator::new(Arc::new(committee.clone()));
5121
5122 for (_, _, authority) in group {
5123 stake_aggregator.insert_generic(authority, ());
5124 }
5125
5126 let total_votes = stake_aggregator.total_votes();
5127 let quorum_threshold = committee.quorum_threshold();
5128 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5129
5130 info!(
5131 protocol_config_digest = ?digest,
5132 ?total_votes,
5133 ?quorum_threshold,
5134 ?buffer_stake_bps,
5135 ?effective_threshold,
5136 ?proposed_protocol_version,
5137 ?packages,
5138 "support for upgrade"
5139 );
5140
5141 let has_support = total_votes >= effective_threshold;
5142 has_support.then_some((proposed_protocol_version, digest, packages))
5143 })
5144 }
5145
5146 fn choose_protocol_version_and_system_packages_v1(
5150 current_protocol_version: ProtocolVersion,
5151 current_protocol_digest: Digest,
5152 committee: &Committee,
5153 capabilities: Vec<AuthorityCapabilitiesV1>,
5154 buffer_stake_bps: u64,
5155 ) -> (ProtocolVersion, Digest, Vec<ObjectReference>) {
5156 let mut next_protocol_version = current_protocol_version;
5157 let mut system_packages = vec![];
5158 let mut protocol_version_digest = current_protocol_digest;
5159
5160 while let Some((version, digest, packages)) = Self::is_protocol_version_supported_v1(
5164 next_protocol_version + 1,
5165 committee,
5166 capabilities.clone(),
5167 buffer_stake_bps,
5168 ) {
5169 next_protocol_version = version;
5170 protocol_version_digest = digest;
5171 system_packages = packages;
5172 }
5173
5174 (
5175 next_protocol_version,
5176 protocol_version_digest,
5177 system_packages,
5178 )
5179 }
5180
5181 fn get_validators_supporting_protocol_version(
5186 target_protocol_version: ProtocolVersion,
5187 target_digest: Digest,
5188 active_validators: &[AuthorityPublicKey],
5189 capabilities: &[AuthorityCapabilitiesV1],
5190 ) -> Vec<u64> {
5191 let mut eligible_validators = Vec::new();
5192
5193 for capability in capabilities {
5194 if let Some(digest) = capability
5196 .supported_protocol_versions
5197 .get_version_digest(target_protocol_version)
5198 {
5199 if digest == target_digest {
5200 if let Some(index) = active_validators
5202 .iter()
5203 .position(|name| AuthorityName::from(name) == capability.authority)
5204 {
5205 eligible_validators.push(index as u64);
5206 }
5207 }
5208 }
5209 }
5210
5211 eligible_validators.sort();
5213 eligible_validators
5214 }
5215
5216 fn calculate_eligible_validators_weight(
5221 eligible_validator_indices: &[u64],
5222 active_validators: &[AuthorityPublicKey],
5223 committee: &Committee,
5224 ) -> u64 {
5225 let mut total_weight = 0u64;
5226
5227 for &index in eligible_validator_indices {
5228 let authority_pubkey = &active_validators[index as usize];
5229 if let Some((_, weight)) = committee
5231 .members()
5232 .find(|(name, _)| *name == AuthorityName::from(authority_pubkey))
5233 {
5234 total_weight += weight;
5235 }
5236 }
5237
5238 total_weight
5239 }
5240
5241 #[instrument(level = "error", skip_all)]
5254 pub async fn create_and_execute_advance_epoch_tx(
5255 &self,
5256 epoch_store: &Arc<AuthorityPerEpochStore>,
5257 gas_cost_summary: &GasCostSummary,
5258 checkpoint: CheckpointSequenceNumber,
5259 epoch_start_timestamp_ms: CheckpointTimestamp,
5260 scores: Vec<u64>,
5261 ) -> CheckpointBuilderResult<(
5262 IotaSystemState,
5263 Option<SystemEpochInfoEvent>,
5264 TransactionEffects,
5265 )> {
5266 let mut txns = Vec::new();
5267
5268 if epoch_store
5274 .protocol_config()
5275 .deny_rule_governance_on_chain()
5276 && epoch_store
5277 .epoch_start_config()
5278 .transaction_deny_rules_obj_initial_shared_version()
5279 .is_none()
5280 {
5281 txns.push(EndOfEpochTransactionKind::TransactionDenyRulesCreate);
5282 }
5283
5284 let next_epoch = epoch_store.epoch() + 1;
5285
5286 let buffer_stake_bps = epoch_store.get_effective_buffer_stake_bps();
5287 let authority_capabilities = epoch_store
5288 .get_capabilities_v1()
5289 .expect("read capabilities from db cannot fail");
5290 let (next_epoch_protocol_version, next_epoch_protocol_digest, next_epoch_system_packages) =
5291 Self::choose_protocol_version_and_system_packages_v1(
5292 epoch_store.protocol_version(),
5293 SupportedProtocolVersionsWithHashes::protocol_config_digest(
5294 epoch_store.protocol_config(),
5295 ),
5296 epoch_store.committee(),
5297 authority_capabilities.clone(),
5298 buffer_stake_bps,
5299 );
5300
5301 let config = epoch_store.protocol_config();
5305 let binary_config = to_binary_config(config);
5306 let Some(next_epoch_system_package_bytes) = self
5307 .get_system_package_bytes(next_epoch_system_packages.clone(), &binary_config)
5308 .await
5309 else {
5310 debug_fatal!(
5311 "upgraded system packages {:?} are not locally available, cannot create \
5312 ChangeEpochTx. validator binary must be upgraded to the correct version!",
5313 next_epoch_system_packages
5314 );
5315 return Err(CheckpointBuilderError::SystemPackagesMissing);
5325 };
5326
5327 if config.select_committee_from_eligible_validators() {
5330 let active_validators = epoch_store.epoch_start_state().get_active_validators();
5332
5333 let mut eligible_active_validators = (0..active_validators.len() as u64).collect();
5334
5335 if config.select_committee_supporting_next_epoch_version() {
5339 eligible_active_validators = Self::get_validators_supporting_protocol_version(
5340 next_epoch_protocol_version,
5341 next_epoch_protocol_digest,
5342 &active_validators,
5343 &authority_capabilities,
5344 );
5345
5346 let eligible_validators_weight = Self::calculate_eligible_validators_weight(
5348 &eligible_active_validators,
5349 &active_validators,
5350 epoch_store.committee(),
5351 );
5352
5353 let committee = epoch_store.committee();
5357 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5358
5359 if eligible_validators_weight < effective_threshold {
5360 error!(
5361 "Eligible validators weight {eligible_validators_weight} is less than effective threshold {effective_threshold}. \
5362 This could indicate a bug in validator selection logic or inconsistency with protocol version decision.",
5363 );
5364 eligible_active_validators = (0..active_validators.len() as u64).collect();
5367 }
5368 }
5369
5370 if config.pass_validator_scores_to_advance_epoch() {
5373 txns.push(EndOfEpochTransactionKind::new_change_epoch_v4(
5374 next_epoch,
5375 next_epoch_protocol_version.as_u64(),
5376 gas_cost_summary.storage_cost,
5377 gas_cost_summary.computation_cost,
5378 gas_cost_summary.computation_cost_burned,
5379 gas_cost_summary.storage_rebate,
5380 gas_cost_summary.non_refundable_storage_fee,
5381 epoch_start_timestamp_ms,
5382 next_epoch_system_package_bytes,
5383 eligible_active_validators,
5384 scores,
5385 config.adjust_rewards_by_score(),
5386 ));
5387 } else {
5388 txns.push(EndOfEpochTransactionKind::new_change_epoch_v3(
5389 next_epoch,
5390 next_epoch_protocol_version.as_u64(),
5391 gas_cost_summary.storage_cost,
5392 gas_cost_summary.computation_cost,
5393 gas_cost_summary.computation_cost_burned,
5394 gas_cost_summary.storage_rebate,
5395 gas_cost_summary.non_refundable_storage_fee,
5396 epoch_start_timestamp_ms,
5397 next_epoch_system_package_bytes,
5398 eligible_active_validators,
5399 ));
5400 }
5401 } else if config.protocol_defined_base_fee()
5402 && config.max_committee_members_count_as_option().is_some()
5403 {
5404 txns.push(EndOfEpochTransactionKind::new_change_epoch_v2(
5405 next_epoch,
5406 next_epoch_protocol_version.as_u64(),
5407 gas_cost_summary.storage_cost,
5408 gas_cost_summary.computation_cost,
5409 gas_cost_summary.computation_cost_burned,
5410 gas_cost_summary.storage_rebate,
5411 gas_cost_summary.non_refundable_storage_fee,
5412 epoch_start_timestamp_ms,
5413 next_epoch_system_package_bytes,
5414 ));
5415 } else {
5416 txns.push(EndOfEpochTransactionKind::new_change_epoch(
5417 next_epoch,
5418 next_epoch_protocol_version.as_u64(),
5419 gas_cost_summary.storage_cost,
5420 gas_cost_summary.computation_cost,
5421 gas_cost_summary.storage_rebate,
5422 gas_cost_summary.non_refundable_storage_fee,
5423 epoch_start_timestamp_ms,
5424 next_epoch_system_package_bytes,
5425 ));
5426 }
5427
5428 let tx = VerifiedTransaction::new_end_of_epoch_transaction(txns);
5429
5430 let executable_tx = VerifiedExecutableTransaction::new_from_checkpoint(
5431 tx.clone(),
5432 epoch_store.epoch(),
5433 checkpoint,
5434 );
5435
5436 let tx_digest = executable_tx.digest();
5437
5438 info!(
5439 ?next_epoch,
5440 ?next_epoch_protocol_version,
5441 ?next_epoch_system_packages,
5442 computation_cost=?gas_cost_summary.computation_cost,
5443 computation_cost_burned=?gas_cost_summary.computation_cost_burned,
5444 storage_cost=?gas_cost_summary.storage_cost,
5445 storage_rebate=?gas_cost_summary.storage_rebate,
5446 non_refundable_storage_fee=?gas_cost_summary.non_refundable_storage_fee,
5447 ?tx_digest,
5448 "Creating advance epoch transaction"
5449 );
5450
5451 fail_point_async!("change_epoch_tx_delay");
5452 let tx_lock = epoch_store.acquire_tx_lock(tx_digest);
5453
5454 if self
5458 .get_transaction_cache_reader()
5459 .try_is_tx_already_executed(tx_digest)?
5460 {
5461 warn!("change epoch tx has already been executed via state sync");
5462 return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
5463 }
5464
5465 let execution_guard = self.execution_lock_for_executable_transaction(&executable_tx)?;
5466
5467 epoch_store.assign_shared_object_versions_idempotent(
5471 self.get_object_cache_reader().as_ref(),
5472 std::slice::from_ref(&executable_tx),
5473 )?;
5474
5475 let (input_objects, _) =
5476 self.read_objects_for_execution(&tx_lock, &executable_tx, epoch_store)?;
5477
5478 let (temporary_store, effects, _execution_error_opt) = self.execute_transaction(
5479 &execution_guard,
5480 &executable_tx,
5481 input_objects,
5482 vec![],
5483 epoch_store,
5484 )?;
5485 let system_obj = get_iota_system_state(&temporary_store.written)
5486 .expect("change epoch tx must write to system object");
5487 let system_epoch_info_event = temporary_store
5489 .events
5490 .0
5491 .into_iter()
5492 .find(|event| event.is_system_epoch_info_event())
5493 .map(SystemEpochInfoEvent::from);
5494 assert!(system_epoch_info_event.is_some() || system_obj.safe_mode());
5497
5498 self.get_state_sync_store()
5502 .try_insert_transaction_and_effects(&tx, &effects)?;
5503
5504 info!(
5505 "Effects summary of the change epoch transaction: {:?}",
5506 effects.summary_for_debug()
5507 );
5508 epoch_store.record_checkpoint_builder_is_safe_mode_metric(system_obj.safe_mode());
5509 assert!(effects.status().is_success());
5511 Ok((system_obj, system_epoch_info_event, effects))
5512 }
5513
5514 #[instrument(level = "error", skip_all)]
5518 async fn revert_uncommitted_epoch_transactions(
5519 &self,
5520 epoch_store: &AuthorityPerEpochStore,
5521 ) -> IotaResult {
5522 {
5523 let state = epoch_store.get_reconfig_state_write_lock_guard();
5524 if state.should_accept_user_certs() {
5525 epoch_store.close_user_certs(state);
5534 }
5535 }
5537
5538 if !epoch_store.protocol_config().enable_pcool_flow() {
5541 let pending_certificates = epoch_store.pending_consensus_certificates();
5542 info!(
5543 "Reverting {} locally executed transactions that was not included in the epoch: \
5544 {:?}",
5545 pending_certificates.len(),
5546 pending_certificates,
5547 );
5548 for digest in pending_certificates {
5549 if epoch_store.is_transaction_executed_in_checkpoint(&digest)? {
5550 info!(
5551 "Not reverting pending consensus transaction {:?} - it was included in \
5552 checkpoint",
5553 digest
5554 );
5555 continue;
5556 }
5557 info!("Reverting {:?} at the end of epoch", digest);
5558 epoch_store.revert_executed_transaction(&digest)?;
5559 self.get_reconfig_api().try_revert_state_update(&digest)?;
5560 }
5561 info!("All uncommitted local transactions reverted");
5562 } else {
5563 info!("P-COOL mode: skipping revert of uncommitted epoch transactions");
5564 }
5565
5566 Ok(())
5567 }
5568
5569 #[instrument(level = "error", skip_all)]
5570 async fn reopen_epoch_db(
5571 &self,
5572 cur_epoch_store: &AuthorityPerEpochStore,
5573 new_committee: Committee,
5574 epoch_start_configuration: EpochStartConfiguration,
5575 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
5576 epoch_last_checkpoint: CheckpointSequenceNumber,
5577 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
5578 let new_epoch = new_committee.epoch;
5579 info!(new_epoch = ?new_epoch, "re-opening AuthorityEpochTables for new epoch");
5580 assert_eq!(
5581 epoch_start_configuration.epoch_start_state().epoch(),
5582 new_committee.epoch
5583 );
5584 fail_point!("before-open-new-epoch-store");
5585 let new_epoch_store = cur_epoch_store.new_at_next_epoch(
5586 self.name,
5587 new_committee,
5588 epoch_start_configuration,
5589 self.get_backing_package_store().clone(),
5590 expensive_safety_check_config,
5591 epoch_last_checkpoint,
5592 )?;
5593 self.epoch_store.store(new_epoch_store.clone());
5594 Ok(new_epoch_store)
5595 }
5596
5597 fn check_move_account_for_execution(
5605 &self,
5606 auth_account_object_id: ObjectId,
5607 auth_account_object_seq_number: Option<Version>,
5608 auth_account_object_digest: Option<ObjectDigest>,
5609 account_object: ObjectReadResult,
5610 signer: &Address,
5611 ) -> AuthenticatorFunctionRefForExecution {
5612 self.check_move_account(
5613 auth_account_object_id,
5614 auth_account_object_seq_number,
5615 auth_account_object_digest,
5616 account_object,
5617 signer,
5618 true,
5619 )
5620 .expect("move account checks cannot fail during execution")
5621 }
5622
5623 fn check_move_account_for_validation(
5627 &self,
5628 auth_account_object_id: ObjectId,
5629 auth_account_object_seq_number: Option<Version>,
5630 auth_account_object_digest: Option<ObjectDigest>,
5631 account_object: ObjectReadResult,
5632 signer: &Address,
5633 ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
5634 self.check_move_account(
5635 auth_account_object_id,
5636 auth_account_object_seq_number,
5637 auth_account_object_digest,
5638 account_object,
5639 signer,
5640 false,
5641 )
5642 }
5643
5644 fn check_move_account(
5651 &self,
5652 auth_account_object_id: ObjectId,
5653 auth_account_object_seq_number: Option<Version>,
5654 auth_account_object_digest: Option<ObjectDigest>,
5655 account_object: ObjectReadResult,
5656 signer: &Address,
5657 is_execution: bool,
5658 ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
5659 let auth_account_object_seq_number = match (&account_object.object, is_execution) {
5660 (ObjectReadResultKind::Object(object), _) => {
5664 let account_object_addr = Address::from(auth_account_object_id);
5665 fp_ensure!(
5666 signer == &account_object_addr,
5667 UserInputError::IncorrectUserSignature {
5668 error: format!("Move authenticator is trying to unlock {account_object_addr:?}, but given signer address is {signer:?}")
5669 }
5670 .into()
5671 );
5672
5673 fp_ensure!(
5674 object.is_shared() || object.is_immutable(),
5675 UserInputError::AccountObjectNotSupported {
5676 object_id: auth_account_object_id
5677 }
5678 .into()
5679 );
5680
5681 let auth_account_object_seq_number =
5682 if let Some(auth_account_object_seq_number) = auth_account_object_seq_number {
5683 let account_object_version = object.version();
5684
5685 fp_ensure!(
5686 account_object_version == auth_account_object_seq_number,
5687 UserInputError::AccountObjectVersionMismatch {
5688 object_id: auth_account_object_id,
5689 expected_version: auth_account_object_seq_number,
5690 actual_version: account_object_version,
5691 }
5692 .into()
5693 );
5694
5695 auth_account_object_seq_number
5696 } else {
5697 object.version()
5698 };
5699
5700 if let Some(auth_account_object_digest) = auth_account_object_digest {
5701 let expected_digest = object.digest();
5702 fp_ensure!(
5703 expected_digest == auth_account_object_digest,
5704 UserInputError::InvalidAccountObjectDigest {
5705 object_id: auth_account_object_id,
5706 expected_digest,
5707 actual_digest: auth_account_object_digest,
5708 }
5709 .into()
5710 );
5711 }
5712
5713 Ok(auth_account_object_seq_number)
5714 }
5715 (ObjectReadResultKind::DeletedSharedObject(version, digest), false) => {
5718 Err(UserInputError::AccountObjectDeleted {
5719 account_id: account_object.id(),
5720 account_version: *version,
5721 transaction_digest: *digest,
5722 })
5723 }
5724 (ObjectReadResultKind::CancelledTransactionObject(version), false) => {
5728 Err(UserInputError::AccountObjectInCanceledTransaction {
5729 account_id: account_object.id(),
5730 account_version: *version,
5731 })
5732 }
5733 (ObjectReadResultKind::DeletedSharedObject(version, _), true) => Ok(*version),
5738 (ObjectReadResultKind::CancelledTransactionObject(version), true) => Ok(*version),
5744 }?;
5745
5746 let authenticator_function_ref_field_id =
5747 derive_authenticator_function_ref_v1_dynamic_field_id(auth_account_object_id)?;
5748
5749 let authenticator_function_ref_field = self
5750 .get_object_cache_reader()
5751 .try_find_object_lt_or_eq_version(
5752 authenticator_function_ref_field_id,
5753 auth_account_object_seq_number,
5754 )?;
5755
5756 if let Some(authenticator_function_ref_field_obj) = authenticator_function_ref_field {
5757 Ok(authenticator_function_ref_v1_from_dynamic_field_object(
5758 auth_account_object_id,
5759 &authenticator_function_ref_field_obj,
5760 )?)
5761 } else {
5762 Err(UserInputError::MoveAuthenticatorNotFound {
5763 authenticator_function_ref_id: authenticator_function_ref_field_id,
5764 account_object_id: auth_account_object_id,
5765 account_object_version: auth_account_object_seq_number,
5766 }
5767 .into())
5768 }
5769 }
5770
5771 #[allow(clippy::type_complexity)]
5772 fn read_objects_for_validation(
5773 &self,
5774 transaction: &VerifiedTransaction,
5775 epoch: u64,
5776 ) -> IotaResult<(
5777 InputObjects,
5778 ReceivingObjects,
5779 Vec<(InputObjects, ObjectReadResult)>,
5780 )> {
5781 let (input_objects, tx_receiving_objects) = self.input_loader.read_objects_for_signing(
5782 Some(transaction.digest()),
5783 &transaction.collect_all_input_object_kind_for_reading()?,
5784 &transaction.data().transaction().receiving_objects(),
5785 epoch,
5786 )?;
5787
5788 transaction
5789 .split_input_objects_into_groups_for_reading(input_objects)
5790 .map(|(tx_input_objects, per_authenticator_inputs)| {
5791 (
5792 tx_input_objects,
5793 tx_receiving_objects,
5794 per_authenticator_inputs,
5795 )
5796 })
5797 }
5798
5799 #[allow(clippy::type_complexity)]
5800 fn check_transaction_inputs_for_validation(
5801 &self,
5802 protocol_config: &ProtocolConfig,
5803 reference_gas_price: u64,
5804 tx: &Transaction,
5805 tx_input_objects: InputObjects,
5806 tx_receiving_objects: &ReceivingObjects,
5807 move_authenticators: &Vec<&MoveAuthenticator>,
5808 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
5809 ) -> IotaResult<(
5810 IotaGasStatus,
5811 CheckedInputObjects,
5812 Vec<(CheckedInputObjects, AuthenticatorFunctionRef)>,
5813 )> {
5814 let authenticator_gas_budget = if move_authenticators.is_empty() {
5815 0
5816 } else {
5817 protocol_config.max_auth_gas()
5820 };
5821
5822 debug_assert_eq!(
5823 move_authenticators.len(),
5824 per_authenticator_inputs.len(),
5825 "Move authenticators amount must match the number of authenticator inputs"
5826 );
5827
5828 let per_authenticator_checked_inputs = move_authenticators
5829 .iter()
5830 .zip(per_authenticator_inputs)
5831 .map(
5832 |(move_authenticator, (authenticator_input_objects, account_object))| {
5833 let (
5835 auth_account_object_id,
5836 auth_account_object_seq_number,
5837 auth_account_object_digest,
5838 ) = move_authenticator.object_to_authenticate_components()?;
5839
5840 let signer = move_authenticator.address();
5841
5842 let AuthenticatorFunctionRefForExecution {
5844 authenticator_function_ref,
5845 ..
5846 } = self.check_move_account_for_validation(
5847 auth_account_object_id,
5848 auth_account_object_seq_number,
5849 auth_account_object_digest,
5850 account_object,
5851 &signer,
5852 )?;
5853
5854 let authenticator_checked_input_objects =
5856 iota_transaction_checks::check_move_authenticator_input_for_validation(
5857 authenticator_input_objects,
5858 )?;
5859
5860 Ok((
5861 authenticator_checked_input_objects,
5862 authenticator_function_ref,
5863 ))
5864 },
5865 )
5866 .collect::<IotaResult<Vec<_>>>()?;
5867
5868 let (gas_status, tx_checked_input_objects) =
5870 iota_transaction_checks::check_transaction_input(
5871 protocol_config,
5872 reference_gas_price,
5873 tx,
5874 tx_input_objects,
5875 tx_receiving_objects,
5876 &self.metrics.bytecode_verifier_metrics,
5877 &self.config.verifier_signing_config,
5878 authenticator_gas_budget,
5879 )?;
5880
5881 Ok((
5882 gas_status,
5883 tx_checked_input_objects,
5884 per_authenticator_checked_inputs,
5885 ))
5886 }
5887
5888 #[cfg(test)]
5889 pub(crate) fn iter_live_object_set_for_testing(
5890 &self,
5891 ) -> impl Iterator<Item = authority_store_tables::LiveObject> + '_ {
5892 self.get_global_state_hash_store()
5893 .iter_cached_live_object_set_for_testing()
5894 }
5895
5896 #[cfg(test)]
5897 pub(crate) fn shutdown_execution_for_test(&self) {
5898 self.tx_execution_shutdown
5899 .lock()
5900 .take()
5901 .unwrap()
5902 .send(())
5903 .unwrap();
5904 }
5905
5906 pub async fn insert_objects_unsafe_for_testing_only(&self, objects: &[Object]) {
5909 self.get_reconfig_api().bulk_insert_genesis_objects(objects);
5910 self.get_object_cache_reader()
5911 .force_reload_system_packages(&BuiltInFramework::all_package_ids());
5912 self.get_reconfig_api()
5913 .clear_state_end_of_epoch(&self.execution_lock_for_reconfiguration().await);
5914 }
5915}
5916
5917pub struct RandomnessRoundReceiver {
5918 authority_state: Arc<AuthorityState>,
5919 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
5920}
5921
5922impl RandomnessRoundReceiver {
5923 pub fn spawn(
5924 authority_state: Arc<AuthorityState>,
5925 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
5926 ) -> JoinHandle<()> {
5927 let rrr = RandomnessRoundReceiver {
5928 authority_state,
5929 randomness_rx,
5930 };
5931 spawn_monitored_task!(rrr.run())
5932 }
5933
5934 async fn run(mut self) {
5935 info!("RandomnessRoundReceiver event loop started");
5936
5937 loop {
5938 tokio::select! {
5939 maybe_recv = self.randomness_rx.recv() => {
5940 if let Some((epoch, round, bytes)) = maybe_recv {
5941 self.handle_new_randomness(epoch, round, bytes).await;
5942 } else {
5943 break;
5944 }
5945 },
5946 }
5947 }
5948
5949 info!("RandomnessRoundReceiver event loop ended");
5950 }
5951
5952 #[instrument(level = "debug", skip_all, fields(?epoch, ?round))]
5953 async fn handle_new_randomness(&self, epoch: EpochId, round: RandomnessRound, bytes: Vec<u8>) {
5954 fail_point_async!("randomness-delay");
5955
5956 let epoch_store = self.authority_state.load_epoch_store_one_call_per_task();
5957 if epoch_store.epoch() != epoch {
5958 warn!(
5959 "dropping randomness for epoch {epoch}, round {round}, because we are in epoch {}",
5960 epoch_store.epoch()
5961 );
5962 return;
5963 }
5964 let transaction = VerifiedTransaction::new_randomness_state_update(
5965 epoch,
5966 round,
5967 bytes,
5968 epoch_store
5969 .epoch_start_config()
5970 .randomness_obj_initial_shared_version(),
5971 );
5972 debug!(
5973 "created randomness state update transaction with digest: {:?}",
5974 transaction.digest()
5975 );
5976 let transaction = VerifiedExecutableTransaction::new_system(transaction, epoch);
5977 let digest = *transaction.digest();
5978
5979 self.authority_state
5984 .get_cache_commit()
5985 .persist_transaction(&transaction);
5986
5987 self.authority_state
5989 .execution_scheduler()
5990 .enqueue(vec![transaction], &epoch_store);
5991
5992 let authority_state = self.authority_state.clone();
5993 spawn_monitored_task!(async move {
5994 const RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT: Duration = Duration::from_secs(300);
6003 let result = tokio::time::timeout(
6004 RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT,
6005 authority_state
6006 .get_transaction_cache_reader()
6007 .try_notify_read_executed_effects(
6008 "RandomnessRoundReceiver::notify_read_executed_effects_first",
6009 &[digest],
6010 ),
6011 )
6012 .await;
6013 let result = match result {
6014 Ok(result) => result,
6015 Err(_) => {
6016 if cfg!(debug_assertions) {
6017 panic!(
6019 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6020 );
6021 }
6022 warn!(
6023 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6024 );
6025 authority_state
6027 .get_transaction_cache_reader()
6028 .try_notify_read_executed_effects(
6029 "RandomnessRoundReceiver::notify_read_executed_effects_second",
6030 &[digest],
6031 )
6032 .await
6033 }
6034 };
6035
6036 let mut effects = result.unwrap_or_else(|_| panic!("failed to get effects for randomness state update transaction at epoch {epoch}, round {round}"));
6037 let effects = effects.pop().expect("should return effects");
6038 if *effects.status() != ExecutionStatus::Success {
6039 fatal!(
6040 "failed to execute randomness state update transaction at epoch {epoch}, round {round}: {effects:?}"
6041 );
6042 }
6043 debug!(
6044 "successfully executed randomness state update transaction at epoch {epoch}, round {round}"
6045 );
6046 });
6047 }
6048}
6049
6050#[async_trait]
6051impl TransactionKeyValueStoreTrait for AuthorityState {
6052 async fn multi_get(
6053 &self,
6054 transaction_keys: &[TransactionDigest],
6055 effects_keys: &[TransactionDigest],
6056 ) -> IotaResult<KVStoreTransactionData> {
6057 let txns = if !transaction_keys.is_empty() {
6058 self.get_transaction_cache_reader()
6059 .try_multi_get_transaction_blocks(transaction_keys)?
6060 .into_iter()
6061 .map(|t| t.map(|t| (*t).clone().into_inner()))
6062 .collect()
6063 } else {
6064 vec![]
6065 };
6066
6067 let fx = if !effects_keys.is_empty() {
6068 self.get_transaction_cache_reader()
6069 .try_multi_get_executed_effects(effects_keys)?
6070 } else {
6071 vec![]
6072 };
6073
6074 Ok((txns, fx))
6075 }
6076
6077 async fn multi_get_checkpoints(
6078 &self,
6079 checkpoint_summaries: &[CheckpointSequenceNumber],
6080 checkpoint_contents: &[CheckpointSequenceNumber],
6081 checkpoint_summaries_by_digest: &[CheckpointDigest],
6082 ) -> IotaResult<(
6083 Vec<Option<CertifiedCheckpointSummary>>,
6084 Vec<Option<CheckpointContents>>,
6085 Vec<Option<CertifiedCheckpointSummary>>,
6086 )> {
6087 let mut summaries = Vec::with_capacity(checkpoint_summaries.len());
6089 let store = self.get_checkpoint_store();
6090 for seq in checkpoint_summaries {
6091 let checkpoint = store
6092 .get_checkpoint_by_sequence_number(*seq)?
6093 .map(|c| c.into_inner());
6094
6095 summaries.push(checkpoint);
6096 }
6097
6098 let mut contents = Vec::with_capacity(checkpoint_contents.len());
6099 for seq in checkpoint_contents {
6100 let checkpoint = store
6101 .get_checkpoint_by_sequence_number(*seq)?
6102 .and_then(|summary| {
6103 store
6104 .get_checkpoint_contents(&summary.contents_digest)
6105 .expect("db read cannot fail")
6106 });
6107 contents.push(checkpoint);
6108 }
6109
6110 let mut summaries_by_digest = Vec::with_capacity(checkpoint_summaries_by_digest.len());
6111 for digest in checkpoint_summaries_by_digest {
6112 let checkpoint = store
6113 .get_checkpoint_by_digest(digest)?
6114 .map(|c| c.into_inner());
6115 summaries_by_digest.push(checkpoint);
6116 }
6117
6118 Ok((summaries, contents, summaries_by_digest))
6119 }
6120
6121 async fn get_transaction_perpetual_checkpoint(
6122 &self,
6123 digest: TransactionDigest,
6124 ) -> IotaResult<Option<CheckpointSequenceNumber>> {
6125 self.get_checkpoint_cache()
6126 .try_get_transaction_perpetual_checkpoint(&digest)
6127 .map(|res| res.map(|(_epoch, checkpoint)| checkpoint))
6128 }
6129
6130 async fn get_object(
6131 &self,
6132 object_id: ObjectId,
6133 version: VersionNumber,
6134 ) -> IotaResult<Option<Object>> {
6135 self.get_object_cache_reader()
6136 .try_get_object_by_key(&object_id, version)
6137 }
6138
6139 #[instrument(skip_all)]
6140 async fn multi_get_objects(
6141 &self,
6142 object_keys: &[ObjectKey],
6143 ) -> IotaResult<Vec<Option<Object>>> {
6144 Ok(self
6145 .get_object_cache_reader()
6146 .multi_get_objects_by_key(object_keys))
6147 }
6148
6149 async fn multi_get_transactions_perpetual_checkpoints(
6150 &self,
6151 digests: &[TransactionDigest],
6152 ) -> IotaResult<Vec<Option<CheckpointSequenceNumber>>> {
6153 let res = self
6154 .get_checkpoint_cache()
6155 .try_multi_get_transactions_perpetual_checkpoints(digests)?;
6156
6157 Ok(res
6158 .into_iter()
6159 .map(|maybe| maybe.map(|(_epoch, checkpoint)| checkpoint))
6160 .collect())
6161 }
6162
6163 #[instrument(skip(self, digests), fields(digests = digests.iter().map(|d| d.to_string()).collect::<Vec<String>>().join(", ")))]
6164 async fn multi_get_events_by_tx_digests(
6165 &self,
6166 digests: &[TransactionDigest],
6167 ) -> IotaResult<Vec<Option<TransactionEvents>>> {
6168 if digests.is_empty() {
6169 return Ok(vec![]);
6170 }
6171
6172 Ok(self
6173 .get_transaction_cache_reader()
6174 .multi_get_events(digests))
6175 }
6176}
6177
6178#[cfg(msim)]
6179pub mod framework_injection {
6180 use std::{
6181 cell::RefCell,
6182 collections::{BTreeMap, BTreeSet},
6183 };
6184
6185 use iota_framework::{BuiltInFramework, SystemPackage};
6186 use iota_sdk_types::ObjectId;
6187 use iota_types::base_types::AuthorityName;
6188 use move_binary_format::CompiledModule;
6189
6190 type FrameworkOverrideConfig = BTreeMap<ObjectId, PackageOverrideConfig>;
6191
6192 thread_local! {
6194 static OVERRIDE: RefCell<FrameworkOverrideConfig> = RefCell::new(FrameworkOverrideConfig::default());
6195 }
6196
6197 type Framework = Vec<CompiledModule>;
6198
6199 pub type PackageUpgradeCallback =
6200 Box<dyn Fn(AuthorityName) -> Option<Framework> + Send + Sync + 'static>;
6201
6202 enum PackageOverrideConfig {
6203 Global(Framework),
6204 PerValidator(PackageUpgradeCallback),
6205 }
6206
6207 fn compiled_modules_to_bytes(modules: &[CompiledModule]) -> Vec<Vec<u8>> {
6208 modules
6209 .iter()
6210 .map(|m| {
6211 let mut buf = Vec::new();
6212 m.serialize_with_version(m.version, &mut buf).unwrap();
6213 buf
6214 })
6215 .collect()
6216 }
6217
6218 pub fn set_override(package_id: ObjectId, modules: Vec<CompiledModule>) {
6219 OVERRIDE.with(|bs| {
6220 bs.borrow_mut()
6221 .insert(package_id, PackageOverrideConfig::Global(modules))
6222 });
6223 }
6224
6225 pub fn set_override_cb(package_id: ObjectId, func: PackageUpgradeCallback) {
6226 OVERRIDE.with(|bs| {
6227 bs.borrow_mut()
6228 .insert(package_id, PackageOverrideConfig::PerValidator(func))
6229 });
6230 }
6231
6232 pub fn get_override_bytes(package_id: &ObjectId, name: AuthorityName) -> Option<Vec<Vec<u8>>> {
6233 OVERRIDE.with(|cfg| {
6234 cfg.borrow().get(package_id).and_then(|entry| match entry {
6235 PackageOverrideConfig::Global(framework) => {
6236 Some(compiled_modules_to_bytes(framework))
6237 }
6238 PackageOverrideConfig::PerValidator(func) => {
6239 func(name).map(|fw| compiled_modules_to_bytes(&fw))
6240 }
6241 })
6242 })
6243 }
6244
6245 pub fn get_override_modules(
6246 package_id: &ObjectId,
6247 name: AuthorityName,
6248 ) -> Option<Vec<CompiledModule>> {
6249 OVERRIDE.with(|cfg| {
6250 cfg.borrow().get(package_id).and_then(|entry| match entry {
6251 PackageOverrideConfig::Global(framework) => Some(framework.clone()),
6252 PackageOverrideConfig::PerValidator(func) => func(name),
6253 })
6254 })
6255 }
6256
6257 pub fn get_override_system_package(
6258 package_id: &ObjectId,
6259 name: AuthorityName,
6260 ) -> Option<SystemPackage> {
6261 let bytes = get_override_bytes(package_id, name)?;
6262 let dependencies = if package_id.is_system_package() {
6263 BuiltInFramework::get_package_by_id(package_id)
6264 .dependencies
6265 .to_vec()
6266 } else {
6267 BuiltInFramework::all_package_ids()
6270 };
6271 Some(SystemPackage {
6272 id: *package_id,
6273 bytes,
6274 dependencies,
6275 })
6276 }
6277
6278 pub fn get_extra_packages(name: AuthorityName) -> Vec<SystemPackage> {
6279 let built_in = BTreeSet::from_iter(BuiltInFramework::all_package_ids());
6280 let extra: Vec<ObjectId> = OVERRIDE.with(|cfg| {
6281 cfg.borrow()
6282 .keys()
6283 .filter_map(|package| (!built_in.contains(package)).then_some(*package))
6284 .collect()
6285 });
6286
6287 extra
6288 .into_iter()
6289 .map(|package| SystemPackage {
6290 id: package,
6291 bytes: get_override_bytes(&package, name).unwrap(),
6292 dependencies: BuiltInFramework::all_package_ids(),
6293 })
6294 .collect()
6295 }
6296}
6297
6298#[derive(Debug, Serialize, Deserialize, Clone)]
6299pub struct ObjDumpFormat {
6300 pub id: ObjectId,
6301 pub version: VersionNumber,
6302 pub digest: ObjectDigest,
6303 pub object: Object,
6304}
6305
6306impl ObjDumpFormat {
6307 fn new(object: Object) -> Self {
6308 let oref = object.object_ref();
6309 Self {
6310 id: oref.object_id,
6311 version: oref.version,
6312 digest: oref.digest,
6313 object,
6314 }
6315 }
6316}
6317
6318#[derive(Debug, Serialize, Deserialize, Clone)]
6319pub struct NodeStateDump {
6320 pub tx_digest: TransactionDigest,
6321 pub sender_signed_data: SenderSignedTransaction,
6322 pub executed_epoch: u64,
6323 pub reference_gas_price: u64,
6324 pub protocol_version: u64,
6325 pub epoch_start_timestamp_ms: u64,
6326 pub computed_effects: TransactionEffects,
6327 pub expected_effects_digest: TransactionEffectsDigest,
6328 pub relevant_system_packages: Vec<ObjDumpFormat>,
6329 pub shared_objects: Vec<ObjDumpFormat>,
6330 pub loaded_child_objects: Vec<ObjDumpFormat>,
6331 pub modified_at_versions: Vec<ObjDumpFormat>,
6332 pub runtime_reads: Vec<ObjDumpFormat>,
6333 pub input_objects: Vec<ObjDumpFormat>,
6334}
6335
6336impl NodeStateDump {
6337 pub fn new(
6338 tx_digest: &TransactionDigest,
6339 effects: &TransactionEffects,
6340 expected_effects_digest: TransactionEffectsDigest,
6341 object_store: &dyn ObjectStore,
6342 epoch_store: &Arc<AuthorityPerEpochStore>,
6343 inner_temporary_store: &InnerTemporaryStore,
6344 transaction: &VerifiedExecutableTransaction,
6345 ) -> IotaResult<Self> {
6346 let executed_epoch = epoch_store.epoch();
6348 let reference_gas_price = epoch_store.reference_gas_price();
6349 let epoch_start_config = epoch_store.epoch_start_config();
6350 let protocol_version = epoch_store.protocol_version().as_u64();
6351 let epoch_start_timestamp_ms = epoch_start_config.epoch_data().epoch_start_timestamp();
6352
6353 let mut relevant_system_packages = Vec::new();
6355 for sys_package_id in BuiltInFramework::all_package_ids() {
6356 if let Some(w) = object_store.try_get_object(&sys_package_id)? {
6357 relevant_system_packages.push(ObjDumpFormat::new(w))
6358 }
6359 }
6360
6361 let mut shared_objects = Vec::new();
6363 for kind in effects.input_shared_objects() {
6364 match kind {
6365 InputSharedObject::Mutate(obj_ref) | InputSharedObject::ReadOnly(obj_ref) => {
6366 if let Some(w) =
6367 object_store.try_get_object_by_key(&obj_ref.object_id, obj_ref.version)?
6368 {
6369 shared_objects.push(ObjDumpFormat::new(w))
6370 }
6371 }
6372 InputSharedObject::ReadDeleted(..)
6373 | InputSharedObject::MutateDeleted(..)
6374 | InputSharedObject::Canceled(..) => (), }
6377 }
6378
6379 let mut loaded_child_objects = Vec::new();
6382 for (id, meta) in &inner_temporary_store.loaded_runtime_objects {
6383 if let Some(w) = object_store.try_get_object_by_key(id, meta.version)? {
6384 loaded_child_objects.push(ObjDumpFormat::new(w))
6385 }
6386 }
6387
6388 let mut modified_at_versions = Vec::new();
6390 for modified in effects.modified_at_versions() {
6391 let (id, ver) = (modified.object_id, modified.version);
6392 if let Some(w) = object_store.try_get_object_by_key(&id, ver)? {
6393 modified_at_versions.push(ObjDumpFormat::new(w))
6394 }
6395 }
6396
6397 let mut runtime_reads = Vec::new();
6401 for obj in inner_temporary_store
6402 .runtime_packages_loaded_from_db
6403 .values()
6404 {
6405 runtime_reads.push(ObjDumpFormat::new(obj.object().clone()));
6406 }
6407
6408 Ok(Self {
6411 tx_digest: *tx_digest,
6412 executed_epoch,
6413 reference_gas_price,
6414 epoch_start_timestamp_ms,
6415 protocol_version,
6416 relevant_system_packages,
6417 shared_objects,
6418 loaded_child_objects,
6419 modified_at_versions,
6420 runtime_reads,
6421 sender_signed_data: transaction.clone().into_message(),
6422 input_objects: inner_temporary_store
6423 .input_objects
6424 .values()
6425 .map(|o| ObjDumpFormat::new(o.clone()))
6426 .collect(),
6427 computed_effects: effects.clone(),
6428 expected_effects_digest,
6429 })
6430 }
6431
6432 pub fn all_objects(&self) -> Vec<ObjDumpFormat> {
6433 let mut objects = Vec::new();
6434 objects.extend(self.relevant_system_packages.clone());
6435 objects.extend(self.shared_objects.clone());
6436 objects.extend(self.loaded_child_objects.clone());
6437 objects.extend(self.modified_at_versions.clone());
6438 objects.extend(self.runtime_reads.clone());
6439 objects.extend(self.input_objects.clone());
6440 objects
6441 }
6442
6443 pub fn write_to_file(&self, path: &Path) -> Result<PathBuf, anyhow::Error> {
6444 let file_name = format!(
6445 "{}_{}_NODE_DUMP.json",
6446 self.tx_digest,
6447 AuthorityState::unixtime_now_ms()
6448 );
6449 let mut path = path.to_path_buf();
6450 path.push(&file_name);
6451 let mut file = File::create(path.clone())?;
6452 file.write_all(serde_json::to_string_pretty(self)?.as_bytes())?;
6453 Ok(path)
6454 }
6455
6456 pub fn read_from_file(path: &PathBuf) -> Result<Self, anyhow::Error> {
6457 let file = File::open(path)?;
6458 serde_json::from_reader(file).map_err(|e| anyhow::anyhow!(e))
6459 }
6460}
6461
6462fn pre_consensus_move_authenticators<'a>(
6474 tx: &'a VerifiedTransaction,
6475 protocol_config: &ProtocolConfig,
6476) -> Vec<&'a MoveAuthenticator> {
6477 if protocol_config.pre_consensus_sponsor_only_move_authentication() {
6478 if tx.transaction().is_sponsored_tx() {
6479 if let Some(sponsor_move_authenticator) = tx.sponsor_move_authenticator() {
6480 vec![sponsor_move_authenticator]
6481 } else {
6482 vec![]
6483 }
6484 } else {
6485 tx.move_authenticators()
6486 }
6487 } else {
6488 tx.move_authenticators()
6489 }
6490}