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