1use std::{
7 cell::Cell,
8 collections::{BTreeMap, HashMap, HashSet},
9 fs::File,
10 io::Write,
11 path::{Path, PathBuf},
12 pin::Pin,
13 sync::{
14 Arc, Weak,
15 atomic::{AtomicBool, Ordering},
16 },
17 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
18 vec,
19};
20
21use arc_swap::{ArcSwap, Guard};
22use async_trait::async_trait;
23use authority_per_epoch_store::TxLockGuard;
24pub use authority_store::{AuthorityStore, ResolverWrapper, UpdateType};
25use fastcrypto::{
26 encoding::{Base58, Encoding},
27 hash::MultisetHash,
28};
29use iota_common::{debug_fatal, fatal};
30use iota_config::{
31 NodeConfig,
32 genesis::Genesis,
33 node::{AuthorityOverloadConfig, ExpensiveSafetyCheckConfig, StateDebugDumpConfig},
34};
35use iota_framework::{BuiltInFramework, SystemPackage as FrameworkSystemPackage};
36use iota_json_rpc_types::{EventFilter, IotaEvent, IotaObjectDataFilter, TransactionFilter};
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, CheckpointCommitment, CheckpointContents, CheckpointContentsDigest, CheckpointDigest,
43 CheckpointSummary, Digest, EndOfEpochTransactionKind, Event, ExecutionStatus, GasCostSummary,
44 InputSharedObject, MoveAuthenticator, ObjectDigest, ObjectId, ObjectReference, RandomnessRound,
45 SenderSignedTransaction, StructTag, SystemPackage, Transaction, TransactionDigest,
46 TransactionEffects, TransactionEffectsDigest, TransactionEvents, TransactionKind, TypeTag,
47 Version,
48 crypto::{Intent, IntentScope},
49};
50use iota_storage::{
51 key_value_store::{
52 KVStoreTransactionData, TransactionKeyValueStore, TransactionKeyValueStoreTrait,
53 },
54 key_value_store_metrics::KeyValueStoreMetrics,
55};
56use iota_traffic_controller::{TrafficController, metrics::TrafficControllerMetrics};
57use iota_transaction_checks::VerifierLimitsSource;
58#[cfg(msim)]
59use iota_types::committee::CommitteeTrait;
60use iota_types::{
61 account_abstraction::authenticator_function::{
62 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
63 MoveAuthenticatorForExecution, MoveAuthenticatorsForExecution,
64 authenticator_function_ref_v1_from_dynamic_field_object,
65 derive_authenticator_function_ref_v1_dynamic_field_id, extract_auth_fun_refs,
66 },
67 attestation::{AttestationRecord, AttestationVerdict},
68 auth_context::AuthContextData,
69 base_types::{AuthorityName, ConciseableName, VersionNumber},
70 committee::{Committee, EpochId, ProtocolVersion},
71 crypto::{AggregateAuthorityPublicKey, AuthoritySignInfo, AuthoritySignature, Signer},
72 deny_list_v1::{check_coin_deny_list_v1, coin_types_for_denylist_check},
73 deny_rule_governance::DenyRuleConfig,
74 digests::ChainIdentifier,
75 dynamic_field::{self, DynamicFieldInfo},
76 effects::{
77 SignedTransactionEffects, TransactionEffectsAPI, TransactionEffectsExt,
78 VerifiedSignedTransactionEffects,
79 },
80 error::{ExecutionError, ExecutionErrorKind, IotaError, IotaResult, UserInputError},
81 event::{EventID, SystemEpochInfoEvent},
82 executable_transaction::VerifiedExecutableTransaction,
83 execution_config_utils::to_binary_config,
84 fp_ensure,
85 gas::IotaGasStatus,
86 gas_coin::mock_simulation_gas_coin,
87 inner_temporary_store::InnerTemporaryStore,
88 iota_system_state::{
89 IotaSystemState, IotaSystemStateTrait,
90 epoch_start_iota_system_state::EpochStartSystemStateTrait, get_iota_system_state,
91 },
92 layout_resolver::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, ObjectSet, PastObjectRead},
108 storage::{
109 BackingPackageStore, BackingStore, ObjectKey, ObjectOrTombstone, ObjectStore,
110 OwnedObjectCursor, TrackingBackingStore,
111 },
112 supported_protocol_versions::{
113 ProtocolConfig, SupportedProtocolVersions, SupportedProtocolVersionsWithHashes,
114 },
115 traffic_control::{PolicyConfig, TrafficControlReconfigParams},
116 transaction::*,
117 transaction_executor::{SimulateTransactionResult, VmChecks},
118};
119use itertools::Itertools;
120use move_binary_format::{CompiledModule, binary_config::BinaryConfig};
121use move_core_types::{
122 account_address::AccountAddress, annotated_value::MoveStructLayout, language_storage::ModuleId,
123};
124use parking_lot::Mutex;
125use prometheus_filtered::{
126 Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, MetricLevel,
127 Registry, register_histogram_vec_with_registry, register_histogram_with_registry,
128 register_int_counter_vec_with_registry, register_int_counter_with_registry,
129 register_int_gauge_vec_with_registry, register_int_gauge_with_registry,
130};
131use serde::{Deserialize, Serialize, de::DeserializeOwned};
132use tap::TapFallible;
133use tokio::{
134 sync::{Notify, RwLock, mpsc, mpsc::unbounded_channel, oneshot, watch},
135 task::JoinHandle,
136};
137use tracing::{debug, error, info, instrument, trace, warn};
138use typed_store::TypedStoreError;
139
140use self::{attestation::attestation_record, authority_store::ExecutionLockWriteGuard};
141#[cfg(msim)]
142pub use crate::checkpoints::checkpoint_executor::utils::{
143 CheckpointTimeoutConfig, init_checkpoint_timeout_config,
144};
145use crate::{
146 authority::{
147 authority_per_epoch_store::{AuthorityPerEpochStore, TxGuard},
148 authority_per_epoch_store_pruner::AuthorityPerEpochStorePruner,
149 authority_store::{ExecutionLockReadGuard, ObjectLockStatus},
150 epoch_start_configuration::{EpochStartConfigTrait, EpochStartConfiguration},
151 historic_ledger::HistoricLedger,
152 historic_objects::HistoricObjects,
153 object_retention::{ObjectRetention, ObjectRetentionGuard},
154 shared_object_version_manager::{AssignedVersions, Schedulable},
155 },
156 authority_client::NetworkAuthorityClient,
157 checkpoints::{CheckpointBuilderError, CheckpointBuilderResult, CheckpointStore},
158 congestion_tracker::CongestionTracker,
159 consensus_adapter::ConsensusAdapter,
160 epoch::committee_store::CommitteeStore,
161 epoch_buckets::PrunedBuckets,
162 epoch_end_db_snapshot::{EpochEndDbSnapshotHandle, HandOver},
163 execution_cache::{
164 CheckpointCache, ExecutionCacheCommit, ExecutionCacheReconfigAPI,
165 ExecutionCacheTraitPointers, ExecutionCacheWrite, ObjectCacheRead, StateSyncAPI,
166 TransactionCacheRead,
167 },
168 execution_driver::execution_process,
169 execution_scheduler::{
170 ExecutionSchedulerAPI, ExecutionSchedulerWrapper, transaction_manager::AttestationSource,
171 },
172 global_state_hasher::{GlobalStateHashStore, GlobalStateHasher},
173 metrics::{LatencyObserver, RateTracker},
174 module_cache_metrics::ResolverMetrics,
175 overload_monitor::{
176 AuthorityOverloadInfo, compute_graduated_load_shedding_percentage,
177 overload_monitor_accept_tx,
178 },
179 post_consensus_input_reader::{
180 AccountVerdict, InputResolution, ReceivingObjectsResolution, ValidationAtCommit,
181 ValidationInputsAtCommit,
182 reader::{CommitIndexedReader, DenyListAtCommit},
183 },
184 rpc_indexes::{
185 RpcIndexesStore,
186 jsonrpc_api::{
187 CachingLayoutResolver, CoinInfo, OwnedObjectsPage, try_create_dynamic_field_info,
188 },
189 schema::{IndexGroup, OwnerTypeFilter},
190 },
191 stake_aggregator::StakeAggregator,
192 transaction_input_loader::TransactionInputLoader,
193 transaction_outputs::TransactionOutputs,
194 validator_tx_finalizer::ValidatorTxFinalizer,
195};
196
197#[cfg(test)]
198#[path = "unit_tests/authority_tests.rs"]
199pub mod authority_tests;
200
201#[cfg(test)]
202#[path = "unit_tests/transaction_tests.rs"]
203pub mod transaction_tests;
204
205#[cfg(test)]
206#[path = "unit_tests/batch_transaction_tests.rs"]
207mod batch_transaction_tests;
208
209#[cfg(test)]
210#[path = "unit_tests/move_integration_tests.rs"]
211pub mod move_integration_tests;
212
213#[cfg(test)]
214#[path = "unit_tests/gas_tests.rs"]
215mod gas_tests;
216
217#[cfg(test)]
218#[path = "unit_tests/batch_verification_tests.rs"]
219mod batch_verification_tests;
220
221#[cfg(test)]
222#[path = "unit_tests/coin_deny_list_tests.rs"]
223mod coin_deny_list_tests;
224
225#[cfg(test)]
226#[path = "unit_tests/pre_execution_failure_tests.rs"]
227mod pre_execution_failure_tests;
228
229#[cfg(test)]
230#[path = "unit_tests/cancelled_move_authenticator_tests.rs"]
231mod cancelled_move_authenticator_tests;
232
233#[cfg(test)]
234#[path = "unit_tests/move_authenticator_attestation_tests.rs"]
235mod move_authenticator_attestation_tests;
236
237#[cfg(test)]
238#[path = "unit_tests/auth_unit_test_utils.rs"]
239pub mod auth_unit_test_utils;
240
241#[cfg(test)]
242#[path = "unit_tests/abstract_account_test_utils.rs"]
243pub mod abstract_account_test_utils;
244
245#[cfg(test)]
246#[path = "unit_tests/attestation_test_utils.rs"]
247pub mod attestation_test_utils;
248
249#[cfg(test)]
250#[path = "unit_tests/attestation_verdict_tests.rs"]
251mod attestation_verdict_tests;
252
253#[cfg(any(test, feature = "test-utils"))]
254pub mod authority_test_utils;
255
256pub(crate) mod attestation;
257mod attestation_verdict;
258pub mod authority_per_epoch_store;
259pub mod authority_per_epoch_store_pruner;
260
261pub mod authority_store_tables;
262pub mod authority_store_types;
263pub mod epoch_markers;
264pub mod epoch_start_configuration;
265pub mod historic_ledger;
266pub mod historic_objects;
267pub mod ledger_backlog_migration;
268pub mod object_backlog_sweep;
269pub mod object_retention;
270pub mod shared_object_congestion_tracker;
271pub mod shared_object_version_manager;
272pub mod suggested_gas_price_calculator;
273#[cfg(any(test, feature = "test-utils"))]
274pub mod test_authority_builder;
275pub mod transaction_deferral;
276
277pub(crate) mod authority_store;
278pub mod backpressure;
279pub(crate) mod dropped_tx_status_cache;
280
281pub struct AuthorityMetrics {
283 tx_orders: IntCounter,
284 total_certs: IntCounter,
285 total_cert_attempts: IntCounter,
286 total_effects: IntCounter,
287 pub shared_obj_tx: IntCounter,
288 sponsored_tx: IntCounter,
289 tx_already_processed: IntCounter,
290 num_input_objs: Histogram,
291 num_shared_objects: Histogram,
292 batch_size: Histogram,
293
294 authority_state_handle_transaction_latency: Histogram,
295
296 execute_certificate_latency_single_writer: Histogram,
297 execute_certificate_latency_shared_object: Histogram,
298
299 internal_execution_latency: Histogram,
300 signed_effects_equivocation_prevented: IntCounterVec,
304 execution_load_input_objects_latency: Histogram,
305 prepare_certificate_latency: Histogram,
306 commit_certificate_latency: Histogram,
307 epoch_end_db_snapshot_handover_latency: Histogram,
308 epoch_end_db_snapshots_skipped: IntCounter,
309
310 pub(crate) transaction_manager_num_enqueued_certificates: IntCounterVec,
311 pub(crate) transaction_manager_num_missing_objects: IntGauge,
312 pub(crate) transaction_manager_num_pending_certificates: IntGauge,
313 pub(crate) transaction_manager_num_executing_certificates: IntGauge,
314 pub(crate) transaction_manager_num_ready: IntGauge,
315 pub(crate) transaction_manager_object_cache_size: IntGauge,
316 pub(crate) transaction_manager_object_cache_hits: IntCounter,
317 pub(crate) transaction_manager_object_cache_misses: IntCounter,
318 pub(crate) transaction_manager_object_cache_evictions: IntCounter,
319 pub(crate) transaction_manager_package_cache_size: IntGauge,
320 pub(crate) transaction_manager_package_cache_hits: IntCounter,
321 pub(crate) transaction_manager_package_cache_misses: IntCounter,
322 pub(crate) transaction_manager_package_cache_evictions: IntCounter,
323 pub(crate) transaction_manager_transaction_queue_age_s: Histogram,
324
325 pub(crate) execution_driver_executed_transactions: IntCounter,
326 pub(crate) execution_driver_dispatch_queue: IntGauge,
327 pub(crate) execution_queueing_delay_s: Histogram,
328 pub(crate) prepare_cert_gas_latency_ratio: Histogram,
329 pub(crate) execution_gas_latency_ratio: Histogram,
330
331 pub(crate) superseded_capture_misses: IntCounter,
334
335 pub(crate) skipped_consensus_txns: IntCounter,
336 pub(crate) skipped_consensus_txns_cache_hit: IntCounter,
337
338 pub(crate) historic_bucket_earliest_retained_epoch: IntGaugeVec,
342 pub(crate) historic_bucket_expiry_duration: HistogramVec,
344
345 pub(crate) authority_overload_status: IntGauge,
346 pub(crate) consensus_queue_load_shedding_percentage: IntGauge,
348 pub(crate) local_post_consensus_load_shedding_percentage: IntGauge,
352
353 pub(crate) transaction_overload_sources: IntCounterVec,
354
355 pub(crate) checkpoint_inclusion_index_wait_timeouts: IntCounter,
358
359 pub consensus_handler_processed: IntCounterVec,
361 pub consensus_handler_transaction_sizes: HistogramVec,
362 pub consensus_handler_num_low_scoring_authorities: IntGauge,
363 pub consensus_handler_scores: IntGaugeVec,
364 pub consensus_handler_deferred_transactions: IntCounter,
365 pub consensus_handler_congested_transactions: IntCounter,
366 pub consensus_handler_cancelled_transactions: IntCounter,
367 pub consensus_handler_validation_dropped_transactions: IntCounter,
371 pub consensus_handler_validation_reader_verdicts: IntCounterVec,
375 pub consensus_handler_commit_execution_lag: IntGauge,
378 pub(crate) consensus_handler_validation_attested_transactions: IntCounterVec,
381 pub(crate) consensus_handler_validation_attestor_cut_off_transactions: IntCounter,
384 pub consensus_handler_load_shedding_dropped_transactions: IntCounter,
388 pub consensus_handler_load_shedding_percentage: IntGauge,
394 pub consensus_handler_max_object_costs: IntGaugeVec,
395 pub consensus_committed_subdags: IntCounterVec,
396 pub consensus_committed_messages: IntGaugeVec,
397 pub consensus_committed_user_transactions: IntGaugeVec,
398 pub consensus_handler_leader_round: IntGauge,
399 pub consensus_calculated_throughput: IntGauge,
400 pub consensus_calculated_throughput_profile: IntGauge,
401
402 pub validator_scoreboard_scores: IntGaugeVec,
403 pub invalid_misbehavior_reports_by_authority: IntGaugeVec,
404
405 pub limits_metrics: Arc<LimitsMetrics>,
406
407 pub bytecode_verifier_metrics: Arc<BytecodeVerifierMetrics>,
409
410 pub multisig_sig_count: IntCounter,
412
413 pub execution_queueing_latency: LatencyObserver,
416
417 pub txn_ready_rate_tracker: Arc<Mutex<RateTracker>>,
424
425 pub execution_rate_tracker: Arc<Mutex<RateTracker>>,
428}
429
430const HELD_BACK_EXPIRY_INTERVAL: Duration = Duration::from_secs(1);
433
434const CATCH_UP_LAG: Duration = Duration::from_secs(10 * 60);
438
439const COMPACTION_RECHECK_INTERVAL: Duration = Duration::from_secs(5 * 60);
442
443const POSITIVE_INT_BUCKETS: &[f64] = &[
445 1., 2., 5., 7., 10., 20., 50., 70., 100., 200., 500., 700., 1000., 2000., 5000., 7000., 10000.,
446 20000., 50000., 70000., 100000., 200000., 500000., 700000., 1000000., 2000000., 5000000.,
447 7000000., 10000000.,
448];
449
450const LATENCY_SEC_BUCKETS: &[f64] = &[
451 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.,
452 10., 20., 30., 60., 90.,
453];
454
455const LOW_LATENCY_SEC_BUCKETS: &[f64] = &[
457 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,
458 0.2, 0.5, 1., 2., 5., 10., 20., 50., 100.,
459];
460
461const HISTORIC_BUCKET_EXPIRY_SEC_BUCKETS: &[f64] = &[
464 0.01, 0.05, 0.1, 0.5, 1., 2., 5., 10., 30., 60., 120., 300., 600., 1200., 1800.,
465];
466
467const GAS_LATENCY_RATIO_BUCKETS: &[f64] = &[
468 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,
469 3000.0, 4000.0, 5000.0, 6000.0, 7000.0, 8000.0, 9000.0, 10000.0, 50000.0, 100000.0, 1000000.0,
470];
471
472impl AuthorityMetrics {
473 pub fn new(registry: &prometheus_filtered::Registry) -> AuthorityMetrics {
474 let execute_certificate_latency = register_histogram_vec_with_registry!(
475 "authority_state_execute_certificate_latency",
476 "Latency of executing certificates, including waiting for inputs",
477 &["tx_type"],
478 LATENCY_SEC_BUCKETS.to_vec(),
479 registry;
480 MetricLevel::Info,
481 )
482 .unwrap();
483
484 let execute_certificate_latency_single_writer =
485 execute_certificate_latency.with_label_values(&[TX_TYPE_SINGLE_WRITER_TX]);
486 let execute_certificate_latency_shared_object =
487 execute_certificate_latency.with_label_values(&[TX_TYPE_SHARED_OBJ_TX]);
488
489 Self {
490 tx_orders: register_int_counter_with_registry!(
491 "total_transaction_orders",
492 "Total number of transaction orders",
493 registry;
494 MetricLevel::Warn,
495 )
496 .unwrap(),
497 total_certs: register_int_counter_with_registry!(
498 "total_transaction_certificates",
499 "Total number of transaction certificates handled",
500 registry;
501 MetricLevel::Warn,
502 )
503 .unwrap(),
504 total_cert_attempts: register_int_counter_with_registry!(
505 "total_handle_certificate_attempts",
506 "Number of calls to handle_certificate",
507 registry,
508 )
509 .unwrap(),
510 total_effects: register_int_counter_with_registry!(
512 "total_transaction_effects",
513 "Total number of transaction effects produced",
514 registry;
515 MetricLevel::Warn,
516 )
517 .unwrap(),
518
519 shared_obj_tx: register_int_counter_with_registry!(
520 "num_shared_obj_tx",
521 "Number of transactions involving shared objects",
522 registry;
523 MetricLevel::Warn,
524 )
525 .unwrap(),
526
527 sponsored_tx: register_int_counter_with_registry!(
528 "num_sponsored_tx",
529 "Number of sponsored transactions",
530 registry,
531 )
532 .unwrap(),
533
534 tx_already_processed: register_int_counter_with_registry!(
535 "num_tx_already_processed",
536 "Number of transaction orders already processed previously",
537 registry,
538 )
539 .unwrap(),
540 num_input_objs: register_histogram_with_registry!(
541 "num_input_objects",
542 "Distribution of number of input TX objects per TX",
543 POSITIVE_INT_BUCKETS.to_vec(),
544 registry;
545 MetricLevel::Warn,
546 )
547 .unwrap(),
548 num_shared_objects: register_histogram_with_registry!(
549 "num_shared_objects",
550 "Number of shared input objects per TX",
551 POSITIVE_INT_BUCKETS.to_vec(),
552 registry,
553 )
554 .unwrap(),
555 batch_size: register_histogram_with_registry!(
556 "batch_size",
557 "Distribution of size of transaction batch",
558 POSITIVE_INT_BUCKETS.to_vec(),
559 registry,
560 )
561 .unwrap(),
562 authority_state_handle_transaction_latency: register_histogram_with_registry!(
563 "authority_state_handle_transaction_latency",
564 "Latency of handling transactions",
565 LATENCY_SEC_BUCKETS.to_vec(),
566 registry,
567 )
568 .unwrap(),
569 execute_certificate_latency_single_writer,
570 execute_certificate_latency_shared_object,
571 internal_execution_latency: register_histogram_with_registry!(
572 "authority_state_internal_execution_latency",
573 "Latency of actual certificate executions",
574 LATENCY_SEC_BUCKETS.to_vec(),
575 registry,
576 )
577 .unwrap(),
578 signed_effects_equivocation_prevented: register_int_counter_vec_with_registry!(
579 "authority_state_signed_effects_equivocation_prevented",
580 "Number of times the validator refused to report effects that differ from previously signed effects for the same transaction, by RPC surface",
581 &["surface"],
582 registry,
583 )
584 .unwrap(),
585 execution_load_input_objects_latency: register_histogram_with_registry!(
586 "authority_state_execution_load_input_objects_latency",
587 "Latency of loading input objects for execution",
588 LOW_LATENCY_SEC_BUCKETS.to_vec(),
589 registry,
590 )
591 .unwrap(),
592 prepare_certificate_latency: register_histogram_with_registry!(
593 "authority_state_prepare_certificate_latency",
594 "Latency of executing certificates, before committing the results",
595 LATENCY_SEC_BUCKETS.to_vec(),
596 registry,
597 )
598 .unwrap(),
599 commit_certificate_latency: register_histogram_with_registry!(
600 "authority_state_commit_certificate_latency",
601 "Latency of committing certificate execution results",
602 LATENCY_SEC_BUCKETS.to_vec(),
603 registry,
604 )
605 .unwrap(),
606 epoch_end_db_snapshot_handover_latency: register_histogram_with_registry!(
607 "epoch_end_db_snapshot_handover_latency",
608 "Time the epoch boundary waits for the consumer to take its database \
609 snapshot of the perpetual store",
610 LATENCY_SEC_BUCKETS.to_vec(),
611 registry,
612 ).unwrap(),
613 epoch_end_db_snapshots_skipped: register_int_counter_with_registry!(
614 "epoch_end_db_snapshots_skipped",
615 "Epoch boundaries whose database snapshot was not taken, because the \
616 consumer was busy or did not take it in time",
617 registry,
618 ).unwrap(),
619 transaction_manager_num_enqueued_certificates: register_int_counter_vec_with_registry!(
620 "transaction_manager_num_enqueued_certificates",
621 "Current number of certificates enqueued to TransactionManager",
622 &["result"],
623 registry,
624 )
625 .unwrap(),
626 transaction_manager_num_missing_objects: register_int_gauge_with_registry!(
627 "transaction_manager_num_missing_objects",
628 "Current number of missing objects in TransactionManager",
629 registry,
630 )
631 .unwrap(),
632 transaction_manager_num_pending_certificates: register_int_gauge_with_registry!(
633 "transaction_manager_num_pending_certificates",
634 "Number of certificates pending in TransactionManager, with at least 1 missing input object",
635 registry;
636 MetricLevel::Warn,
637 )
638 .unwrap(),
639 transaction_manager_num_executing_certificates: register_int_gauge_with_registry!(
640 "transaction_manager_num_executing_certificates",
641 "Number of executing certificates, including queued and actually running certificates",
642 registry;
643 MetricLevel::Warn,
644 )
645 .unwrap(),
646 transaction_manager_num_ready: register_int_gauge_with_registry!(
647 "transaction_manager_num_ready",
648 "Number of ready transactions in TransactionManager",
649 registry,
650 )
651 .unwrap(),
652 transaction_manager_object_cache_size: register_int_gauge_with_registry!(
653 "transaction_manager_object_cache_size",
654 "Current size of object-availability cache in TransactionManager",
655 registry,
656 )
657 .unwrap(),
658 transaction_manager_object_cache_hits: register_int_counter_with_registry!(
659 "transaction_manager_object_cache_hits",
660 "Number of object-availability cache hits in TransactionManager",
661 registry,
662 )
663 .unwrap(),
664 historic_bucket_earliest_retained_epoch: register_int_gauge_vec_with_registry!(
665 "historic_bucket_earliest_retained_epoch",
666 "Earliest epoch whose history a store retains",
667 &["store"],
668 registry;
669 MetricLevel::Warn,
670 )
671 .unwrap(),
672 historic_bucket_expiry_duration: register_histogram_vec_with_registry!(
673 "historic_bucket_expiry_duration_seconds",
674 "How long a store's expiries of historic buckets that dropped a bucket took",
675 &["store"],
676 HISTORIC_BUCKET_EXPIRY_SEC_BUCKETS.to_vec(),
677 registry;
678 MetricLevel::Warn,
679 )
680 .unwrap(),
681 authority_overload_status: register_int_gauge_with_registry!(
682 "authority_overload_status",
683 "Whether authority is current experiencing overload and enters load shedding mode.",
684 registry;
685 MetricLevel::Warn,)
686 .unwrap(),
687 local_post_consensus_load_shedding_percentage: register_int_gauge_with_registry!(
688 "authority_load_shedding_percentage",
689 "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).",
690 registry;
691 MetricLevel::Info,)
692 .unwrap(),
693 consensus_queue_load_shedding_percentage: register_int_gauge_with_registry!(
694 "consensus_queue_load_shedding_percentage",
695 "Percentage of transactions shed due to consensus queue length. Separate admission-control signal, not an input to authority_load_shedding_percentage.",
696 registry)
697 .unwrap(),
698 transaction_manager_object_cache_misses: register_int_counter_with_registry!(
699 "transaction_manager_object_cache_misses",
700 "Number of object-availability cache misses in TransactionManager",
701 registry,
702 )
703 .unwrap(),
704 transaction_manager_object_cache_evictions: register_int_counter_with_registry!(
705 "transaction_manager_object_cache_evictions",
706 "Number of object-availability cache evictions in TransactionManager",
707 registry,
708 )
709 .unwrap(),
710 transaction_manager_package_cache_size: register_int_gauge_with_registry!(
711 "transaction_manager_package_cache_size",
712 "Current size of package-availability cache in TransactionManager",
713 registry,
714 )
715 .unwrap(),
716 transaction_manager_package_cache_hits: register_int_counter_with_registry!(
717 "transaction_manager_package_cache_hits",
718 "Number of package-availability cache hits in TransactionManager",
719 registry,
720 )
721 .unwrap(),
722 transaction_manager_package_cache_misses: register_int_counter_with_registry!(
723 "transaction_manager_package_cache_misses",
724 "Number of package-availability cache misses in TransactionManager",
725 registry,
726 )
727 .unwrap(),
728 transaction_manager_package_cache_evictions: register_int_counter_with_registry!(
729 "transaction_manager_package_cache_evictions",
730 "Number of package-availability cache evictions in TransactionManager",
731 registry,
732 )
733 .unwrap(),
734 transaction_manager_transaction_queue_age_s: register_histogram_with_registry!(
735 "transaction_manager_transaction_queue_age_s",
736 "Time spent in waiting for transaction in the queue",
737 LATENCY_SEC_BUCKETS.to_vec(),
738 registry;
739 MetricLevel::Warn,
740 )
741 .unwrap(),
742 transaction_overload_sources: register_int_counter_vec_with_registry!(
743 "transaction_overload_sources",
744 "Number of times each source indicates transaction overload.",
745 &["source"],
746 registry)
747 .unwrap(),
748 execution_driver_executed_transactions: register_int_counter_with_registry!(
749 "execution_driver_executed_transactions",
750 "Cumulative number of transaction executed by execution driver",
751 registry;
752 MetricLevel::Warn,
753 )
754 .unwrap(),
755 execution_driver_dispatch_queue: register_int_gauge_with_registry!(
756 "execution_driver_dispatch_queue",
757 "Number of transaction pending in execution driver dispatch queue",
758 registry,
759 )
760 .unwrap(),
761 execution_queueing_delay_s: register_histogram_with_registry!(
762 "execution_queueing_delay_s",
763 "Queueing delay between a transaction is ready for execution until it starts executing.",
764 LATENCY_SEC_BUCKETS.to_vec(),
765 registry
766 )
767 .unwrap(),
768 prepare_cert_gas_latency_ratio: register_histogram_with_registry!(
769 "prepare_cert_gas_latency_ratio",
770 "The ratio of computation gas divided by VM execution latency.",
771 GAS_LATENCY_RATIO_BUCKETS.to_vec(),
772 registry
773 )
774 .unwrap(),
775 execution_gas_latency_ratio: register_histogram_with_registry!(
776 "execution_gas_latency_ratio",
777 "The ratio of computation gas divided by certificate execution latency, include committing certificate.",
778 GAS_LATENCY_RATIO_BUCKETS.to_vec(),
779 registry
780 )
781 .unwrap(),
782 superseded_capture_misses: register_int_counter_with_registry!(
783 "superseded_capture_misses",
784 "Count of modified object versions whose pre-image could not be captured for relocation into the historic store",
785 registry;
786 MetricLevel::Warn,
787 )
788 .unwrap(),
789 skipped_consensus_txns: register_int_counter_with_registry!(
790 "skipped_consensus_txns",
791 "Total number of consensus transactions skipped",
792 registry,
793 )
794 .unwrap(),
795 skipped_consensus_txns_cache_hit: register_int_counter_with_registry!(
796 "skipped_consensus_txns_cache_hit",
797 "Total number of consensus transactions skipped because of local cache hit",
798 registry,
799 )
800 .unwrap(),
801 checkpoint_inclusion_index_wait_timeouts: register_int_counter_with_registry!(
802 "checkpoint_inclusion_index_wait_timeouts",
803 "Total number of checkpoint-inclusion waits that returned before the RPC indexes had caught up",
804 registry,
805 )
806 .unwrap(),
807 consensus_handler_processed: register_int_counter_vec_with_registry!(
808 "consensus_handler_processed",
809 "Number of transactions processed by consensus handler",
810 &["class"],
811 registry
812 ).unwrap(),
813 consensus_handler_transaction_sizes: register_histogram_vec_with_registry!(
814 "consensus_handler_transaction_sizes",
815 "Sizes of each type of transactions processed by consensus handler",
816 &["class"],
817 POSITIVE_INT_BUCKETS.to_vec(),
818 registry;
819 MetricLevel::Warn,
820 ).unwrap(),
821 consensus_handler_num_low_scoring_authorities: register_int_gauge_with_registry!(
822 "consensus_handler_num_low_scoring_authorities",
823 "Number of low scoring authorities based on reputation scores from consensus",
824 registry
825 ).unwrap(),
826 consensus_handler_scores: register_int_gauge_vec_with_registry!(
827 "consensus_handler_scores",
828 "scores from consensus for each authority",
829 &["authority"],
830 registry,
831 ).unwrap(),
832 validator_scoreboard_scores: register_int_gauge_vec_with_registry!(
833 "validator_scoreboard_scores",
834 "Per-authority validator scores published by the local Scoreboard after each consensus commit. Range [0, MAX_SCORE].",
835 &["authority"],
836 registry;
837 MetricLevel::Warn,
838 ).unwrap(),
839 invalid_misbehavior_reports_by_authority: register_int_gauge_vec_with_registry!(
840 "invalid_misbehavior_reports_by_authority",
841 "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.",
842 &["authority"],
843 registry;
844 MetricLevel::Warn,
845 ).unwrap(),
846 consensus_handler_deferred_transactions: register_int_counter_with_registry!(
847 "consensus_handler_deferred_transactions",
848 "Number of transactions deferred by consensus handler",
849 registry,
850 ).unwrap(),
851 consensus_handler_congested_transactions: register_int_counter_with_registry!(
852 "consensus_handler_congested_transactions",
853 "Number of transactions deferred by consensus handler due to congestion",
854 registry,
855 ).unwrap(),
856 consensus_handler_cancelled_transactions: register_int_counter_with_registry!(
857 "consensus_handler_cancelled_transactions",
858 "Number of transactions cancelled by consensus handler",
859 registry,
860 ).unwrap(),
861 consensus_handler_validation_dropped_transactions: register_int_counter_with_registry!(
862 "consensus_handler_validation_dropped_transactions",
863 "Number of user transactions dropped by post-consensus validation",
864 registry,
865 ).unwrap(),
866 consensus_handler_validation_reader_verdicts: register_int_counter_vec_with_registry!(
867 "consensus_handler_validation_reader_verdicts",
868 "Verdicts of the commit-indexed reader in post-consensus validation, by verdict and deciding reason",
869 &["verdict", "reason"],
870 registry,
871 ).unwrap(),
872 consensus_handler_commit_execution_lag: register_int_gauge_with_registry!(
873 "consensus_handler_commit_execution_lag",
874 "The consensus commit being validated minus the highest fully executed commit",
875 registry,
876 ).unwrap(),
877 consensus_handler_validation_attested_transactions: register_int_counter_vec_with_registry!(
878 "consensus_handler_validation_attested_transactions",
879 "Number of attested transactions that passed post-consensus validation, by attestation kind; a deferred transaction counts again when reloaded",
880 &["attestation"],
881 registry;
882 MetricLevel::Warn,
883 ).unwrap(),
884 consensus_handler_validation_attestor_cut_off_transactions: register_int_counter_with_registry!(
885 "consensus_handler_validation_attestor_cut_off_transactions",
886 "Number of attested transactions dropped by post-consensus validation because their attestor is cut off for the rest of the epoch",
887 registry,
888 ).unwrap(),
889 consensus_handler_load_shedding_dropped_transactions: register_int_counter_with_registry!(
890 "consensus_handler_load_shedding_dropped_transactions",
891 "Number of user transactions dropped by post-consensus load shedding, based on the quorum load shedding percentage",
892 registry,
893 ).unwrap(),
894 consensus_handler_load_shedding_percentage: register_int_gauge_with_registry!(
895 "consensus_handler_load_shedding_percentage",
896 "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.",
897 registry,
898 ).unwrap(),
899 consensus_handler_max_object_costs: register_int_gauge_vec_with_registry!(
900 "consensus_handler_max_congestion_control_object_costs",
901 "Max object costs for congestion control in the current consensus commit",
902 &["commit_type"],
903 registry,
904 ).unwrap(),
905 consensus_committed_subdags: register_int_counter_vec_with_registry!(
906 "consensus_committed_subdags",
907 "Number of committed subdags, sliced by leader",
908 &["authority"],
909 registry,
910 ).unwrap(),
911 consensus_committed_messages: register_int_gauge_vec_with_registry!(
912 "consensus_committed_messages",
913 "Total number of committed consensus messages, sliced by author",
914 &["authority"],
915 registry;
916 MetricLevel::Warn,
917 ).unwrap(),
918 consensus_committed_user_transactions: register_int_gauge_vec_with_registry!(
919 "consensus_committed_user_transactions",
920 "Number of committed user transactions, sliced by submitter",
921 &["authority"],
922 registry,
923 ).unwrap(),
924 consensus_handler_leader_round: register_int_gauge_with_registry!(
925 "consensus_handler_leader_round",
926 "The leader round of the current consensus output being processed in the consensus handler",
927 registry;
928 MetricLevel::Warn,
929 ).unwrap(),
930 limits_metrics: Arc::new(LimitsMetrics::new(registry)),
931 bytecode_verifier_metrics: Arc::new(BytecodeVerifierMetrics::new(registry)),
932 multisig_sig_count: register_int_counter_with_registry!(
933 "multisig_sig_count",
934 "Count of multisig signatures",
935 registry,
936 )
937 .unwrap(),
938 consensus_calculated_throughput: register_int_gauge_with_registry!(
939 "consensus_calculated_throughput",
940 "The calculated throughput from consensus output. Result is calculated based on unique transactions.",
941 registry,
942 ).unwrap(),
943 consensus_calculated_throughput_profile: register_int_gauge_with_registry!(
944 "consensus_calculated_throughput_profile",
945 "The current active calculated throughput profile",
946 registry
947 ).unwrap(),
948 execution_queueing_latency: LatencyObserver::new(),
949 txn_ready_rate_tracker: Arc::new(Mutex::new(RateTracker::new(Duration::from_secs(10)))),
950 execution_rate_tracker: Arc::new(Mutex::new(RateTracker::new(Duration::from_secs(10)))),
951 }
952 }
953
954 pub fn reset_on_reconfigure(&self) {
958 self.consensus_committed_messages.reset();
959 self.consensus_handler_scores.reset();
960 self.validator_scoreboard_scores.reset();
961 self.invalid_misbehavior_reports_by_authority.reset();
962 self.consensus_committed_user_transactions.reset();
963 }
964}
965
966pub type StableSyncAuthoritySigner = Pin<Arc<dyn Signer<AuthoritySignature> + Send + Sync>>;
972
973type CheckedValidationInputs = (CheckedInputObjects, Vec<CheckedInputObjects>);
975
976#[derive(Debug, Clone, Default)]
980pub struct ExecutionEnv {
981 pub assigned_versions: AssignedVersions,
983 pub expected_effects_digest: Option<TransactionEffectsDigest>,
986 pub attestation: AttestationSource,
988}
989
990impl ExecutionEnv {
991 pub fn new() -> Self {
992 Default::default()
993 }
994
995 pub fn with_expected_effects_digest(
996 mut self,
997 expected_effects_digest: TransactionEffectsDigest,
998 ) -> Self {
999 self.expected_effects_digest = Some(expected_effects_digest);
1000 self
1001 }
1002
1003 pub fn with_assigned_versions(mut self, assigned_versions: AssignedVersions) -> Self {
1004 if !assigned_versions.is_empty() {
1005 self.assigned_versions = assigned_versions;
1006 }
1007 self
1008 }
1009
1010 pub fn with_attestation(mut self, attestation: AttestationSource) -> Self {
1011 self.attestation = attestation;
1012 self
1013 }
1014}
1015
1016type TransactionExecutionResult = (
1021 InnerTemporaryStore,
1022 TransactionEffects,
1023 Option<ExecutionError>,
1024 ObjectSet,
1025 Option<AttestationRecord>,
1026);
1027
1028struct ObjectStoreWithHistoricFallback<'a>(&'a AuthorityState);
1031
1032impl ObjectStore for ObjectStoreWithHistoricFallback<'_> {
1033 fn try_get_object(
1034 &self,
1035 object_id: &ObjectId,
1036 ) -> iota_types::storage::error::Result<Option<Object>> {
1037 self.0.get_object_store().try_get_object(object_id)
1038 }
1039
1040 fn try_get_object_by_key(
1041 &self,
1042 object_id: &ObjectId,
1043 version: Version,
1044 ) -> iota_types::storage::error::Result<Option<Object>> {
1045 self.0
1046 .get_object_with_historic_fallback(&ObjectKey(*object_id, version))
1047 .map_err(iota_types::storage::error::Error::custom)
1048 }
1049
1050 fn try_multi_get_objects_by_key(
1051 &self,
1052 object_keys: &[ObjectKey],
1053 ) -> iota_types::storage::error::Result<Vec<Option<Object>>> {
1054 let mut objects = self
1055 .0
1056 .get_object_store()
1057 .try_multi_get_objects_by_key(object_keys)?;
1058 self.0
1059 .historic_objects
1060 .fill_missing(object_keys, &mut objects, None)
1061 .map_err(iota_types::storage::error::Error::custom)?;
1062 Ok(objects)
1063 }
1064}
1065
1066pub struct AuthorityState {
1067 pub name: AuthorityName,
1070 pub secret: StableSyncAuthoritySigner,
1072
1073 input_loader: TransactionInputLoader,
1075 execution_cache_trait_pointers: ExecutionCacheTraitPointers,
1076
1077 epoch_store: ArcSwap<AuthorityPerEpochStore>,
1078
1079 execution_lock: RwLock<EpochId>,
1085
1086 pub rpc_indexes_store: Option<Arc<RpcIndexesStore>>,
1088
1089 historic_objects: Arc<HistoricObjects>,
1091
1092 historic_ledger: Arc<HistoricLedger>,
1094
1095 pub checkpoint_store: Arc<CheckpointStore>,
1096
1097 committee_store: Arc<CommitteeStore>,
1098
1099 execution_scheduler: Arc<ExecutionSchedulerWrapper>,
1101
1102 #[cfg_attr(not(test), expect(unused))]
1104 tx_execution_shutdown: Mutex<Option<oneshot::Sender<()>>>,
1105
1106 pub metrics: Arc<AuthorityMetrics>,
1107 authority_per_epoch_pruner: AuthorityPerEpochStorePruner,
1108 object_retention: ObjectRetention,
1111
1112 historic_bucket_expiry: watch::Sender<EpochId>,
1115 historic_bucket_work_stopped: Arc<AtomicBool>,
1117
1118 pub config: NodeConfig,
1119
1120 pub overload_info: AuthorityOverloadInfo,
1122
1123 pub validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
1124
1125 chain_identifier: ChainIdentifier,
1128
1129 pub(crate) congestion_tracker: Arc<CongestionTracker>,
1130
1131 pub traffic_controller: Option<Arc<TrafficController>>,
1133 epoch_end_db_snapshots: Option<EpochEndDbSnapshotHandle>,
1136}
1137
1138struct ValidationOutputs<'a> {
1141 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
1142 move_authenticators: Vec<&'a MoveAuthenticator>,
1143 gas_status: IotaGasStatus,
1144 tx_checked_input_objects: CheckedInputObjects,
1145 per_authenticator_checked_inputs: Vec<(CheckedInputObjects, AuthenticatorFunctionRef)>,
1146}
1147
1148impl AuthorityState {
1157 pub fn is_committee_validator(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1158 epoch_store.committee().authority_exists(&self.name)
1159 }
1160
1161 pub fn is_active_validator(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1162 epoch_store
1163 .active_validators()
1164 .iter()
1165 .any(|a| AuthorityName::from(a) == self.name)
1166 }
1167
1168 pub fn is_fullnode(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1169 !self.is_committee_validator(epoch_store)
1170 }
1171
1172 pub fn committee_store(&self) -> &Arc<CommitteeStore> {
1173 &self.committee_store
1174 }
1175
1176 pub fn clone_committee_store(&self) -> Arc<CommitteeStore> {
1177 self.committee_store.clone()
1178 }
1179
1180 pub fn overload_config(&self) -> &AuthorityOverloadConfig {
1181 &self.config.authority_overload_config
1182 }
1183
1184 pub fn get_epoch_state_commitments(
1185 &self,
1186 epoch: EpochId,
1187 ) -> IotaResult<Option<Vec<CheckpointCommitment>>> {
1188 self.checkpoint_store.get_epoch_state_commitments(epoch)
1189 }
1190
1191 #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1213 pub(crate) async fn handle_transaction_validation_checks(
1214 &self,
1215 transaction: &VerifiedTransaction,
1216 epoch_store: &Arc<AuthorityPerEpochStore>,
1217 deny_config: &dyn DenyRuleConfig,
1218 ) -> IotaResult<Vec<ObjectReference>> {
1219 let protocol_config = epoch_store.protocol_config();
1220 let tx = transaction.data().transaction();
1221
1222 let ValidationOutputs {
1223 move_authenticators,
1224 gas_status,
1225 tx_checked_input_objects,
1226 per_authenticator_checked_inputs,
1227 per_authenticator_inputs: _,
1228 } = self.run_validation_checks(transaction, epoch_store, deny_config, false)?;
1229
1230 let (_, signer, gas_data) = tx.execution_parts();
1231
1232 let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) =
1233 extract_auth_fun_refs(signer, gas_data.owner, |address| {
1234 move_authenticators
1235 .iter()
1236 .zip(per_authenticator_checked_inputs.iter())
1237 .find(|(move_authenticator, _)| move_authenticator.address() == address)
1238 .map(|(_, (_, auth_fun_ref))| auth_fun_ref.clone())
1239 });
1240
1241 let pre_consensus_move_authenticators =
1246 pre_consensus_move_authenticators(transaction, protocol_config);
1247 debug_assert_eq!(
1250 move_authenticators.len(),
1251 per_authenticator_checked_inputs.len(),
1252 "Move authenticators amount must match the number of checked authenticator inputs"
1253 );
1254 let (move_authenticators, per_authenticator_checked_inputs): (Vec<_>, Vec<_>) =
1255 move_authenticators
1256 .into_iter()
1257 .zip(per_authenticator_checked_inputs)
1258 .filter(|(a, _)| pre_consensus_move_authenticators.contains(a))
1259 .unzip();
1260 if !move_authenticators.is_empty() {
1263 let authenticators = move_authenticators
1264 .into_iter()
1265 .zip(per_authenticator_checked_inputs)
1266 .map(
1267 |(
1268 move_authenticator,
1269 (authenticator_checked_input_objects, authenticator_function_ref),
1270 )| {
1271 (
1272 move_authenticator.to_owned(),
1273 authenticator_function_ref,
1274 authenticator_checked_input_objects,
1275 )
1276 },
1277 )
1278 .collect();
1279 self.authenticate_before_consensus(
1280 epoch_store,
1281 transaction,
1282 gas_status,
1283 authenticators,
1284 (
1285 sender_authenticator_function_ref,
1286 sponsor_authenticator_function_ref,
1287 ),
1288 )?;
1289 }
1290
1291 Ok(tx_checked_input_objects.inner().filter_owned_objects())
1292 }
1293
1294 fn authenticate_before_consensus(
1299 &self,
1300 epoch_store: &Arc<AuthorityPerEpochStore>,
1301 transaction: &VerifiedTransaction,
1302 gas_status: IotaGasStatus,
1303 authenticators: Vec<(
1304 MoveAuthenticator,
1305 AuthenticatorFunctionRef,
1306 CheckedInputObjects,
1307 )>,
1308 function_refs: (
1309 Option<AuthenticatorFunctionRef>,
1310 Option<AuthenticatorFunctionRef>,
1311 ),
1312 ) -> IotaResult<()> {
1313 let tx = transaction.data().transaction();
1314 let (kind, signer, gas_data) = tx.execution_parts();
1315 let input_objects: Vec<_> = authenticators
1316 .iter()
1317 .map(|(_, _, input_objects)| input_objects)
1318 .collect();
1319 let aggregated_authenticator_input_objects =
1320 iota_transaction_checks::aggregate_authenticator_input_objects(&input_objects)?;
1321 let (sender_auth_digest, sponsor_auth_digest) =
1322 transaction.data().compute_auth_digests()?;
1323 let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) = function_refs;
1324 let auth_context_data = AuthContextData {
1325 transaction_data_bytes: bcs::to_bytes(tx)
1326 .expect("Transaction serialization cannot fail"),
1327 sender_auth_digest,
1328 sponsor_auth_digest,
1329 sender_authenticator_function_ref,
1330 sponsor_authenticator_function_ref,
1331 };
1332
1333 let (_gas_status, result) = epoch_store.executor().authenticate_transaction(
1334 self.get_backing_store().as_ref(),
1335 epoch_store.protocol_config(),
1336 self.metrics.limits_metrics.clone(),
1337 &epoch_store.epoch_start_config().epoch_data().epoch_id(),
1338 epoch_store
1339 .epoch_start_config()
1340 .epoch_data()
1341 .epoch_start_timestamp(),
1342 gas_data,
1343 gas_status,
1344 authenticators,
1345 aggregated_authenticator_input_objects,
1346 kind,
1347 signer,
1348 transaction.digest().to_owned(),
1349 auth_context_data,
1350 &mut None,
1351 );
1352 result.map_err(|error| IotaError::MoveAuthenticatorExecutionFailure {
1353 error: error.to_string(),
1354 })
1355 }
1356
1357 #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1378 pub(crate) fn handle_transaction_validation_checks_at_commit(
1379 &self,
1380 reader: &CommitIndexedReader,
1381 transaction: &VerifiedTransaction,
1382 epoch_store: &Arc<AuthorityPerEpochStore>,
1383 deny_config: &dyn DenyRuleConfig,
1384 verifier_limits_source: VerifierLimitsSource<'_>,
1385 attested: bool,
1386 ) -> IotaResult<ValidationAtCommit> {
1387 let protocol_config = epoch_store.protocol_config();
1388 let reference_gas_price = epoch_store.reference_gas_price();
1389
1390 let tx = transaction.data().transaction();
1391
1392 let (tx_input_objects, tx_receiving_objects, per_authenticator_inputs) = match self
1393 .read_objects_for_validation_at_commit(reader, transaction, protocol_config)?
1394 {
1395 ValidationInputsAtCommit::Loaded {
1396 tx_input_objects,
1397 tx_receiving_objects,
1398 per_authenticator_inputs,
1399 } => (
1400 tx_input_objects,
1401 tx_receiving_objects,
1402 per_authenticator_inputs,
1403 ),
1404 ValidationInputsAtCommit::Drop(kind, reason) => {
1405 return Ok(ValidationAtCommit::Drop(kind, reason));
1406 }
1407 ValidationInputsAtCommit::Missing(kind, reason) => {
1408 return Ok(ValidationAtCommit::Missing(kind, reason));
1409 }
1410 };
1411
1412 iota_transaction_checks::deny::check_transaction_for_validation(
1417 tx,
1418 transaction.signatures(),
1419 &transaction
1420 .input_objects(protocol_config.move_authenticator_type_arg_packages_as_inputs())?,
1421 &tx.receiving_objects(),
1422 deny_config,
1423 reader,
1424 )?;
1425
1426 let move_authenticators = transaction.move_authenticators();
1427
1428 let (tx_checked_input_objects, per_authenticator_checked_inputs) = if attested {
1440 self.check_attested_transaction_inputs_at_commit(
1441 protocol_config,
1442 reference_gas_price,
1443 tx,
1444 tx_input_objects,
1445 &tx_receiving_objects,
1446 &move_authenticators,
1447 per_authenticator_inputs,
1448 )?
1449 } else {
1450 self.check_transaction_inputs_at_commit(
1451 protocol_config,
1452 reference_gas_price,
1453 tx,
1454 tx_input_objects,
1455 &tx_receiving_objects,
1456 &move_authenticators,
1457 per_authenticator_inputs,
1458 verifier_limits_source,
1459 )?
1460 };
1461
1462 let per_authenticator_checked_input_objects =
1463 per_authenticator_checked_inputs.iter().collect::<Vec<_>>();
1464
1465 debug_assert!(
1466 per_authenticator_checked_input_objects
1467 .iter()
1468 .all(|objects| objects.inner().filter_owned_objects().is_empty()),
1469 "Move authenticator input objects must not contain owned objects"
1470 );
1471
1472 let accounts = move_authenticators
1476 .iter()
1477 .map(|move_authenticator| {
1478 let account_kind = move_authenticator
1479 .object_to_authenticate()
1480 .input_object_kind()
1481 .expect("the object to authenticate is validated before consensus");
1482 Ok((account_kind, reader.read_account(account_kind.object_id())?))
1483 })
1484 .collect::<IotaResult<Vec<_>>>()?;
1485
1486 if protocol_config.deny_authenticator_packages() && deny_config.has_denied_packages() {
1490 let mut function_refs = Vec::new();
1491 for (account_kind, verdict) in &accounts {
1492 if let AccountVerdict::Account(field) = verdict {
1493 function_refs.extend(
1494 reader
1495 .visible_authenticator_function_ref(account_kind.object_id(), field)?,
1496 );
1497 }
1498 }
1499 if let Err(error) = iota_transaction_checks::deny::check_authenticator_packages(
1500 deny_config,
1501 &function_refs,
1502 reader,
1503 ) {
1504 if error.is_storage_or_epoch_error() {
1505 return Err(error);
1506 }
1507 return Ok(ValidationAtCommit::AuthenticatorPackageDenied(error));
1508 }
1509 }
1510
1511 let mut shared_objects = Vec::new();
1519 for input in tx_checked_input_objects.inner().iter().chain(
1520 per_authenticator_checked_input_objects
1521 .iter()
1522 .flat_map(|objects| objects.inner().iter()),
1523 ) {
1524 if let (
1525 InputObjectKind::SharedMoveObject {
1526 id,
1527 initial_shared_version,
1528 ..
1529 },
1530 None,
1531 ) = (input.input_object_kind, input.as_object())
1532 {
1533 shared_objects
1534 .push(reader.read_shared_object_for_type(id, initial_shared_version)?);
1535 }
1536 }
1537 let coin_types = coin_types_for_denylist_check(
1538 tx_checked_input_objects
1539 .inner()
1540 .iter_objects()
1541 .chain(
1542 per_authenticator_checked_input_objects
1543 .iter()
1544 .flat_map(|objects| objects.inner().iter_objects()),
1545 )
1546 .chain(&shared_objects)
1547 .chain(tx_receiving_objects.iter_objects()),
1548 );
1549 if let Some(denial) = DenyListAtCommit::new(reader).denial(tx.sender(), coin_types)? {
1550 return Err(denial.into());
1551 }
1552
1553 for (account_kind, verdict) in accounts {
1556 if let AccountVerdict::Missing(reason) = verdict {
1557 return Ok(ValidationAtCommit::Missing(account_kind, reason));
1558 }
1559 }
1560
1561 Ok(ValidationAtCommit::Keep(
1562 tx_checked_input_objects.inner().filter_owned_objects(),
1563 ))
1564 }
1565
1566 async fn handle_transaction_impl(
1570 &self,
1571 transaction: VerifiedTransaction,
1572 epoch_store: &Arc<AuthorityPerEpochStore>,
1573 ) -> IotaResult<VerifiedSignedTransaction> {
1574 let _execution_lock = self.execution_lock_for_signing()?;
1576
1577 let owned_objects = self
1578 .handle_transaction_validation_checks(
1579 &transaction,
1580 epoch_store,
1581 &self.config.transaction_deny_config,
1582 )
1583 .await?;
1584
1585 let epoch = epoch_store.epoch();
1586 let signed_transaction =
1587 VerifiedSignedTransaction::new(epoch, transaction, self.name, &*self.secret);
1588
1589 self.get_cache_writer().try_acquire_transaction_locks(
1594 epoch_store,
1595 &owned_objects,
1596 signed_transaction.clone(),
1597 )?;
1598
1599 Ok(signed_transaction)
1600 }
1601
1602 #[instrument(name = "handle_transaction", level = "trace", skip_all, fields(tx_digest = ?transaction.digest(), sender = transaction.data().transaction().gas_owner().to_string()
1604 ))]
1605 pub async fn handle_transaction(
1606 &self,
1607 epoch_store: &Arc<AuthorityPerEpochStore>,
1608 transaction: VerifiedTransaction,
1609 ) -> IotaResult<HandleTransactionResponse> {
1610 let tx_digest = *transaction.digest();
1611 debug!("handle_transaction");
1612
1613 if let Some((_, status)) = self.get_transaction_status(&tx_digest, epoch_store)? {
1615 return Ok(HandleTransactionResponse { status });
1616 }
1617
1618 let _metrics_guard = self
1619 .metrics
1620 .authority_state_handle_transaction_latency
1621 .start_timer();
1622 self.metrics.tx_orders.inc();
1623
1624 let signed = self.handle_transaction_impl(transaction, epoch_store).await;
1625 match signed {
1626 Ok(s) => {
1627 if self.is_committee_validator(epoch_store) {
1628 if let Some(validator_tx_finalizer) = &self.validator_tx_finalizer {
1629 let tx = s.clone();
1630 let validator_tx_finalizer = validator_tx_finalizer.clone();
1631 let cache_reader = self.get_transaction_cache_reader().clone();
1632 let epoch_store = epoch_store.clone();
1633 spawn_monitored_task!(epoch_store.within_alive_epoch(
1634 validator_tx_finalizer.track_signed_tx(cache_reader, &epoch_store, tx)
1635 ));
1636 }
1637 }
1638 Ok(HandleTransactionResponse {
1639 status: TransactionStatus::Signed(s.into_inner().into_sig()),
1640 })
1641 }
1642 Err(err) => Ok(HandleTransactionResponse {
1646 status: self
1647 .get_transaction_status(&tx_digest, epoch_store)?
1648 .ok_or(err)?
1649 .1,
1650 }),
1651 }
1652 }
1653
1654 pub fn check_system_overload_at_signing(&self) -> bool {
1655 self.config
1656 .authority_overload_config
1657 .check_system_overload_at_signing
1658 }
1659
1660 pub fn check_system_overload_at_execution(&self) -> bool {
1661 self.config
1662 .authority_overload_config
1663 .check_system_overload_at_execution
1664 }
1665
1666 pub(crate) fn check_system_overload(
1676 &self,
1677 consensus_adapter: &Arc<ConsensusAdapter>,
1678 tx: &SenderSignedTransaction,
1679 do_authority_overload_check: bool,
1680 pcool_flow_enabled: bool,
1681 ) -> IotaResult {
1682 if pcool_flow_enabled {
1683 self.check_consensus_queue_graduated_limits(consensus_adapter, tx)
1686 .tap_err(|_| {
1687 self.update_overload_metrics("consensus");
1688 })?;
1689
1690 consensus_adapter.check_consensus_overload().tap_err(|_| {
1697 self.update_overload_metrics("consensus");
1698 })?;
1699 } else {
1700 if do_authority_overload_check {
1701 self.check_authority_overload(tx).tap_err(|_| {
1702 self.update_overload_metrics("execution_queue");
1703 })?;
1704 }
1705 self.execution_scheduler
1706 .check_execution_overload(self.overload_config(), tx)
1707 .tap_err(|_| {
1708 self.update_overload_metrics("execution_pending");
1709 })?;
1710 consensus_adapter.check_consensus_overload().tap_err(|_| {
1711 self.update_overload_metrics("consensus");
1712 })?;
1713
1714 let pending_tx_count = self
1715 .get_cache_commit()
1716 .approximate_pending_transaction_count();
1717 if pending_tx_count
1718 > self
1719 .config
1720 .execution_cache_config
1721 .writeback_cache
1722 .backpressure_threshold_for_rpc()
1723 {
1724 return Err(IotaError::ValidatorOverloadedRetryAfter {
1725 retry_after_secs: 10,
1726 });
1727 }
1728 }
1729
1730 Ok(())
1731 }
1732
1733 fn check_consensus_queue_graduated_limits(
1741 &self,
1742 consensus_adapter: &Arc<ConsensusAdapter>,
1743 tx: &SenderSignedTransaction,
1744 ) -> IotaResult {
1745 let num_inflight_txs = consensus_adapter.num_inflight_transactions() as usize;
1746
1747 let shedding_pct = compute_graduated_load_shedding_percentage(
1748 num_inflight_txs,
1749 consensus_adapter.max_pending_transactions(),
1750 consensus_adapter.graduated_load_shedding_soft_limit_pct(),
1751 );
1752
1753 self.metrics
1754 .consensus_queue_load_shedding_percentage
1755 .set(shedding_pct as i64);
1756
1757 if shedding_pct == 0 {
1758 return Ok(());
1759 }
1760
1761 if shedding_pct >= 100 {
1766 return Err(IotaError::TooManyTransactionsPendingConsensus);
1767 }
1768
1769 overload_monitor_accept_tx(shedding_pct, tx.digest())
1770 }
1771
1772 fn check_authority_overload(&self, tx: &SenderSignedTransaction) -> IotaResult {
1773 if !self.overload_info.is_overload.load(Ordering::Relaxed) {
1774 return Ok(());
1775 }
1776
1777 let load_shedding_percentage = self
1778 .overload_info
1779 .local_load_shedding_percentage
1780 .load(Ordering::Relaxed);
1781 overload_monitor_accept_tx(load_shedding_percentage, tx.digest())
1782 }
1783
1784 fn update_overload_metrics(&self, source: &str) {
1785 self.metrics
1786 .transaction_overload_sources
1787 .with_label_values(&[source])
1788 .inc();
1789 }
1790
1791 #[instrument(level = "trace", skip_all)]
1796 pub async fn wait_for_certificate_execution(
1797 &self,
1798 certificate: &VerifiedCertificate,
1799 epoch_store: &Arc<AuthorityPerEpochStore>,
1800 ) -> IotaResult<TransactionEffects> {
1801 let _metrics_guard = if certificate.contains_shared_object() {
1802 self.metrics
1803 .execute_certificate_latency_shared_object
1804 .start_timer()
1805 } else {
1806 self.metrics
1807 .execute_certificate_latency_single_writer
1808 .start_timer()
1809 };
1810 trace!("wait_for_certificate_execution");
1811
1812 self.metrics.total_cert_attempts.inc();
1813
1814 if !certificate.contains_shared_object() {
1815 self.execution_scheduler.enqueue(
1820 vec![(
1821 Schedulable::Transaction(VerifiedExecutableTransaction::new_from_certificate(
1822 certificate.clone(),
1823 )),
1824 ExecutionEnv::new(),
1825 )],
1826 epoch_store,
1827 );
1828 }
1829
1830 epoch_store
1833 .within_alive_epoch(self.notify_read_effects(
1834 "AuthorityState::wait_for_certificate_execution",
1835 certificate,
1836 ))
1837 .await
1838 .and_then(|r| r)
1839 }
1840
1841 #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1855 pub fn try_execute_immediately(
1856 &self,
1857 transaction: &VerifiedExecutableTransaction,
1858 execution_env: ExecutionEnv,
1859 epoch_store: &Arc<AuthorityPerEpochStore>,
1860 ) -> IotaResult<(TransactionEffects, Option<ExecutionError>)> {
1861 let _scope = monitored_scope("Execution::try_execute_immediately");
1862 let _metrics_guard = self.metrics.internal_execution_latency.start_timer();
1863
1864 let tx_digest = transaction.digest();
1865
1866 let tx_guard = epoch_store.acquire_tx_guard(transaction)?;
1868
1869 if let Some(effects) = self
1872 .get_transaction_cache_reader()
1873 .try_get_executed_effects(tx_digest)?
1874 {
1875 if let Some(expected_effects_digest_inner) = execution_env.expected_effects_digest {
1876 assert_eq!(
1877 effects.digest(),
1878 expected_effects_digest_inner,
1879 "Unexpected effects digest for transaction {tx_digest}"
1880 );
1881 }
1882 tx_guard.release();
1883 return Ok((effects, None));
1884 }
1885
1886 let (tx_input_objects, per_authenticator_inputs) = self.read_objects_for_execution(
1887 tx_guard.as_lock_guard(),
1888 transaction,
1889 execution_env.assigned_versions,
1890 epoch_store,
1891 )?;
1892
1893 self.process_transaction(
1894 tx_guard,
1895 transaction,
1896 tx_input_objects,
1897 per_authenticator_inputs,
1898 execution_env.expected_effects_digest,
1899 &execution_env.attestation,
1900 epoch_store,
1901 )
1902 .tap_err(|e| info!(?tx_digest, "process_transaction failed: {e}"))
1903 .tap_ok(
1904 |(fx, _)| debug!(?tx_digest, fx_digest=?fx.digest(), "process_transaction succeeded"),
1905 )
1906 }
1907
1908 pub fn read_objects_for_execution(
1909 &self,
1910 tx_lock: &TxLockGuard,
1911 transaction: &VerifiedExecutableTransaction,
1912 assigned_shared_object_versions: AssignedVersions,
1913 epoch_store: &Arc<AuthorityPerEpochStore>,
1914 ) -> IotaResult<(InputObjects, Vec<(InputObjects, ObjectReadResult)>)> {
1915 let _scope = monitored_scope("Execution::load_input_objects");
1916 let _metrics_guard = self
1917 .metrics
1918 .execution_load_input_objects_latency
1919 .start_timer();
1920
1921 let input_objects = transaction.collect_all_input_object_kind_for_reading(
1922 epoch_store
1923 .protocol_config()
1924 .move_authenticator_type_arg_packages_as_inputs(),
1925 )?;
1926
1927 let input_objects = self.input_loader.read_objects_for_execution(
1928 &transaction.key(),
1929 tx_lock,
1930 &input_objects,
1931 &assigned_shared_object_versions,
1932 epoch_store.epoch(),
1933 )?;
1934
1935 transaction.split_input_objects_into_groups_for_reading(input_objects)
1936 }
1937
1938 pub fn try_execute_for_test(
1945 &self,
1946 certificate: &VerifiedCertificate,
1947 execution_env: ExecutionEnv,
1948 ) -> IotaResult<(VerifiedSignedTransactionEffects, Option<ExecutionError>)> {
1949 let epoch_store = self.epoch_store_for_testing();
1950 epoch_store.assign_to_a_new_commit_for_testing(&[certificate.key()]);
1951 let (effects, execution_error_opt) = self.try_execute_immediately(
1952 &VerifiedExecutableTransaction::new_from_certificate(certificate.clone()),
1953 execution_env,
1954 &epoch_store,
1955 )?;
1956 let signed_effects = self.sign_effects(effects, &epoch_store)?;
1957 Ok((signed_effects, execution_error_opt))
1958 }
1959
1960 pub fn execute_for_test(
1962 &self,
1963 certificate: &VerifiedCertificate,
1964 execution_env: ExecutionEnv,
1965 ) -> (VerifiedSignedTransactionEffects, Option<ExecutionError>) {
1966 self.try_execute_for_test(certificate, execution_env)
1967 .expect("try_execute_for_test should not fail")
1968 }
1969
1970 pub async fn notify_read_effects(
1971 &self,
1972 task_name: &'static str,
1973 certificate: &VerifiedCertificate,
1974 ) -> IotaResult<TransactionEffects> {
1975 self.get_transaction_cache_reader()
1976 .try_notify_read_executed_effects(task_name, &[*certificate.digest()])
1977 .await
1978 .map(|mut r| r.pop().expect("must return correct number of effects"))
1979 }
1980
1981 fn check_owned_locks(&self, owned_object_refs: &[ObjectReference]) -> IotaResult {
1982 self.get_object_cache_reader()
1983 .try_check_owned_objects_are_live(owned_object_refs)
1984 }
1985
1986 pub(crate) fn debug_dump_transaction_state(
1991 &self,
1992 tx_digest: &TransactionDigest,
1993 effects: &TransactionEffects,
1994 expected_effects_digest: TransactionEffectsDigest,
1995 inner_temporary_store: &InnerTemporaryStore,
1996 transaction: &VerifiedExecutableTransaction,
1997 debug_dump_config: &StateDebugDumpConfig,
1998 ) -> IotaResult<PathBuf> {
1999 let dump_dir = debug_dump_config
2002 .dump_file_directory
2003 .as_ref()
2004 .cloned()
2005 .unwrap_or(std::env::temp_dir());
2006 let epoch_store = self.load_epoch_store_one_call_per_task();
2007
2008 NodeStateDump::new(
2009 tx_digest,
2010 effects,
2011 expected_effects_digest,
2012 self.get_object_store().as_ref(),
2013 &epoch_store,
2014 inner_temporary_store,
2015 transaction,
2016 )?
2017 .write_to_file(&dump_dir)
2018 .map_err(|e| IotaError::FileIO(e.to_string()))
2019 }
2020
2021 #[instrument(name = "process_certificate", level = "trace", skip_all, fields(tx_digest = ?transaction.digest(), sender = ?transaction.data().transaction().gas_owner().to_string()))]
2022 pub(crate) fn process_transaction(
2023 &self,
2024 tx_guard: TxGuard,
2025 transaction: &VerifiedExecutableTransaction,
2026 tx_input_objects: InputObjects,
2027 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
2028 expected_effects_digest: Option<TransactionEffectsDigest>,
2029 attestation: &AttestationSource,
2030 epoch_store: &Arc<AuthorityPerEpochStore>,
2031 ) -> IotaResult<(TransactionEffects, Option<ExecutionError>)> {
2032 let process_transaction_start_time = tokio::time::Instant::now();
2033 let digest = *transaction.digest();
2034
2035 let _scope = monitored_scope("Execution::process_certificate");
2036
2037 fail_point_if!("correlated-crash-process-transaction", || {
2038 if iota_simulator::random::deterministic_probability_once(digest, 0.01) {
2039 iota_simulator::task::kill_current_node(None);
2040 }
2041 });
2042
2043 let execution_guard = self.execution_lock_for_executable_transaction(transaction);
2044 let execution_guard = match execution_guard {
2050 Ok(execution_guard) => execution_guard,
2051 Err(err) => {
2052 tx_guard.release();
2053 return Err(err);
2054 }
2055 };
2056 if *execution_guard != epoch_store.epoch() {
2060 tx_guard.release();
2061 info!("The epoch of the execution_guard doesn't match the epoch store");
2062 return Err(IotaError::WrongEpoch {
2063 expected_epoch: epoch_store.epoch(),
2064 actual_epoch: *execution_guard,
2065 });
2066 }
2067
2068 let (inner_temporary_store, effects, execution_error_opt, read_objects, attestation_record) =
2074 match self.execute_transaction(
2075 &execution_guard,
2076 transaction,
2077 tx_input_objects,
2078 per_authenticator_inputs,
2079 attestation,
2080 epoch_store,
2081 ) {
2082 Err(e) => {
2083 info!(name = ?self.name, ?digest, "Error preparing transaction: {e}");
2084 tx_guard.release();
2085 return Err(e);
2086 }
2087 Ok(res) => res,
2088 };
2089
2090 if let Some(expected_effects_digest) = expected_effects_digest {
2091 if effects.digest() != expected_effects_digest {
2092 match self.debug_dump_transaction_state(
2094 &digest,
2095 &effects,
2096 expected_effects_digest,
2097 &inner_temporary_store,
2098 transaction,
2099 &self.config.state_debug_dump_config,
2100 ) {
2101 Ok(out_path) => {
2102 info!(
2103 "Dumped node state for transaction {} to {}",
2104 digest,
2105 out_path.as_path().display().to_string()
2106 );
2107 }
2108 Err(e) => {
2109 error!("Error dumping state for transaction {}: {e}", digest);
2110 }
2111 }
2112 error!(
2113 tx_digest = ?digest,
2114 ?expected_effects_digest,
2115 actual_effects = ?effects,
2116 "fork detected!"
2117 );
2118 panic!(
2119 "Transaction {} is expected to have effects digest {}, but got {}!",
2120 digest,
2121 expected_effects_digest,
2122 effects.digest(),
2123 );
2124 }
2125 }
2126
2127 fail_point!("crash");
2128
2129 self.commit_transaction(
2130 transaction,
2131 inner_temporary_store,
2132 &effects,
2133 read_objects,
2134 attestation_record,
2135 tx_guard,
2136 execution_guard,
2137 expected_effects_digest,
2138 epoch_store,
2139 )?;
2140
2141 let elapsed = process_transaction_start_time.elapsed().as_micros() as f64;
2142 if elapsed > 0.0 {
2143 self.metrics
2144 .execution_gas_latency_ratio
2145 .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed);
2146 };
2147 Ok((effects, execution_error_opt))
2148 }
2149
2150 pub async fn reconfigure_traffic_control(
2151 &self,
2152 params: TrafficControlReconfigParams,
2153 ) -> Result<TrafficControlReconfigParams, IotaError> {
2154 if let Some(traffic_controller) = self.traffic_controller.as_ref() {
2155 traffic_controller.admin_reconfigure(params)
2156 } else {
2157 Err(IotaError::InvalidAdminRequest(
2158 "Traffic controller is not configured on this node".to_string(),
2159 ))
2160 }
2161 }
2162
2163 #[instrument(level = "trace", skip_all)]
2164 fn commit_transaction(
2165 &self,
2166 transaction: &VerifiedExecutableTransaction,
2167 inner_temporary_store: InnerTemporaryStore,
2168 effects: &TransactionEffects,
2169 read_objects: ObjectSet,
2170 attestation_record: Option<AttestationRecord>,
2171 tx_guard: TxGuard,
2172 _execution_guard: ExecutionLockReadGuard<'_>,
2173 expected_effects_digest: Option<TransactionEffectsDigest>,
2174 epoch_store: &Arc<AuthorityPerEpochStore>,
2175 ) -> IotaResult {
2176 let _scope: Option<iota_metrics::MonitoredScopeGuard> =
2177 monitored_scope("Execution::commit_certificate");
2178 let _metrics_guard = self.metrics.commit_certificate_latency.start_timer();
2179
2180 let tx_digest = transaction.digest();
2181 let input_object_count = inner_temporary_store.input_objects.len();
2182 let shared_object_count = effects.input_shared_objects().len();
2183
2184 let output_keys = inner_temporary_store.get_output_keys(effects);
2185
2186 epoch_store.insert_executed_in_epoch(tx_digest);
2190
2191 let key = transaction.key();
2192 if !matches!(key, TransactionKey::Digest(_)) {
2193 epoch_store.insert_tx_key(key, *tx_digest)?;
2194 }
2195
2196 if epoch_store.pcool_bookkeeping_enabled()
2205 && !transaction.transaction().is_genesis_tx()
2206 && !transaction.transaction().is_end_of_epoch_tx()
2207 {
2208 epoch_store.record_executed_transaction(&key, effects);
2209 }
2210
2211 fail_point!("crash");
2213
2214 let transaction_outputs = TransactionOutputs::build_transaction_outputs(
2215 transaction.clone().into_unsigned(),
2216 effects.clone(),
2217 inner_temporary_store,
2218 read_objects,
2219 &self.metrics,
2220 epoch_store.protocol_config().enable_validator_attestation(),
2221 attestation_record,
2222 );
2223 self.get_cache_writer()
2224 .try_write_transaction_outputs(epoch_store.epoch(), transaction_outputs.into())?;
2225
2226 self.report_failed_deny_rule_update_execution(
2227 transaction,
2228 effects,
2229 expected_effects_digest,
2230 epoch_store,
2231 );
2232
2233 if transaction.transaction().is_end_of_epoch_tx() {
2234 self.get_object_cache_reader()
2237 .force_reload_system_packages(&BuiltInFramework::all_package_ids());
2238 }
2239
2240 tx_guard.commit_tx();
2242
2243 match self.execution_scheduler.as_ref() {
2244 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
2245 ExecutionSchedulerWrapper::TransactionManager(tm) => {
2246 tm.notify_commit(tx_digest, output_keys, epoch_store);
2250 if let Some(key) = transaction.non_digest_key() {
2256 tm.notify_transaction_key(epoch_store, key, *tx_digest);
2257 }
2258 }
2259 }
2260
2261 self.update_metrics(transaction, input_object_count, shared_object_count);
2262
2263 Ok(())
2264 }
2265
2266 fn update_metrics(
2267 &self,
2268 transaction: &VerifiedExecutableTransaction,
2269 input_object_count: usize,
2270 shared_object_count: usize,
2271 ) {
2272 if transaction.has_multisig() {
2274 self.metrics.multisig_sig_count.inc();
2275 }
2276
2277 self.metrics.total_effects.inc();
2278 self.metrics.total_certs.inc();
2279
2280 if shared_object_count > 0 {
2281 self.metrics.shared_obj_tx.inc();
2282 }
2283
2284 if transaction.is_sponsored_tx() {
2285 self.metrics.sponsored_tx.inc();
2286 }
2287
2288 self.metrics
2289 .num_input_objs
2290 .observe(input_object_count as f64);
2291 self.metrics
2292 .num_shared_objects
2293 .observe(shared_object_count as f64);
2294 self.metrics
2295 .batch_size
2296 .observe(transaction.data().transaction().kind().num_commands() as f64);
2297 }
2298
2299 #[instrument(level = "trace", skip_all)]
2311 fn execute_transaction(
2312 &self,
2313 _execution_guard: &ExecutionLockReadGuard<'_>,
2314 transaction: &VerifiedExecutableTransaction,
2315 tx_input_objects: InputObjects,
2316 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
2317 attestation: &AttestationSource,
2318 epoch_store: &Arc<AuthorityPerEpochStore>,
2319 ) -> IotaResult<TransactionExecutionResult> {
2320 let _scope = monitored_scope("Execution::execute_certificate");
2321 let _metrics_guard = self.metrics.prepare_certificate_latency.start_timer();
2322 let prepare_transaction_start_time = tokio::time::Instant::now();
2323
2324 let protocol_config = epoch_store.protocol_config();
2325
2326 let reference_gas_price = epoch_store.reference_gas_price();
2327
2328 let epoch_id = epoch_store.epoch_start_config().epoch_data().epoch_id();
2329 let epoch_start_timestamp = epoch_store
2330 .epoch_start_config()
2331 .epoch_data()
2332 .epoch_start_timestamp();
2333
2334 let tracking_store = TrackingBackingStore::new(self.get_backing_store().as_ref());
2335 let backing_store = &tracking_store;
2336
2337 let tx_digest = *transaction.digest();
2338
2339 let tx = transaction.data().transaction();
2342 tx.validity_check(protocol_config)?;
2343
2344 let (kind, signer, gas_data) = tx.execution_parts();
2349
2350 let move_authenticators = transaction.move_authenticators();
2351
2352 #[cfg_attr(not(any(msim, fail_points)), expect(unused_mut))]
2353 let (inner_temp_store, mut effects, execution_error, outcome) = if move_authenticators
2354 .is_empty()
2355 {
2356 let (tx_gas_status, tx_checked_input_objects) =
2361 iota_transaction_checks::check_certificate_input(
2362 transaction,
2363 tx_input_objects,
2364 protocol_config,
2365 reference_gas_price,
2366 )?;
2367
2368 let owned_object_refs = tx_checked_input_objects.inner().filter_owned_objects();
2369 self.check_owned_locks(&owned_object_refs)?;
2370 let (inner_temp_store, _gas_status, effects, _timings, execution_error_opt) =
2371 epoch_store.executor().execute_transaction_to_effects(
2372 backing_store,
2373 protocol_config,
2374 self.metrics.limits_metrics.clone(),
2375 self.config
2378 .expensive_safety_check_config
2379 .enable_deep_per_tx_iota_conservation_check(),
2380 self.config.certificate_deny_config.certificate_deny_set(),
2381 &epoch_id,
2382 epoch_start_timestamp,
2383 tx_checked_input_objects,
2384 gas_data,
2385 tx_gas_status,
2386 kind,
2387 signer,
2388 tx_digest,
2389 &mut None,
2390 );
2391 let outcome = attestation_verdict::ExecutionOutcome {
2393 blame: None,
2394 consumed_units: 0,
2395 body_ran: attestation_verdict::body_ran(false, execution_error_opt.as_ref().err()),
2396 };
2397 (inner_temp_store, effects, execution_error_opt, outcome)
2398 } else {
2399 debug_assert_eq!(
2405 move_authenticators.len(),
2406 per_authenticator_inputs.len(),
2407 "Move authenticators amount must match the number of authenticator inputs"
2408 );
2409
2410 let mut per_authenticator_input_objects = Vec::with_capacity(move_authenticators.len());
2414 let mut resolutions = Vec::with_capacity(move_authenticators.len());
2415 for (move_authenticator, (authenticator_input_objects, account_object)) in
2416 move_authenticators.iter().zip(per_authenticator_inputs)
2417 {
2418 let (account_object_id, account_object_version, account_object_digest) =
2422 move_authenticator
2423 .object_to_authenticate_components()
2424 .expect(
2425 "the object to authenticate is validated before consensus and cannot \
2426 be invalid during execution",
2427 );
2428
2429 resolutions.push(self.check_move_account_for_execution(
2434 account_object_id,
2435 account_object_version,
2436 account_object_digest,
2437 account_object,
2438 &move_authenticator.address(),
2439 protocol_config,
2440 ));
2441
2442 per_authenticator_input_objects.push(authenticator_input_objects);
2443 }
2444
2445 let tx_bytes = bcs::to_bytes(tx).expect("Transaction serialization cannot fail");
2447
2448 let (sender_auth_digest, sponsor_auth_digest) =
2449 transaction.data().compute_auth_digests()?;
2450
2451 let authenticator_gas_budget = protocol_config.max_auth_gas();
2457 let (
2458 gas_status,
2459 per_authenticator_checked_input_objects,
2460 authenticator_and_tx_checked_input_objects,
2461 ) = iota_transaction_checks::check_certificate_and_move_authenticator_input(
2462 tx,
2463 tx_input_objects,
2464 per_authenticator_input_objects,
2465 None,
2466 authenticator_gas_budget,
2467 protocol_config,
2468 reference_gas_price,
2469 )?;
2470
2471 let owned_object_refs = authenticator_and_tx_checked_input_objects
2472 .inner()
2473 .filter_owned_objects();
2474 self.check_owned_locks(&owned_object_refs)?;
2475
2476 let attestation_verdict_context = match attestation {
2479 AttestationSource::Attestation(attestation) => {
2480 Some(attestation_verdict::AttestationVerdictContext {
2481 attestation,
2482 attested_versions: attestation_verdict::AttestedObjectVersions {
2483 object_cache: self.get_object_cache_reader().as_ref(),
2484 current_epoch: epoch_id,
2485 },
2486 store: backing_store,
2487 executor: epoch_store.executor().as_ref(),
2488 protocol_config,
2489 metrics: self.metrics.limits_metrics.clone(),
2490 epoch_id,
2491 epoch_timestamp_ms: epoch_start_timestamp,
2492 reference_gas_price,
2493 gas_data: gas_data.clone(),
2494 authenticators: attestation_verdict::authenticator_inputs(
2495 &move_authenticators,
2496 &per_authenticator_checked_input_objects,
2497 ),
2498 executed_versions: attestation_verdict::executed_versions(
2499 &per_authenticator_checked_input_objects,
2500 &resolutions,
2501 ),
2502 transaction: tx,
2503 transaction_signer: signer,
2504 transaction_digest: tx_digest,
2505 sender_auth_digest,
2506 sponsor_auth_digest,
2507 })
2508 }
2509 AttestationSource::Unattested | AttestationSource::Certified(_) => None,
2510 };
2511
2512 let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) =
2516 extract_auth_fun_refs(signer, gas_data.owner, |address| {
2517 move_authenticators
2518 .iter()
2519 .zip(&resolutions)
2520 .find(|(move_authenticator, _)| move_authenticator.address() == address)
2521 .and_then(|(_, resolution)| resolution.as_ref().ok())
2522 .map(|function_ref| function_ref.authenticator_function_ref.clone())
2523 });
2524
2525 let accounts = move_authenticators
2526 .iter()
2527 .map(|move_authenticator| move_authenticator.address())
2528 .collect::<Vec<_>>();
2529 debug_assert_eq!(
2530 move_authenticators.len(),
2531 per_authenticator_checked_input_objects.len(),
2532 "Move authenticators amount must match the number of checked authenticator inputs"
2533 );
2534 let pcool_flow = protocol_config.enable_pcool_flow();
2538 let mut first_resolution_error = None;
2539 let mut gas_owner_resolution_error = None;
2540 let mut resolved_authenticators = Vec::with_capacity(move_authenticators.len());
2541 for ((move_authenticator, resolution), authenticator_checked_input_objects) in
2542 move_authenticators
2543 .into_iter()
2544 .zip(resolutions)
2545 .zip(per_authenticator_checked_input_objects)
2546 {
2547 match resolution {
2548 Ok(function_ref) => {
2549 resolved_authenticators.push(MoveAuthenticatorForExecution {
2550 authenticator: move_authenticator.to_owned(),
2551 function_ref,
2552 input_objects: authenticator_checked_input_objects,
2553 })
2554 }
2555 Err(error) if pcool_flow && move_authenticator.address() == gas_data.owner => {
2556 gas_owner_resolution_error = Some(error);
2557 }
2558 Err(error) => {
2559 first_resolution_error.get_or_insert(error);
2560 }
2561 }
2562 }
2563
2564 let auth_context_data = AuthContextData {
2565 transaction_data_bytes: tx_bytes,
2566 sender_auth_digest,
2567 sponsor_auth_digest,
2568 sender_authenticator_function_ref,
2569 sponsor_authenticator_function_ref,
2570 };
2571
2572 let authenticators = match gas_owner_resolution_error.or(first_resolution_error) {
2577 Some(error) => MoveAuthenticatorsForExecution::ResolutionFailed {
2578 error,
2579 accounts,
2580 gas_owner: if pcool_flow {
2581 resolved_authenticators
2582 .into_iter()
2583 .find(|resolved| resolved.authenticator.address() == gas_data.owner)
2584 .map(Box::new)
2585 } else {
2586 None
2587 },
2588 },
2589 None => MoveAuthenticatorsForExecution::Resolved(resolved_authenticators),
2590 };
2591
2592 let blame = Cell::new(None);
2597 let gas_owner_pays = |kind: &ExecutionErrorKind| {
2598 match (attestation, &attestation_verdict_context) {
2599 (AttestationSource::Attestation(_), Some(context)) => {
2600 let answer = context.decide_authentication_failure_blame(kind);
2601 blame.set(Some(answer));
2602
2603 answer == attestation_verdict::AuthenticationFailureBlame::Account
2604 }
2605 (AttestationSource::Certified(record), _)
2606 if protocol_config.enable_validator_attestation() =>
2607 {
2608 !matches!(
2614 record,
2615 Some(AttestationRecord {
2616 verdict: AttestationVerdict::Refuted { .. }
2617 | AttestationVerdict::Undecided,
2618 ..
2619 })
2620 )
2621 }
2622 _ => false,
2623 }
2624 };
2625
2626 let (
2627 inner_temp_store,
2628 gas_status,
2629 effects,
2630 _timings,
2631 execution_error_opt,
2632 authentication_error,
2633 ) = epoch_store
2634 .executor()
2635 .authenticate_then_execute_transaction_to_effects(
2636 backing_store,
2637 protocol_config,
2638 self.metrics.limits_metrics.clone(),
2639 self.config
2640 .expensive_safety_check_config
2641 .enable_deep_per_tx_iota_conservation_check(),
2642 self.config.certificate_deny_config.certificate_deny_set(),
2643 &epoch_id,
2644 epoch_start_timestamp,
2645 gas_data,
2646 gas_status,
2647 authenticators,
2648 authenticator_and_tx_checked_input_objects,
2649 Some(&gas_owner_pays),
2650 kind,
2651 signer,
2652 tx_digest,
2653 auth_context_data,
2654 &mut None,
2655 );
2656 let blame = blame.get().or_else(|| {
2664 match (&attestation_verdict_context, &authentication_error) {
2665 (Some(context), Some(kind)) => {
2666 Some(context.decide_authentication_failure_blame(kind))
2667 }
2668 _ => None,
2669 }
2670 });
2671 let outcome = attestation_verdict::ExecutionOutcome {
2672 blame,
2673 consumed_units: attestation_verdict::consumed_units(gas_status),
2674 body_ran: attestation_verdict::body_ran(
2675 authentication_error.is_some(),
2676 execution_error_opt.as_ref().err(),
2677 ),
2678 };
2679
2680 (inner_temp_store, effects, execution_error_opt, outcome)
2681 };
2682
2683 let attestation_record = attestation_record(
2686 attestation,
2687 &outcome,
2688 &effects,
2689 tx.gas_price(),
2690 protocol_config,
2691 );
2692
2693 fail_point_if!("cp_execution_nondeterminism", || {
2694 #[cfg(msim)]
2695 self.create_fail_state(transaction, epoch_store, &mut effects);
2696 });
2697
2698 let elapsed = prepare_transaction_start_time.elapsed().as_micros() as f64;
2699 if elapsed > 0.0 {
2700 self.metrics
2701 .prepare_cert_gas_latency_ratio
2702 .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed);
2703 }
2704
2705 let read_objects = tracking_store.into_read_objects();
2706
2707 Ok((
2708 inner_temp_store,
2709 effects,
2710 execution_error.err(),
2711 read_objects,
2712 attestation_record,
2713 ))
2714 }
2715
2716 pub fn prepare_transaction_for_benchmark(
2717 &self,
2718 transaction: &VerifiedExecutableTransaction,
2719 input_objects: InputObjects,
2720 epoch_store: &Arc<AuthorityPerEpochStore>,
2721 ) -> IotaResult<(
2722 InnerTemporaryStore,
2723 TransactionEffects,
2724 Option<ExecutionError>,
2725 )> {
2726 let lock = RwLock::new(epoch_store.epoch());
2727 let execution_guard = lock.try_read().unwrap();
2728
2729 self.execute_transaction(
2730 &execution_guard,
2731 transaction,
2732 input_objects,
2733 vec![],
2734 &AttestationSource::Unattested,
2735 epoch_store,
2736 )
2737 .map(|(inner_temp_store, effects, execution_error, _, _)| {
2738 (inner_temp_store, effects, execution_error)
2739 })
2740 }
2741
2742 pub fn simulate_transaction(
2775 &self,
2776 transaction: Transaction,
2777 checks: VmChecks,
2778 ) -> IotaResult<SimulateTransactionResult> {
2779 let epoch_store = self.load_epoch_store_one_call_per_task();
2780 self.simulate_transaction_in_epoch(&epoch_store, transaction, checks)
2781 }
2782
2783 #[instrument("simulate_tx", level = "trace", skip_all)]
2797 pub fn simulate_transaction_in_epoch(
2798 &self,
2799 epoch_store: &AuthorityPerEpochStore,
2800 transaction: Transaction,
2801 checks: VmChecks,
2802 ) -> IotaResult<SimulateTransactionResult> {
2803 if !self.is_fullnode(epoch_store) {
2804 return Err(IotaError::UnsupportedFeature {
2805 error: "simulate is only supported on fullnodes".to_string(),
2806 });
2807 }
2808
2809 self.simulate_transaction_inner(epoch_store, transaction, checks)
2810 }
2811
2812 pub fn simulate_transaction_for_benchmark(
2816 &self,
2817 transaction: Transaction,
2818 checks: VmChecks,
2819 ) -> IotaResult<SimulateTransactionResult> {
2820 let epoch_store = self.load_epoch_store_one_call_per_task();
2821 self.simulate_transaction_inner(&epoch_store, transaction, checks)
2822 }
2823
2824 #[instrument(level = "trace", skip_all)]
2825 fn simulate_transaction_inner(
2826 &self,
2827 epoch_store: &AuthorityPerEpochStore,
2828 mut transaction: Transaction,
2829 checks: VmChecks,
2830 ) -> IotaResult<SimulateTransactionResult> {
2831 if transaction.kind().is_system() {
2832 return Err(IotaError::UnsupportedFeature {
2833 error: "simulate does not support system transactions".to_string(),
2834 });
2835 }
2836
2837 transaction.check_serialized_size(epoch_store.protocol_config())?;
2838
2839 transaction.validity_check_no_gas_check(epoch_store.protocol_config())?;
2843
2844 transaction.check_gas_payment_size(epoch_store.protocol_config())?;
2848
2849 let input_object_kinds = transaction.input_objects()?;
2850 let receiving_object_refs = transaction.receiving_objects();
2851
2852 iota_transaction_checks::deny::check_transaction_for_validation(
2855 &transaction,
2856 &[],
2857 &input_object_kinds,
2858 &receiving_object_refs,
2859 &self.config.transaction_deny_config,
2860 self.get_backing_package_store().as_ref(),
2861 )?;
2862
2863 let (mut input_objects, receiving_objects) = self.input_loader.read_objects_for_signing(
2865 None,
2867 &input_object_kinds,
2868 &receiving_object_refs,
2869 epoch_store.epoch(),
2870 )?;
2871
2872 let mock_gas_id = if transaction.gas().is_empty() {
2874 let mock_gas_object = mock_simulation_gas_coin(transaction.gas_data().owner);
2875 let mock_gas_object_ref = mock_gas_object.object_ref();
2876 transaction.gas_data_mut().objects = vec![mock_gas_object_ref];
2877 input_objects.push(ObjectReadResult::new_from_gas_object(&mock_gas_object));
2878 Some(mock_gas_object.id())
2879 } else {
2880 None
2881 };
2882
2883 let protocol_config = epoch_store.protocol_config();
2884
2885 iota_types::gas::fill_in_unset_simulation_gas(
2886 &mut transaction,
2887 &input_objects,
2888 epoch_store.reference_gas_price(),
2889 protocol_config,
2890 );
2891
2892 let authenticator_gas_budget = 0;
2895
2896 let (gas_status, checked_input_objects) = if checks.enabled() {
2899 iota_transaction_checks::check_transaction_input(
2900 protocol_config,
2901 epoch_store.reference_gas_price(),
2902 &transaction,
2903 input_objects,
2904 &receiving_objects,
2905 &self.metrics.bytecode_verifier_metrics,
2906 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2907 authenticator_gas_budget,
2908 false,
2909 )?
2910 } else {
2911 iota_types::gas::check_gas_coins_cover_budget_in_simulation(
2917 &input_objects,
2918 transaction.gas(),
2919 transaction.gas_budget(),
2920 )?;
2921
2922 let checked_input_objects = iota_transaction_checks::check_simulation_input(
2923 protocol_config,
2924 transaction.kind(),
2925 input_objects,
2926 receiving_objects,
2927 )?;
2928
2929 iota_transaction_checks::check_non_system_packages_to_be_published(
2935 &transaction,
2936 protocol_config,
2937 &self.metrics.bytecode_verifier_metrics,
2938 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2939 )?;
2940
2941 let gas_status = IotaGasStatus::new(
2942 transaction.gas_budget(),
2943 transaction.gas_price(),
2944 epoch_store.reference_gas_price(),
2945 protocol_config,
2946 )?;
2947
2948 (gas_status, checked_input_objects)
2949 };
2950
2951 let executor = iota_execution::executor(
2953 protocol_config,
2954 true, None,
2956 )
2957 .expect("Creating an executor should not fail here");
2958
2959 let (kind, signer, gas_data) = transaction.execution_parts();
2961 let (inner_temp_store, _, effects, execution_result) = executor.dev_inspect_transaction(
2962 self.get_backing_store().as_ref(),
2963 protocol_config,
2964 self.metrics.limits_metrics.clone(),
2965 false, self.config.certificate_deny_config.certificate_deny_set(),
2967 &epoch_store.epoch_start_config().epoch_data().epoch_id(),
2968 epoch_store
2969 .epoch_start_config()
2970 .epoch_data()
2971 .epoch_start_timestamp(),
2972 checked_input_objects,
2973 gas_data,
2974 gas_status,
2975 kind,
2976 signer,
2977 transaction.digest(),
2978 checks.disabled(),
2979 );
2980
2981 let mut input_objects = inner_temp_store.input_objects;
2982 iota_types::storage::extend_input_objects_with_loaded_runtime_objects(
2983 &mut input_objects,
2984 &effects,
2985 &inner_temp_store.loaded_runtime_objects,
2986 self.get_backing_store().as_object_store(),
2987 );
2988
2989 Ok(SimulateTransactionResult {
2990 input_objects,
2991 output_objects: inner_temp_store.written,
2992 events: effects.events_digest().map(|_| inner_temp_store.events),
2993 effects,
2994 execution_result,
2995 suggested_gas_price: self
2996 .congestion_tracker
2997 .get_prediction_suggested_gas_price(&transaction),
2998 mock_gas_id,
2999 gas_data: transaction.gas_data().clone(),
3000 })
3001 }
3002
3003 pub fn reference_gas_price_for_testing(&self) -> Result<u64, anyhow::Error> {
3005 let epoch_store = self.epoch_store_for_testing();
3006 Ok(epoch_store.reference_gas_price())
3007 }
3008
3009 #[instrument(level = "trace", skip_all)]
3010 pub fn try_is_tx_already_executed(&self, digest: &TransactionDigest) -> IotaResult<bool> {
3011 self.get_transaction_cache_reader()
3012 .try_is_tx_already_executed(digest)
3013 }
3014
3015 pub fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
3017 self.try_is_tx_already_executed(digest)
3018 .expect("storage access failed")
3019 }
3020
3021 #[cfg(msim)]
3022 fn create_fail_state(
3023 &self,
3024 transaction: &VerifiedExecutableTransaction,
3025 epoch_store: &Arc<AuthorityPerEpochStore>,
3026 effects: &mut TransactionEffects,
3027 ) {
3028 use std::cell::RefCell;
3029
3030 use iota_types::effects::TransactionEffectsAPIForTesting;
3031 thread_local! {
3032 static FAIL_STATE: RefCell<(u64, HashSet<AuthorityName>)> = RefCell::new((0, HashSet::new()));
3033 }
3034 if !transaction.data().transaction().is_system_tx() {
3035 let committee = epoch_store.committee();
3036 let cur_stake = (**committee).weight(&self.name);
3037 if cur_stake > 0 {
3038 FAIL_STATE.with_borrow_mut(|fail_state| {
3039 if fail_state.0 < committee.validity_threshold() {
3041 fail_state.0 += cur_stake;
3042 fail_state.1.insert(self.name);
3043 }
3044
3045 if fail_state.1.contains(&self.name) {
3046 info!("cp_exec failing tx");
3047 effects.gas_cost_summary_mut_for_testing().computation_cost += 1;
3048 }
3049 });
3050 }
3051 }
3052 }
3053
3054 pub fn unixtime_now_ms() -> u64 {
3055 let now = SystemTime::now()
3056 .duration_since(UNIX_EPOCH)
3057 .expect("Time went backwards")
3058 .as_millis();
3059 u64::try_from(now).expect("Travelling in time machine")
3060 }
3061
3062 #[instrument(level = "trace", skip_all)]
3063 pub async fn handle_transaction_info_request(
3064 &self,
3065 request: TransactionInfoRequest,
3066 ) -> IotaResult<TransactionInfoResponse> {
3067 let epoch_store = self.load_epoch_store_one_call_per_task();
3068 let (transaction, status) = self
3069 .get_transaction_status(&request.transaction_digest, &epoch_store)?
3070 .ok_or(IotaError::TransactionNotFound {
3071 digest: request.transaction_digest,
3072 })?;
3073 Ok(TransactionInfoResponse {
3074 transaction,
3075 status,
3076 })
3077 }
3078
3079 #[instrument(level = "trace", skip_all)]
3080 pub async fn handle_object_info_request(
3081 &self,
3082 request: ObjectInfoRequest,
3083 ) -> IotaResult<ObjectInfoResponse> {
3084 let epoch_store = self.load_epoch_store_one_call_per_task();
3085
3086 let requested_object_seq = match request.request_kind {
3087 ObjectInfoRequestKind::LatestObjectInfo => {
3088 self.try_get_object_or_tombstone(request.object_id)?
3089 .ok_or_else(|| {
3090 IotaError::from(UserInputError::ObjectNotFound {
3091 object_id: request.object_id,
3092 version: None,
3093 })
3094 })?
3095 .version
3096 }
3097 ObjectInfoRequestKind::PastObjectInfoDebug(seq) => seq,
3098 };
3099
3100 let object = self
3103 .get_object_with_historic_fallback(&ObjectKey(request.object_id, requested_object_seq))?
3104 .ok_or_else(|| {
3105 IotaError::from(UserInputError::ObjectNotFound {
3106 object_id: request.object_id,
3107 version: Some(requested_object_seq),
3108 })
3109 })?;
3110
3111 let layout = if let (LayoutGenerationOption::Generate, Some(move_obj)) =
3112 (request.generate_layout, object.data.as_opt_struct())
3113 {
3114 Some(into_struct_layout(
3115 epoch_store
3116 .executor()
3117 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
3118 .get_annotated_layout(move_obj.struct_tag())?,
3119 )?)
3120 } else {
3121 None
3122 };
3123
3124 let lock = if !object.is_address_owned() {
3125 None
3127 } else {
3128 self.get_transaction_lock(&object.object_ref(), &epoch_store)?
3129 .map(|s| s.into_inner())
3130 };
3131
3132 Ok(ObjectInfoResponse {
3133 object,
3134 layout,
3135 lock_for_debugging: lock,
3136 })
3137 }
3138
3139 #[instrument(level = "trace", skip_all)]
3140 pub fn handle_checkpoint_request(
3141 &self,
3142 request: &CheckpointRequest,
3143 ) -> IotaResult<CheckpointResponse> {
3144 let summary = if request.certified {
3145 let summary = match request.sequence_number {
3146 Some(seq) => self
3147 .checkpoint_store
3148 .get_checkpoint_by_sequence_number(seq)?,
3149 None => self.checkpoint_store.get_latest_certified_checkpoint()?,
3150 }
3151 .map(|v| v.into_inner());
3152 summary.map(CheckpointSummaryResponse::Certified)
3153 } else {
3154 let summary = match request.sequence_number {
3155 Some(seq) => self.checkpoint_store.get_locally_computed_checkpoint(seq)?,
3156 None => self
3157 .checkpoint_store
3158 .get_latest_locally_computed_checkpoint()?,
3159 };
3160 summary.map(CheckpointSummaryResponse::Pending)
3161 };
3162 let contents = match &summary {
3163 Some(s) => self
3164 .checkpoint_store
3165 .get_checkpoint_contents(&s.contents_digest())?,
3166 None => None,
3167 };
3168 Ok(CheckpointResponse {
3169 checkpoint: summary,
3170 contents,
3171 })
3172 }
3173
3174 fn check_protocol_version(
3175 supported_protocol_versions: SupportedProtocolVersions,
3176 current_version: ProtocolVersion,
3177 ) {
3178 info!("current protocol version is now {:?}", current_version);
3179 info!("supported versions are: {:?}", supported_protocol_versions);
3180 if !supported_protocol_versions.is_version_supported(current_version) {
3181 let msg = format!(
3182 "Unsupported protocol version. The network is at {current_version:?}, but this IotaNode only supports: {supported_protocol_versions:?}. Shutting down.",
3183 );
3184
3185 error!("{}", msg);
3186 eprintln!("{msg}");
3187
3188 #[cfg(not(msim))]
3189 std::process::exit(1);
3190
3191 #[cfg(msim)]
3192 iota_simulator::task::shutdown_current_node();
3193 }
3194 }
3195
3196 #[expect(clippy::disallowed_methods)] pub async fn new(
3198 name: AuthorityName,
3199 secret: StableSyncAuthoritySigner,
3200 supported_protocol_versions: SupportedProtocolVersions,
3201 store: Arc<AuthorityStore>,
3202 execution_cache_trait_pointers: ExecutionCacheTraitPointers,
3203 epoch_store: Arc<AuthorityPerEpochStore>,
3204 committee_store: Arc<CommitteeStore>,
3205 rpc_indexes_store: Option<Arc<RpcIndexesStore>>,
3206 checkpoint_store: Arc<CheckpointStore>,
3207 prometheus_registry: &Registry,
3208 config: NodeConfig,
3209 validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
3210 chain_identifier: ChainIdentifier,
3211 policy_config: Option<PolicyConfig>,
3212 epoch_end_db_snapshots: Option<EpochEndDbSnapshotHandle>,
3213 ) -> Arc<Self> {
3214 Self::check_protocol_version(supported_protocol_versions, epoch_store.protocol_version());
3215
3216 epoch_store.set_effects_store(
3219 execution_cache_trait_pointers
3220 .transaction_cache_reader
3221 .clone(),
3222 );
3223
3224 let metrics = Arc::new(AuthorityMetrics::new(prometheus_registry));
3225 let (tx_ready_transactions, rx_ready_transactions) = unbounded_channel();
3226 let execution_scheduler = Arc::new(ExecutionSchedulerWrapper::new(
3227 execution_cache_trait_pointers.object_cache_reader.clone(),
3228 execution_cache_trait_pointers
3229 .transaction_cache_reader
3230 .clone(),
3231 tx_ready_transactions,
3232 &epoch_store,
3233 metrics.clone(),
3234 ));
3235 let (tx_execution_shutdown, rx_execution_shutdown) = oneshot::channel();
3236
3237 let authority_per_epoch_pruner = AuthorityPerEpochStorePruner::new(
3238 epoch_store.get_parent_path(),
3239 config
3240 .authority_store_pruning_config
3241 .num_latest_epoch_dbs_to_retain,
3242 )
3243 .await;
3244 let object_retention = ObjectRetention::new(
3245 checkpoint_store
3246 .get_highest_executed_checkpoint_seq_number()
3247 .ok()
3248 .flatten()
3249 .unwrap_or_default(),
3250 );
3251 let num_epochs_to_retain = config.authority_store_pruning_config.num_epochs_to_retain;
3252 if epoch_store.committee().authority_exists(&name)
3253 && num_epochs_to_retain > 0
3254 && num_epochs_to_retain < u64::MAX
3255 {
3256 warn!(
3257 num_epochs_to_retain,
3258 "this validator retains superseded object versions it does not serve, which \
3259 grows its database; lowering the retention later expires every epoch they \
3260 span at once, at the next start. Set 0 to retain none beyond the current epoch."
3261 );
3262 }
3263 if let Some(delay_days) = config
3264 .authority_store_pruning_config
3265 .periodic_compaction_threshold_days
3266 {
3267 store.perpetual_tables.spawn_periodic_compaction(delay_days);
3268 }
3269 let input_loader =
3270 TransactionInputLoader::new(execution_cache_trait_pointers.object_cache_reader.clone());
3271 let epoch = epoch_store.epoch();
3272 let (historic_bucket_expiry, expiry_epochs) = watch::channel(epoch);
3273 let rgp = epoch_store.reference_gas_price();
3274 let traffic_controller_metrics =
3275 Arc::new(TrafficControllerMetrics::new(prometheus_registry));
3276 let traffic_controller = policy_config.map(|policy_config| {
3277 Arc::new(TrafficController::init(
3278 policy_config,
3279 traffic_controller_metrics,
3280 ))
3281 });
3282 let state = Arc::new(AuthorityState {
3283 name,
3284 secret,
3285 execution_lock: RwLock::new(epoch),
3286 epoch_store: ArcSwap::new(epoch_store.clone()),
3287 input_loader,
3288 execution_cache_trait_pointers,
3289 rpc_indexes_store,
3290 historic_objects: store.get_historic_objects().clone(),
3291 historic_ledger: store.get_historic_ledger().clone(),
3292 checkpoint_store,
3293 committee_store,
3294 execution_scheduler,
3295 tx_execution_shutdown: Mutex::new(Some(tx_execution_shutdown)),
3296 metrics,
3297 authority_per_epoch_pruner,
3298 object_retention,
3299 config,
3300 overload_info: AuthorityOverloadInfo::default(),
3301 validator_tx_finalizer,
3302 chain_identifier,
3303 congestion_tracker: Arc::new(CongestionTracker::new(rgp)),
3304 traffic_controller,
3305 epoch_end_db_snapshots,
3306 historic_bucket_expiry,
3307 historic_bucket_work_stopped: Arc::new(AtomicBool::new(false)),
3308 });
3309 Self::record_pruned_checkpoints(&state.historic_ledger, &state.checkpoint_store);
3312
3313 let expiry = Self::expire_historic_buckets_in_background(
3314 Arc::downgrade(&state),
3315 expiry_epochs,
3316 state.object_retention.released(),
3317 );
3318 spawn_monitored_task!(expiry);
3319
3320 let authority_state = Arc::downgrade(&state);
3322 spawn_monitored_task!(execution_process(
3323 authority_state,
3324 rx_ready_transactions,
3325 rx_execution_shutdown,
3326 ));
3327
3328 state
3329 }
3330
3331 pub fn epoch_db_pruner(&self) -> &AuthorityPerEpochStorePruner {
3332 &self.authority_per_epoch_pruner
3333 }
3334
3335 pub fn get_historic_objects(&self) -> &Arc<HistoricObjects> {
3337 &self.historic_objects
3338 }
3339
3340 pub fn get_historic_ledger(&self) -> &Arc<HistoricLedger> {
3342 &self.historic_ledger
3343 }
3344
3345 pub fn get_object_cache_reader(&self) -> &Arc<dyn ObjectCacheRead> {
3347 &self.execution_cache_trait_pointers.object_cache_reader
3348 }
3349
3350 pub fn get_transaction_cache_reader(&self) -> &Arc<dyn TransactionCacheRead> {
3351 &self.execution_cache_trait_pointers.transaction_cache_reader
3352 }
3353
3354 pub fn get_cache_writer(&self) -> &Arc<dyn ExecutionCacheWrite> {
3355 &self.execution_cache_trait_pointers.cache_writer
3356 }
3357
3358 pub fn get_backing_store(&self) -> &Arc<dyn BackingStore + Send + Sync> {
3359 &self.execution_cache_trait_pointers.backing_store
3360 }
3361
3362 pub fn get_backing_package_store(&self) -> &Arc<dyn BackingPackageStore + Send + Sync> {
3363 &self.execution_cache_trait_pointers.backing_package_store
3364 }
3365
3366 pub fn get_object_store(&self) -> &Arc<dyn ObjectStore + Send + Sync> {
3367 &self.execution_cache_trait_pointers.object_store
3368 }
3369
3370 pub fn get_reconfig_api(&self) -> &Arc<dyn ExecutionCacheReconfigAPI> {
3371 &self.execution_cache_trait_pointers.reconfig_api
3372 }
3373
3374 pub fn get_global_state_hash_store(&self) -> &Arc<dyn GlobalStateHashStore> {
3375 &self.execution_cache_trait_pointers.global_state_hash_store
3376 }
3377
3378 pub fn get_checkpoint_cache(&self) -> &Arc<dyn CheckpointCache> {
3379 &self.execution_cache_trait_pointers.checkpoint_cache
3380 }
3381
3382 pub fn get_state_sync_store(&self) -> &Arc<dyn StateSyncAPI> {
3383 &self.execution_cache_trait_pointers.state_sync_store
3384 }
3385
3386 pub fn get_cache_commit(&self) -> &Arc<dyn ExecutionCacheCommit> {
3387 &self.execution_cache_trait_pointers.cache_commit
3388 }
3389
3390 pub fn database_for_testing(&self) -> Arc<AuthorityStore> {
3391 self.execution_cache_trait_pointers
3392 .testing_api
3393 .database_for_testing()
3394 }
3395
3396 #[cfg(test)]
3399 pub fn evict_committed_object_for_testing(&self, id: &ObjectId) {
3400 self.execution_cache_trait_pointers
3401 .testing_api
3402 .evict_committed_object_for_testing(id)
3403 }
3404
3405 pub fn clear_execution_caches_for_testing(&self) {
3408 self.execution_cache_trait_pointers
3409 .testing_api
3410 .clear_caches_for_testing()
3411 }
3412
3413 #[cfg(test)]
3415 pub fn uncommitted_transactions_for_testing(&self) -> Vec<TransactionDigest> {
3416 self.execution_cache_trait_pointers
3417 .testing_api
3418 .uncommitted_transactions_for_testing()
3419 }
3420
3421 pub fn execution_scheduler(&self) -> &Arc<ExecutionSchedulerWrapper> {
3422 &self.execution_scheduler
3423 }
3424
3425 pub fn uses_execution_scheduler(&self) -> bool {
3428 self.execution_scheduler.uses_execution_scheduler()
3429 }
3430
3431 pub fn execution_lock_for_executable_transaction(
3435 &self,
3436 transaction: &VerifiedExecutableTransaction,
3437 ) -> IotaResult<ExecutionLockReadGuard<'_>> {
3438 let lock = self
3439 .execution_lock
3440 .try_read()
3441 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)?;
3442 if *lock == transaction.auth_sig().epoch() {
3443 Ok(lock)
3444 } else {
3445 Err(IotaError::WrongEpoch {
3446 expected_epoch: *lock,
3447 actual_epoch: transaction.auth_sig().epoch(),
3448 })
3449 }
3450 }
3451
3452 pub fn execution_lock_for_signing(&self) -> IotaResult<ExecutionLockReadGuard<'_>> {
3458 self.execution_lock
3459 .try_read()
3460 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)
3461 }
3462
3463 pub async fn execution_lock_for_reconfiguration(&self) -> ExecutionLockWriteGuard<'_> {
3464 self.execution_lock.write().await
3465 }
3466
3467 pub(crate) fn check_transaction_deny_rules_consistency(
3477 &self,
3478 cur_epoch_store: &AuthorityPerEpochStore,
3479 epoch_start_configuration: &EpochStartConfiguration,
3480 ) {
3481 if self.is_fullnode(cur_epoch_store) {
3482 return;
3483 }
3484 let Some(walked_deny_rules) = epoch_start_configuration.transaction_deny_rules_state()
3485 else {
3486 if cur_epoch_store
3487 .epoch_start_config()
3488 .transaction_deny_rules_obj_initial_shared_version()
3489 .is_some()
3490 {
3491 fatal!(
3492 "TransactionDenyRules object existed in epoch {} but is missing from the \
3493 state walked for the next epoch — the local store is corrupted; restore or \
3494 state-sync before rejoining",
3495 cur_epoch_store.epoch(),
3496 );
3497 }
3498 return;
3499 };
3500 if cur_epoch_store
3504 .get_reconfig_state_read_lock_guard()
3505 .should_accept_tx()
3506 {
3507 info!(
3508 "skipping the deny-rule mirror comparison: consensus did not close epoch {} on \
3509 this node",
3510 cur_epoch_store.epoch(),
3511 );
3512 return;
3513 }
3514 let mirrored_deny_rules = cur_epoch_store.get_mirrored_transaction_deny_rules();
3515 if *walked_deny_rules != *mirrored_deny_rules {
3516 debug_fatal!(
3517 "TransactionDenyRules object diverged from the mirrored state at the end of \
3518 epoch {}; continuing from the object (walked: {walked_deny_rules:?}, mirrored: \
3519 {mirrored_deny_rules:?})",
3520 cur_epoch_store.epoch(),
3521 );
3522 cur_epoch_store.metrics.deny_rule_mirror_divergence.set(1);
3523 }
3524 }
3525
3526 pub(crate) fn report_failed_deny_rule_update_execution(
3538 &self,
3539 transaction: &VerifiedExecutableTransaction,
3540 effects: &TransactionEffects,
3541 expected_effects_digest: Option<TransactionEffectsDigest>,
3542 epoch_store: &AuthorityPerEpochStore,
3543 ) {
3544 if !matches!(
3545 transaction.transaction().kind(),
3546 TransactionKind::TransactionDenyRulesUpdate(_)
3547 ) || effects.status().is_success()
3548 {
3549 return;
3550 }
3551 epoch_store
3552 .metrics
3553 .deny_rule_update_execution_failures
3554 .inc();
3555 if expected_effects_digest.is_some() {
3556 error!(
3557 digest = ?transaction.digest(),
3558 status = ?effects.status(),
3559 "TransactionDenyRulesUpdate failed execution; the object misses its delta until \
3560 the epoch boundary re-seeds the mirror"
3561 );
3562 return;
3563 }
3564 debug_fatal!(
3565 "TransactionDenyRulesUpdate failed execution; the object misses its delta until the \
3566 epoch boundary re-seeds the mirror (digest: {:?}, status: {:?})",
3567 transaction.digest(),
3568 effects.status(),
3569 );
3570 }
3571
3572 #[instrument(level = "error", skip_all)]
3573 pub async fn reconfigure(
3574 &self,
3575 cur_epoch_store: &AuthorityPerEpochStore,
3576 supported_protocol_versions: SupportedProtocolVersions,
3577 new_committee: Committee,
3578 epoch_start_configuration: EpochStartConfiguration,
3579 state_hasher: Arc<GlobalStateHasher>,
3580 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3581 epoch_supply_change: i64,
3582 epoch_last_checkpoint: CheckpointSequenceNumber,
3583 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
3584 Self::check_protocol_version(
3585 supported_protocol_versions,
3586 epoch_start_configuration
3587 .epoch_start_state()
3588 .protocol_version(),
3589 );
3590 self.metrics.reset_on_reconfigure();
3591 self.committee_store.insert_new_committee(&new_committee)?;
3592
3593 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3595
3596 cur_epoch_store.epoch_terminated().await;
3598
3599 let highest_locally_built_checkpoint_seq = self
3600 .checkpoint_store
3601 .get_latest_locally_computed_checkpoint()?
3602 .map(|c| c.sequence_number())
3603 .unwrap_or(0);
3604
3605 assert!(
3606 epoch_last_checkpoint >= highest_locally_built_checkpoint_seq,
3607 "expected {epoch_last_checkpoint} >= {highest_locally_built_checkpoint_seq}"
3608 );
3609
3610 self.revert_uncommitted_epoch_transactions(cur_epoch_store)
3616 .await?;
3617 self.get_reconfig_api()
3618 .clear_state_end_of_epoch(&execution_lock);
3619 self.check_system_consistency(
3620 cur_epoch_store,
3621 state_hasher,
3622 expensive_safety_check_config,
3623 epoch_supply_change,
3624 )?;
3625 self.check_transaction_deny_rules_consistency(cur_epoch_store, &epoch_start_configuration);
3626
3627 self.get_reconfig_api()
3628 .try_set_epoch_start_configuration(&epoch_start_configuration)?;
3629 self.hand_over_epoch_end_db_snapshot(cur_epoch_store.epoch())
3630 .await;
3631
3632 let new_epoch = new_committee.epoch;
3633 self.open_historic_buckets(new_epoch)?;
3634 let new_epoch_store = self
3635 .reopen_epoch_db(
3636 cur_epoch_store,
3637 new_committee,
3638 epoch_start_configuration,
3639 expensive_safety_check_config,
3640 epoch_last_checkpoint,
3641 )
3642 .await?;
3643 assert_eq!(new_epoch_store.epoch(), new_epoch);
3644 match self.execution_scheduler.as_ref() {
3645 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3646 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3647 tm.reconfigure(new_epoch);
3648 }
3649 }
3650 *execution_lock = new_epoch;
3651 if let Err(err) = self
3654 .get_reconfig_api()
3655 .expire_epoch_markers(new_epoch, &execution_lock)
3656 {
3657 error!("Failed to expire the epoch marker buckets: {err:?}");
3658 }
3659 self.historic_bucket_expiry.send_replace(new_epoch);
3662 Ok(new_epoch_store)
3666 }
3667
3668 fn open_historic_buckets(&self, new_epoch: EpochId) -> IotaResult<()> {
3675 self.historic_objects.ensure(new_epoch)?;
3676 self.historic_ledger.ensure(new_epoch)?;
3677 self.checkpoint_store
3678 .historic_checkpoints
3679 .ensure(new_epoch)?;
3680 if let Some(indexes) = &self.rpc_indexes_store {
3682 if let Err(err) = indexes.ensure_history_bucket_exists(new_epoch) {
3683 error!("Failed to open the RPC index history bucket of {new_epoch}: {err:?}");
3684 }
3685 }
3686 Ok(())
3687 }
3688
3689 #[cfg(test)]
3692 async fn advance_historic_buckets(&self, new_epoch: EpochId) -> IotaResult<()> {
3693 self.open_historic_buckets(new_epoch)?;
3694 self.expire_historic_buckets(new_epoch).await;
3695 Ok(())
3696 }
3697
3698 async fn expire_historic_buckets(&self, current_epoch: EpochId) -> bool {
3708 let pruning_config = &self.config.authority_store_pruning_config;
3711 let configured_objects_to_retain = pruning_config.num_epochs_to_retain();
3712 let objects_to_retain = configured_objects_to_retain.map(|epochs| {
3713 self.oldest_epoch_retained_for_object_reads()
3714 .map_or(epochs, |epoch| {
3715 epochs.max(current_epoch.saturating_sub(epoch))
3716 })
3717 });
3718 let held_back = objects_to_retain != configured_objects_to_retain;
3719 let checkpoints_to_retain = pruning_config.num_epochs_to_retain_for_checkpoints();
3720
3721 let historic_objects = self.historic_objects.clone();
3723 let historic_ledger = self.historic_ledger.clone();
3724 let checkpoint_store = self.checkpoint_store.clone();
3725 let rpc_indexes_store = self.rpc_indexes_store.clone();
3726 let stopped = self.historic_bucket_work_stopped.clone();
3727 let metrics = self.metrics.clone();
3728 let expired = tokio::task::spawn_blocking(move || {
3729 let expire =
3735 |store: &str, prune: &dyn Fn() -> Result<Option<PrunedBuckets>, String>| {
3736 if stopped.load(Ordering::Acquire) {
3737 return;
3738 }
3739 let started = Instant::now();
3740 match prune() {
3741 Ok(Some(pruned)) => {
3742 if pruned.dropped > 0 {
3743 metrics
3744 .historic_bucket_expiry_duration
3745 .with_label_values(&[store])
3746 .observe(started.elapsed().as_secs_f64());
3747 }
3748 metrics
3749 .historic_bucket_earliest_retained_epoch
3750 .with_label_values(&[store])
3751 .set(pruned.earliest_retained as i64);
3752 }
3753 Ok(None) => {}
3754 Err(err) if stopped.load(Ordering::Acquire) => {
3755 info!(
3756 store,
3757 "Stopped expiring historic buckets for a shutdown: {err}"
3758 )
3759 }
3760 Err(err) => error!(store, "Failed to expire historic buckets: {err}"),
3761 }
3762 };
3763 if let Some(indexes) = &rpc_indexes_store {
3764 expire("indexes", &|| {
3765 indexes.prune(current_epoch).map_err(|e| format!("{e:?}"))
3766 });
3767 }
3768 if let Some(epochs_to_retain) = checkpoints_to_retain {
3769 let record =
3772 || Self::record_pruned_checkpoints(&historic_ledger, &checkpoint_store);
3773 expire("checkpoints", &|| {
3774 checkpoint_store
3775 .historic_checkpoints
3776 .prune(current_epoch, epochs_to_retain, &record)
3777 .map_err(|e| format!("{e:?}"))
3778 });
3779 expire("ledger", &|| {
3780 historic_ledger
3781 .prune(current_epoch, epochs_to_retain, &record)
3782 .map_err(|e| format!("{e:?}"))
3783 });
3784 record();
3787 }
3788 if let Some(epochs_to_retain) = objects_to_retain {
3789 expire("objects", &|| {
3790 historic_objects
3791 .prune(current_epoch, epochs_to_retain)
3792 .map_err(|e| format!("{e:?}"))
3793 });
3794 }
3795 })
3796 .await;
3797 if let Err(err) = expired {
3798 error!("The historic bucket expiry task failed: {err:?}");
3799 }
3800 held_back
3801 }
3802
3803 pub fn stop_historic_bucket_work(&self) {
3810 self.historic_bucket_work_stopped
3811 .store(true, Ordering::Release);
3812 self.historic_objects.stop();
3813 }
3814
3815 fn execution_lag(&self) -> Option<Duration> {
3818 let Ok(Some(executed)) = self.checkpoint_store.get_highest_executed_checkpoint() else {
3819 return None;
3820 };
3821 let executed_at = UNIX_EPOCH + Duration::from_millis(executed.timestamp_ms);
3822 Some(
3823 SystemTime::now()
3824 .duration_since(executed_at)
3825 .unwrap_or_default(),
3826 )
3827 }
3828
3829 fn is_catching_up(&self) -> bool {
3833 self.execution_lag().is_none_or(|lag| lag > CATCH_UP_LAG)
3834 }
3835
3836 async fn compact_closed_buckets(
3842 current_epoch: EpochId,
3843 historic_objects: Arc<HistoricObjects>,
3844 historic_ledger: Arc<HistoricLedger>,
3845 checkpoint_store: Arc<CheckpointStore>,
3846 rpc_indexes_store: Option<Arc<RpcIndexesStore>>,
3847 epochs: watch::Receiver<EpochId>,
3848 stopped: Arc<AtomicBool>,
3849 ) {
3850 let compacted = tokio::task::spawn_blocking(move || {
3851 let stop =
3852 || stopped.load(Ordering::Acquire) || !matches!(epochs.has_changed(), Ok(false));
3853 if let Some(indexes) = &rpc_indexes_store {
3854 if indexes.is_history_backfill_running() {
3857 info!("Not compacting the RPC index history while its backfill runs");
3858 } else if let Err(err) = indexes.compact_closed_buckets(current_epoch, &stop) {
3859 error!("Failed to compact the RPC index history: {err:?}");
3860 }
3861 }
3862 if let Err(err) = checkpoint_store
3863 .historic_checkpoints
3864 .compact_closed_buckets(current_epoch, &stop)
3865 {
3866 error!("Failed to compact historic checkpoint buckets: {err:?}");
3867 }
3868 if let Err(err) = historic_ledger.compact_closed_buckets(current_epoch, &stop) {
3869 error!("Failed to compact historic ledger buckets: {err:?}");
3870 }
3871 if let Err(err) = historic_objects.compact_closed_buckets(current_epoch, &stop) {
3872 error!("Failed to compact historic object buckets: {err:?}");
3873 }
3874 })
3875 .await;
3876 if let Err(err) = compacted {
3877 error!("The closed bucket compaction task failed: {err:?}");
3878 }
3879 }
3880
3881 async fn expire_historic_buckets_in_background(
3892 state: Weak<AuthorityState>,
3893 mut epochs: watch::Receiver<EpochId>,
3894 released: Arc<Notify>,
3895 ) {
3896 let mut compaction_held_back = None;
3899 loop {
3900 let epoch = *epochs.borrow_and_update();
3901 let Some(this) = state.upgrade() else {
3902 return;
3903 };
3904 if this.historic_bucket_work_stopped.load(Ordering::Acquire) {
3905 return;
3906 }
3907 let held_back = this.expire_historic_buckets(epoch).await;
3908 let catching_up = this.is_catching_up();
3909 let state = (held_back, catching_up);
3910 if compaction_held_back != Some(state) {
3911 match state {
3912 (false, false) => info!("Compacting the buckets of closed epochs"),
3913 (true, _) => info!(
3914 "Not compacting the buckets of closed epochs while a read holds back the \
3915 expiry of historic objects"
3916 ),
3917 (false, true) => info!(
3918 lag_s = this.execution_lag().map(|lag| lag.as_secs()),
3919 "Not compacting the buckets of closed epochs while the node catches up: \
3920 its newest executed checkpoint is more than {} minutes old",
3921 CATCH_UP_LAG.as_secs() / 60
3922 ),
3923 }
3924 compaction_held_back = Some(state);
3925 }
3926 let compaction = (!held_back && !catching_up).then(|| {
3927 (
3928 this.historic_objects.clone(),
3929 this.historic_ledger.clone(),
3930 this.checkpoint_store.clone(),
3931 this.rpc_indexes_store.clone(),
3932 this.historic_bucket_work_stopped.clone(),
3933 )
3934 });
3935 drop(this);
3936 if let Some((
3937 historic_objects,
3938 historic_ledger,
3939 checkpoint_store,
3940 rpc_indexes_store,
3941 stopped,
3942 )) = compaction
3943 {
3944 Self::compact_closed_buckets(
3945 epoch,
3946 historic_objects,
3947 historic_ledger,
3948 checkpoint_store,
3949 rpc_indexes_store,
3950 epochs.clone(),
3951 stopped,
3952 )
3953 .await;
3954 }
3955 tokio::select! {
3956 changed = epochs.changed() => {
3957 if changed.is_err() {
3958 return;
3959 }
3960 }
3961 () = released.notified(), if held_back => {
3962 tokio::time::sleep(HELD_BACK_EXPIRY_INTERVAL).await;
3965 }
3966 () = tokio::time::sleep(COMPACTION_RECHECK_INTERVAL), if catching_up && !held_back => {}
3967 }
3968 }
3969 }
3970
3971 fn record_pruned_checkpoints(
3977 historic_ledger: &HistoricLedger,
3978 checkpoint_store: &CheckpointStore,
3979 ) {
3980 let floor = historic_ledger.earliest_retained_epoch().max(
3981 checkpoint_store
3982 .historic_checkpoints
3983 .earliest_retained_epoch(),
3984 );
3985 if let Err(err) = checkpoint_store.advance_highest_pruned_checkpoint(floor) {
3986 error!("Failed to record the pruned checkpoint range: {err:?}");
3987 }
3988 }
3989
3990 fn oldest_epoch_retained_for_object_reads(&self) -> Option<EpochId> {
3993 let retained = self.object_retention.lowest_retained()?;
3994 match self
3997 .checkpoint_store
3998 .get_checkpoint_by_sequence_number(retained)
3999 {
4000 Ok(checkpoint) => Some(checkpoint.map_or(0, |checkpoint| checkpoint.epoch())),
4001 Err(err) => {
4002 error!(
4003 "Failed to read the epoch of retained checkpoint {retained}, keeping \
4004 every historic object bucket: {err:?}"
4005 );
4006 Some(0)
4007 }
4008 }
4009 }
4010
4011 pub async fn reconfigure_for_testing(&self) {
4016 self.reconfigure_for_testing_impl(None).await;
4017 }
4018
4019 pub async fn reconfigure_for_testing_with_protocol_config(
4022 &self,
4023 protocol_config: ProtocolConfig,
4024 ) {
4025 self.reconfigure_for_testing_impl(Some(protocol_config))
4026 .await;
4027 }
4028
4029 async fn reconfigure_for_testing_impl(&self, protocol_config: Option<ProtocolConfig>) {
4030 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
4031 let epoch_store = self.epoch_store_for_testing().clone();
4032 let protocol_config =
4036 protocol_config.unwrap_or_else(|| epoch_store.protocol_config().clone());
4037 let _guard =
4038 ProtocolConfig::apply_overrides_for_testing(move |_, _| protocol_config.clone());
4039 let new_epoch_store = epoch_store.new_at_next_epoch_for_testing(
4040 self.get_backing_package_store().clone(),
4041 &self.config.expensive_safety_check_config,
4042 self.checkpoint_store
4043 .get_epoch_last_checkpoint(epoch_store.epoch())
4044 .unwrap()
4045 .map(|c| c.sequence_number())
4046 .unwrap_or_default(),
4047 );
4048 let new_epoch = new_epoch_store.epoch();
4049 match self.execution_scheduler.as_ref() {
4050 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
4051 ExecutionSchedulerWrapper::TransactionManager(tm) => {
4052 tm.reconfigure(new_epoch);
4053 }
4054 }
4055 self.epoch_store.store(new_epoch_store);
4056 epoch_store.epoch_terminated().await;
4057 *execution_lock = new_epoch;
4058 }
4059
4060 #[instrument(level = "error", skip_all)]
4061 fn check_system_consistency(
4062 &self,
4063 cur_epoch_store: &AuthorityPerEpochStore,
4064 state_hasher: Arc<GlobalStateHasher>,
4065 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
4066 epoch_supply_change: i64,
4067 ) -> IotaResult<()> {
4068 info!(
4069 "Performing iota conservation consistency check for epoch {}",
4070 cur_epoch_store.epoch()
4071 );
4072
4073 if cfg!(debug_assertions) {
4074 cur_epoch_store.check_all_executed_transactions_in_checkpoint();
4075 }
4076
4077 self.get_reconfig_api()
4078 .try_expensive_check_iota_conservation(cur_epoch_store, Some(epoch_supply_change))?;
4079
4080 if expensive_safety_check_config.enable_state_consistency_check() {
4082 info!(
4083 "Performing state consistency check for epoch {}",
4084 cur_epoch_store.epoch()
4085 );
4086 self.expensive_check_is_consistent_state(state_hasher, cur_epoch_store);
4087 }
4088
4089 Ok(())
4090 }
4091
4092 fn expensive_check_is_consistent_state(
4093 &self,
4094 state_hasher: Arc<GlobalStateHasher>,
4095 cur_epoch_store: &AuthorityPerEpochStore,
4096 ) {
4097 let live_object_set_hash = state_hasher
4098 .digest_live_object_set()
4099 .expect("Reading the live object set cannot fail");
4100
4101 let root_state_hash: ECMHLiveObjectSetDigest = self
4102 .get_global_state_hash_store()
4103 .get_root_state_hash_for_epoch(cur_epoch_store.epoch())
4104 .expect("Retrieving root state hash cannot fail")
4105 .expect("Root state hash for epoch must exist")
4106 .1
4107 .digest()
4108 .into();
4109
4110 let is_inconsistent = root_state_hash != live_object_set_hash;
4111 if is_inconsistent {
4112 debug_fatal!(
4113 "Inconsistent state detected: root state hash: {:?}, live object set hash: {:?}",
4114 root_state_hash,
4115 live_object_set_hash
4116 );
4117 } else {
4118 info!("State consistency check passed");
4119 }
4120
4121 state_hasher.set_inconsistent_state(is_inconsistent);
4122 }
4123
4124 pub fn current_epoch_for_testing(&self) -> EpochId {
4125 self.epoch_store_for_testing().epoch()
4126 }
4127
4128 #[instrument(level = "error", skip_all)]
4132 async fn hand_over_epoch_end_db_snapshot(&self, epoch: EpochId) {
4133 let Some(handle) = &self.epoch_end_db_snapshots else {
4134 return;
4135 };
4136 let _metrics_guard = self
4137 .metrics
4138 .epoch_end_db_snapshot_handover_latency
4139 .start_timer();
4140 if handle.hand_over(epoch).await == HandOver::Skipped {
4141 self.metrics.epoch_end_db_snapshots_skipped.inc();
4142 }
4143 }
4144
4145 pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
4152 self.epoch_store.load()
4153 }
4154
4155 pub fn epoch_store_for_testing(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
4157 self.load_epoch_store_one_call_per_task()
4158 }
4159
4160 pub fn clone_committee_for_testing(&self) -> Committee {
4161 Committee::clone(self.epoch_store_for_testing().committee())
4162 }
4163
4164 #[instrument(level = "trace", skip_all)]
4165 pub fn try_get_object(&self, object_id: &ObjectId) -> IotaResult<Option<Object>> {
4166 self.get_object_store()
4167 .try_get_object(object_id)
4168 .map_err(Into::into)
4169 }
4170
4171 pub fn get_object(&self, object_id: &ObjectId) -> Option<Object> {
4173 self.try_get_object(object_id)
4174 .expect("storage access failed")
4175 }
4176
4177 pub fn get_iota_system_package_object_ref(&self) -> IotaResult<ObjectReference> {
4178 Ok(self
4179 .try_get_object(&ObjectId::SYSTEM)?
4180 .expect("system package should always exist")
4181 .object_ref())
4182 }
4183
4184 pub fn get_iota_system_state_object_for_testing(&self) -> IotaResult<IotaSystemState> {
4186 self.get_object_cache_reader()
4187 .try_get_iota_system_state_object_unsafe()
4188 }
4189
4190 #[instrument(level = "trace", skip_all)]
4191 pub fn get_checkpoint_by_sequence_number(
4192 &self,
4193 sequence_number: CheckpointSequenceNumber,
4194 ) -> IotaResult<Option<VerifiedCheckpoint>> {
4195 Ok(self
4196 .checkpoint_store
4197 .get_checkpoint_by_sequence_number(sequence_number)?)
4198 }
4199
4200 pub async fn wait_for_checkpoint_inclusion(
4218 &self,
4219 digests: &[TransactionDigest],
4220 timeout: Duration,
4221 ) -> IotaResult<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>> {
4222 let deadline = tokio::time::Instant::now() + timeout;
4223 let results = self.wait_for_checkpoint_mapping(digests, deadline).await?;
4224
4225 if let Some(max_seq) = results.values().map(|(seq, _)| *seq).max() {
4229 let indexed = self
4230 .checkpoint_store
4231 .notify_read_executed_checkpoint(max_seq);
4232 let all_checkpointed = digests.iter().all(|digest| results.contains_key(digest));
4233 if tokio::time::timeout_at(deadline, indexed).await.is_err() && all_checkpointed {
4235 self.metrics.checkpoint_inclusion_index_wait_timeouts.inc();
4236 warn!(
4237 checkpoint_seq = max_seq,
4238 "transactions are checkpointed but the RPC indexes have not caught up \
4239 within the timeout; reporting them without the read-after-write guarantee"
4240 );
4241 }
4242 }
4243
4244 Ok(results)
4245 }
4246
4247 pub fn is_checkpoint_indexed(&self, seq: CheckpointSequenceNumber) -> IotaResult<bool> {
4250 Ok(self
4251 .checkpoint_store
4252 .get_highest_executed_checkpoint_seq_number()?
4253 .is_some_and(|indexed| seq <= indexed))
4254 }
4255
4256 pub(crate) async fn wait_for_checkpoint_mapping(
4261 &self,
4262 digests: &[TransactionDigest],
4263 deadline: tokio::time::Instant,
4264 ) -> IotaResult<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>> {
4265 let mut checkpoint_timestamp_cache = HashMap::<CheckpointSequenceNumber, u64>::new();
4266 let mut results = BTreeMap::new();
4267 let mut remaining = digests.to_vec();
4268 let mut epoch_store = self.load_epoch_store_one_call_per_task().clone();
4269
4270 loop {
4271 let wait = epoch_store.wait_for_transactions_in_checkpoint_with_timeout(
4272 &remaining,
4273 deadline.saturating_duration_since(tokio::time::Instant::now()),
4274 |seq| self.checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache),
4275 );
4276 tokio::select! {
4277 wait_results = wait => {
4278 for (digest, seq_and_ts) in remaining.iter().zip(wait_results?) {
4279 if let Some(seq_and_ts) = seq_and_ts {
4280 results.insert(*digest, seq_and_ts);
4281 }
4282 }
4283 return Ok(results);
4284 }
4285 _ = epoch_store.wait_epoch_terminated() => {}
4286 }
4287
4288 let found = match epoch_store.multi_get_transaction_checkpoint(&remaining) {
4295 Ok(found) => found,
4296 Err(IotaError::EpochEnded(_)) => vec![None; remaining.len()],
4301 Err(err) => return Err(err),
4302 };
4303 let mut still_uncheckpointed = Vec::new();
4304 for (digest, found_seq) in remaining.iter().zip(found) {
4305 match found_seq {
4306 Some(seq) => {
4307 let ts = self
4308 .checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache);
4309 results.insert(*digest, (seq, ts));
4310 }
4311 None => still_uncheckpointed.push(*digest),
4312 }
4313 }
4314 remaining = still_uncheckpointed;
4315 if remaining.is_empty() {
4316 return Ok(results);
4317 }
4318
4319 match self
4320 .wait_for_next_epoch_store(epoch_store.epoch(), deadline)
4321 .await
4322 {
4323 Some(next) => epoch_store = next,
4324 None => return Ok(results),
4325 }
4326 }
4327 }
4328
4329 async fn wait_for_next_epoch_store(
4332 &self,
4333 prev_epoch: EpochId,
4334 deadline: tokio::time::Instant,
4335 ) -> Option<Arc<AuthorityPerEpochStore>> {
4336 const EPOCH_STORE_SWAP_POLL_INTERVAL: Duration = Duration::from_millis(100);
4341
4342 loop {
4343 let current = self.load_epoch_store_one_call_per_task().clone();
4346 if current.epoch() > prev_epoch {
4347 return Some(current);
4348 }
4349 if tokio::time::Instant::now() >= deadline {
4350 return None;
4351 }
4352 tokio::time::sleep(EPOCH_STORE_SWAP_POLL_INTERVAL).await;
4353 }
4354 }
4355
4356 fn checkpoint_timestamp_ms_cached(
4360 &self,
4361 seq: CheckpointSequenceNumber,
4362 cache: &mut HashMap<CheckpointSequenceNumber, u64>,
4363 ) -> u64 {
4364 *cache.entry(seq).or_insert_with(|| {
4365 self.get_checkpoint_by_sequence_number(seq)
4366 .ok()
4367 .flatten()
4368 .map(|c| c.timestamp_ms)
4369 .unwrap_or(0)
4370 })
4371 }
4372
4373 #[instrument(level = "trace", skip_all)]
4374 pub fn get_transaction_checkpoint_for_tests(
4375 &self,
4376 digest: &TransactionDigest,
4377 epoch_store: &AuthorityPerEpochStore,
4378 ) -> IotaResult<Option<VerifiedCheckpoint>> {
4379 let checkpoint = epoch_store.get_transaction_checkpoint(digest)?;
4380 let Some(checkpoint) = checkpoint else {
4381 return Ok(None);
4382 };
4383 let checkpoint = self
4384 .checkpoint_store
4385 .get_checkpoint_by_sequence_number(checkpoint)?;
4386 Ok(checkpoint)
4387 }
4388
4389 #[instrument(level = "trace", skip_all)]
4390 pub fn get_object_read(&self, object_id: &ObjectId) -> IotaResult<ObjectRead> {
4391 Ok(
4392 match self
4393 .get_object_cache_reader()
4394 .try_get_latest_object_or_tombstone(*object_id)?
4395 {
4396 Some((_, ObjectOrTombstone::Object(object))) => {
4397 let layout = self.get_object_layout(&object)?;
4398 ObjectRead::Exists(object.object_ref(), object, layout)
4399 }
4400 Some((_, ObjectOrTombstone::Tombstone(objref))) => ObjectRead::Deleted(objref),
4401 None => ObjectRead::NotExists(*object_id),
4402 },
4403 )
4404 }
4405
4406 pub fn get_chain_identifier(&self) -> ChainIdentifier {
4408 self.chain_identifier
4409 }
4410
4411 #[instrument(level = "trace", skip_all)]
4412 pub fn get_move_object<T>(&self, object_id: &ObjectId) -> IotaResult<T>
4413 where
4414 T: DeserializeOwned,
4415 {
4416 let o = self.get_object_read(object_id)?.into_object()?;
4417 if let Some(move_object) = o.data.as_opt_struct() {
4418 Ok(bcs::from_bytes(move_object.contents()).map_err(|e| {
4419 IotaError::ObjectDeserialization {
4420 error: format!("{e}"),
4421 }
4422 })?)
4423 } else {
4424 Err(IotaError::ObjectDeserialization {
4425 error: format!("Provided object : [{object_id}] is not a Move object."),
4426 })
4427 }
4428 }
4429
4430 #[instrument(level = "trace", skip_all)]
4436 pub fn get_past_object_read(
4437 &self,
4438 object_id: &ObjectId,
4439 version: Version,
4440 ) -> IotaResult<PastObjectRead> {
4441 let Some(obj_ref) = self
4443 .get_object_cache_reader()
4444 .try_get_latest_object_ref_or_tombstone(*object_id)?
4445 else {
4446 return Ok(PastObjectRead::ObjectNotExists(*object_id));
4447 };
4448
4449 if version > obj_ref.version {
4450 return Ok(PastObjectRead::VersionTooHigh {
4451 object_id: *object_id,
4452 asked_version: version,
4453 latest_version: obj_ref.version,
4454 });
4455 }
4456
4457 if version < obj_ref.version {
4458 return Ok(match self.read_object_at_version(object_id, version)? {
4460 Some((object, layout)) => {
4461 let obj_ref = object.object_ref();
4462 PastObjectRead::VersionFound(obj_ref, object, layout)
4463 }
4464
4465 None => PastObjectRead::VersionNotFound(*object_id, version),
4466 });
4467 }
4468
4469 if !obj_ref.digest.is_alive() {
4470 return Ok(PastObjectRead::ObjectDeleted(obj_ref));
4471 }
4472
4473 match self.read_object_at_version(object_id, obj_ref.version)? {
4474 Some((object, layout)) => Ok(PastObjectRead::VersionFound(obj_ref, object, layout)),
4475 None => {
4476 debug_fatal!(
4477 "Object with in parent_entry is missing from object store, datastore is \
4478 inconsistent",
4479 );
4480 Err(UserInputError::ObjectNotFound {
4481 object_id: *object_id,
4482 version: Some(obj_ref.version),
4483 }
4484 .into())
4485 }
4486 }
4487 }
4488
4489 #[instrument(level = "trace", skip_all)]
4490 fn read_object_at_version(
4491 &self,
4492 object_id: &ObjectId,
4493 version: Version,
4494 ) -> IotaResult<Option<(Object, Option<MoveStructLayout>)>> {
4495 let Some(object) =
4496 self.get_object_with_historic_fallback(&ObjectKey(*object_id, version))?
4497 else {
4498 return Ok(None);
4499 };
4500
4501 let layout = self.get_object_layout(&object)?;
4502 Ok(Some((object, layout)))
4503 }
4504
4505 pub(crate) fn get_object_with_historic_fallback(
4509 &self,
4510 key: &ObjectKey,
4511 ) -> IotaResult<Option<Object>> {
4512 match self
4513 .get_object_cache_reader()
4514 .try_get_object_by_key(&key.0, key.1)?
4515 {
4516 Some(object) => Ok(Some(object)),
4517 None => self.historic_objects.get(key),
4518 }
4519 }
4520
4521 fn object_store_with_historic_fallback(&self) -> ObjectStoreWithHistoricFallback<'_> {
4525 ObjectStoreWithHistoricFallback(self)
4526 }
4527
4528 pub fn get_object_layout(&self, object: &Object) -> IotaResult<Option<MoveStructLayout>> {
4530 let layout = object
4531 .data
4532 .as_opt_struct()
4533 .map(|object| {
4534 into_struct_layout(
4535 self.load_epoch_store_one_call_per_task()
4536 .executor()
4537 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
4539 .get_annotated_layout(object.struct_tag())?,
4540 )
4541 })
4542 .transpose()?;
4543 Ok(layout)
4544 }
4545
4546 #[instrument(level = "trace", skip_all)]
4549 pub fn get_owner_objects(
4550 &self,
4551 owner: Address,
4552 cursor: Option<&OwnedObjectCursor>,
4554 limit: usize,
4555 filter: Option<IotaObjectDataFilter>,
4556 max_read: usize,
4557 ) -> IotaResult<OwnedObjectsPage> {
4558 let indexes = self.require_jsonrpc_indexes()?;
4559 indexes.get_owner_objects(
4560 owner,
4561 cursor,
4562 limit,
4563 filter,
4564 max_read,
4565 &self.object_store_with_historic_fallback(),
4566 )
4567 }
4568
4569 #[instrument(level = "trace", skip_all)]
4573 pub fn get_owned_coins_page(
4574 &self,
4575 owner: Address,
4576 cursor: Option<&OwnedObjectCursor>,
4578 coin_type: Option<TypeTag>,
4579 limit: usize,
4580 ) -> IotaResult<Vec<(TypeTag, ObjectId, CoinInfo, OwnedObjectCursor)>> {
4581 let indexes = self.require_jsonrpc_indexes()?;
4582 indexes.get_owned_coins(
4583 owner,
4584 cursor,
4585 coin_type,
4586 limit,
4587 &self.object_store_with_historic_fallback(),
4588 )
4589 }
4590
4591 #[instrument(level = "trace", skip_all)]
4594 pub fn owned_coin_rows(
4595 &self,
4596 owner: Address,
4597 cursor: Option<&OwnedObjectCursor>,
4598 coin_type: TypeTag,
4599 limit: usize,
4600 ) -> IotaResult<Vec<OwnedObjectCursor>> {
4601 self.require_jsonrpc_indexes()?
4602 .owned_coin_rows(owner, cursor, coin_type, limit)
4603 }
4604
4605 #[instrument(level = "trace", skip_all)]
4606 pub fn get_move_objects<T>(&self, owner: Address, tag: StructTag) -> IotaResult<Vec<T>>
4607 where
4608 T: DeserializeOwned,
4609 {
4610 let indexes = self.require_jsonrpc_indexes()?;
4611 let object_ids = indexes
4614 .owner_iter(owner, None, OwnerTypeFilter::from_struct_tag(Some(&tag)))?
4615 .filter_ok(|(_, info)| info.object_type == tag)
4616 .map_ok(|(key, info)| ObjectKey(key.object_id, info.version))
4617 .collect::<Result<Vec<_>, _>>()?;
4618 let mut move_objects = vec![];
4619
4620 let objects = self
4621 .object_store_with_historic_fallback()
4622 .try_multi_get_objects_by_key(&object_ids)?;
4623
4624 for (o, id) in objects.into_iter().zip(object_ids) {
4625 let object = o.ok_or_else(|| {
4626 IotaError::from(UserInputError::ObjectNotFound {
4627 object_id: id.0,
4628 version: Some(id.1),
4629 })
4630 })?;
4631 let move_object = object.data.as_opt_struct().ok_or_else(|| {
4632 IotaError::from(UserInputError::MovePackageAsObject { object_id: id.0 })
4633 })?;
4634 move_objects.push(bcs::from_bytes(move_object.contents()).map_err(|e| {
4635 IotaError::ObjectDeserialization {
4636 error: format!("{e}"),
4637 }
4638 })?);
4639 }
4640 Ok(move_objects)
4641 }
4642
4643 #[instrument(level = "trace", skip_all)]
4647 pub fn get_dynamic_fields(
4648 &self,
4649 owner: ObjectId,
4650 cursor: Option<ObjectId>,
4652 limit: usize,
4653 ) -> IotaResult<Vec<(ObjectId, Option<DynamicFieldInfo>)>> {
4654 let indexes = self.require_jsonrpc_indexes()?;
4655 let epoch_store = self.load_epoch_store_one_call_per_task();
4656 let mut base_resolver = epoch_store
4657 .executor()
4658 .type_layout_resolver(Box::new(self.get_backing_package_store().clone()));
4659 let mut layout_resolver = CachingLayoutResolver::new(base_resolver.as_mut());
4661 let object_store = self.get_object_store();
4662
4663 let mut fields = Vec::new();
4664 for field_id in indexes
4665 .get_dynamic_field_ids_iterator(owner, cursor)?
4666 .take(limit)
4667 {
4668 let field_id = field_id?;
4669 let Some(field_object) = object_store.try_get_object(&field_id)? else {
4670 fields.push((field_id, None));
4671 continue;
4672 };
4673 match try_create_dynamic_field_info(
4674 &field_object,
4675 object_store.as_ref(),
4676 &mut layout_resolver,
4677 ) {
4678 Ok(info) => fields.push((field_id, info)),
4679 Err(e) => {
4680 warn!(?field_id, "failed to resolve dynamic field: {e}");
4681 fields.push((field_id, None));
4682 }
4683 }
4684 }
4685 Ok(fields)
4686 }
4687
4688 #[instrument(level = "trace", skip_all)]
4689 pub fn get_dynamic_field_objects(
4693 &self,
4694 owner: ObjectId,
4695 limit: usize,
4696 ) -> IotaResult<Vec<(ObjectId, Option<Object>)>> {
4697 let indexes = self.require_jsonrpc_indexes()?;
4698 let object_store = self.get_object_store();
4699 indexes
4700 .get_dynamic_field_ids_iterator(owner, None)?
4701 .take(limit)
4702 .map(|field_id| {
4703 let field_id = field_id?;
4704 Ok((field_id, object_store.try_get_object(&field_id)?))
4705 })
4706 .collect()
4707 }
4708
4709 pub fn get_dynamic_field_object_id(
4711 &self,
4712 owner: ObjectId,
4713 name_type: TypeTag,
4714 name_bcs_bytes: &[u8],
4715 ) -> IotaResult<Option<ObjectId>> {
4716 Ok(self
4717 .get_dynamic_field_object(owner, name_type, name_bcs_bytes)?
4718 .map(|object| object.id()))
4719 }
4720
4721 pub fn get_dynamic_field_object(
4725 &self,
4726 owner: ObjectId,
4727 name_type: TypeTag,
4728 name_bcs_bytes: &[u8],
4729 ) -> IotaResult<Option<Object>> {
4730 let derive = |name_type: &TypeTag| {
4731 dynamic_field::derive_dynamic_field_id(owner, name_type, name_bcs_bytes).map_err(|e| {
4732 IotaError::Unknown(format!(
4733 "Unable to generate dynamic field id. Got error: {e:?}"
4734 ))
4735 })
4736 };
4737 let object_store = self.get_object_store();
4738
4739 if let Some(field) = object_store.try_get_object(&derive(&name_type)?)? {
4743 let wrapped_name = matches!(
4744 &name_type,
4745 TypeTag::Struct(tag) if DynamicFieldInfo::is_dynamic_object_field_wrapper(tag)
4746 );
4747 if !wrapped_name {
4748 return Ok(Some(field));
4749 }
4750 return self.dynamic_field_value(field);
4753 }
4754
4755 let wrapper_type = TypeTag::Struct(Box::new(
4758 DynamicFieldInfo::dynamic_object_field_wrapper(name_type),
4759 ));
4760 match object_store.try_get_object(&derive(&wrapper_type)?)? {
4761 Some(wrapper) => self.dynamic_field_value(wrapper),
4762 None => Ok(None),
4763 }
4764 }
4765
4766 fn dynamic_field_value(&self, field: Object) -> IotaResult<Option<Object>> {
4770 let epoch_store = self.load_epoch_store_one_call_per_task();
4771 let mut layout_resolver = epoch_store
4772 .executor()
4773 .type_layout_resolver(Box::new(self.get_backing_package_store().clone()));
4774 let Some(info) = try_create_dynamic_field_info(
4775 &field,
4776 self.get_object_store().as_ref(),
4777 layout_resolver.as_mut(),
4778 )?
4779 else {
4780 return Ok(None);
4781 };
4782 if info.object_id == field.id() {
4783 return Ok(Some(field));
4784 }
4785 Ok(self.get_object_store().try_get_object(&info.object_id)?)
4786 }
4787
4788 #[instrument(level = "trace", skip_all)]
4789 pub fn get_total_transaction_blocks(&self) -> IotaResult<u64> {
4790 Ok(self.get_indexes()?.next_sequence_number())
4791 }
4792
4793 #[instrument(level = "trace", skip_all)]
4794 pub async fn get_executed_transaction_and_effects(
4795 &self,
4796 digest: TransactionDigest,
4797 kv_store: Arc<TransactionKeyValueStore>,
4798 ) -> IotaResult<(TransactionEnvelope, TransactionEffects)> {
4799 let transaction = kv_store.get_tx(digest).await?;
4800 let effects = kv_store.get_fx_by_tx_digest(digest).await?;
4801 Ok((transaction, effects))
4802 }
4803
4804 #[instrument(level = "trace", skip_all)]
4805 pub fn multi_get_checkpoint_by_sequence_number(
4806 &self,
4807 sequence_numbers: &[CheckpointSequenceNumber],
4808 ) -> IotaResult<Vec<Option<VerifiedCheckpoint>>> {
4809 Ok(self
4810 .checkpoint_store
4811 .multi_get_checkpoint_by_sequence_number(sequence_numbers)?)
4812 }
4813
4814 #[instrument(level = "trace", skip_all)]
4815 pub fn get_transaction_events(
4816 &self,
4817 digest: &TransactionDigest,
4818 ) -> IotaResult<TransactionEvents> {
4819 self.get_transaction_cache_reader()
4820 .try_get_events(digest)?
4821 .ok_or(IotaError::TransactionEventsNotFound { digest: *digest })
4822 }
4823
4824 pub fn get_transaction_input_objects(
4828 &self,
4829 effects: &TransactionEffects,
4830 ) -> anyhow::Result<Vec<Object>> {
4831 historic_objects::get_transaction_input_objects(
4832 self.get_object_store().as_ref(),
4833 &self.historic_objects,
4834 effects,
4835 )
4836 .map_err(Into::into)
4837 }
4838
4839 pub fn get_transaction_output_objects(
4843 &self,
4844 effects: &TransactionEffects,
4845 ) -> anyhow::Result<Vec<Object>> {
4846 historic_objects::get_transaction_output_objects(
4847 self.get_object_store().as_ref(),
4848 &self.historic_objects,
4849 effects,
4850 )
4851 .map_err(Into::into)
4852 }
4853
4854 fn get_indexes(&self) -> IotaResult<Arc<RpcIndexesStore>> {
4855 match self.jsonrpc_indexes() {
4856 Some(i) => Ok(i.clone()),
4857 None => Err(IotaError::UnsupportedFeature {
4858 error: "extended object indexing is not enabled on this server".into(),
4859 }),
4860 }
4861 }
4862
4863 fn jsonrpc_indexes(&self) -> Option<&Arc<RpcIndexesStore>> {
4865 self.rpc_indexes_store
4866 .as_ref()
4867 .filter(|store| store.serves(IndexGroup::JsonRpc))
4868 }
4869
4870 fn require_jsonrpc_indexes(&self) -> IotaResult<&Arc<RpcIndexesStore>> {
4873 self.jsonrpc_indexes()
4874 .ok_or(IotaError::IndexStoreNotAvailable)
4875 }
4876
4877 pub async fn get_transactions_for_tests(
4878 self: &Arc<Self>,
4879 filter: Option<TransactionFilter>,
4880 cursor: Option<TransactionDigest>,
4881 limit: Option<usize>,
4882 reverse: bool,
4883 ) -> IotaResult<Vec<TransactionDigest>> {
4884 let metrics = KeyValueStoreMetrics::new_for_tests();
4885 let kv_store = Arc::new(TransactionKeyValueStore::new(
4886 "rocksdb",
4887 metrics,
4888 self.clone(),
4889 ));
4890 self.get_transactions(&kv_store, filter, cursor, limit, reverse)
4891 .await
4892 }
4893
4894 #[instrument(level = "trace", skip_all)]
4895 pub async fn get_transactions(
4896 &self,
4897 kv_store: &Arc<TransactionKeyValueStore>,
4898 filter: Option<TransactionFilter>,
4899 cursor: Option<TransactionDigest>,
4901 limit: Option<usize>,
4902 reverse: bool,
4903 ) -> IotaResult<Vec<TransactionDigest>> {
4904 if let Some(TransactionFilter::Checkpoint(sequence_number)) = filter {
4905 let checkpoint_contents = kv_store.get_checkpoint_contents(sequence_number).await?;
4906 let iter = checkpoint_contents.iter().map(|c| c.transaction);
4907 if reverse {
4908 let iter = iter
4909 .rev()
4910 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4911 .skip(usize::from(cursor.is_some()));
4912 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4913 } else {
4914 let iter = iter
4915 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4916 .skip(usize::from(cursor.is_some()));
4917 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4918 }
4919 }
4920 self.get_indexes()?
4921 .get_transactions(filter, cursor, limit, reverse)
4922 }
4923
4924 pub fn get_checkpoint_store(&self) -> &Arc<CheckpointStore> {
4925 &self.checkpoint_store
4926 }
4927
4928 pub fn retain_objects(&self) -> ObjectRetentionGuard {
4934 self.object_retention.retain()
4935 }
4936
4937 pub(crate) fn record_executed_for_object_retention(
4941 &self,
4942 executed_seq: CheckpointSequenceNumber,
4943 ) {
4944 self.object_retention.record_executed(executed_seq);
4945 }
4946
4947 pub fn get_latest_checkpoint_sequence_number(&self) -> IotaResult<CheckpointSequenceNumber> {
4948 self.get_checkpoint_store()
4949 .get_highest_executed_checkpoint_seq_number()?
4950 .ok_or(IotaError::UserInput {
4951 error: UserInputError::LatestCheckpointSequenceNumberNotFound,
4952 })
4953 }
4954
4955 #[instrument(level = "trace", skip_all)]
4956 pub fn get_checkpoint_summary_by_sequence_number(
4957 &self,
4958 sequence_number: CheckpointSequenceNumber,
4959 ) -> IotaResult<CheckpointSummary> {
4960 let verified_checkpoint = self
4961 .get_checkpoint_store()
4962 .get_checkpoint_by_sequence_number(sequence_number)?;
4963 match verified_checkpoint {
4964 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4965 None => Err(IotaError::UserInput {
4966 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4967 }),
4968 }
4969 }
4970
4971 #[instrument(level = "trace", skip_all)]
4972 pub fn get_checkpoint_summary_by_digest(
4973 &self,
4974 digest: CheckpointDigest,
4975 ) -> IotaResult<CheckpointSummary> {
4976 let verified_checkpoint = self
4977 .get_checkpoint_store()
4978 .get_checkpoint_by_digest(&digest)?;
4979 match verified_checkpoint {
4980 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4981 None => Err(IotaError::UserInput {
4982 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4983 }),
4984 }
4985 }
4986
4987 #[instrument(level = "trace", skip_all)]
4988 pub fn find_publish_txn_digest(&self, package_id: ObjectId) -> IotaResult<TransactionDigest> {
4989 if package_id.is_system_package() {
4990 return self.find_genesis_txn_digest();
4991 }
4992 Ok(self
4993 .get_object_read(&package_id)?
4994 .into_object()?
4995 .previous_transaction)
4996 }
4997
4998 #[instrument(level = "trace", skip_all)]
4999 pub fn find_genesis_txn_digest(&self) -> IotaResult<TransactionDigest> {
5000 let summary = self
5001 .get_verified_checkpoint_by_sequence_number(0)?
5002 .into_message();
5003 let content = self.get_checkpoint_contents(summary.contents_digest)?;
5004 let genesis_transaction = content.enumerate_transactions(&summary).next();
5005 Ok(genesis_transaction
5006 .ok_or(IotaError::UserInput {
5007 error: UserInputError::GenesisTransactionNotFound,
5008 })?
5009 .1
5010 .transaction)
5011 }
5012
5013 #[instrument(level = "trace", skip_all)]
5014 pub fn get_verified_checkpoint_by_sequence_number(
5015 &self,
5016 sequence_number: CheckpointSequenceNumber,
5017 ) -> IotaResult<VerifiedCheckpoint> {
5018 let verified_checkpoint = self
5019 .get_checkpoint_store()
5020 .get_checkpoint_by_sequence_number(sequence_number)?;
5021 match verified_checkpoint {
5022 Some(verified_checkpoint) => Ok(verified_checkpoint),
5023 None => Err(IotaError::UserInput {
5024 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
5025 }),
5026 }
5027 }
5028
5029 #[instrument(level = "trace", skip_all)]
5030 pub fn get_verified_checkpoint_summary_by_digest(
5031 &self,
5032 digest: CheckpointDigest,
5033 ) -> IotaResult<VerifiedCheckpoint> {
5034 let verified_checkpoint = self
5035 .get_checkpoint_store()
5036 .get_checkpoint_by_digest(&digest)?;
5037 match verified_checkpoint {
5038 Some(verified_checkpoint) => Ok(verified_checkpoint),
5039 None => Err(IotaError::UserInput {
5040 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
5041 }),
5042 }
5043 }
5044
5045 #[instrument(level = "trace", skip_all)]
5046 pub fn get_checkpoint_contents(
5047 &self,
5048 digest: CheckpointContentsDigest,
5049 ) -> IotaResult<CheckpointContents> {
5050 self.get_checkpoint_store()
5051 .get_checkpoint_contents(&digest)?
5052 .ok_or(IotaError::UserInput {
5053 error: UserInputError::CheckpointContentsNotFound(digest),
5054 })
5055 }
5056
5057 #[instrument(level = "trace", skip_all)]
5058 pub fn get_checkpoint_contents_by_sequence_number(
5059 &self,
5060 sequence_number: CheckpointSequenceNumber,
5061 ) -> IotaResult<CheckpointContents> {
5062 let verified_checkpoint = self
5063 .get_checkpoint_store()
5064 .get_checkpoint_by_sequence_number(sequence_number)?;
5065 match verified_checkpoint {
5066 Some(verified_checkpoint) => {
5067 let contents_digest = verified_checkpoint.into_inner().contents_digest;
5068 self.get_checkpoint_contents(contents_digest)
5069 }
5070 None => Err(IotaError::UserInput {
5071 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
5072 }),
5073 }
5074 }
5075
5076 #[instrument(level = "trace", skip_all)]
5077 pub async fn query_events(
5078 &self,
5079 kv_store: &Arc<TransactionKeyValueStore>,
5080 query: EventFilter,
5081 cursor: Option<EventID>,
5083 limit: usize,
5084 descending: bool,
5085 ) -> IotaResult<Vec<IotaEvent>> {
5086 let stored_events = match query {
5087 EventFilter::Transaction(digest) => {
5090 Self::transaction_events_page(kv_store, digest, cursor, limit, descending).await?
5091 }
5092 query => {
5093 self.indexed_events_page(kv_store, query, cursor, limit, descending)
5094 .await?
5095 }
5096 };
5097
5098 let epoch_store = self.load_epoch_store_one_call_per_task();
5099 let backing_store = self.get_backing_package_store().as_ref();
5100 let mut layout_resolver = epoch_store
5101 .executor()
5102 .type_layout_resolver(Box::new(backing_store));
5103 let mut events = vec![];
5104 for (e, tx_digest, event_seq, timestamp) in stored_events.into_iter() {
5105 events.push(IotaEvent::try_from(
5106 e.clone(),
5107 tx_digest,
5108 event_seq as u64,
5109 timestamp,
5110 layout_resolver.get_annotated_layout(&e.struct_tag)?,
5111 )?)
5112 }
5113 Ok(events)
5114 }
5115
5116 async fn indexed_events_page(
5119 &self,
5120 kv_store: &Arc<TransactionKeyValueStore>,
5121 query: EventFilter,
5122 cursor: Option<EventID>,
5123 limit: usize,
5124 descending: bool,
5125 ) -> IotaResult<Vec<(Event, TransactionDigest, usize, Option<u64>)>> {
5126 let index_store = self.get_indexes()?;
5127
5128 let (tx_num, event_num) = if let Some(cursor) = cursor.as_ref() {
5130 let tx_seq = index_store.lookup_digest(&cursor.tx_digest)?.ok_or(
5131 IotaError::TransactionNotFound {
5132 digest: cursor.tx_digest,
5133 },
5134 )?;
5135 let event = (tx_seq, cursor.event_seq as usize);
5136 if index_store.event_timestamp(event)?.is_none() {
5139 return Err(IotaError::TransactionEventsNotFound {
5140 digest: cursor.tx_digest,
5141 });
5142 }
5143 event
5144 } else if descending {
5145 (u64::MAX, usize::MAX)
5146 } else {
5147 (0, 0)
5148 };
5149
5150 let limit = limit + 1;
5151 let mut event_keys = match query {
5152 EventFilter::All(filters) => {
5153 if filters.is_empty() {
5154 index_store.all_events(tx_num, event_num, limit, descending)?
5155 } else {
5156 return Err(IotaError::UserInput {
5157 error: UserInputError::Unsupported(
5158 "This query type does not currently support filter combinations"
5159 .to_string(),
5160 ),
5161 });
5162 }
5163 }
5164 EventFilter::MoveModule { package, module } => {
5165 let module_id = ModuleId::new(
5166 AccountAddress::new(package.into_bytes()),
5167 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
5168 );
5169 index_store.events_by_module_id(&module_id, tx_num, event_num, limit, descending)?
5170 }
5171 EventFilter::MoveEventType(struct_name) => index_store
5172 .events_by_move_event_struct_name(
5173 &struct_name,
5174 tx_num,
5175 event_num,
5176 limit,
5177 descending,
5178 )?,
5179 EventFilter::Sender(sender) => {
5180 index_store.events_by_sender(&sender, tx_num, event_num, limit, descending)?
5181 }
5182 EventFilter::TimeRange {
5183 start_time,
5184 end_time,
5185 } => index_store.event_iterator(
5186 start_time,
5187 end_time,
5188 cursor.is_some().then_some((tx_num, event_num)),
5189 limit,
5190 descending,
5191 )?,
5192 EventFilter::MoveEventModule { package, module } => index_store
5193 .events_by_move_event_module(
5194 &ModuleId::new(
5195 AccountAddress::new(package.into_bytes()),
5196 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
5197 ),
5198 tx_num,
5199 event_num,
5200 limit,
5201 descending,
5202 )?,
5203 EventFilter::Transaction(_)
5206 | EventFilter::Package(_)
5207 | EventFilter::MoveEventField { .. }
5208 | EventFilter::Any(_)
5209 | EventFilter::And(_, _)
5210 | EventFilter::Or(_, _) => {
5211 return Err(IotaError::UserInput {
5212 error: UserInputError::Unsupported(
5213 "This query type is not supported by the full node.".to_string(),
5214 ),
5215 });
5216 }
5217 };
5218
5219 if cursor.is_some() {
5222 if !event_keys.is_empty() {
5223 event_keys.remove(0);
5224 }
5225 } else {
5226 event_keys.truncate(limit - 1);
5227 }
5228
5229 let transaction_digests = event_keys
5231 .iter()
5232 .map(|(_, digest, _, _)| *digest)
5233 .collect::<HashSet<_>>()
5234 .into_iter()
5235 .collect::<Vec<_>>();
5236
5237 let events = kv_store
5238 .multi_get_events_by_tx_digests(&transaction_digests)
5239 .await?;
5240
5241 let events_map: HashMap<_, _> = transaction_digests.iter().zip(events).collect();
5242
5243 event_keys
5244 .into_iter()
5245 .map(|k| {
5246 (
5247 k,
5248 events_map
5249 .get(&k.1)
5250 .expect("fetched digest is missing")
5251 .clone()
5252 .and_then(|e| e.get(k.2).cloned()),
5253 )
5254 })
5255 .map(
5256 |((_event_digest, tx_digest, event_seq, timestamp), event)| {
5257 event
5258 .map(|e| (e, tx_digest, event_seq, Some(timestamp)))
5259 .ok_or(IotaError::TransactionEventsNotFound { digest: tx_digest })
5260 },
5261 )
5262 .collect::<Result<Vec<_>, _>>()
5263 }
5264
5265 async fn transaction_events_page(
5268 kv_store: &Arc<TransactionKeyValueStore>,
5269 digest: TransactionDigest,
5270 cursor: Option<EventID>,
5271 limit: usize,
5272 descending: bool,
5273 ) -> IotaResult<Vec<(Event, TransactionDigest, usize, Option<u64>)>> {
5274 let effects = kv_store.get_fx_by_tx_digest(digest).await?;
5275 let events = match effects.events_digest() {
5276 None => Vec::new(),
5277 Some(_) => {
5278 kv_store
5279 .multi_get_events_by_tx_digests(&[digest])
5280 .await?
5281 .into_iter()
5282 .next()
5283 .flatten()
5284 .ok_or(IotaError::TransactionEventsNotFound { digest })?
5285 .0
5286 }
5287 };
5288 let after = match cursor {
5289 None => None,
5290 Some(cursor) if cursor.tx_digest != digest => {
5291 return Err(IotaError::UserInput {
5292 error: UserInputError::Unsupported(
5293 "the cursor must name an event of the transaction the filter names"
5294 .to_string(),
5295 ),
5296 });
5297 }
5298 Some(cursor) if cursor.event_seq as usize >= events.len() => {
5299 return Err(IotaError::TransactionEventsNotFound { digest });
5300 }
5301 Some(cursor) => Some(cursor.event_seq as usize),
5302 };
5303 let page: Vec<usize> = if descending {
5304 (0..after.unwrap_or(events.len()))
5305 .rev()
5306 .take(limit)
5307 .collect()
5308 } else {
5309 (after.map_or(0, |seq| seq + 1)..events.len())
5310 .take(limit)
5311 .collect()
5312 };
5313 if page.is_empty() {
5314 return Ok(Vec::new());
5315 }
5316 let timestamp = match kv_store
5319 .get_transaction_perpetual_checkpoint(digest)
5320 .await?
5321 {
5322 Some(checkpoint) => Some(
5323 kv_store
5324 .get_checkpoint_summary(checkpoint)
5325 .await?
5326 .timestamp_ms,
5327 ),
5328 None => None,
5329 };
5330 Ok(page
5331 .into_iter()
5332 .map(|seq| (events[seq].clone(), digest, seq, timestamp))
5333 .collect())
5334 }
5335
5336 pub fn insert_genesis_object(&self, object: Object) {
5337 self.get_reconfig_api()
5338 .try_insert_genesis_object(object)
5339 .expect("Cannot insert genesis object")
5340 }
5341
5342 pub fn insert_genesis_objects(&self, objects: &[Object]) {
5343 for o in objects {
5344 self.insert_genesis_object(o.clone());
5345 }
5346 }
5347
5348 #[instrument(level = "trace", skip_all)]
5350 pub fn get_transaction_status(
5351 &self,
5352 transaction_digest: &TransactionDigest,
5353 epoch_store: &Arc<AuthorityPerEpochStore>,
5354 ) -> IotaResult<Option<(SenderSignedTransaction, TransactionStatus)>> {
5355 if let Some(effects) =
5357 self.get_signed_effects_and_maybe_resign(transaction_digest, epoch_store)?
5358 {
5359 if let Some(transaction) = self
5360 .get_transaction_cache_reader()
5361 .try_get_transaction_block(transaction_digest)?
5362 {
5363 let cert_sig = epoch_store.get_transaction_cert_sig(transaction_digest)?;
5364 let events = if effects.events_digest().is_some() {
5365 self.get_transaction_events(effects.transaction_digest())?
5366 } else {
5367 TransactionEvents::default()
5368 };
5369 return Ok(Some((
5370 (*transaction).clone().into_message(),
5371 TransactionStatus::Executed(cert_sig, effects.into_inner(), events),
5372 )));
5373 } else {
5374 debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
5379 }
5380 }
5381 if let Some(signed) = epoch_store.get_signed_transaction(transaction_digest)? {
5382 self.metrics.tx_already_processed.inc();
5383 let (transaction, sig) = signed.into_inner().into_data_and_sig();
5384 Ok(Some((transaction, TransactionStatus::Signed(sig))))
5385 } else {
5386 Ok(None)
5387 }
5388 }
5389
5390 #[instrument(level = "trace", skip_all)]
5394 pub fn get_signed_effects_and_maybe_resign(
5395 &self,
5396 transaction_digest: &TransactionDigest,
5397 epoch_store: &Arc<AuthorityPerEpochStore>,
5398 ) -> IotaResult<Option<VerifiedSignedTransactionEffects>> {
5399 let effects = self
5400 .get_transaction_cache_reader()
5401 .try_get_executed_effects(transaction_digest)?;
5402 match effects {
5403 Some(effects) => {
5404 if effects.epoch() != epoch_store.epoch() {
5425 debug!(
5426 tx_digest=?transaction_digest,
5427 effects_epoch=?effects.epoch(),
5428 epoch=?epoch_store.epoch(),
5429 "Re-signing the effects with the current epoch"
5430 );
5431 }
5432 Ok(Some(self.sign_effects(effects, epoch_store)?))
5433 }
5434 None => Ok(None),
5435 }
5436 }
5437
5438 pub fn check_effects_against_previously_signed(
5448 &self,
5449 epoch_store: &AuthorityPerEpochStore,
5450 tx_digest: &TransactionDigest,
5451 effects_digest: &TransactionEffectsDigest,
5452 surface: &'static str,
5453 ) -> IotaResult<()> {
5454 if let Some(previously_signed_digest) = epoch_store.get_signed_effects_digest(tx_digest)? {
5455 if previously_signed_digest != *effects_digest {
5456 self.metrics
5457 .signed_effects_equivocation_prevented
5458 .with_label_values(&[surface])
5459 .inc();
5460 error!(
5461 ?tx_digest,
5462 ?previously_signed_digest,
5463 executed_digest = ?effects_digest,
5464 surface,
5465 "refusing to report effects that differ from previously signed effects"
5466 );
5467 return Err(IotaError::GenericAuthority {
5468 error: format!(
5469 "Refusing to report effects for transaction {tx_digest}: effects digest \
5470 {effects_digest} differs from previously signed effects digest \
5471 {previously_signed_digest}"
5472 ),
5473 });
5474 }
5475 }
5476 Ok(())
5477 }
5478
5479 #[instrument(level = "trace", skip_all)]
5480 pub(crate) fn sign_effects(
5481 &self,
5482 effects: TransactionEffects,
5483 epoch_store: &Arc<AuthorityPerEpochStore>,
5484 ) -> IotaResult<VerifiedSignedTransactionEffects> {
5485 let tx_digest = *effects.transaction_digest();
5486
5487 self.check_effects_against_previously_signed(
5488 epoch_store,
5489 &tx_digest,
5490 &effects.digest(),
5491 "sign_effects",
5492 )?;
5493
5494 let signed_effects = match epoch_store.get_effects_signature(&tx_digest)? {
5495 Some(sig) => {
5496 debug_assert!(sig.epoch == epoch_store.epoch());
5497 SignedTransactionEffects::new_from_data_and_sig(effects, sig)
5498 }
5499 _ => {
5500 let sig = AuthoritySignInfo::new(
5501 epoch_store.epoch(),
5502 &effects,
5503 Intent::iota_app(IntentScope::TransactionEffects),
5504 self.name,
5505 &*self.secret,
5506 );
5507
5508 let effects = SignedTransactionEffects::new_from_data_and_sig(effects, sig.clone());
5509
5510 epoch_store.insert_effects_digest_and_signature(
5511 &tx_digest,
5512 effects.digest(),
5513 &sig,
5514 )?;
5515
5516 effects
5517 }
5518 };
5519
5520 Ok(VerifiedSignedTransactionEffects::new_unchecked(
5521 signed_effects,
5522 ))
5523 }
5524
5525 #[instrument(level = "trace", skip_all)]
5537 pub fn get_transaction_lock(
5538 &self,
5539 object_ref: &ObjectReference,
5540 epoch_store: &AuthorityPerEpochStore,
5541 ) -> IotaResult<Option<VerifiedSignedTransaction>> {
5542 let lock_info = self
5543 .get_object_cache_reader()
5544 .try_get_lock(*object_ref, epoch_store)?;
5545 let lock_info = match lock_info {
5546 ObjectLockStatus::LockedAtDifferentVersion { locked_ref } => {
5547 return Err(UserInputError::ObjectVersionUnavailableForConsumption {
5548 provided_obj_ref: *object_ref,
5549 current_version: locked_ref.version,
5550 }
5551 .into());
5552 }
5553 ObjectLockStatus::Initialized => {
5554 return Ok(None);
5555 }
5556 ObjectLockStatus::LockedToTx { locked_by_tx } => locked_by_tx,
5557 };
5558
5559 epoch_store.get_signed_transaction(&lock_info)
5560 }
5561
5562 pub fn try_get_objects(&self, objects: &[ObjectId]) -> IotaResult<Vec<Option<Object>>> {
5563 self.get_object_cache_reader().try_get_objects(objects)
5564 }
5565
5566 pub fn get_objects(&self, objects: &[ObjectId]) -> Vec<Option<Object>> {
5568 self.try_get_objects(objects)
5569 .expect("storage access failed")
5570 }
5571
5572 pub fn try_get_object_or_tombstone(
5573 &self,
5574 object_id: ObjectId,
5575 ) -> IotaResult<Option<ObjectReference>> {
5576 self.get_object_cache_reader()
5577 .try_get_latest_object_ref_or_tombstone(object_id)
5578 }
5579
5580 pub fn get_object_or_tombstone(&self, object_id: ObjectId) -> Option<ObjectReference> {
5582 self.try_get_object_or_tombstone(object_id)
5583 .expect("storage access failed")
5584 }
5585
5586 pub fn set_override_protocol_upgrade_buffer_stake(
5596 &self,
5597 expected_epoch: EpochId,
5598 buffer_stake_bps: u64,
5599 ) -> IotaResult {
5600 let epoch_store = self.load_epoch_store_one_call_per_task();
5601 let actual_epoch = epoch_store.epoch();
5602 if actual_epoch != expected_epoch {
5603 return Err(IotaError::WrongEpoch {
5604 expected_epoch,
5605 actual_epoch,
5606 });
5607 }
5608
5609 epoch_store.set_override_protocol_upgrade_buffer_stake(buffer_stake_bps)
5610 }
5611
5612 pub fn clear_override_protocol_upgrade_buffer_stake(
5613 &self,
5614 expected_epoch: EpochId,
5615 ) -> IotaResult {
5616 let epoch_store = self.load_epoch_store_one_call_per_task();
5617 let actual_epoch = epoch_store.epoch();
5618 if actual_epoch != expected_epoch {
5619 return Err(IotaError::WrongEpoch {
5620 expected_epoch,
5621 actual_epoch,
5622 });
5623 }
5624
5625 epoch_store.clear_override_protocol_upgrade_buffer_stake()
5626 }
5627
5628 pub async fn get_available_system_packages(
5632 &self,
5633 protocol_config: &ProtocolConfig,
5634 ) -> Vec<ObjectReference> {
5635 let mut results = vec![];
5636
5637 let system_packages = BuiltInFramework::iter_system_packages();
5638
5639 #[cfg(msim)]
5641 let extra_packages = framework_injection::get_extra_packages(self.name);
5642 #[cfg(msim)]
5643 let system_packages = {
5644 let mut packages: Vec<_> = system_packages.collect();
5645 packages.extend(extra_packages.iter());
5646 packages
5647 };
5648
5649 for system_package in system_packages {
5650 let modules = system_package.modules().to_vec();
5651 #[cfg(msim)]
5653 let modules = framework_injection::get_override_modules(&system_package.id, self.name)
5654 .unwrap_or(modules);
5655
5656 let Some(obj_ref) = iota_framework::compare_system_package(
5657 &self.get_object_store(),
5658 &system_package.id,
5659 &modules,
5660 system_package.dependencies.to_vec(),
5661 protocol_config,
5662 )
5663 .await
5664 else {
5665 return vec![];
5666 };
5667 results.push(obj_ref);
5668 }
5669
5670 results
5671 }
5672
5673 async fn get_system_package_bytes(
5696 &self,
5697 system_packages: Vec<ObjectReference>,
5698 binary_config: &BinaryConfig,
5699 ) -> Option<Vec<SystemPackage>> {
5700 let object_store = self.get_object_cache_reader();
5701
5702 let mut res = Vec::with_capacity(system_packages.len());
5703 for system_package_ref in system_packages {
5704 if object_store
5705 .get_object_by_key(&system_package_ref.object_id, system_package_ref.version)
5706 .is_some_and(|object| object.object_ref() == system_package_ref)
5707 {
5708 info!(
5710 "Framework {} does not need updating",
5711 system_package_ref.object_id
5712 );
5713 continue;
5714 }
5715
5716 let prev_transaction = if system_package_ref.version == Version::OBJECT_START {
5721 TransactionDigest::GENESIS_MARKER
5722 } else {
5723 let prev_version = system_package_ref
5724 .version
5725 .previous()
5726 .expect("version is greater than Version::OBJECT_START");
5727 let Some(prev_object) =
5728 object_store.get_object_by_key(&system_package_ref.object_id, prev_version)
5729 else {
5730 error!(
5731 "Framework {} not available locally at version {prev_version:?}, cannot \
5732 derive upgrade to {system_package_ref:?}",
5733 system_package_ref.object_id
5734 );
5735 return None;
5736 };
5737 prev_object.previous_transaction
5738 };
5739
5740 #[cfg(msim)]
5741 let FrameworkSystemPackage {
5742 id: _,
5743 bytes,
5744 dependencies,
5745 } = framework_injection::get_override_system_package(
5746 &system_package_ref.object_id,
5747 self.name,
5748 )
5749 .unwrap_or_else(|| {
5750 BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone()
5751 });
5752
5753 #[cfg(not(msim))]
5754 let FrameworkSystemPackage {
5755 id: _,
5756 bytes,
5757 dependencies,
5758 } = BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone();
5759
5760 let modules: Vec<_> = bytes
5761 .iter()
5762 .map(|m| CompiledModule::deserialize_with_config(m, binary_config).unwrap())
5763 .collect();
5764
5765 let new_object = Object::new_system_package(
5766 &modules,
5767 system_package_ref.version,
5768 dependencies.clone(),
5769 prev_transaction,
5770 );
5771
5772 let new_ref = new_object.object_ref();
5773 if new_ref != system_package_ref {
5774 debug_fatal!(
5775 "Framework mismatch -- binary: {new_ref:?}\n upgrade: {system_package_ref:?}"
5776 );
5777 return None;
5778 }
5779
5780 res.push(SystemPackage {
5781 version: system_package_ref.version,
5782 modules: bytes,
5783 dependencies,
5784 });
5785 }
5786
5787 Some(res)
5788 }
5789
5790 fn is_protocol_version_supported_v1(
5794 proposed_protocol_version: ProtocolVersion,
5795 committee: &Committee,
5796 capabilities: Vec<AuthorityCapabilitiesV1>,
5797 mut buffer_stake_bps: u64,
5798 ) -> Option<(ProtocolVersion, Digest, Vec<ObjectReference>)> {
5799 if buffer_stake_bps > 10000 {
5800 warn!("clamping buffer_stake_bps to 10000");
5801 buffer_stake_bps = 10000;
5802 }
5803
5804 let mut desired_upgrades: Vec<_> = capabilities
5807 .into_iter()
5808 .filter_map(|mut cap| {
5809 if cap.available_system_packages.is_empty() {
5811 return None;
5812 }
5813
5814 cap.available_system_packages.sort();
5815
5816 info!(
5817 "validator {:?} supports {:?} with system packages: {:?}",
5818 cap.authority.concise(),
5819 cap.supported_protocol_versions,
5820 cap.available_system_packages,
5821 );
5822
5823 cap.supported_protocol_versions
5827 .get_version_digest(proposed_protocol_version)
5828 .map(|digest| (digest, cap.available_system_packages, cap.authority))
5829 })
5830 .collect();
5831
5832 desired_upgrades.sort();
5835 desired_upgrades
5836 .into_iter()
5837 .chunk_by(|(digest, packages, _authority)| (*digest, packages.clone()))
5838 .into_iter()
5839 .find_map(|((digest, packages), group)| {
5840 assert!(!packages.is_empty());
5842
5843 let mut stake_aggregator: StakeAggregator<(), true> =
5844 StakeAggregator::new(Arc::new(committee.clone()));
5845
5846 for (_, _, authority) in group {
5847 stake_aggregator.insert_generic(authority, ());
5848 }
5849
5850 let total_votes = stake_aggregator.total_votes();
5851 let quorum_threshold = committee.quorum_threshold();
5852 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5853
5854 info!(
5855 protocol_config_digest = ?digest,
5856 ?total_votes,
5857 ?quorum_threshold,
5858 ?buffer_stake_bps,
5859 ?effective_threshold,
5860 ?proposed_protocol_version,
5861 ?packages,
5862 "support for upgrade"
5863 );
5864
5865 let has_support = total_votes >= effective_threshold;
5866 has_support.then_some((proposed_protocol_version, digest, packages))
5867 })
5868 }
5869
5870 fn choose_protocol_version_and_system_packages_v1(
5874 current_protocol_version: ProtocolVersion,
5875 current_protocol_digest: Digest,
5876 committee: &Committee,
5877 capabilities: Vec<AuthorityCapabilitiesV1>,
5878 buffer_stake_bps: u64,
5879 ) -> (ProtocolVersion, Digest, Vec<ObjectReference>) {
5880 let mut next_protocol_version = current_protocol_version;
5881 let mut system_packages = vec![];
5882 let mut protocol_version_digest = current_protocol_digest;
5883
5884 while let Some((version, digest, packages)) = Self::is_protocol_version_supported_v1(
5888 next_protocol_version + 1,
5889 committee,
5890 capabilities.clone(),
5891 buffer_stake_bps,
5892 ) {
5893 next_protocol_version = version;
5894 protocol_version_digest = digest;
5895 system_packages = packages;
5896 }
5897
5898 (
5899 next_protocol_version,
5900 protocol_version_digest,
5901 system_packages,
5902 )
5903 }
5904
5905 fn get_validators_supporting_protocol_version(
5910 target_protocol_version: ProtocolVersion,
5911 target_digest: Digest,
5912 active_validators: &[AggregateAuthorityPublicKey],
5913 capabilities: &[AuthorityCapabilitiesV1],
5914 ) -> Vec<u64> {
5915 let mut eligible_validators = Vec::new();
5916
5917 for capability in capabilities {
5918 if let Some(digest) = capability
5920 .supported_protocol_versions
5921 .get_version_digest(target_protocol_version)
5922 {
5923 if digest == target_digest {
5924 if let Some(index) = active_validators
5926 .iter()
5927 .position(|name| AuthorityName::from(name) == capability.authority)
5928 {
5929 eligible_validators.push(index as u64);
5930 }
5931 }
5932 }
5933 }
5934
5935 eligible_validators.sort();
5937 eligible_validators
5938 }
5939
5940 fn calculate_eligible_validators_weight(
5945 eligible_validator_indices: &[u64],
5946 active_validators: &[AggregateAuthorityPublicKey],
5947 committee: &Committee,
5948 ) -> u64 {
5949 let mut total_weight = 0u64;
5950
5951 for &index in eligible_validator_indices {
5952 let authority_pubkey = &active_validators[index as usize];
5953 if let Some((_, weight)) = committee
5955 .members()
5956 .find(|(name, _)| *name == AuthorityName::from(authority_pubkey))
5957 {
5958 total_weight += weight;
5959 }
5960 }
5961
5962 total_weight
5963 }
5964
5965 #[instrument(level = "error", skip_all)]
5984 pub async fn create_and_execute_advance_epoch_tx(
5985 &self,
5986 epoch_store: &Arc<AuthorityPerEpochStore>,
5987 gas_cost_summary: &GasCostSummary,
5988 checkpoint: CheckpointSequenceNumber,
5989 epoch_start_timestamp_ms: CheckpointTimestamp,
5990 scores: Vec<u64>,
5991 ) -> CheckpointBuilderResult<(
5992 IotaSystemState,
5993 Option<SystemEpochInfoEvent>,
5994 TransactionEffects,
5995 )> {
5996 let mut txns = Vec::new();
5997
5998 if epoch_store.protocol_config().enable_pcool_flow()
6004 && epoch_store
6005 .epoch_start_config()
6006 .transaction_deny_rules_obj_initial_shared_version()
6007 .is_none()
6008 {
6009 txns.push(EndOfEpochTransactionKind::TransactionDenyRulesCreate);
6010 }
6011
6012 let next_epoch = epoch_store.epoch() + 1;
6013
6014 let buffer_stake_bps = epoch_store.get_effective_buffer_stake_bps();
6015 let authority_capabilities = epoch_store
6016 .get_capabilities_v1()
6017 .expect("read capabilities from db cannot fail");
6018 let (next_epoch_protocol_version, next_epoch_protocol_digest, next_epoch_system_packages) =
6019 Self::choose_protocol_version_and_system_packages_v1(
6020 epoch_store.protocol_version(),
6021 SupportedProtocolVersionsWithHashes::protocol_config_digest(
6022 epoch_store.protocol_config(),
6023 ),
6024 epoch_store.committee(),
6025 authority_capabilities.clone(),
6026 buffer_stake_bps,
6027 );
6028
6029 let config = epoch_store.protocol_config();
6033 let binary_config = to_binary_config(config, None);
6034 let Some(next_epoch_system_package_bytes) = self
6035 .get_system_package_bytes(next_epoch_system_packages.clone(), &binary_config)
6036 .await
6037 else {
6038 debug_fatal!(
6039 "upgraded system packages {:?} are not locally available, cannot create \
6040 ChangeEpochTx. validator binary must be upgraded to the correct version!",
6041 next_epoch_system_packages
6042 );
6043 return Err(CheckpointBuilderError::SystemPackagesMissing);
6052 };
6053
6054 if config.select_committee_from_eligible_validators() {
6057 let active_validators = epoch_store.epoch_start_state().get_active_validators();
6059
6060 let mut eligible_active_validators = (0..active_validators.len() as u64).collect();
6061
6062 if config.select_committee_supporting_next_epoch_version() {
6066 eligible_active_validators = Self::get_validators_supporting_protocol_version(
6067 next_epoch_protocol_version,
6068 next_epoch_protocol_digest,
6069 &active_validators,
6070 &authority_capabilities,
6071 );
6072
6073 let eligible_validators_weight = Self::calculate_eligible_validators_weight(
6075 &eligible_active_validators,
6076 &active_validators,
6077 epoch_store.committee(),
6078 );
6079
6080 let committee = epoch_store.committee();
6084 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
6085
6086 if eligible_validators_weight < effective_threshold {
6087 error!(
6088 "Eligible validators weight {eligible_validators_weight} is less than effective threshold {effective_threshold}. \
6089 This could indicate a bug in validator selection logic or inconsistency with protocol version decision.",
6090 );
6091 eligible_active_validators = (0..active_validators.len() as u64).collect();
6094 }
6095 }
6096
6097 if config.pass_validator_scores_to_advance_epoch() {
6100 txns.push(EndOfEpochTransactionKind::new_change_epoch_v4(
6101 next_epoch,
6102 next_epoch_protocol_version.as_u64(),
6103 gas_cost_summary.storage_cost,
6104 gas_cost_summary.computation_cost,
6105 gas_cost_summary.computation_cost_burned,
6106 gas_cost_summary.storage_rebate,
6107 gas_cost_summary.non_refundable_storage_fee,
6108 epoch_start_timestamp_ms,
6109 next_epoch_system_package_bytes,
6110 eligible_active_validators,
6111 epoch_store.scores_for_advance_epoch(&scores),
6112 config.adjust_rewards_by_score(),
6113 ));
6114 } else {
6115 txns.push(EndOfEpochTransactionKind::new_change_epoch_v3(
6116 next_epoch,
6117 next_epoch_protocol_version.as_u64(),
6118 gas_cost_summary.storage_cost,
6119 gas_cost_summary.computation_cost,
6120 gas_cost_summary.computation_cost_burned,
6121 gas_cost_summary.storage_rebate,
6122 gas_cost_summary.non_refundable_storage_fee,
6123 epoch_start_timestamp_ms,
6124 next_epoch_system_package_bytes,
6125 eligible_active_validators,
6126 ));
6127 }
6128 } else if config.protocol_defined_base_fee()
6129 && config.max_committee_members_count_as_option().is_some()
6130 {
6131 txns.push(EndOfEpochTransactionKind::new_change_epoch_v2(
6132 next_epoch,
6133 next_epoch_protocol_version.as_u64(),
6134 gas_cost_summary.storage_cost,
6135 gas_cost_summary.computation_cost,
6136 gas_cost_summary.computation_cost_burned,
6137 gas_cost_summary.storage_rebate,
6138 gas_cost_summary.non_refundable_storage_fee,
6139 epoch_start_timestamp_ms,
6140 next_epoch_system_package_bytes,
6141 ));
6142 } else {
6143 txns.push(EndOfEpochTransactionKind::new_change_epoch(
6144 next_epoch,
6145 next_epoch_protocol_version.as_u64(),
6146 gas_cost_summary.storage_cost,
6147 gas_cost_summary.computation_cost,
6148 gas_cost_summary.storage_rebate,
6149 gas_cost_summary.non_refundable_storage_fee,
6150 epoch_start_timestamp_ms,
6151 next_epoch_system_package_bytes,
6152 ));
6153 }
6154
6155 let tx = VerifiedTransaction::new_end_of_epoch_transaction(txns);
6156
6157 let executable_tx = VerifiedExecutableTransaction::new_from_checkpoint(
6158 tx.clone(),
6159 epoch_store.epoch(),
6160 checkpoint,
6161 );
6162
6163 let tx_digest = executable_tx.digest();
6164
6165 info!(
6166 ?next_epoch,
6167 ?next_epoch_protocol_version,
6168 ?next_epoch_system_packages,
6169 computation_cost=?gas_cost_summary.computation_cost,
6170 computation_cost_burned=?gas_cost_summary.computation_cost_burned,
6171 storage_cost=?gas_cost_summary.storage_cost,
6172 storage_rebate=?gas_cost_summary.storage_rebate,
6173 non_refundable_storage_fee=?gas_cost_summary.non_refundable_storage_fee,
6174 ?tx_digest,
6175 "Creating advance epoch transaction"
6176 );
6177
6178 fail_point_async!("change_epoch_tx_delay");
6179 let tx_lock = epoch_store.acquire_tx_lock(tx_digest);
6180
6181 if self
6185 .get_transaction_cache_reader()
6186 .try_is_tx_already_executed(tx_digest)?
6187 {
6188 warn!("change epoch tx has already been executed via state sync");
6189 return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
6190 }
6191
6192 let execution_guard = self.execution_lock_for_executable_transaction(&executable_tx)?;
6193
6194 let assigned_versions = epoch_store.assign_shared_object_versions_idempotent(
6198 self.get_object_cache_reader().as_ref(),
6199 std::iter::once(&Schedulable::Transaction(&executable_tx)),
6200 )?;
6201
6202 assert_eq!(assigned_versions.0.len(), 1);
6203 let assigned_versions = assigned_versions.0.into_iter().next().unwrap().1;
6204
6205 let (input_objects, _) = self.read_objects_for_execution(
6206 &tx_lock,
6207 &executable_tx,
6208 assigned_versions,
6209 epoch_store,
6210 )?;
6211
6212 let (temporary_store, effects, _execution_error_opt, _, _) = self.execute_transaction(
6213 &execution_guard,
6214 &executable_tx,
6215 input_objects,
6216 vec![],
6217 &AttestationSource::Unattested,
6218 epoch_store,
6219 )?;
6220 let system_obj = get_iota_system_state(&temporary_store.written)
6221 .expect("change epoch tx must write to system object");
6222 let system_epoch_info_event = temporary_store
6224 .events
6225 .0
6226 .into_iter()
6227 .find(|event| event.is_system_epoch_info_event())
6228 .map(SystemEpochInfoEvent::from);
6229 assert!(system_epoch_info_event.is_some() || system_obj.safe_mode());
6232
6233 self.get_state_sync_store()
6237 .try_insert_transaction_and_effects(&tx, &effects)?;
6238
6239 info!(
6240 "Effects summary of the change epoch transaction: {:?}",
6241 effects.summary_for_debug()
6242 );
6243 epoch_store.record_checkpoint_builder_is_safe_mode_metric(system_obj.safe_mode());
6244 assert!(effects.status().is_success());
6246 Ok((system_obj, system_epoch_info_event, effects))
6247 }
6248
6249 #[instrument(level = "error", skip_all)]
6253 async fn revert_uncommitted_epoch_transactions(
6254 &self,
6255 epoch_store: &AuthorityPerEpochStore,
6256 ) -> IotaResult {
6257 {
6258 let state = epoch_store.get_reconfig_state_write_lock_guard();
6259 if state.should_accept_user_certs() {
6260 epoch_store.close_user_certs(state);
6269 }
6270 }
6272
6273 if !epoch_store.protocol_config().enable_pcool_flow() {
6276 let pending_certificates = epoch_store.pending_consensus_certificates();
6277 info!(
6278 "Reverting {} locally executed transactions that was not included in the epoch: \
6279 {:?}",
6280 pending_certificates.len(),
6281 pending_certificates,
6282 );
6283 for digest in pending_certificates {
6284 if epoch_store.is_transaction_executed_in_checkpoint(&digest)? {
6285 info!(
6286 "Not reverting pending consensus transaction {:?} - it was included in \
6287 checkpoint",
6288 digest
6289 );
6290 continue;
6291 }
6292 info!("Reverting {:?} at the end of epoch", digest);
6293 epoch_store.revert_executed_transaction(&digest)?;
6294 self.get_reconfig_api().try_revert_state_update(&digest)?;
6295 }
6296 info!("All uncommitted local transactions reverted");
6297 } else {
6298 info!("P-COOL mode: skipping revert of uncommitted epoch transactions");
6299 }
6300
6301 Ok(())
6302 }
6303
6304 #[instrument(level = "error", skip_all)]
6305 async fn reopen_epoch_db(
6306 &self,
6307 cur_epoch_store: &AuthorityPerEpochStore,
6308 new_committee: Committee,
6309 epoch_start_configuration: EpochStartConfiguration,
6310 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
6311 epoch_last_checkpoint: CheckpointSequenceNumber,
6312 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
6313 let new_epoch = new_committee.epoch;
6314 info!(new_epoch = ?new_epoch, "re-opening AuthorityEpochTables for new epoch");
6315 assert_eq!(
6316 epoch_start_configuration.epoch_start_state().epoch(),
6317 new_committee.epoch
6318 );
6319 fail_point!("before-open-new-epoch-store");
6320 let new_epoch_store = cur_epoch_store.new_at_next_epoch(
6321 self.name,
6322 new_committee,
6323 epoch_start_configuration,
6324 self.get_backing_package_store().clone(),
6325 expensive_safety_check_config,
6326 epoch_last_checkpoint,
6327 )?;
6328 self.epoch_store.store(new_epoch_store.clone());
6329 Ok(new_epoch_store)
6330 }
6331
6332 fn check_move_account_for_execution(
6354 &self,
6355 auth_account_object_id: ObjectId,
6356 auth_account_object_seq_number: Option<Version>,
6357 auth_account_object_digest: Option<ObjectDigest>,
6358 account_object: ObjectReadResult,
6359 signer: &Address,
6360 protocol_config: &ProtocolConfig,
6361 ) -> Result<AuthenticatorFunctionRefForExecution, ExecutionError> {
6362 match self.check_move_account(
6363 auth_account_object_id,
6364 auth_account_object_seq_number,
6365 auth_account_object_digest,
6366 account_object,
6367 signer,
6368 true,
6369 protocol_config,
6370 ) {
6371 Ok(function_ref) => Ok(function_ref),
6372 Err(MoveAccountCheckError::Input(input_error)) => {
6373 let status = match &input_error {
6374 UserInputError::MoveAuthenticatorNotFound {
6375 account_object_id, ..
6376 }
6377 | UserInputError::InvalidAuthenticatorFunctionRefField { account_object_id } => {
6378 ExecutionErrorKind::AuthenticatorFunctionNotFound {
6379 object_id: *account_object_id,
6380 }
6381 }
6382 UserInputError::AccountObjectNotSupported { object_id }
6387 | UserInputError::ImmutableAccountObjectNotSupported { object_id }
6388 | UserInputError::InvalidAccountObjectDigest { object_id, .. } => {
6389 ExecutionErrorKind::AccountNotSharedObject {
6390 object_id: *object_id,
6391 }
6392 }
6393 _ => ExecutionErrorKind::FunctionNotFound,
6396 };
6397 Err(ExecutionError::new_with_source(status, input_error))
6398 }
6399 Err(MoveAccountCheckError::Storage(storage_error)) => {
6400 panic!("failed to read the store while checking a Move account: {storage_error}")
6401 }
6402 }
6403 }
6404
6405 fn check_move_account_for_validation(
6409 &self,
6410 auth_account_object_id: ObjectId,
6411 auth_account_object_seq_number: Option<Version>,
6412 auth_account_object_digest: Option<ObjectDigest>,
6413 account_object: ObjectReadResult,
6414 signer: &Address,
6415 protocol_config: &ProtocolConfig,
6416 ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
6417 self.check_move_account(
6418 auth_account_object_id,
6419 auth_account_object_seq_number,
6420 auth_account_object_digest,
6421 account_object,
6422 signer,
6423 false,
6424 protocol_config,
6425 )
6426 .map_err(IotaError::from)
6427 }
6428
6429 fn check_move_account(
6446 &self,
6447 auth_account_object_id: ObjectId,
6448 auth_account_object_seq_number: Option<Version>,
6449 auth_account_object_digest: Option<ObjectDigest>,
6450 account_object: ObjectReadResult,
6451 signer: &Address,
6452 is_execution: bool,
6453 protocol_config: &ProtocolConfig,
6454 ) -> Result<AuthenticatorFunctionRefForExecution, MoveAccountCheckError> {
6455 let auth_account_object_seq_number = match (&account_object.object, is_execution) {
6456 (ObjectReadResultKind::Object(object), _) => {
6460 let account_object_addr = Address::from(auth_account_object_id);
6461 fp_ensure!(
6462 signer == &account_object_addr,
6463 UserInputError::IncorrectUserSignature {
6464 error: format!("Move authenticator is trying to unlock {account_object_addr:?}, but given signer address is {signer:?}")
6465 }
6466 .into()
6467 );
6468
6469 if protocol_config.reject_immutable_account_objects() {
6470 fp_ensure!(
6471 !object.is_immutable(),
6472 UserInputError::ImmutableAccountObjectNotSupported {
6473 object_id: auth_account_object_id
6474 }
6475 .into()
6476 );
6477 }
6478
6479 fp_ensure!(
6480 object.is_shared() || object.is_immutable(),
6481 UserInputError::AccountObjectNotSupported {
6482 object_id: auth_account_object_id
6483 }
6484 .into()
6485 );
6486
6487 let auth_account_object_seq_number =
6488 if let Some(expected_version) = auth_account_object_seq_number {
6489 let account_object_version = object.version();
6490
6491 fp_ensure!(
6492 account_object_version == expected_version,
6493 UserInputError::AccountObjectVersionMismatch {
6494 object_id: auth_account_object_id,
6495 expected_version,
6496 actual_version: account_object_version,
6497 }
6498 .into()
6499 );
6500
6501 expected_version
6502 } else {
6503 object.version()
6504 };
6505
6506 if let Some(expected_digest) = auth_account_object_digest {
6507 let account_object_digest = object.digest();
6508 fp_ensure!(
6509 account_object_digest == expected_digest,
6510 UserInputError::InvalidAccountObjectDigest {
6511 object_id: auth_account_object_id,
6512 expected_digest,
6513 actual_digest: account_object_digest,
6514 }
6515 .into()
6516 );
6517 }
6518
6519 Ok(auth_account_object_seq_number)
6520 }
6521 (ObjectReadResultKind::DeletedSharedObject(version, digest), false) => {
6524 Err(UserInputError::AccountObjectDeleted {
6525 account_id: account_object.id(),
6526 account_version: *version,
6527 transaction_digest: *digest,
6528 })
6529 }
6530 (ObjectReadResultKind::CancelledTransactionObject(version), false) => {
6534 Err(UserInputError::AccountObjectInCanceledTransaction {
6535 account_id: account_object.id(),
6536 account_version: *version,
6537 })
6538 }
6539 (ObjectReadResultKind::DeletedSharedObject(version, _), true) => Ok(*version),
6544 (ObjectReadResultKind::CancelledTransactionObject(version), true) => Ok(*version),
6550 (ObjectReadResultKind::UnreadSharedObject, _) => unreachable!(
6553 "only post-consensus validation at a commit lists an unread shared object, and \
6554 it leaves the account to execution"
6555 ),
6556 }?;
6557
6558 let authenticator_function_ref_field_id =
6559 derive_authenticator_function_ref_v1_dynamic_field_id(auth_account_object_id)?;
6560
6561 let authenticator_function_ref_field = self
6562 .get_object_cache_reader()
6563 .try_find_object_lt_or_eq_version(
6564 authenticator_function_ref_field_id,
6565 auth_account_object_seq_number,
6566 )
6567 .map_err(MoveAccountCheckError::Storage)?;
6568
6569 if let Some(authenticator_function_ref_field_obj) = authenticator_function_ref_field {
6570 Ok(authenticator_function_ref_v1_from_dynamic_field_object(
6571 auth_account_object_id,
6572 &authenticator_function_ref_field_obj,
6573 )?)
6574 } else {
6575 Err(UserInputError::MoveAuthenticatorNotFound {
6576 authenticator_function_ref_id: authenticator_function_ref_field_id,
6577 account_object_id: auth_account_object_id,
6578 account_object_version: auth_account_object_seq_number,
6579 }
6580 .into())
6581 }
6582 }
6583
6584 fn run_validation_checks<'a>(
6598 &self,
6599 transaction: &'a VerifiedTransaction,
6600 epoch_store: &Arc<AuthorityPerEpochStore>,
6601 deny_config: &dyn DenyRuleConfig,
6602 is_execute_transaction_to_effects: bool,
6603 ) -> IotaResult<ValidationOutputs<'a>> {
6604 let protocol_config = epoch_store.protocol_config();
6605 let reference_gas_price = epoch_store.reference_gas_price();
6606 let epoch = epoch_store.epoch();
6607 let tx = transaction.data().transaction();
6608
6609 iota_transaction_checks::deny::check_transaction_for_validation(
6614 tx,
6615 transaction.signatures(),
6616 &transaction
6617 .input_objects(protocol_config.move_authenticator_type_arg_packages_as_inputs())?,
6618 &tx.receiving_objects(),
6619 deny_config,
6620 self.get_backing_package_store().as_ref(),
6621 )?;
6622
6623 let (tx_input_objects, tx_receiving_objects, per_authenticator_inputs) =
6625 self.read_objects_for_validation(transaction, epoch, protocol_config)?;
6626
6627 let move_authenticators = transaction.move_authenticators();
6629
6630 let per_authenticator_inputs_for_output = if is_execute_transaction_to_effects {
6642 per_authenticator_inputs.clone()
6643 } else {
6644 Vec::new()
6645 };
6646 let (gas_status, tx_checked_input_objects, per_authenticator_checked_inputs) = self
6647 .check_transaction_inputs_for_validation(
6648 protocol_config,
6649 reference_gas_price,
6650 tx,
6651 tx_input_objects,
6652 &tx_receiving_objects,
6653 &move_authenticators,
6654 per_authenticator_inputs,
6655 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
6656 is_execute_transaction_to_effects,
6657 )?;
6658
6659 debug_assert!(
6662 per_authenticator_checked_inputs
6663 .iter()
6664 .all(|(objects, _)| objects.inner().filter_owned_objects().is_empty()),
6665 "Move authenticator input objects must not contain owned objects"
6666 );
6667
6668 if protocol_config.deny_authenticator_packages() {
6675 iota_transaction_checks::deny::check_authenticator_packages(
6676 deny_config,
6677 per_authenticator_checked_inputs
6678 .iter()
6679 .map(|(_, authenticator_function_ref)| authenticator_function_ref),
6680 self.get_backing_package_store().as_ref(),
6681 )?;
6682 }
6683
6684 let per_authenticator_input_objects: Vec<&InputObjects> = per_authenticator_checked_inputs
6689 .iter()
6690 .map(|i| i.0.inner())
6691 .collect();
6692 check_coin_deny_list_v1(
6693 tx.sender(),
6694 tx_checked_input_objects.inner(),
6695 &tx_receiving_objects,
6696 &per_authenticator_input_objects,
6697 &self.get_object_store(),
6698 )?;
6699
6700 Ok(ValidationOutputs {
6701 per_authenticator_inputs: per_authenticator_inputs_for_output,
6702 move_authenticators,
6703 gas_status,
6704 tx_checked_input_objects,
6705 per_authenticator_checked_inputs,
6706 })
6707 }
6708
6709 #[allow(clippy::type_complexity)]
6710 fn read_objects_for_validation(
6711 &self,
6712 transaction: &VerifiedTransaction,
6713 epoch: u64,
6714 protocol_config: &ProtocolConfig,
6715 ) -> IotaResult<(
6716 InputObjects,
6717 ReceivingObjects,
6718 Vec<(InputObjects, ObjectReadResult)>,
6719 )> {
6720 let (input_objects, tx_receiving_objects) = self.input_loader.read_objects_for_signing(
6721 Some(transaction.digest()),
6722 &transaction.collect_all_input_object_kind_for_reading(
6723 protocol_config.move_authenticator_type_arg_packages_as_inputs(),
6724 )?,
6725 &transaction.data().transaction().receiving_objects(),
6726 epoch,
6727 )?;
6728
6729 transaction
6730 .split_input_objects_into_groups_for_reading(input_objects)
6731 .map(|(tx_input_objects, per_authenticator_inputs)| {
6732 (
6733 tx_input_objects,
6734 tx_receiving_objects,
6735 per_authenticator_inputs,
6736 )
6737 })
6738 }
6739
6740 fn read_objects_for_validation_at_commit(
6745 &self,
6746 reader: &CommitIndexedReader,
6747 transaction: &VerifiedTransaction,
6748 protocol_config: &ProtocolConfig,
6749 ) -> IotaResult<ValidationInputsAtCommit> {
6750 let input_objects = match self.input_loader.read_objects_at_commit(
6751 reader,
6752 &transaction.collect_all_input_object_kind_for_reading(
6753 protocol_config.move_authenticator_type_arg_packages_as_inputs(),
6754 )?,
6755 )? {
6756 InputResolution::Loaded(input_objects) => input_objects,
6757 InputResolution::Drop(kind, reason) => {
6758 return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6759 }
6760 InputResolution::Missing(kind, reason) => {
6761 return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6762 }
6763 };
6764 let tx_receiving_objects = match self.input_loader.read_receiving_objects_at_commit(
6765 reader,
6766 &transaction.data().transaction().receiving_objects(),
6767 )? {
6768 ReceivingObjectsResolution::Loaded(receiving_objects) => receiving_objects,
6769 ReceivingObjectsResolution::Drop(kind, reason) => {
6770 return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6771 }
6772 ReceivingObjectsResolution::Missing(kind, reason) => {
6773 return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6774 }
6775 };
6776
6777 let (tx_input_objects, per_authenticator_inputs) =
6778 transaction.split_input_objects_into_groups_for_reading(input_objects)?;
6779 Ok(ValidationInputsAtCommit::Loaded {
6780 tx_input_objects,
6781 tx_receiving_objects,
6782 per_authenticator_inputs,
6783 })
6784 }
6785
6786 #[allow(clippy::type_complexity)]
6787 fn check_transaction_inputs_for_validation(
6788 &self,
6789 protocol_config: &ProtocolConfig,
6790 reference_gas_price: u64,
6791 tx: &Transaction,
6792 tx_input_objects: InputObjects,
6793 tx_receiving_objects: &ReceivingObjects,
6794 move_authenticators: &Vec<&MoveAuthenticator>,
6795 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6796 verifier_limits_source: VerifierLimitsSource<'_>,
6797 is_execute_transaction_to_effects: bool,
6798 ) -> IotaResult<(
6799 IotaGasStatus,
6800 CheckedInputObjects,
6801 Vec<(CheckedInputObjects, AuthenticatorFunctionRef)>,
6802 )> {
6803 let authenticator_gas_budget = if move_authenticators.is_empty() {
6804 0
6805 } else {
6806 protocol_config.max_auth_gas()
6809 };
6810
6811 debug_assert_eq!(
6812 move_authenticators.len(),
6813 per_authenticator_inputs.len(),
6814 "Move authenticators amount must match the number of authenticator inputs"
6815 );
6816
6817 let per_authenticator_checked_inputs = move_authenticators
6818 .iter()
6819 .zip(per_authenticator_inputs)
6820 .map(
6821 |(move_authenticator, (authenticator_input_objects, account_object))| {
6822 let (
6824 auth_account_object_id,
6825 auth_account_object_seq_number,
6826 auth_account_object_digest,
6827 ) = move_authenticator.object_to_authenticate_components()?;
6828
6829 let signer = move_authenticator.address();
6830
6831 let AuthenticatorFunctionRefForExecution {
6833 authenticator_function_ref,
6834 ..
6835 } = self.check_move_account_for_validation(
6836 auth_account_object_id,
6837 auth_account_object_seq_number,
6838 auth_account_object_digest,
6839 account_object,
6840 &signer,
6841 protocol_config,
6842 )?;
6843
6844 let authenticator_checked_input_objects =
6846 iota_transaction_checks::check_move_authenticator_input_for_validation(
6847 authenticator_input_objects,
6848 )?;
6849
6850 Ok((
6851 authenticator_checked_input_objects,
6852 authenticator_function_ref,
6853 ))
6854 },
6855 )
6856 .collect::<IotaResult<Vec<_>>>()?;
6857
6858 let (gas_status, tx_checked_input_objects) =
6860 iota_transaction_checks::check_transaction_input(
6861 protocol_config,
6862 reference_gas_price,
6863 tx,
6864 tx_input_objects,
6865 tx_receiving_objects,
6866 &self.metrics.bytecode_verifier_metrics,
6867 verifier_limits_source,
6868 authenticator_gas_budget,
6869 is_execute_transaction_to_effects,
6870 )?;
6871
6872 Ok((
6873 gas_status,
6874 tx_checked_input_objects,
6875 per_authenticator_checked_inputs,
6876 ))
6877 }
6878
6879 fn check_transaction_inputs_at_commit(
6886 &self,
6887 protocol_config: &ProtocolConfig,
6888 reference_gas_price: u64,
6889 tx: &Transaction,
6890 tx_input_objects: InputObjects,
6891 tx_receiving_objects: &ReceivingObjects,
6892 move_authenticators: &[&MoveAuthenticator],
6893 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6894 verifier_limits_source: VerifierLimitsSource<'_>,
6895 ) -> IotaResult<CheckedValidationInputs> {
6896 let authenticator_gas_budget = if move_authenticators.is_empty() {
6897 0
6898 } else {
6899 protocol_config.max_auth_gas()
6900 };
6901
6902 debug_assert_eq!(
6903 move_authenticators.len(),
6904 per_authenticator_inputs.len(),
6905 "Move authenticators amount must match the number of authenticator inputs"
6906 );
6907
6908 let per_authenticator_checked_inputs = per_authenticator_inputs
6917 .into_iter()
6918 .map(|(authenticator_input_objects, _account_object)| {
6919 iota_transaction_checks::check_move_authenticator_input_for_validation(
6920 authenticator_input_objects,
6921 )
6922 })
6923 .collect::<IotaResult<Vec<_>>>()?;
6924
6925 let (_gas_status, tx_checked_input_objects) =
6927 iota_transaction_checks::check_transaction_input(
6928 protocol_config,
6929 reference_gas_price,
6930 tx,
6931 tx_input_objects,
6932 tx_receiving_objects,
6933 &self.metrics.bytecode_verifier_metrics,
6934 verifier_limits_source,
6935 authenticator_gas_budget,
6936 false,
6937 )?;
6938
6939 Ok((tx_checked_input_objects, per_authenticator_checked_inputs))
6940 }
6941
6942 #[cfg(test)]
6943 pub(crate) fn iter_live_object_set_for_testing(
6944 &self,
6945 ) -> impl Iterator<Item = authority_store_tables::LiveObject> + '_ {
6946 self.get_global_state_hash_store()
6947 .iter_cached_live_object_set_for_testing()
6948 .map(|live_object| live_object.expect("reading the live object set cannot fail"))
6949 }
6950
6951 #[cfg(test)]
6952 pub(crate) fn shutdown_execution_for_test(&self) {
6953 self.tx_execution_shutdown
6954 .lock()
6955 .take()
6956 .unwrap()
6957 .send(())
6958 .unwrap();
6959 }
6960
6961 pub async fn insert_objects_unsafe_for_testing_only(&self, objects: &[Object]) {
6964 self.get_reconfig_api().bulk_insert_genesis_objects(objects);
6965 self.get_object_cache_reader()
6966 .force_reload_system_packages(&BuiltInFramework::all_package_ids());
6967 self.get_reconfig_api()
6968 .clear_state_end_of_epoch(&self.execution_lock_for_reconfiguration().await);
6969 }
6970}
6971
6972pub struct RandomnessRoundReceiver {
6973 authority_state: Arc<AuthorityState>,
6974 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6975}
6976
6977impl RandomnessRoundReceiver {
6978 pub fn spawn(
6979 authority_state: Arc<AuthorityState>,
6980 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6981 ) -> JoinHandle<()> {
6982 let rrr = RandomnessRoundReceiver {
6983 authority_state,
6984 randomness_rx,
6985 };
6986 spawn_monitored_task!(rrr.run())
6987 }
6988
6989 async fn run(mut self) {
6990 info!("RandomnessRoundReceiver event loop started");
6991
6992 loop {
6993 tokio::select! {
6994 maybe_recv = self.randomness_rx.recv() => {
6995 if let Some((epoch, round, bytes)) = maybe_recv {
6996 self.handle_new_randomness(epoch, round, bytes).await;
6997 } else {
6998 break;
6999 }
7000 },
7001 }
7002 }
7003
7004 info!("RandomnessRoundReceiver event loop ended");
7005 }
7006
7007 #[instrument(level = "debug", skip_all, fields(?epoch, ?round))]
7008 async fn handle_new_randomness(&self, epoch: EpochId, round: RandomnessRound, bytes: Vec<u8>) {
7009 fail_point_async!("randomness-delay");
7010
7011 let epoch_store = self.authority_state.load_epoch_store_one_call_per_task();
7012 if epoch_store.epoch() != epoch {
7013 warn!(
7014 "dropping randomness for epoch {epoch}, round {round}, because we are in epoch {}",
7015 epoch_store.epoch()
7016 );
7017 return;
7018 }
7019 let key = TransactionKey::RandomnessRound(epoch, round);
7020 let transaction = VerifiedTransaction::new_randomness_state_update(
7021 epoch,
7022 round,
7023 bytes,
7024 epoch_store
7025 .epoch_start_config()
7026 .randomness_obj_initial_shared_version(),
7027 );
7028 debug!(
7029 "created randomness state update transaction with digest: {:?}",
7030 transaction.digest()
7031 );
7032 let transaction = VerifiedExecutableTransaction::new_system(transaction, epoch);
7033 let digest = *transaction.digest();
7034
7035 self.authority_state
7040 .get_cache_commit()
7041 .persist_transaction(&transaction);
7042
7043 if epoch_store.insert_tx_key(key, digest).is_err() {
7045 warn!("epoch ended while handling new randomness");
7046 }
7047
7048 match self.authority_state.execution_scheduler().as_ref() {
7050 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
7051 ExecutionSchedulerWrapper::TransactionManager(manager) => {
7052 manager.notify_transaction_key(&epoch_store, key, digest);
7056 }
7057 }
7058
7059 let authority_state = self.authority_state.clone();
7060 spawn_monitored_task!(async move {
7061 const RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT: Duration = Duration::from_secs(300);
7070 let result = tokio::time::timeout(
7071 RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT,
7072 authority_state
7073 .get_transaction_cache_reader()
7074 .try_notify_read_executed_effects(
7075 "RandomnessRoundReceiver::notify_read_executed_effects_first",
7076 &[digest],
7077 ),
7078 )
7079 .await;
7080 let result = match result {
7081 Ok(result) => result,
7082 Err(_) => {
7083 if cfg!(debug_assertions) {
7084 panic!(
7086 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
7087 );
7088 }
7089 warn!(
7090 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
7091 );
7092 authority_state
7094 .get_transaction_cache_reader()
7095 .try_notify_read_executed_effects(
7096 "RandomnessRoundReceiver::notify_read_executed_effects_second",
7097 &[digest],
7098 )
7099 .await
7100 }
7101 };
7102
7103 let mut effects = result.unwrap_or_else(|_| panic!("failed to get effects for randomness state update transaction at epoch {epoch}, round {round}"));
7104 let effects = effects.pop().expect("should return effects");
7105 if *effects.status() != ExecutionStatus::Success {
7106 fatal!(
7107 "failed to execute randomness state update transaction at epoch {epoch}, round {round}: {effects:?}"
7108 );
7109 }
7110 debug!(
7111 "successfully executed randomness state update transaction at epoch {epoch}, round {round}"
7112 );
7113 });
7114 }
7115}
7116
7117#[async_trait]
7118impl TransactionKeyValueStoreTrait for AuthorityState {
7119 async fn multi_get(
7120 &self,
7121 transaction_keys: &[TransactionDigest],
7122 effects_keys: &[TransactionDigest],
7123 ) -> IotaResult<KVStoreTransactionData> {
7124 let txns = if !transaction_keys.is_empty() {
7125 self.get_transaction_cache_reader()
7126 .try_multi_get_transaction_blocks(transaction_keys)?
7127 .into_iter()
7128 .map(|t| t.map(|t| (*t).clone().into_inner()))
7129 .collect()
7130 } else {
7131 vec![]
7132 };
7133
7134 let fx = if !effects_keys.is_empty() {
7135 self.get_transaction_cache_reader()
7136 .try_multi_get_executed_effects(effects_keys)?
7137 } else {
7138 vec![]
7139 };
7140
7141 Ok((txns, fx))
7142 }
7143
7144 async fn multi_get_checkpoints(
7145 &self,
7146 checkpoint_summaries: &[CheckpointSequenceNumber],
7147 checkpoint_contents: &[CheckpointSequenceNumber],
7148 checkpoint_summaries_by_digest: &[CheckpointDigest],
7149 ) -> IotaResult<(
7150 Vec<Option<CertifiedCheckpointSummary>>,
7151 Vec<Option<CheckpointContents>>,
7152 Vec<Option<CertifiedCheckpointSummary>>,
7153 )> {
7154 let mut summaries = Vec::with_capacity(checkpoint_summaries.len());
7156 let store = self.get_checkpoint_store();
7157 for seq in checkpoint_summaries {
7158 let checkpoint = store
7159 .get_checkpoint_by_sequence_number(*seq)?
7160 .map(|c| c.into_inner());
7161
7162 summaries.push(checkpoint);
7163 }
7164
7165 let mut contents = Vec::with_capacity(checkpoint_contents.len());
7166 for seq in checkpoint_contents {
7167 let checkpoint = store
7168 .get_checkpoint_by_sequence_number(*seq)?
7169 .and_then(|summary| {
7170 store
7171 .get_checkpoint_contents(&summary.contents_digest)
7172 .expect("db read cannot fail")
7173 });
7174 contents.push(checkpoint);
7175 }
7176
7177 let mut summaries_by_digest = Vec::with_capacity(checkpoint_summaries_by_digest.len());
7178 for digest in checkpoint_summaries_by_digest {
7179 let checkpoint = store
7180 .get_checkpoint_by_digest(digest)?
7181 .map(|c| c.into_inner());
7182 summaries_by_digest.push(checkpoint);
7183 }
7184
7185 Ok((summaries, contents, summaries_by_digest))
7186 }
7187
7188 async fn get_transaction_perpetual_checkpoint(
7189 &self,
7190 digest: TransactionDigest,
7191 ) -> IotaResult<Option<CheckpointSequenceNumber>> {
7192 self.get_checkpoint_cache()
7193 .try_get_transaction_perpetual_checkpoint(&digest)
7194 .map(|res| res.map(|(_epoch, checkpoint)| checkpoint))
7195 }
7196
7197 async fn get_object(
7198 &self,
7199 object_id: ObjectId,
7200 version: VersionNumber,
7201 ) -> IotaResult<Option<Object>> {
7202 self.get_object_with_historic_fallback(&ObjectKey(object_id, version))
7203 }
7204
7205 #[instrument(skip_all)]
7206 async fn multi_get_objects(
7207 &self,
7208 object_keys: &[ObjectKey],
7209 ) -> IotaResult<Vec<Option<Object>>> {
7210 let mut objects = self
7211 .get_object_cache_reader()
7212 .multi_get_objects_by_key(object_keys);
7213 self.historic_objects
7214 .fill_missing(object_keys, &mut objects, None)?;
7215 Ok(objects)
7216 }
7217
7218 async fn multi_get_transactions_perpetual_checkpoints(
7219 &self,
7220 digests: &[TransactionDigest],
7221 ) -> IotaResult<Vec<Option<CheckpointSequenceNumber>>> {
7222 let res = self
7223 .get_checkpoint_cache()
7224 .try_multi_get_transactions_perpetual_checkpoints(digests)?;
7225
7226 Ok(res
7227 .into_iter()
7228 .map(|maybe| maybe.map(|(_epoch, checkpoint)| checkpoint))
7229 .collect())
7230 }
7231
7232 #[instrument(skip(self, digests), fields(digests = digests.iter().map(|d| d.to_string()).collect::<Vec<String>>().join(", ")))]
7233 async fn multi_get_events_by_tx_digests(
7234 &self,
7235 digests: &[TransactionDigest],
7236 ) -> IotaResult<Vec<Option<TransactionEvents>>> {
7237 if digests.is_empty() {
7238 return Ok(vec![]);
7239 }
7240
7241 Ok(self
7242 .get_transaction_cache_reader()
7243 .multi_get_events(digests))
7244 }
7245}
7246
7247#[cfg(msim)]
7248pub mod framework_injection {
7249 use std::{
7250 cell::RefCell,
7251 collections::{BTreeMap, BTreeSet},
7252 };
7253
7254 use iota_framework::{BuiltInFramework, SystemPackage};
7255 use iota_sdk_types::ObjectId;
7256 use iota_types::base_types::AuthorityName;
7257 use move_binary_format::CompiledModule;
7258
7259 type FrameworkOverrideConfig = BTreeMap<ObjectId, PackageOverrideConfig>;
7260
7261 thread_local! {
7263 static OVERRIDE: RefCell<FrameworkOverrideConfig> = RefCell::new(FrameworkOverrideConfig::default());
7264 }
7265
7266 type Framework = Vec<CompiledModule>;
7267
7268 pub type PackageUpgradeCallback =
7269 Box<dyn Fn(AuthorityName) -> Option<Framework> + Send + Sync + 'static>;
7270
7271 enum PackageOverrideConfig {
7272 Global(Framework),
7273 PerValidator(PackageUpgradeCallback),
7274 }
7275
7276 fn compiled_modules_to_bytes(modules: &[CompiledModule]) -> Vec<Vec<u8>> {
7277 modules
7278 .iter()
7279 .map(|m| {
7280 let mut buf = Vec::new();
7281 m.serialize_with_version(m.version, &mut buf).unwrap();
7282 buf
7283 })
7284 .collect()
7285 }
7286
7287 pub fn set_override(package_id: ObjectId, modules: Vec<CompiledModule>) {
7288 OVERRIDE.with(|bs| {
7289 bs.borrow_mut()
7290 .insert(package_id, PackageOverrideConfig::Global(modules))
7291 });
7292 }
7293
7294 pub fn set_override_cb(package_id: ObjectId, func: PackageUpgradeCallback) {
7295 OVERRIDE.with(|bs| {
7296 bs.borrow_mut()
7297 .insert(package_id, PackageOverrideConfig::PerValidator(func))
7298 });
7299 }
7300
7301 pub fn get_override_bytes(package_id: &ObjectId, name: AuthorityName) -> Option<Vec<Vec<u8>>> {
7302 OVERRIDE.with(|cfg| {
7303 cfg.borrow().get(package_id).and_then(|entry| match entry {
7304 PackageOverrideConfig::Global(framework) => {
7305 Some(compiled_modules_to_bytes(framework))
7306 }
7307 PackageOverrideConfig::PerValidator(func) => {
7308 func(name).map(|fw| compiled_modules_to_bytes(&fw))
7309 }
7310 })
7311 })
7312 }
7313
7314 pub fn get_override_modules(
7315 package_id: &ObjectId,
7316 name: AuthorityName,
7317 ) -> Option<Vec<CompiledModule>> {
7318 OVERRIDE.with(|cfg| {
7319 cfg.borrow().get(package_id).and_then(|entry| match entry {
7320 PackageOverrideConfig::Global(framework) => Some(framework.clone()),
7321 PackageOverrideConfig::PerValidator(func) => func(name),
7322 })
7323 })
7324 }
7325
7326 pub fn get_override_system_package(
7327 package_id: &ObjectId,
7328 name: AuthorityName,
7329 ) -> Option<SystemPackage> {
7330 let bytes = get_override_bytes(package_id, name)?;
7331 let dependencies = BuiltInFramework::try_get_package_by_id(package_id)
7335 .map_or_else(BuiltInFramework::all_package_ids, |package| {
7336 package.dependencies.to_vec()
7337 });
7338 Some(SystemPackage {
7339 id: *package_id,
7340 bytes,
7341 dependencies,
7342 })
7343 }
7344
7345 pub fn get_extra_packages(name: AuthorityName) -> Vec<SystemPackage> {
7346 let built_in = BTreeSet::from_iter(BuiltInFramework::all_package_ids());
7347 let extra: Vec<ObjectId> = OVERRIDE.with(|cfg| {
7348 cfg.borrow()
7349 .keys()
7350 .filter_map(|package| (!built_in.contains(package)).then_some(*package))
7351 .collect()
7352 });
7353
7354 extra
7355 .into_iter()
7356 .map(|package| SystemPackage {
7357 id: package,
7358 bytes: get_override_bytes(&package, name).unwrap(),
7359 dependencies: BuiltInFramework::all_package_ids(),
7360 })
7361 .collect()
7362 }
7363}
7364
7365#[derive(Debug, Serialize, Deserialize, Clone)]
7366pub struct ObjDumpFormat {
7367 pub id: ObjectId,
7368 pub version: VersionNumber,
7369 pub digest: ObjectDigest,
7370 pub object: Object,
7371}
7372
7373impl ObjDumpFormat {
7374 fn new(object: Object) -> Self {
7375 let oref = object.object_ref();
7376 Self {
7377 id: oref.object_id,
7378 version: oref.version,
7379 digest: oref.digest,
7380 object,
7381 }
7382 }
7383}
7384
7385#[derive(Debug, Serialize, Deserialize, Clone)]
7386pub struct NodeStateDump {
7387 pub tx_digest: TransactionDigest,
7388 pub sender_signed_data: SenderSignedTransaction,
7389 pub executed_epoch: u64,
7390 pub reference_gas_price: u64,
7391 pub protocol_version: u64,
7392 pub epoch_start_timestamp_ms: u64,
7393 pub computed_effects: TransactionEffects,
7394 pub expected_effects_digest: TransactionEffectsDigest,
7395 pub relevant_system_packages: Vec<ObjDumpFormat>,
7396 pub shared_objects: Vec<ObjDumpFormat>,
7397 pub loaded_child_objects: Vec<ObjDumpFormat>,
7398 pub modified_at_versions: Vec<ObjDumpFormat>,
7399 pub runtime_reads: Vec<ObjDumpFormat>,
7400 pub input_objects: Vec<ObjDumpFormat>,
7401}
7402
7403impl NodeStateDump {
7404 pub fn new(
7405 tx_digest: &TransactionDigest,
7406 effects: &TransactionEffects,
7407 expected_effects_digest: TransactionEffectsDigest,
7408 object_store: &dyn ObjectStore,
7409 epoch_store: &Arc<AuthorityPerEpochStore>,
7410 inner_temporary_store: &InnerTemporaryStore,
7411 transaction: &VerifiedExecutableTransaction,
7412 ) -> IotaResult<Self> {
7413 let executed_epoch = epoch_store.epoch();
7415 let reference_gas_price = epoch_store.reference_gas_price();
7416 let epoch_start_config = epoch_store.epoch_start_config();
7417 let protocol_version = epoch_store.protocol_version().as_u64();
7418 let epoch_start_timestamp_ms = epoch_start_config.epoch_data().epoch_start_timestamp();
7419
7420 let mut relevant_system_packages = Vec::new();
7422 for sys_package_id in BuiltInFramework::all_package_ids() {
7423 if let Some(w) = object_store.try_get_object(&sys_package_id)? {
7424 relevant_system_packages.push(ObjDumpFormat::new(w))
7425 }
7426 }
7427
7428 let mut shared_objects = Vec::new();
7430 for kind in effects.input_shared_objects() {
7431 match kind {
7432 InputSharedObject::Mutate(obj_ref) | InputSharedObject::ReadOnly(obj_ref) => {
7433 if let Some(w) =
7434 object_store.try_get_object_by_key(&obj_ref.object_id, obj_ref.version)?
7435 {
7436 shared_objects.push(ObjDumpFormat::new(w))
7437 }
7438 }
7439 InputSharedObject::ReadDeleted(..)
7440 | InputSharedObject::MutateDeleted(..)
7441 | InputSharedObject::Canceled(..) => (),
7443 _ => unimplemented!(
7444 "a new InputSharedObject enum variant was added and needs to be handled"
7445 ),
7446 }
7447 }
7448
7449 let mut loaded_child_objects = Vec::new();
7452 for (id, meta) in &inner_temporary_store.loaded_runtime_objects {
7453 if let Some(w) = object_store.try_get_object_by_key(id, meta.version)? {
7454 loaded_child_objects.push(ObjDumpFormat::new(w))
7455 }
7456 }
7457
7458 let mut modified_at_versions = Vec::new();
7460 for modified in effects.modified_at_versions() {
7461 let (id, ver) = (modified.object_id(), modified.version());
7462 if let Some(w) = object_store.try_get_object_by_key(id, ver)? {
7463 modified_at_versions.push(ObjDumpFormat::new(w))
7464 }
7465 }
7466
7467 let mut runtime_reads = Vec::new();
7471 for obj in inner_temporary_store
7472 .runtime_packages_loaded_from_db
7473 .values()
7474 {
7475 runtime_reads.push(ObjDumpFormat::new(obj.object().clone()));
7476 }
7477
7478 Ok(Self {
7481 tx_digest: *tx_digest,
7482 executed_epoch,
7483 reference_gas_price,
7484 epoch_start_timestamp_ms,
7485 protocol_version,
7486 relevant_system_packages,
7487 shared_objects,
7488 loaded_child_objects,
7489 modified_at_versions,
7490 runtime_reads,
7491 sender_signed_data: transaction.clone().into_message(),
7492 input_objects: inner_temporary_store
7493 .input_objects
7494 .values()
7495 .map(|o| ObjDumpFormat::new(o.clone()))
7496 .collect(),
7497 computed_effects: effects.clone(),
7498 expected_effects_digest,
7499 })
7500 }
7501
7502 pub fn all_objects(&self) -> Vec<ObjDumpFormat> {
7503 let mut objects = Vec::new();
7504 objects.extend(self.relevant_system_packages.clone());
7505 objects.extend(self.shared_objects.clone());
7506 objects.extend(self.loaded_child_objects.clone());
7507 objects.extend(self.modified_at_versions.clone());
7508 objects.extend(self.runtime_reads.clone());
7509 objects.extend(self.input_objects.clone());
7510 objects
7511 }
7512
7513 pub fn write_to_file(&self, path: &Path) -> Result<PathBuf, anyhow::Error> {
7514 let file_name = format!(
7515 "{}_{}_NODE_DUMP.json",
7516 self.tx_digest,
7517 AuthorityState::unixtime_now_ms()
7518 );
7519 let mut path = path.to_path_buf();
7520 path.push(&file_name);
7521 let mut file = File::create(path.clone())?;
7522 file.write_all(serde_json::to_string_pretty(self)?.as_bytes())?;
7523 Ok(path)
7524 }
7525
7526 pub fn read_from_file(path: &PathBuf) -> Result<Self, anyhow::Error> {
7527 let file = File::open(path)?;
7528 serde_json::from_reader(file).map_err(|e| anyhow::anyhow!(e))
7529 }
7530}
7531
7532enum MoveAccountCheckError {
7536 Input(UserInputError),
7538
7539 Storage(IotaError),
7541}
7542
7543impl From<UserInputError> for MoveAccountCheckError {
7544 fn from(error: UserInputError) -> Self {
7545 Self::Input(error)
7546 }
7547}
7548
7549impl From<MoveAccountCheckError> for IotaError {
7550 fn from(error: MoveAccountCheckError) -> Self {
7551 match error {
7552 MoveAccountCheckError::Input(error) => IotaError::UserInput { error },
7553 MoveAccountCheckError::Storage(error) => error,
7554 }
7555 }
7556}
7557
7558fn pre_consensus_move_authenticators<'a>(
7570 tx: &'a VerifiedTransaction,
7571 protocol_config: &ProtocolConfig,
7572) -> Vec<&'a MoveAuthenticator> {
7573 if protocol_config.pre_consensus_sponsor_only_move_authentication() {
7574 if tx.transaction().is_sponsored_tx() {
7575 if let Some(sponsor_move_authenticator) = tx.sponsor_move_authenticator() {
7576 vec![sponsor_move_authenticator]
7577 } else {
7578 vec![]
7579 }
7580 } else {
7581 tx.move_authenticators()
7582 }
7583 } else {
7584 tx.move_authenticators()
7585 }
7586}