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