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::{AuthorityPublicKey, AuthoritySignInfo, AuthoritySignature, Signer},
70 deny_list_v1::check_coin_deny_list_v1,
71 deny_rule_governance::DenyRuleConfig,
72 digests::ChainIdentifier,
73 dynamic_field::{DynamicFieldInfo, DynamicFieldName, visitor as DFV},
74 effects::{
75 SignedTransactionEffects, TransactionEffectsAPI, TransactionEffectsExt,
76 VerifiedSignedTransactionEffects,
77 },
78 error::{ExecutionError, IotaError, IotaResult, UserInputError},
79 event::{EventID, SystemEpochInfoEvent},
80 executable_transaction::VerifiedExecutableTransaction,
81 execution_config_utils::to_binary_config,
82 fp_ensure,
83 gas::IotaGasStatus,
84 gas_coin::mock_simulation_gas_coin,
85 inner_temporary_store::{
86 InnerTemporaryStore, ObjectMap, PackageStoreWithFallback, TxCoins, WrittenObjects,
87 },
88 iota_sdk_types_conversions::type_tag_core_to_sdk,
89 iota_system_state::{
90 IotaSystemState, IotaSystemStateTrait,
91 epoch_start_iota_system_state::EpochStartSystemStateTrait, get_iota_system_state,
92 },
93 layout_resolver::{LayoutResolver, into_struct_layout},
94 message_envelope::Message,
95 messages_checkpoint::{
96 CertifiedCheckpointSummary, CheckpointContentsExt, CheckpointRequest, CheckpointResponse,
97 CheckpointSequenceNumber, CheckpointSummaryResponse, CheckpointTimestamp,
98 ECMHLiveObjectSetDigest, VerifiedCheckpoint,
99 },
100 messages_consensus::AuthorityCapabilitiesV1,
101 messages_grpc::{
102 HandleTransactionResponse, LayoutGenerationOption, ObjectInfoRequest,
103 ObjectInfoRequestKind, ObjectInfoResponse, TransactionInfoRequest, TransactionInfoResponse,
104 TransactionStatus,
105 },
106 metrics::{BytecodeVerifierMetrics, LimitsMetrics},
107 move_authenticator::MoveAuthenticatorExt,
108 object::{Object, ObjectRead, PastObjectRead, bounded_visitor::BoundedVisitor},
109 storage::{BackingPackageStore, BackingStore, ObjectKey, ObjectOrTombstone, ObjectStore},
110 supported_protocol_versions::{
111 ProtocolConfig, SupportedProtocolVersions, SupportedProtocolVersionsWithHashes,
112 },
113 traffic_control::{PolicyConfig, RemoteFirewallConfig, TrafficControlReconfigParams},
114 transaction::*,
115 transaction_executor::{SimulateTransactionResult, VmChecks},
116};
117use itertools::Itertools;
118use move_binary_format::{CompiledModule, binary_config::BinaryConfig};
119use move_core_types::{
120 account_address::AccountAddress, annotated_value::MoveStructLayout, language_storage::ModuleId,
121};
122use parking_lot::Mutex;
123use prometheus_filtered::{
124 Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, MetricLevel,
125 Registry, register_histogram_vec_with_registry, register_histogram_with_registry,
126 register_int_counter_vec_with_registry, register_int_counter_with_registry,
127 register_int_gauge_vec_with_registry, register_int_gauge_with_registry,
128};
129use serde::{Deserialize, Serialize, de::DeserializeOwned};
130use tap::TapFallible;
131use tokio::{
132 sync::{RwLock, mpsc, mpsc::unbounded_channel, oneshot},
133 task::JoinHandle,
134};
135use tracing::{debug, error, info, instrument, trace, warn};
136use typed_store::TypedStoreError;
137
138use self::{
139 authority_store::ExecutionLockWriteGuard, authority_store_pruner::AuthorityStorePruningMetrics,
140};
141#[cfg(msim)]
142pub use crate::checkpoints::checkpoint_executor::utils::{
143 CheckpointTimeoutConfig, init_checkpoint_timeout_config,
144};
145use crate::{
146 authority::{
147 authority_per_epoch_store::{AuthorityPerEpochStore, TxGuard},
148 authority_per_epoch_store_pruner::AuthorityPerEpochStorePruner,
149 authority_store::{ExecutionLockReadGuard, ObjectLockStatus},
150 authority_store_pruner::{AuthorityStorePruner, EPOCH_DURATION_MS_FOR_TESTING},
151 authority_store_tables::AuthorityPrunerTables,
152 epoch_start_configuration::{EpochStartConfigTrait, EpochStartConfiguration},
153 shared_object_version_manager::{AssignedVersions, Schedulable},
154 },
155 authority_client::NetworkAuthorityClient,
156 checkpoint_progress_tracker::CheckpointProgressTracker,
157 checkpoints::{CheckpointBuilderError, CheckpointBuilderResult, CheckpointStore},
158 congestion_tracker::CongestionTracker,
159 consensus_adapter::ConsensusAdapter,
160 epoch::committee_store::CommitteeStore,
161 execution_cache::{
162 CheckpointCache, ExecutionCacheCommit, ExecutionCacheReconfigAPI,
163 ExecutionCacheTraitPointers, ExecutionCacheWrite, ObjectCacheRead, StateSyncAPI,
164 TransactionCacheRead,
165 },
166 execution_driver::execution_process,
167 execution_scheduler::{ExecutionSchedulerAPI, ExecutionSchedulerWrapper},
168 global_state_hasher::{GlobalStateHashStore, GlobalStateHasher},
169 grpc_indexes::GrpcIndexesStore,
170 jsonrpc_index::{CoinInfo, IndexStore, ObjectIndexChanges},
171 metrics::{LatencyObserver, RateTracker},
172 module_cache_metrics::ResolverMetrics,
173 overload_monitor::{
174 AuthorityOverloadInfo, compute_graduated_load_shedding_percentage,
175 overload_monitor_accept_tx,
176 },
177 stake_aggregator::StakeAggregator,
178 subscription_handler::SubscriptionHandler,
179 transaction_input_loader::TransactionInputLoader,
180 transaction_outputs::TransactionOutputs,
181 validator_tx_finalizer::ValidatorTxFinalizer,
182 verify_indexes::verify_indexes,
183};
184
185#[cfg(test)]
186#[path = "unit_tests/authority_tests.rs"]
187pub mod authority_tests;
188
189#[cfg(test)]
190#[path = "unit_tests/transaction_tests.rs"]
191pub mod transaction_tests;
192
193#[cfg(test)]
194#[path = "unit_tests/batch_transaction_tests.rs"]
195mod batch_transaction_tests;
196
197#[cfg(test)]
198#[path = "unit_tests/move_integration_tests.rs"]
199pub mod move_integration_tests;
200
201#[cfg(test)]
202#[path = "unit_tests/gas_tests.rs"]
203mod gas_tests;
204
205#[cfg(test)]
206#[path = "unit_tests/batch_verification_tests.rs"]
207mod batch_verification_tests;
208
209#[cfg(test)]
210#[path = "unit_tests/coin_deny_list_tests.rs"]
211mod coin_deny_list_tests;
212
213#[cfg(test)]
214#[path = "unit_tests/auth_unit_test_utils.rs"]
215pub mod auth_unit_test_utils;
216
217#[cfg(any(test, feature = "test-utils"))]
218pub mod authority_test_utils;
219
220pub mod authority_per_epoch_store;
221pub mod authority_per_epoch_store_pruner;
222
223pub mod authority_store_pruner;
224pub mod authority_store_tables;
225pub mod authority_store_types;
226pub mod epoch_start_configuration;
227pub mod shared_object_congestion_tracker;
228pub mod shared_object_version_manager;
229pub mod suggested_gas_price_calculator;
230#[cfg(any(test, feature = "test-utils"))]
231pub mod test_authority_builder;
232pub mod transaction_deferral;
233
234pub(crate) mod authority_store;
235pub mod backpressure;
236pub(crate) mod dropped_tx_status_cache;
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 check_coin_deny_list_v1(
1100 tx.sender(),
1101 &tx_checked_input_objects,
1102 &tx_receiving_objects,
1103 &per_authenticator_checked_input_objects,
1104 &self.get_object_store(),
1105 epoch_gated_coin_deny_list.then_some(epoch),
1106 )?;
1107
1108 let (kind, signer, gas_data) = tx.execution_parts();
1109
1110 let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) =
1111 extract_auth_fun_refs(signer, gas_data.owner, |address| {
1112 move_authenticators
1113 .iter()
1114 .zip(per_authenticator_checked_inputs.iter())
1115 .find(|(move_authenticator, _)| move_authenticator.address() == address)
1116 .map(|(_, (_, auth_fun_ref))| auth_fun_ref.clone())
1117 });
1118
1119 let pre_consensus_move_authenticators =
1124 pre_consensus_move_authenticators(transaction, protocol_config);
1125 debug_assert_eq!(
1128 move_authenticators.len(),
1129 per_authenticator_checked_inputs.len(),
1130 "Move authenticators amount must match the number of checked authenticator inputs"
1131 );
1132 let (move_authenticators, per_authenticator_checked_inputs): (Vec<_>, Vec<_>) =
1133 move_authenticators
1134 .into_iter()
1135 .zip(per_authenticator_checked_inputs)
1136 .filter(|(a, _)| pre_consensus_move_authenticators.contains(a))
1137 .unzip();
1138 let per_authenticator_checked_input_objects: Vec<_> = per_authenticator_checked_inputs
1139 .iter()
1140 .map(|i| &i.0)
1141 .collect();
1142
1143 if !move_authenticators.is_empty() {
1146 let aggregated_authenticator_input_objects =
1147 iota_transaction_checks::aggregate_authenticator_input_objects(
1148 &per_authenticator_checked_input_objects,
1149 )?;
1150
1151 let move_authenticators = move_authenticators
1152 .into_iter()
1153 .zip(per_authenticator_checked_inputs)
1154 .map(
1155 |(
1156 move_authenticator,
1157 (authenticator_checked_input_objects, authenticator_function_ref),
1158 )| {
1159 (
1160 move_authenticator.to_owned(),
1161 authenticator_function_ref,
1162 authenticator_checked_input_objects,
1163 )
1164 },
1165 )
1166 .collect();
1167
1168 let tx_bytes = bcs::to_bytes(tx).expect("Transaction serialization cannot fail");
1173
1174 let (sender_auth_digest, sponsor_auth_digest) =
1175 transaction.data().compute_auth_digests()?;
1176
1177 let auth_context_data = AuthContextData {
1178 transaction_data_bytes: tx_bytes,
1179 sender_auth_digest,
1180 sponsor_auth_digest,
1181 sender_authenticator_function_ref,
1182 sponsor_authenticator_function_ref,
1183 };
1184
1185 let validation_result = epoch_store.executor().authenticate_transaction(
1187 self.get_backing_store().as_ref(),
1188 protocol_config,
1189 self.metrics.limits_metrics.clone(),
1190 &epoch_store.epoch_start_config().epoch_data().epoch_id(),
1191 epoch_store
1192 .epoch_start_config()
1193 .epoch_data()
1194 .epoch_start_timestamp(),
1195 gas_data,
1196 gas_status,
1197 move_authenticators,
1198 aggregated_authenticator_input_objects,
1199 kind,
1200 signer,
1201 transaction.digest().to_owned(),
1202 auth_context_data,
1203 &mut None,
1204 );
1205
1206 if let Err(validation_error) = validation_result {
1207 return Err(IotaError::MoveAuthenticatorExecutionFailure {
1208 error: validation_error.to_string(),
1209 });
1210 }
1211 }
1212
1213 Ok(tx_checked_input_objects.inner().filter_owned_objects())
1214 }
1215
1216 async fn handle_transaction_impl(
1220 &self,
1221 transaction: VerifiedTransaction,
1222 epoch_store: &Arc<AuthorityPerEpochStore>,
1223 ) -> IotaResult<VerifiedSignedTransaction> {
1224 let _execution_lock = self.execution_lock_for_signing()?;
1226
1227 let owned_objects = self
1228 .handle_transaction_validation_checks(
1229 &transaction,
1230 epoch_store,
1231 &self.config.transaction_deny_config,
1232 false,
1237 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
1238 )
1239 .await?;
1240
1241 let epoch = epoch_store.epoch();
1242 let signed_transaction =
1243 VerifiedSignedTransaction::new(epoch, transaction, self.name, &*self.secret);
1244
1245 self.get_cache_writer().try_acquire_transaction_locks(
1250 epoch_store,
1251 &owned_objects,
1252 signed_transaction.clone(),
1253 )?;
1254
1255 Ok(signed_transaction)
1256 }
1257
1258 #[instrument(name = "handle_transaction", level = "trace", skip_all, fields(tx_digest = ?transaction.digest(), sender = transaction.data().transaction().gas_owner().to_string()
1260 ))]
1261 pub async fn handle_transaction(
1262 &self,
1263 epoch_store: &Arc<AuthorityPerEpochStore>,
1264 transaction: VerifiedTransaction,
1265 ) -> IotaResult<HandleTransactionResponse> {
1266 let tx_digest = *transaction.digest();
1267 debug!("handle_transaction");
1268
1269 if let Some((_, status)) = self.get_transaction_status(&tx_digest, epoch_store)? {
1271 return Ok(HandleTransactionResponse { status });
1272 }
1273
1274 let _metrics_guard = self
1275 .metrics
1276 .authority_state_handle_transaction_latency
1277 .start_timer();
1278 self.metrics.tx_orders.inc();
1279
1280 let signed = self.handle_transaction_impl(transaction, epoch_store).await;
1281 match signed {
1282 Ok(s) => {
1283 if self.is_committee_validator(epoch_store) {
1284 if let Some(validator_tx_finalizer) = &self.validator_tx_finalizer {
1285 let tx = s.clone();
1286 let validator_tx_finalizer = validator_tx_finalizer.clone();
1287 let cache_reader = self.get_transaction_cache_reader().clone();
1288 let epoch_store = epoch_store.clone();
1289 spawn_monitored_task!(epoch_store.within_alive_epoch(
1290 validator_tx_finalizer.track_signed_tx(cache_reader, &epoch_store, tx)
1291 ));
1292 }
1293 }
1294 Ok(HandleTransactionResponse {
1295 status: TransactionStatus::Signed(s.into_inner().into_sig()),
1296 })
1297 }
1298 Err(err) => Ok(HandleTransactionResponse {
1302 status: self
1303 .get_transaction_status(&tx_digest, epoch_store)?
1304 .ok_or(err)?
1305 .1,
1306 }),
1307 }
1308 }
1309
1310 pub fn check_system_overload_at_signing(&self) -> bool {
1311 self.config
1312 .authority_overload_config
1313 .check_system_overload_at_signing
1314 }
1315
1316 pub fn check_system_overload_at_execution(&self) -> bool {
1317 self.config
1318 .authority_overload_config
1319 .check_system_overload_at_execution
1320 }
1321
1322 pub(crate) fn check_system_overload(
1332 &self,
1333 consensus_adapter: &Arc<ConsensusAdapter>,
1334 tx: &SenderSignedTransaction,
1335 do_authority_overload_check: bool,
1336 pcool_flow_enabled: bool,
1337 ) -> IotaResult {
1338 if pcool_flow_enabled {
1339 self.check_consensus_queue_graduated_limits(consensus_adapter, tx)
1342 .tap_err(|_| {
1343 self.update_overload_metrics("consensus");
1344 })?;
1345
1346 consensus_adapter.check_consensus_overload().tap_err(|_| {
1353 self.update_overload_metrics("consensus");
1354 })?;
1355 } else {
1356 if do_authority_overload_check {
1357 self.check_authority_overload(tx).tap_err(|_| {
1358 self.update_overload_metrics("execution_queue");
1359 })?;
1360 }
1361 self.execution_scheduler
1362 .check_execution_overload(self.overload_config(), tx)
1363 .tap_err(|_| {
1364 self.update_overload_metrics("execution_pending");
1365 })?;
1366 consensus_adapter.check_consensus_overload().tap_err(|_| {
1367 self.update_overload_metrics("consensus");
1368 })?;
1369
1370 let pending_tx_count = self
1371 .get_cache_commit()
1372 .approximate_pending_transaction_count();
1373 if pending_tx_count
1374 > self
1375 .config
1376 .execution_cache_config
1377 .writeback_cache
1378 .backpressure_threshold_for_rpc()
1379 {
1380 return Err(IotaError::ValidatorOverloadedRetryAfter {
1381 retry_after_secs: 10,
1382 });
1383 }
1384 }
1385
1386 Ok(())
1387 }
1388
1389 fn check_consensus_queue_graduated_limits(
1397 &self,
1398 consensus_adapter: &Arc<ConsensusAdapter>,
1399 tx: &SenderSignedTransaction,
1400 ) -> IotaResult {
1401 let num_inflight_txs = consensus_adapter.num_inflight_transactions() as usize;
1402
1403 let shedding_pct = compute_graduated_load_shedding_percentage(
1404 num_inflight_txs,
1405 consensus_adapter.max_pending_transactions(),
1406 consensus_adapter.graduated_load_shedding_soft_limit_pct(),
1407 );
1408
1409 self.metrics
1410 .consensus_queue_load_shedding_percentage
1411 .set(shedding_pct as i64);
1412
1413 if shedding_pct == 0 {
1414 return Ok(());
1415 }
1416
1417 if shedding_pct >= 100 {
1422 return Err(IotaError::TooManyTransactionsPendingConsensus);
1423 }
1424
1425 overload_monitor_accept_tx(shedding_pct, tx.digest())
1426 }
1427
1428 fn check_authority_overload(&self, tx: &SenderSignedTransaction) -> IotaResult {
1429 if !self.overload_info.is_overload.load(Ordering::Relaxed) {
1430 return Ok(());
1431 }
1432
1433 let load_shedding_percentage = self
1434 .overload_info
1435 .local_load_shedding_percentage
1436 .load(Ordering::Relaxed);
1437 overload_monitor_accept_tx(load_shedding_percentage, tx.digest())
1438 }
1439
1440 fn update_overload_metrics(&self, source: &str) {
1441 self.metrics
1442 .transaction_overload_sources
1443 .with_label_values(&[source])
1444 .inc();
1445 }
1446
1447 #[instrument(level = "trace", skip_all)]
1452 pub async fn wait_for_certificate_execution(
1453 &self,
1454 certificate: &VerifiedCertificate,
1455 epoch_store: &Arc<AuthorityPerEpochStore>,
1456 ) -> IotaResult<TransactionEffects> {
1457 let _metrics_guard = if certificate.contains_shared_object() {
1458 self.metrics
1459 .execute_certificate_latency_shared_object
1460 .start_timer()
1461 } else {
1462 self.metrics
1463 .execute_certificate_latency_single_writer
1464 .start_timer()
1465 };
1466 trace!("wait_for_certificate_execution");
1467
1468 self.metrics.total_cert_attempts.inc();
1469
1470 if !certificate.contains_shared_object() {
1471 self.execution_scheduler.enqueue(
1476 vec![(
1477 Schedulable::Transaction(VerifiedExecutableTransaction::new_from_certificate(
1478 certificate.clone(),
1479 )),
1480 ExecutionEnv::new(),
1481 )],
1482 epoch_store,
1483 );
1484 }
1485
1486 epoch_store
1489 .within_alive_epoch(self.notify_read_effects(
1490 "AuthorityState::wait_for_certificate_execution",
1491 certificate,
1492 ))
1493 .await
1494 .and_then(|r| r)
1495 }
1496
1497 #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1512 pub fn try_execute_immediately(
1513 &self,
1514 transaction: &VerifiedExecutableTransaction,
1515 execution_env: ExecutionEnv,
1516 epoch_store: &Arc<AuthorityPerEpochStore>,
1517 ) -> IotaResult<(TransactionEffects, Option<ExecutionError>)> {
1518 let _scope = monitored_scope("Execution::try_execute_immediately");
1519 let _metrics_guard = self.metrics.internal_execution_latency.start_timer();
1520
1521 let tx_digest = transaction.digest();
1522
1523 let tx_guard = epoch_store.acquire_tx_guard(transaction)?;
1525
1526 if let Some(effects) = self
1529 .get_transaction_cache_reader()
1530 .try_get_executed_effects(tx_digest)?
1531 {
1532 if let Some(expected_effects_digest_inner) = execution_env.expected_effects_digest {
1533 assert_eq!(
1534 effects.digest(),
1535 expected_effects_digest_inner,
1536 "Unexpected effects digest for transaction {tx_digest}"
1537 );
1538 }
1539 tx_guard.release();
1540 return Ok((effects, None));
1541 }
1542
1543 let (tx_input_objects, per_authenticator_inputs) = self.read_objects_for_execution(
1544 tx_guard.as_lock_guard(),
1545 transaction,
1546 execution_env.assigned_versions,
1547 epoch_store,
1548 )?;
1549
1550 self.process_transaction(
1551 tx_guard,
1552 transaction,
1553 tx_input_objects,
1554 per_authenticator_inputs,
1555 execution_env.expected_effects_digest,
1556 epoch_store,
1557 )
1558 .tap_err(|e| info!(?tx_digest, "process_transaction failed: {e}"))
1559 .tap_ok(
1560 |(fx, _)| debug!(?tx_digest, fx_digest=?fx.digest(), "process_transaction succeeded"),
1561 )
1562 }
1563
1564 pub fn read_objects_for_execution(
1565 &self,
1566 tx_lock: &TxLockGuard,
1567 transaction: &VerifiedExecutableTransaction,
1568 assigned_shared_object_versions: AssignedVersions,
1569 epoch_store: &Arc<AuthorityPerEpochStore>,
1570 ) -> IotaResult<(InputObjects, Vec<(InputObjects, ObjectReadResult)>)> {
1571 let _scope = monitored_scope("Execution::load_input_objects");
1572 let _metrics_guard = self
1573 .metrics
1574 .execution_load_input_objects_latency
1575 .start_timer();
1576
1577 let input_objects = transaction.collect_all_input_object_kind_for_reading()?;
1578
1579 let input_objects = self.input_loader.read_objects_for_execution(
1580 &transaction.key(),
1581 tx_lock,
1582 &input_objects,
1583 &assigned_shared_object_versions,
1584 epoch_store.epoch(),
1585 )?;
1586
1587 transaction.split_input_objects_into_groups_for_reading(input_objects)
1588 }
1589
1590 pub fn try_execute_for_test(
1594 &self,
1595 certificate: &VerifiedCertificate,
1596 execution_env: ExecutionEnv,
1597 ) -> IotaResult<(VerifiedSignedTransactionEffects, Option<ExecutionError>)> {
1598 let epoch_store = self.epoch_store_for_testing();
1599 let (effects, execution_error_opt) = self.try_execute_immediately(
1600 &VerifiedExecutableTransaction::new_from_certificate(certificate.clone()),
1601 execution_env,
1602 &epoch_store,
1603 )?;
1604 let signed_effects = self.sign_effects(effects, &epoch_store)?;
1605 Ok((signed_effects, execution_error_opt))
1606 }
1607
1608 pub fn execute_for_test(
1610 &self,
1611 certificate: &VerifiedCertificate,
1612 execution_env: ExecutionEnv,
1613 ) -> (VerifiedSignedTransactionEffects, Option<ExecutionError>) {
1614 self.try_execute_for_test(certificate, execution_env)
1615 .expect("try_execute_for_test should not fail")
1616 }
1617
1618 pub async fn notify_read_effects(
1619 &self,
1620 task_name: &'static str,
1621 certificate: &VerifiedCertificate,
1622 ) -> IotaResult<TransactionEffects> {
1623 self.get_transaction_cache_reader()
1624 .try_notify_read_executed_effects(task_name, &[*certificate.digest()])
1625 .await
1626 .map(|mut r| r.pop().expect("must return correct number of effects"))
1627 }
1628
1629 fn check_owned_locks(&self, owned_object_refs: &[ObjectReference]) -> IotaResult {
1630 self.get_object_cache_reader()
1631 .try_check_owned_objects_are_live(owned_object_refs)
1632 }
1633
1634 pub(crate) fn debug_dump_transaction_state(
1639 &self,
1640 tx_digest: &TransactionDigest,
1641 effects: &TransactionEffects,
1642 expected_effects_digest: TransactionEffectsDigest,
1643 inner_temporary_store: &InnerTemporaryStore,
1644 transaction: &VerifiedExecutableTransaction,
1645 debug_dump_config: &StateDebugDumpConfig,
1646 ) -> IotaResult<PathBuf> {
1647 let dump_dir = debug_dump_config
1650 .dump_file_directory
1651 .as_ref()
1652 .cloned()
1653 .unwrap_or(std::env::temp_dir());
1654 let epoch_store = self.load_epoch_store_one_call_per_task();
1655
1656 NodeStateDump::new(
1657 tx_digest,
1658 effects,
1659 expected_effects_digest,
1660 self.get_object_store().as_ref(),
1661 &epoch_store,
1662 inner_temporary_store,
1663 transaction,
1664 )?
1665 .write_to_file(&dump_dir)
1666 .map_err(|e| IotaError::FileIO(e.to_string()))
1667 }
1668
1669 #[instrument(name = "process_certificate", level = "trace", skip_all, fields(tx_digest = ?transaction.digest(), sender = ?transaction.data().transaction().gas_owner().to_string()))]
1670 pub(crate) fn process_transaction(
1671 &self,
1672 tx_guard: TxGuard,
1673 transaction: &VerifiedExecutableTransaction,
1674 tx_input_objects: InputObjects,
1675 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
1676 expected_effects_digest: Option<TransactionEffectsDigest>,
1677 epoch_store: &Arc<AuthorityPerEpochStore>,
1678 ) -> IotaResult<(TransactionEffects, Option<ExecutionError>)> {
1679 let process_transaction_start_time = tokio::time::Instant::now();
1680 let digest = *transaction.digest();
1681
1682 let _scope = monitored_scope("Execution::process_certificate");
1683
1684 fail_point_if!("correlated-crash-process-transaction", || {
1685 if iota_simulator::random::deterministic_probability_once(digest, 0.01) {
1686 iota_simulator::task::kill_current_node(None);
1687 }
1688 });
1689
1690 let execution_guard = self.execution_lock_for_executable_transaction(transaction);
1691 let execution_guard = match execution_guard {
1697 Ok(execution_guard) => execution_guard,
1698 Err(err) => {
1699 tx_guard.release();
1700 return Err(err);
1701 }
1702 };
1703 if *execution_guard != epoch_store.epoch() {
1707 tx_guard.release();
1708 info!("The epoch of the execution_guard doesn't match the epoch store");
1709 return Err(IotaError::WrongEpoch {
1710 expected_epoch: epoch_store.epoch(),
1711 actual_epoch: *execution_guard,
1712 });
1713 }
1714
1715 let (inner_temporary_store, effects, execution_error_opt) = match self.execute_transaction(
1721 &execution_guard,
1722 transaction,
1723 tx_input_objects,
1724 per_authenticator_inputs,
1725 epoch_store,
1726 ) {
1727 Err(e) => {
1728 info!(name = ?self.name, ?digest, "Error preparing transaction: {e}");
1729 tx_guard.release();
1730 return Err(e);
1731 }
1732 Ok(res) => res,
1733 };
1734
1735 if let Some(expected_effects_digest) = expected_effects_digest {
1736 if effects.digest() != expected_effects_digest {
1737 match self.debug_dump_transaction_state(
1739 &digest,
1740 &effects,
1741 expected_effects_digest,
1742 &inner_temporary_store,
1743 transaction,
1744 &self.config.state_debug_dump_config,
1745 ) {
1746 Ok(out_path) => {
1747 info!(
1748 "Dumped node state for transaction {} to {}",
1749 digest,
1750 out_path.as_path().display().to_string()
1751 );
1752 }
1753 Err(e) => {
1754 error!("Error dumping state for transaction {}: {e}", digest);
1755 }
1756 }
1757 error!(
1758 tx_digest = ?digest,
1759 ?expected_effects_digest,
1760 actual_effects = ?effects,
1761 "fork detected!"
1762 );
1763 panic!(
1764 "Transaction {} is expected to have effects digest {}, but got {}!",
1765 digest,
1766 expected_effects_digest,
1767 effects.digest(),
1768 );
1769 }
1770 }
1771
1772 fail_point!("crash");
1773
1774 self.commit_transaction(
1775 transaction,
1776 inner_temporary_store,
1777 &effects,
1778 tx_guard,
1779 execution_guard,
1780 expected_effects_digest,
1781 epoch_store,
1782 )?;
1783
1784 let elapsed = process_transaction_start_time.elapsed().as_micros() as f64;
1785 if elapsed > 0.0 {
1786 self.metrics
1787 .execution_gas_latency_ratio
1788 .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed);
1789 };
1790 Ok((effects, execution_error_opt))
1791 }
1792
1793 pub async fn reconfigure_traffic_control(
1794 &self,
1795 params: TrafficControlReconfigParams,
1796 ) -> Result<TrafficControlReconfigParams, IotaError> {
1797 if let Some(traffic_controller) = self.traffic_controller.as_ref() {
1798 traffic_controller.admin_reconfigure(params)
1799 } else {
1800 Err(IotaError::InvalidAdminRequest(
1801 "Traffic controller is not configured on this node".to_string(),
1802 ))
1803 }
1804 }
1805
1806 #[instrument(level = "trace", skip_all)]
1807 fn commit_transaction(
1808 &self,
1809 transaction: &VerifiedExecutableTransaction,
1810 inner_temporary_store: InnerTemporaryStore,
1811 effects: &TransactionEffects,
1812 tx_guard: TxGuard,
1813 _execution_guard: ExecutionLockReadGuard<'_>,
1814 expected_effects_digest: Option<TransactionEffectsDigest>,
1815 epoch_store: &Arc<AuthorityPerEpochStore>,
1816 ) -> IotaResult {
1817 let _scope: Option<iota_metrics::MonitoredScopeGuard> =
1818 monitored_scope("Execution::commit_certificate");
1819 let _metrics_guard = self.metrics.commit_certificate_latency.start_timer();
1820
1821 let tx_digest = transaction.digest();
1822 let input_object_count = inner_temporary_store.input_objects.len();
1823 let shared_object_count = effects.input_shared_objects().len();
1824
1825 let output_keys = inner_temporary_store.get_output_keys(effects);
1826
1827 let _ = self
1829 .post_process_one_tx(transaction, effects, &inner_temporary_store, epoch_store)
1830 .tap_err(|e| {
1831 self.metrics.post_processing_total_failures.inc();
1832 error!(?tx_digest, "tx post processing failed: {e}");
1833 });
1834
1835 epoch_store.insert_executed_in_epoch(tx_digest);
1839
1840 let key = transaction.key();
1841 if !matches!(key, TransactionKey::Digest(_)) {
1842 epoch_store.insert_tx_key(key, *tx_digest)?;
1843 }
1844
1845 fail_point!("crash");
1847
1848 let transaction_outputs = TransactionOutputs::build_transaction_outputs(
1849 transaction.clone().into_unsigned(),
1850 effects.clone(),
1851 inner_temporary_store,
1852 );
1853 self.get_cache_writer()
1854 .try_write_transaction_outputs(epoch_store.epoch(), transaction_outputs.into())?;
1855
1856 self.report_failed_deny_rule_update_execution(
1857 transaction,
1858 effects,
1859 expected_effects_digest,
1860 epoch_store,
1861 );
1862
1863 if transaction.transaction().is_end_of_epoch_tx() {
1864 self.get_object_cache_reader()
1867 .force_reload_system_packages(&BuiltInFramework::all_package_ids());
1868 }
1869
1870 tx_guard.commit_tx();
1872
1873 match self.execution_scheduler.as_ref() {
1874 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
1875 ExecutionSchedulerWrapper::TransactionManager(tm) => {
1876 tm.notify_commit(tx_digest, output_keys, epoch_store);
1880 if let Some(key) = transaction.non_digest_key() {
1886 tm.notify_transaction_key(epoch_store, key, *tx_digest);
1887 }
1888 }
1889 }
1890
1891 self.update_metrics(transaction, input_object_count, shared_object_count);
1892
1893 Ok(())
1894 }
1895
1896 fn update_metrics(
1897 &self,
1898 transaction: &VerifiedExecutableTransaction,
1899 input_object_count: usize,
1900 shared_object_count: usize,
1901 ) {
1902 if transaction.has_multisig() {
1904 self.metrics.multisig_sig_count.inc();
1905 }
1906
1907 self.metrics.total_effects.inc();
1908 self.metrics.total_certs.inc();
1909
1910 if shared_object_count > 0 {
1911 self.metrics.shared_obj_tx.inc();
1912 }
1913
1914 if transaction.is_sponsored_tx() {
1915 self.metrics.sponsored_tx.inc();
1916 }
1917
1918 self.metrics
1919 .num_input_objs
1920 .observe(input_object_count as f64);
1921 self.metrics
1922 .num_shared_objects
1923 .observe(shared_object_count as f64);
1924 self.metrics
1925 .batch_size
1926 .observe(transaction.data().transaction().kind().num_commands() as f64);
1927 }
1928
1929 #[instrument(level = "trace", skip_all)]
1941 fn execute_transaction(
1942 &self,
1943 _execution_guard: &ExecutionLockReadGuard<'_>,
1944 transaction: &VerifiedExecutableTransaction,
1945 tx_input_objects: InputObjects,
1946 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
1947 epoch_store: &Arc<AuthorityPerEpochStore>,
1948 ) -> IotaResult<(
1949 InnerTemporaryStore,
1950 TransactionEffects,
1951 Option<ExecutionError>,
1952 )> {
1953 let _scope = monitored_scope("Execution::execute_certificate");
1954 let _metrics_guard = self.metrics.prepare_certificate_latency.start_timer();
1955 let prepare_transaction_start_time = tokio::time::Instant::now();
1956
1957 let protocol_config = epoch_store.protocol_config();
1958
1959 let reference_gas_price = epoch_store.reference_gas_price();
1960
1961 let epoch_id = epoch_store.epoch_start_config().epoch_data().epoch_id();
1962 let epoch_start_timestamp = epoch_store
1963 .epoch_start_config()
1964 .epoch_data()
1965 .epoch_start_timestamp();
1966
1967 let backing_store = self.get_backing_store().as_ref();
1968
1969 let tx_digest = *transaction.digest();
1970
1971 let tx = transaction.data().transaction();
1974 tx.validity_check(protocol_config)?;
1975
1976 let (kind, signer, gas_data) = tx.execution_parts();
1977
1978 let move_authenticators = transaction.move_authenticators();
1979
1980 #[cfg_attr(not(any(msim, fail_points)), expect(unused_mut))]
1981 let (inner_temp_store, _, mut effects, _, execution_error_opt) = if move_authenticators
1982 .is_empty()
1983 {
1984 let (tx_gas_status, tx_checked_input_objects) =
1989 iota_transaction_checks::check_certificate_input(
1990 transaction,
1991 tx_input_objects,
1992 protocol_config,
1993 reference_gas_price,
1994 )?;
1995
1996 let owned_object_refs = tx_checked_input_objects.inner().filter_owned_objects();
1997 self.check_owned_locks(&owned_object_refs)?;
1998 epoch_store.executor().execute_transaction_to_effects(
1999 backing_store,
2000 protocol_config,
2001 self.metrics.limits_metrics.clone(),
2002 self.config
2005 .expensive_safety_check_config
2006 .enable_deep_per_tx_iota_conservation_check(),
2007 self.config.certificate_deny_config.certificate_deny_set(),
2008 &epoch_id,
2009 epoch_start_timestamp,
2010 tx_checked_input_objects,
2011 gas_data,
2012 tx_gas_status,
2013 kind,
2014 signer,
2015 tx_digest,
2016 &mut None,
2017 )
2018 } else {
2019 debug_assert_eq!(
2025 move_authenticators.len(),
2026 per_authenticator_inputs.len(),
2027 "Move authenticators amount must match the number of authenticator inputs"
2028 );
2029
2030 let per_authenticator_inputs = move_authenticators
2031 .iter()
2032 .zip(per_authenticator_inputs)
2033 .map(
2034 |(move_authenticator, (authenticator_input_objects, account_object))| {
2035 let (
2038 auth_account_object_id,
2039 auth_account_object_seq_number,
2040 auth_account_object_digest,
2041 ) = move_authenticator
2042 .object_to_authenticate_components()
2043 .expect("the object to authenticate is validated before consensus and cannot be invalid during execution");
2044
2045 let signer = move_authenticator.address();
2046
2047 let authenticator_function_ref_for_execution = self
2048 .check_move_account_for_execution(
2049 auth_account_object_id,
2050 auth_account_object_seq_number,
2051 auth_account_object_digest,
2052 account_object,
2053 &signer,
2054 );
2055
2056 (
2057 authenticator_input_objects,
2058 authenticator_function_ref_for_execution,
2059 )
2060 },
2061 )
2062 .collect::<Vec<_>>();
2063
2064 let per_authenticator_input_objects = per_authenticator_inputs
2065 .iter()
2066 .map(|(authenticator_input_objects, _)| authenticator_input_objects.clone())
2067 .collect::<Vec<_>>();
2068
2069 let tx_bytes = bcs::to_bytes(tx).expect("Transaction serialization cannot fail");
2071
2072 let (sender_auth_digest, sponsor_auth_digest) =
2073 transaction.data().compute_auth_digests()?;
2074
2075 let authenticator_gas_budget = protocol_config.max_auth_gas();
2080 let (
2081 gas_status,
2082 per_authenticator_checked_input_objects,
2083 authenticator_and_tx_checked_input_objects,
2084 ) = iota_transaction_checks::check_certificate_and_move_authenticator_input(
2085 transaction,
2086 tx_input_objects,
2087 per_authenticator_input_objects,
2088 authenticator_gas_budget,
2089 protocol_config,
2090 reference_gas_price,
2091 )?;
2092
2093 debug_assert_eq!(
2094 move_authenticators.len(),
2095 per_authenticator_checked_input_objects.len(),
2096 "Move authenticators amount must match the number of checked authenticator inputs"
2097 );
2098
2099 let move_authenticators = move_authenticators
2100 .into_iter()
2101 .zip(per_authenticator_inputs)
2102 .zip(per_authenticator_checked_input_objects)
2103 .map(
2104 |(
2105 (move_authenticator, (_, authenticator_function_ref_for_execution)),
2106 authenticator_checked_input_objects,
2107 )| {
2108 (
2109 move_authenticator.to_owned(),
2110 authenticator_function_ref_for_execution,
2111 authenticator_checked_input_objects,
2112 )
2113 },
2114 )
2115 .collect::<Vec<_>>();
2116
2117 let owned_object_refs = authenticator_and_tx_checked_input_objects
2118 .inner()
2119 .filter_owned_objects();
2120 self.check_owned_locks(&owned_object_refs)?;
2121
2122 let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) =
2123 extract_auth_fun_refs(signer, gas_data.owner, |address| {
2124 move_authenticators
2125 .iter()
2126 .find(|t| t.0.address() == address)
2127 .map(|t| t.1.authenticator_function_ref.clone())
2128 });
2129
2130 let auth_context_data = AuthContextData {
2131 transaction_data_bytes: tx_bytes,
2132 sender_auth_digest,
2133 sponsor_auth_digest,
2134 sender_authenticator_function_ref,
2135 sponsor_authenticator_function_ref,
2136 };
2137
2138 epoch_store
2139 .executor()
2140 .authenticate_then_execute_transaction_to_effects(
2141 backing_store,
2142 protocol_config,
2143 self.metrics.limits_metrics.clone(),
2144 self.config
2145 .expensive_safety_check_config
2146 .enable_deep_per_tx_iota_conservation_check(),
2147 self.config.certificate_deny_config.certificate_deny_set(),
2148 &epoch_id,
2149 epoch_start_timestamp,
2150 gas_data,
2151 gas_status,
2152 move_authenticators,
2153 authenticator_and_tx_checked_input_objects,
2154 kind,
2155 signer,
2156 tx_digest,
2157 auth_context_data,
2158 &mut None,
2159 )
2160 };
2161
2162 fail_point_if!("cp_execution_nondeterminism", || {
2163 #[cfg(msim)]
2164 self.create_fail_state(transaction, epoch_store, &mut effects);
2165 });
2166
2167 let elapsed = prepare_transaction_start_time.elapsed().as_micros() as f64;
2168 if elapsed > 0.0 {
2169 self.metrics
2170 .prepare_cert_gas_latency_ratio
2171 .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed);
2172 }
2173
2174 Ok((inner_temp_store, effects, execution_error_opt.err()))
2175 }
2176
2177 pub fn prepare_transaction_for_benchmark(
2178 &self,
2179 transaction: &VerifiedExecutableTransaction,
2180 input_objects: InputObjects,
2181 epoch_store: &Arc<AuthorityPerEpochStore>,
2182 ) -> IotaResult<(
2183 InnerTemporaryStore,
2184 TransactionEffects,
2185 Option<ExecutionError>,
2186 )> {
2187 let lock = RwLock::new(epoch_store.epoch());
2188 let execution_guard = lock.try_read().unwrap();
2189
2190 self.execute_transaction(
2191 &execution_guard,
2192 transaction,
2193 input_objects,
2194 vec![],
2195 epoch_store,
2196 )
2197 }
2198
2199 pub fn simulate_transaction(
2227 &self,
2228 transaction: Transaction,
2229 checks: VmChecks,
2230 ) -> IotaResult<SimulateTransactionResult> {
2231 let epoch_store = self.load_epoch_store_one_call_per_task();
2232 self.simulate_transaction_in_epoch(&epoch_store, transaction, checks)
2233 }
2234
2235 #[instrument("simulate_tx", level = "trace", skip_all)]
2249 pub fn simulate_transaction_in_epoch(
2250 &self,
2251 epoch_store: &AuthorityPerEpochStore,
2252 transaction: Transaction,
2253 checks: VmChecks,
2254 ) -> IotaResult<SimulateTransactionResult> {
2255 if !self.is_fullnode(epoch_store) {
2256 return Err(IotaError::UnsupportedFeature {
2257 error: "simulate is only supported on fullnodes".to_string(),
2258 });
2259 }
2260
2261 self.simulate_transaction_inner(epoch_store, transaction, checks)
2262 }
2263
2264 pub fn simulate_transaction_for_benchmark(
2268 &self,
2269 transaction: Transaction,
2270 checks: VmChecks,
2271 ) -> IotaResult<SimulateTransactionResult> {
2272 let epoch_store = self.load_epoch_store_one_call_per_task();
2273 self.simulate_transaction_inner(&epoch_store, transaction, checks)
2274 }
2275
2276 #[instrument(level = "trace", skip_all)]
2277 fn simulate_transaction_inner(
2278 &self,
2279 epoch_store: &AuthorityPerEpochStore,
2280 mut transaction: Transaction,
2281 checks: VmChecks,
2282 ) -> IotaResult<SimulateTransactionResult> {
2283 if transaction.kind().is_system() {
2284 return Err(IotaError::UnsupportedFeature {
2285 error: "simulate does not support system transactions".to_string(),
2286 });
2287 }
2288
2289 transaction.validity_check_no_gas_check(epoch_store.protocol_config())?;
2293
2294 transaction.check_gas_payment_size(epoch_store.protocol_config())?;
2298
2299 let input_object_kinds = transaction.input_objects()?;
2300 let receiving_object_refs = transaction.receiving_objects();
2301
2302 iota_transaction_checks::deny::check_transaction_for_validation(
2305 &transaction,
2306 &[],
2307 &input_object_kinds,
2308 &receiving_object_refs,
2309 &self.config.transaction_deny_config,
2310 self.get_backing_package_store().as_ref(),
2311 )?;
2312
2313 let (mut input_objects, receiving_objects) = self.input_loader.read_objects_for_signing(
2315 None,
2317 &input_object_kinds,
2318 &receiving_object_refs,
2319 epoch_store.epoch(),
2320 )?;
2321
2322 let mock_gas_id = if transaction.gas().is_empty() {
2324 let mock_gas_object = mock_simulation_gas_coin(transaction.gas_data().owner);
2325 let mock_gas_object_ref = mock_gas_object.object_ref();
2326 transaction.gas_data_mut().objects = vec![mock_gas_object_ref];
2327 input_objects.push(ObjectReadResult::new_from_gas_object(&mock_gas_object));
2328 Some(mock_gas_object.id())
2329 } else {
2330 None
2331 };
2332
2333 let protocol_config = epoch_store.protocol_config();
2334
2335 iota_types::gas::fill_in_unset_simulation_gas(
2336 &mut transaction,
2337 &input_objects,
2338 epoch_store.reference_gas_price(),
2339 protocol_config,
2340 );
2341
2342 let authenticator_gas_budget = 0;
2345
2346 let (gas_status, checked_input_objects) = if checks.enabled() {
2349 iota_transaction_checks::check_transaction_input(
2350 protocol_config,
2351 epoch_store.reference_gas_price(),
2352 &transaction,
2353 input_objects,
2354 &receiving_objects,
2355 &self.metrics.bytecode_verifier_metrics,
2356 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2357 authenticator_gas_budget,
2358 )?
2359 } else {
2360 iota_types::gas::check_gas_coins_cover_budget_in_simulation(
2366 &input_objects,
2367 transaction.gas(),
2368 transaction.gas_budget(),
2369 )?;
2370
2371 let checked_input_objects = iota_transaction_checks::check_simulation_input(
2372 protocol_config,
2373 transaction.kind(),
2374 input_objects,
2375 receiving_objects,
2376 )?;
2377 let gas_status = IotaGasStatus::new(
2378 transaction.gas_budget(),
2379 transaction.gas_price(),
2380 epoch_store.reference_gas_price(),
2381 protocol_config,
2382 )?;
2383
2384 (gas_status, checked_input_objects)
2385 };
2386
2387 let executor = iota_execution::executor(
2389 protocol_config,
2390 true, None,
2392 )
2393 .expect("Creating an executor should not fail here");
2394
2395 let (kind, signer, gas_data) = transaction.execution_parts();
2397 let (inner_temp_store, _, effects, execution_result) = executor.dev_inspect_transaction(
2398 self.get_backing_store().as_ref(),
2399 protocol_config,
2400 self.metrics.limits_metrics.clone(),
2401 false, self.config.certificate_deny_config.certificate_deny_set(),
2403 &epoch_store.epoch_start_config().epoch_data().epoch_id(),
2404 epoch_store
2405 .epoch_start_config()
2406 .epoch_data()
2407 .epoch_start_timestamp(),
2408 checked_input_objects,
2409 gas_data,
2410 gas_status,
2411 kind,
2412 signer,
2413 transaction.digest(),
2414 checks.disabled(),
2415 );
2416
2417 let mut input_objects = inner_temp_store.input_objects;
2418 iota_types::storage::extend_input_objects_with_loaded_runtime_objects(
2419 &mut input_objects,
2420 &effects,
2421 &inner_temp_store.loaded_runtime_objects,
2422 self.get_backing_store().as_object_store(),
2423 );
2424
2425 Ok(SimulateTransactionResult {
2426 input_objects,
2427 output_objects: inner_temp_store.written,
2428 events: effects.events_digest().map(|_| inner_temp_store.events),
2429 effects,
2430 execution_result,
2431 suggested_gas_price: self
2432 .congestion_tracker
2433 .get_prediction_suggested_gas_price(&transaction),
2434 mock_gas_id,
2435 gas_data: transaction.gas_data().clone(),
2436 })
2437 }
2438
2439 pub fn reference_gas_price_for_testing(&self) -> Result<u64, anyhow::Error> {
2441 let epoch_store = self.epoch_store_for_testing();
2442 Ok(epoch_store.reference_gas_price())
2443 }
2444
2445 #[instrument(level = "trace", skip_all)]
2446 pub fn try_is_tx_already_executed(&self, digest: &TransactionDigest) -> IotaResult<bool> {
2447 self.get_transaction_cache_reader()
2448 .try_is_tx_already_executed(digest)
2449 }
2450
2451 pub fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
2453 self.try_is_tx_already_executed(digest)
2454 .expect("storage access failed")
2455 }
2456
2457 #[instrument(level = "debug", skip_all, err)]
2459 fn index_tx(
2460 &self,
2461 indexes: &IndexStore,
2462 digest: &TransactionDigest,
2463 transaction: &VerifiedExecutableTransaction,
2465 effects: &TransactionEffects,
2466 events: &TransactionEvents,
2467 timestamp_ms: u64,
2468 tx_coins: Option<TxCoins>,
2469 written: &WrittenObjects,
2470 inner_temporary_store: &InnerTemporaryStore,
2471 epoch_store: &Arc<AuthorityPerEpochStore>,
2472 ) -> IotaResult<u64> {
2473 let changes = self
2474 .process_object_index(effects, written, inner_temporary_store, epoch_store)
2475 .tap_err(|e| warn!(tx_digest=?digest, "Failed to process object index, index_tx is skipped: {e}"))?;
2476
2477 indexes.index_tx(
2478 transaction.data().transaction().sender(),
2479 transaction
2480 .data()
2481 .transaction()
2482 .input_objects()?
2483 .iter()
2484 .map(|o| o.object_id()),
2485 effects
2486 .all_changed_objects()
2487 .into_iter()
2488 .map(|(changed, _kind)| (*changed.reference(), *changed.owner())),
2489 transaction
2490 .data()
2491 .transaction()
2492 .move_calls()
2493 .into_iter()
2494 .map(|(package, module, function)| {
2495 (*package, module.to_owned(), function.to_owned())
2496 }),
2497 events,
2498 changes,
2499 digest,
2500 timestamp_ms,
2501 tx_coins,
2502 )
2503 }
2504
2505 #[cfg(msim)]
2506 fn create_fail_state(
2507 &self,
2508 transaction: &VerifiedExecutableTransaction,
2509 epoch_store: &Arc<AuthorityPerEpochStore>,
2510 effects: &mut TransactionEffects,
2511 ) {
2512 use std::cell::RefCell;
2513
2514 use iota_types::effects::TransactionEffectsAPIForTesting;
2515 thread_local! {
2516 static FAIL_STATE: RefCell<(u64, HashSet<AuthorityName>)> = RefCell::new((0, HashSet::new()));
2517 }
2518 if !transaction.data().transaction().is_system_tx() {
2519 let committee = epoch_store.committee();
2520 let cur_stake = (**committee).weight(&self.name);
2521 if cur_stake > 0 {
2522 FAIL_STATE.with_borrow_mut(|fail_state| {
2523 if fail_state.0 < committee.validity_threshold() {
2525 fail_state.0 += cur_stake;
2526 fail_state.1.insert(self.name);
2527 }
2528
2529 if fail_state.1.contains(&self.name) {
2530 info!("cp_exec failing tx");
2531 effects.gas_cost_summary_mut_for_testing().computation_cost += 1;
2532 }
2533 });
2534 }
2535 }
2536 }
2537
2538 fn process_object_index(
2539 &self,
2540 effects: &TransactionEffects,
2541 written: &WrittenObjects,
2542 inner_temporary_store: &InnerTemporaryStore,
2543 epoch_store: &Arc<AuthorityPerEpochStore>,
2544 ) -> IotaResult<ObjectIndexChanges> {
2545 let mut layout_resolver =
2546 epoch_store
2547 .executor()
2548 .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
2549 inner_temporary_store,
2550 self.get_backing_package_store(),
2551 )));
2552
2553 let modified_at_version = effects
2554 .modified_at_versions()
2555 .into_iter()
2556 .map(|modified| (*modified.object_id(), modified.version()))
2557 .collect::<HashMap<_, _>>();
2558
2559 let tx_digest = effects.transaction_digest();
2560 let mut deleted_owners = vec![];
2561 let mut deleted_dynamic_fields = vec![];
2562 for object_ref in effects.deleted().into_iter().chain(effects.wrapped()) {
2563 let old_version = modified_at_version.get(&object_ref.object_id).unwrap();
2564 match self.get_owner_at_version(&object_ref.object_id, *old_version).unwrap_or_else(
2567 |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)
2568 ) {
2569 Owner::Address(addr) => deleted_owners.push((addr, object_ref.object_id)),
2570 Owner::Object(object_id) => {
2571 deleted_dynamic_fields.push((object_id, object_ref.object_id))
2572 }
2573 _ => {}
2574 }
2575 }
2576
2577 let mut new_owners = vec![];
2578 let mut new_dynamic_fields = vec![];
2579
2580 for (changed, kind) in effects.all_changed_objects() {
2581 let (oref, owner) = (*changed.reference(), *changed.owner());
2582 let id = &oref.object_id;
2583 if let WriteKind::Mutate = kind {
2586 let Some(old_version) = modified_at_version.get(id) else {
2587 panic!(
2588 "tx_digest={tx_digest}, error processing object owner index, cannot find modified at version for mutated object [{id}]."
2589 );
2590 };
2591 let Some(old_object) = self
2594 .get_object_store()
2595 .try_get_object_by_key(id, *old_version)?
2596 else {
2597 panic!(
2598 "tx_digest={tx_digest}, error processing object owner index, cannot find owner for object {id} at version {old_version:?}"
2599 );
2600 };
2601 if old_object.owner != owner {
2602 match old_object.owner {
2603 Owner::Address(addr) => {
2604 deleted_owners.push((addr, *id));
2605 }
2606 Owner::Object(object_id) => deleted_dynamic_fields.push((object_id, *id)),
2607 _ => {}
2608 }
2609 }
2610 }
2611
2612 match owner {
2613 Owner::Address(addr) => {
2614 let new_object = written.get(id).unwrap_or_else(
2617 || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2618 );
2619 assert_eq!(
2620 new_object.version(),
2621 oref.version,
2622 "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2623 tx_digest,
2624 id,
2625 new_object.version(),
2626 oref.version
2627 );
2628
2629 let object_type = new_object
2630 .data
2631 .opt_object_type()
2632 .map(|ty| ObjectType::Struct(ty.clone()))
2633 .unwrap_or(ObjectType::Package);
2634
2635 new_owners.push((
2636 (addr, *id),
2637 ObjectInfo {
2638 object_id: *id,
2639 version: oref.version,
2640 digest: oref.digest,
2641 object_type,
2642 owner,
2643 previous_transaction: *effects.transaction_digest(),
2644 },
2645 ));
2646 }
2647 Owner::Object(owner) => {
2648 let new_object = written.get(id).unwrap_or_else(
2649 || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2650 );
2651 assert_eq!(
2652 new_object.version(),
2653 oref.version,
2654 "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2655 tx_digest,
2656 id,
2657 new_object.version(),
2658 oref.version
2659 );
2660
2661 let Some(df_info) = self
2662 .try_create_dynamic_field_info(new_object, written, layout_resolver.as_mut())
2663 .unwrap_or_else(|e| {
2664 error!(
2665 "try_create_dynamic_field_info should not fail, {}, new_object={}, new_object_type={}",
2666 e,
2667 new_object.id(),
2668 ObjectType::from(new_object)
2669 );
2670 None
2671 }
2672 )
2673 else {
2674 continue;
2676 };
2677 new_dynamic_fields.push(((owner, *id), df_info))
2678 }
2679 _ => {}
2680 }
2681 }
2682
2683 Ok(ObjectIndexChanges {
2684 deleted_owners,
2685 deleted_dynamic_fields,
2686 new_owners,
2687 new_dynamic_fields,
2688 })
2689 }
2690
2691 fn try_create_dynamic_field_info(
2692 &self,
2693 o: &Object,
2694 written: &WrittenObjects,
2695 resolver: &mut dyn LayoutResolver,
2696 ) -> IotaResult<Option<DynamicFieldInfo>> {
2697 let Some(move_object) = o.data.as_opt_struct().cloned() else {
2699 return Ok(None);
2700 };
2701
2702 if !move_object.struct_tag().is_dynamic_field() {
2704 return Ok(None);
2705 }
2706
2707 let layout = match resolver.get_annotated_layout(move_object.struct_tag()) {
2708 Ok(annotated_layout) => annotated_layout.into_layout(),
2709 Err(e) => {
2710 error!(
2711 "unable to load layout for type `{:?}`: {e}",
2712 move_object.struct_tag()
2713 );
2714 return Ok(None);
2715 }
2716 };
2717
2718 let field =
2719 DFV::FieldVisitor::deserialize(move_object.contents(), &layout).map_err(|e| {
2720 IotaError::ObjectDeserialization {
2721 error: e.to_string(),
2722 }
2723 })?;
2724
2725 let type_ = field.kind;
2726 let name_type: TypeTag = type_tag_core_to_sdk(&field.name_layout.into());
2727 let bcs_name = field.name_bytes.to_owned();
2728
2729 let name_value = BoundedVisitor::deserialize_value(field.name_bytes, field.name_layout)
2730 .map_err(|e| {
2731 warn!("{e}");
2732 IotaError::ObjectDeserialization {
2733 error: e.to_string(),
2734 }
2735 })?;
2736
2737 let name = DynamicFieldName {
2738 type_tag: name_type,
2739 value: IotaMoveValue::from(name_value).to_json_value(),
2740 };
2741
2742 let value_metadata = field.value_metadata().map_err(|e| {
2743 warn!("{e}");
2744 IotaError::ObjectDeserialization {
2745 error: e.to_string(),
2746 }
2747 })?;
2748
2749 Ok(Some(match value_metadata {
2750 DFV::ValueMetadata::DynamicField(object_type) => DynamicFieldInfo {
2751 name,
2752 bcs_name,
2753 type_,
2754 object_type: object_type.to_canonical_string(true),
2755 object_id: o.id(),
2756 version: o.version(),
2757 digest: o.digest(),
2758 },
2759
2760 DFV::ValueMetadata::DynamicObjectField(object_id) => {
2761 let (version, digest, object_type) = if let Some(object) = written.get(&object_id) {
2766 (
2767 object.version(),
2768 object.digest(),
2769 object.data.opt_object_type().unwrap().clone(),
2770 )
2771 } else {
2772 let object = self
2774 .get_object_store()
2775 .try_get_object_by_key(&object_id, o.version())?
2776 .ok_or_else(|| UserInputError::ObjectNotFound {
2777 object_id,
2778 version: Some(o.version()),
2779 })?;
2780 let version = object.version();
2781 let digest = object.digest();
2782 let object_type = object.data.opt_object_type().unwrap().clone();
2783 (version, digest, object_type)
2784 };
2785
2786 DynamicFieldInfo {
2787 name,
2788 bcs_name,
2789 type_,
2790 object_type: object_type.to_string(),
2791 object_id,
2792 version,
2793 digest,
2794 }
2795 }
2796 }))
2797 }
2798
2799 #[instrument(level = "trace", skip_all, err)]
2800 fn post_process_one_tx(
2801 &self,
2802 transaction: &VerifiedExecutableTransaction,
2803 effects: &TransactionEffects,
2804 inner_temporary_store: &InnerTemporaryStore,
2805 epoch_store: &Arc<AuthorityPerEpochStore>,
2806 ) -> IotaResult {
2807 if self.indexes.is_none() {
2808 return Ok(());
2809 }
2810
2811 let _scope = monitored_scope("Execution::post_process_one_tx");
2812
2813 let tx_digest = transaction.digest();
2814 let timestamp_ms = Self::unixtime_now_ms();
2815 let events = &inner_temporary_store.events;
2816 let written = &inner_temporary_store.written;
2817 let tx_coins = self.fullnode_only_get_tx_coins_for_indexing(
2818 effects,
2819 inner_temporary_store,
2820 epoch_store,
2821 );
2822
2823 if let Some(indexes) = &self.indexes {
2825 let _ = self
2826 .index_tx(
2827 indexes.as_ref(),
2828 tx_digest,
2829 transaction,
2830 effects,
2831 events,
2832 timestamp_ms,
2833 tx_coins,
2834 written,
2835 inner_temporary_store,
2836 epoch_store,
2837 )
2838 .tap_ok(|_| self.metrics.post_processing_total_tx_indexed.inc())
2839 .tap_err(|e| error!(?tx_digest, "Post processing - Couldn't index tx: {e}"))
2840 .expect("Indexing tx should not fail");
2841
2842 let effects: IotaTransactionBlockEffects = effects.clone().try_into()?;
2843 let events = self.make_transaction_block_events(
2844 events.clone(),
2845 *tx_digest,
2846 timestamp_ms,
2847 epoch_store,
2848 inner_temporary_store,
2849 )?;
2850 self.subscription_handler
2852 .process_tx(transaction.data().transaction(), &effects, &events)
2853 .tap_ok(|_| {
2854 self.metrics
2855 .post_processing_total_tx_had_event_processed
2856 .inc()
2857 })
2858 .tap_err(|e| {
2859 warn!(
2860 ?tx_digest,
2861 "Post processing - Couldn't process events for tx: {}", e
2862 )
2863 })?;
2864
2865 self.metrics
2866 .post_processing_total_events_emitted
2867 .inc_by(events.data.len() as u64);
2868 };
2869 Ok(())
2870 }
2871
2872 fn make_transaction_block_events(
2873 &self,
2874 transaction_events: TransactionEvents,
2875 digest: TransactionDigest,
2876 timestamp_ms: u64,
2877 epoch_store: &Arc<AuthorityPerEpochStore>,
2878 inner_temporary_store: &InnerTemporaryStore,
2879 ) -> IotaResult<IotaTransactionBlockEvents> {
2880 let mut layout_resolver =
2881 epoch_store
2882 .executor()
2883 .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
2884 inner_temporary_store,
2885 self.get_backing_package_store(),
2886 )));
2887 IotaTransactionBlockEvents::try_from(
2888 transaction_events,
2889 digest,
2890 Some(timestamp_ms),
2891 layout_resolver.as_mut(),
2892 )
2893 }
2894
2895 pub fn unixtime_now_ms() -> u64 {
2896 let now = SystemTime::now()
2897 .duration_since(UNIX_EPOCH)
2898 .expect("Time went backwards")
2899 .as_millis();
2900 u64::try_from(now).expect("Travelling in time machine")
2901 }
2902
2903 #[instrument(level = "trace", skip_all)]
2904 pub async fn handle_transaction_info_request(
2905 &self,
2906 request: TransactionInfoRequest,
2907 ) -> IotaResult<TransactionInfoResponse> {
2908 let epoch_store = self.load_epoch_store_one_call_per_task();
2909 let (transaction, status) = self
2910 .get_transaction_status(&request.transaction_digest, &epoch_store)?
2911 .ok_or(IotaError::TransactionNotFound {
2912 digest: request.transaction_digest,
2913 })?;
2914 Ok(TransactionInfoResponse {
2915 transaction,
2916 status,
2917 })
2918 }
2919
2920 #[instrument(level = "trace", skip_all)]
2921 pub async fn handle_object_info_request(
2922 &self,
2923 request: ObjectInfoRequest,
2924 ) -> IotaResult<ObjectInfoResponse> {
2925 let epoch_store = self.load_epoch_store_one_call_per_task();
2926
2927 let requested_object_seq = match request.request_kind {
2928 ObjectInfoRequestKind::LatestObjectInfo => {
2929 self.try_get_object_or_tombstone(request.object_id)?
2930 .ok_or_else(|| {
2931 IotaError::from(UserInputError::ObjectNotFound {
2932 object_id: request.object_id,
2933 version: None,
2934 })
2935 })?
2936 .version
2937 }
2938 ObjectInfoRequestKind::PastObjectInfoDebug(seq) => seq,
2939 };
2940
2941 let object = self
2942 .get_object_store()
2943 .try_get_object_by_key(&request.object_id, requested_object_seq)?
2944 .ok_or_else(|| {
2945 IotaError::from(UserInputError::ObjectNotFound {
2946 object_id: request.object_id,
2947 version: Some(requested_object_seq),
2948 })
2949 })?;
2950
2951 let layout = if let (LayoutGenerationOption::Generate, Some(move_obj)) =
2952 (request.generate_layout, object.data.as_opt_struct())
2953 {
2954 Some(into_struct_layout(
2955 epoch_store
2956 .executor()
2957 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
2958 .get_annotated_layout(move_obj.struct_tag())?,
2959 )?)
2960 } else {
2961 None
2962 };
2963
2964 let lock = if !object.is_address_owned() {
2965 None
2967 } else {
2968 self.get_transaction_lock(&object.object_ref(), &epoch_store)?
2969 .map(|s| s.into_inner())
2970 };
2971
2972 Ok(ObjectInfoResponse {
2973 object,
2974 layout,
2975 lock_for_debugging: lock,
2976 })
2977 }
2978
2979 #[instrument(level = "trace", skip_all)]
2980 pub fn handle_checkpoint_request(
2981 &self,
2982 request: &CheckpointRequest,
2983 ) -> IotaResult<CheckpointResponse> {
2984 let summary = if request.certified {
2985 let summary = match request.sequence_number {
2986 Some(seq) => self
2987 .checkpoint_store
2988 .get_checkpoint_by_sequence_number(seq)?,
2989 None => self.checkpoint_store.get_latest_certified_checkpoint()?,
2990 }
2991 .map(|v| v.into_inner());
2992 summary.map(CheckpointSummaryResponse::Certified)
2993 } else {
2994 let summary = match request.sequence_number {
2995 Some(seq) => self.checkpoint_store.get_locally_computed_checkpoint(seq)?,
2996 None => self
2997 .checkpoint_store
2998 .get_latest_locally_computed_checkpoint()?,
2999 };
3000 summary.map(CheckpointSummaryResponse::Pending)
3001 };
3002 let contents = match &summary {
3003 Some(s) => self
3004 .checkpoint_store
3005 .get_checkpoint_contents(&s.contents_digest())?,
3006 None => None,
3007 };
3008 Ok(CheckpointResponse {
3009 checkpoint: summary,
3010 contents,
3011 })
3012 }
3013
3014 fn check_protocol_version(
3015 supported_protocol_versions: SupportedProtocolVersions,
3016 current_version: ProtocolVersion,
3017 ) {
3018 info!("current protocol version is now {:?}", current_version);
3019 info!("supported versions are: {:?}", supported_protocol_versions);
3020 if !supported_protocol_versions.is_version_supported(current_version) {
3021 let msg = format!(
3022 "Unsupported protocol version. The network is at {current_version:?}, but this IotaNode only supports: {supported_protocol_versions:?}. Shutting down.",
3023 );
3024
3025 error!("{}", msg);
3026 eprintln!("{msg}");
3027
3028 #[cfg(not(msim))]
3029 std::process::exit(1);
3030
3031 #[cfg(msim)]
3032 iota_simulator::task::shutdown_current_node();
3033 }
3034 }
3035
3036 #[expect(clippy::disallowed_methods)] pub async fn new(
3038 name: AuthorityName,
3039 secret: StableSyncAuthoritySigner,
3040 supported_protocol_versions: SupportedProtocolVersions,
3041 store: Arc<AuthorityStore>,
3042 execution_cache_trait_pointers: ExecutionCacheTraitPointers,
3043 epoch_store: Arc<AuthorityPerEpochStore>,
3044 committee_store: Arc<CommitteeStore>,
3045 indexes: Option<Arc<IndexStore>>,
3046 grpc_indexes_store: Option<Arc<GrpcIndexesStore>>,
3047 checkpoint_store: Arc<CheckpointStore>,
3048 prometheus_registry: &Registry,
3049 genesis_objects: &[Object],
3050 config: NodeConfig,
3051 validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
3052 chain_identifier: ChainIdentifier,
3053 pruner_db: Option<Arc<AuthorityPrunerTables>>,
3054 checkpoint_progress_tracker: Option<Arc<CheckpointProgressTracker>>,
3055 policy_config: Option<PolicyConfig>,
3056 firewall_config: Option<RemoteFirewallConfig>,
3057 ) -> Arc<Self> {
3058 Self::check_protocol_version(supported_protocol_versions, epoch_store.protocol_version());
3059
3060 let metrics = Arc::new(AuthorityMetrics::new(prometheus_registry));
3061 let (tx_ready_transactions, rx_ready_transactions) = unbounded_channel();
3062 let execution_scheduler = Arc::new(ExecutionSchedulerWrapper::new(
3063 execution_cache_trait_pointers.object_cache_reader.clone(),
3064 execution_cache_trait_pointers
3065 .transaction_cache_reader
3066 .clone(),
3067 tx_ready_transactions,
3068 &epoch_store,
3069 metrics.clone(),
3070 ));
3071 let (tx_execution_shutdown, rx_execution_shutdown) = oneshot::channel();
3072
3073 let authority_per_epoch_pruner = AuthorityPerEpochStorePruner::new(
3074 epoch_store.get_parent_path(),
3075 config
3076 .authority_store_pruning_config
3077 .num_latest_epoch_dbs_to_retain,
3078 )
3079 .await;
3080 let pruner = AuthorityStorePruner::new(
3081 store.perpetual_tables.clone(),
3082 checkpoint_store.clone(),
3083 grpc_indexes_store.clone(),
3084 indexes.clone(),
3085 config.authority_store_pruning_config.clone(),
3086 epoch_store.committee().authority_exists(&name),
3087 epoch_store.epoch_start_state().epoch_duration_ms(),
3088 prometheus_registry,
3089 pruner_db,
3090 checkpoint_progress_tracker.clone(),
3091 );
3092 let input_loader =
3093 TransactionInputLoader::new(execution_cache_trait_pointers.object_cache_reader.clone());
3094 let epoch = epoch_store.epoch();
3095 let rgp = epoch_store.reference_gas_price();
3096 let traffic_controller_metrics =
3097 Arc::new(TrafficControllerMetrics::new(prometheus_registry));
3098 let traffic_controller = policy_config.map(|policy_config| {
3099 Arc::new(TrafficController::init(
3100 policy_config,
3101 traffic_controller_metrics,
3102 firewall_config.clone(),
3103 ))
3104 });
3105 let state = Arc::new(AuthorityState {
3106 name,
3107 secret,
3108 execution_lock: RwLock::new(epoch),
3109 epoch_store: ArcSwap::new(epoch_store.clone()),
3110 input_loader,
3111 execution_cache_trait_pointers,
3112 indexes,
3113 grpc_indexes_store,
3114 subscription_handler: Arc::new(SubscriptionHandler::new(prometheus_registry)),
3115 checkpoint_store,
3116 committee_store,
3117 execution_scheduler,
3118 tx_execution_shutdown: Mutex::new(Some(tx_execution_shutdown)),
3119 metrics,
3120 pruner,
3121 authority_per_epoch_pruner,
3122 checkpoint_progress_tracker,
3123 config,
3124 overload_info: AuthorityOverloadInfo::default(),
3125 validator_tx_finalizer,
3126 chain_identifier,
3127 congestion_tracker: Arc::new(CongestionTracker::new(rgp)),
3128 traffic_controller,
3129 });
3130
3131 let authority_state = Arc::downgrade(&state);
3133 spawn_monitored_task!(execution_process(
3134 authority_state,
3135 rx_ready_transactions,
3136 rx_execution_shutdown,
3137 ));
3138 state
3140 .create_owner_index_if_empty(genesis_objects, &epoch_store)
3141 .expect("Error indexing genesis objects.");
3142
3143 state
3144 }
3145
3146 pub fn epoch_db_pruner(&self) -> &AuthorityPerEpochStorePruner {
3147 &self.authority_per_epoch_pruner
3148 }
3149
3150 pub fn get_object_cache_reader(&self) -> &Arc<dyn ObjectCacheRead> {
3152 &self.execution_cache_trait_pointers.object_cache_reader
3153 }
3154
3155 pub fn get_transaction_cache_reader(&self) -> &Arc<dyn TransactionCacheRead> {
3156 &self.execution_cache_trait_pointers.transaction_cache_reader
3157 }
3158
3159 pub fn get_cache_writer(&self) -> &Arc<dyn ExecutionCacheWrite> {
3160 &self.execution_cache_trait_pointers.cache_writer
3161 }
3162
3163 pub fn get_backing_store(&self) -> &Arc<dyn BackingStore + Send + Sync> {
3164 &self.execution_cache_trait_pointers.backing_store
3165 }
3166
3167 pub fn get_backing_package_store(&self) -> &Arc<dyn BackingPackageStore + Send + Sync> {
3168 &self.execution_cache_trait_pointers.backing_package_store
3169 }
3170
3171 pub fn get_object_store(&self) -> &Arc<dyn ObjectStore + Send + Sync> {
3172 &self.execution_cache_trait_pointers.object_store
3173 }
3174
3175 pub fn get_reconfig_api(&self) -> &Arc<dyn ExecutionCacheReconfigAPI> {
3176 &self.execution_cache_trait_pointers.reconfig_api
3177 }
3178
3179 pub fn get_global_state_hash_store(&self) -> &Arc<dyn GlobalStateHashStore> {
3180 &self.execution_cache_trait_pointers.global_state_hash_store
3181 }
3182
3183 pub fn get_checkpoint_cache(&self) -> &Arc<dyn CheckpointCache> {
3184 &self.execution_cache_trait_pointers.checkpoint_cache
3185 }
3186
3187 pub fn get_state_sync_store(&self) -> &Arc<dyn StateSyncAPI> {
3188 &self.execution_cache_trait_pointers.state_sync_store
3189 }
3190
3191 pub fn get_cache_commit(&self) -> &Arc<dyn ExecutionCacheCommit> {
3192 &self.execution_cache_trait_pointers.cache_commit
3193 }
3194
3195 pub fn database_for_testing(&self) -> Arc<AuthorityStore> {
3196 self.execution_cache_trait_pointers
3197 .testing_api
3198 .database_for_testing()
3199 }
3200
3201 pub async fn prune_checkpoints_for_eligible_epochs_for_testing(
3202 &self,
3203 config: NodeConfig,
3204 metrics: Arc<AuthorityStorePruningMetrics>,
3205 ) -> anyhow::Result<()> {
3206 AuthorityStorePruner::prune_checkpoints_for_eligible_epochs(
3207 &self.database_for_testing().perpetual_tables,
3208 &self.checkpoint_store,
3209 self.grpc_indexes_store.as_deref(),
3210 None,
3211 config.authority_store_pruning_config,
3212 metrics,
3213 EPOCH_DURATION_MS_FOR_TESTING,
3214 self.checkpoint_progress_tracker.as_ref(),
3215 )
3216 .await
3217 }
3218
3219 pub fn execution_scheduler(&self) -> &Arc<ExecutionSchedulerWrapper> {
3220 &self.execution_scheduler
3221 }
3222
3223 pub fn uses_execution_scheduler(&self) -> bool {
3226 self.execution_scheduler.uses_execution_scheduler()
3227 }
3228
3229 fn create_owner_index_if_empty(
3230 &self,
3231 genesis_objects: &[Object],
3232 epoch_store: &Arc<AuthorityPerEpochStore>,
3233 ) -> IotaResult {
3234 let Some(index_store) = &self.indexes else {
3235 return Ok(());
3236 };
3237 if !index_store.is_empty() {
3238 return Ok(());
3239 }
3240
3241 let mut new_owners = vec![];
3242 let mut new_dynamic_fields = vec![];
3243 let mut layout_resolver = epoch_store
3244 .executor()
3245 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()));
3246 for o in genesis_objects.iter() {
3247 match o.owner {
3248 Owner::Address(addr) => {
3249 new_owners.push(((addr, o.id()), ObjectInfo::new(&o.object_ref(), o)))
3250 }
3251 Owner::Object(object_id) => {
3252 let id = o.id();
3253 let info = match self.try_create_dynamic_field_info(
3254 o,
3255 &BTreeMap::new(),
3256 layout_resolver.as_mut(),
3257 ) {
3258 Ok(Some(info)) => info,
3259 Ok(None) => continue,
3260 Err(IotaError::UserInput {
3261 error:
3262 UserInputError::ObjectNotFound {
3263 object_id: not_found_id,
3264 version,
3265 },
3266 }) => {
3267 warn!(
3268 ?not_found_id,
3269 ?version,
3270 object_owner=?object_id,
3271 field=?id,
3272 "Skipping dynamic field: referenced genesis object not found"
3273 );
3274 continue;
3275 }
3276 Err(e) => return Err(e),
3277 };
3278 new_dynamic_fields.push(((object_id, id), info));
3279 }
3280 _ => {}
3281 }
3282 }
3283
3284 index_store.insert_genesis_objects(ObjectIndexChanges {
3285 deleted_owners: vec![],
3286 deleted_dynamic_fields: vec![],
3287 new_owners,
3288 new_dynamic_fields,
3289 })
3290 }
3291
3292 pub fn execution_lock_for_executable_transaction(
3296 &self,
3297 transaction: &VerifiedExecutableTransaction,
3298 ) -> IotaResult<ExecutionLockReadGuard<'_>> {
3299 let lock = self
3300 .execution_lock
3301 .try_read()
3302 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)?;
3303 if *lock == transaction.auth_sig().epoch() {
3304 Ok(lock)
3305 } else {
3306 Err(IotaError::WrongEpoch {
3307 expected_epoch: *lock,
3308 actual_epoch: transaction.auth_sig().epoch(),
3309 })
3310 }
3311 }
3312
3313 pub fn execution_lock_for_signing(&self) -> IotaResult<ExecutionLockReadGuard<'_>> {
3319 self.execution_lock
3320 .try_read()
3321 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)
3322 }
3323
3324 pub async fn execution_lock_for_reconfiguration(&self) -> ExecutionLockWriteGuard<'_> {
3325 self.execution_lock.write().await
3326 }
3327
3328 pub(crate) fn check_transaction_deny_rules_consistency(
3338 &self,
3339 cur_epoch_store: &AuthorityPerEpochStore,
3340 epoch_start_configuration: &EpochStartConfiguration,
3341 ) {
3342 if self.is_fullnode(cur_epoch_store) {
3343 return;
3344 }
3345 let Some(walked_deny_rules) = epoch_start_configuration.transaction_deny_rules_state()
3346 else {
3347 if cur_epoch_store
3348 .epoch_start_config()
3349 .transaction_deny_rules_obj_initial_shared_version()
3350 .is_some()
3351 {
3352 fatal!(
3353 "TransactionDenyRules object existed in epoch {} but is missing from the \
3354 state walked for the next epoch — the local store is corrupted; restore or \
3355 state-sync before rejoining",
3356 cur_epoch_store.epoch(),
3357 );
3358 }
3359 return;
3360 };
3361 if cur_epoch_store
3365 .get_reconfig_state_read_lock_guard()
3366 .should_accept_tx()
3367 {
3368 info!(
3369 "skipping the deny-rule mirror comparison: consensus did not close epoch {} on \
3370 this node",
3371 cur_epoch_store.epoch(),
3372 );
3373 return;
3374 }
3375 let mirrored_deny_rules = cur_epoch_store.get_mirrored_transaction_deny_rules();
3376 if *walked_deny_rules != *mirrored_deny_rules {
3377 debug_fatal!(
3378 "TransactionDenyRules object diverged from the mirrored state at the end of \
3379 epoch {}; continuing from the object (walked: {walked_deny_rules:?}, mirrored: \
3380 {mirrored_deny_rules:?})",
3381 cur_epoch_store.epoch(),
3382 );
3383 cur_epoch_store.metrics.deny_rule_mirror_divergence.set(1);
3384 }
3385 }
3386
3387 pub(crate) fn report_failed_deny_rule_update_execution(
3399 &self,
3400 transaction: &VerifiedExecutableTransaction,
3401 effects: &TransactionEffects,
3402 expected_effects_digest: Option<TransactionEffectsDigest>,
3403 epoch_store: &AuthorityPerEpochStore,
3404 ) {
3405 if !matches!(
3406 transaction.transaction().kind(),
3407 TransactionKind::TransactionDenyRulesUpdate(_)
3408 ) || effects.status().is_success()
3409 {
3410 return;
3411 }
3412 epoch_store
3413 .metrics
3414 .deny_rule_update_execution_failures
3415 .inc();
3416 if expected_effects_digest.is_some() {
3417 error!(
3418 digest = ?transaction.digest(),
3419 status = ?effects.status(),
3420 "TransactionDenyRulesUpdate failed execution; the object misses its delta until \
3421 the epoch boundary re-seeds the mirror"
3422 );
3423 return;
3424 }
3425 debug_fatal!(
3426 "TransactionDenyRulesUpdate failed execution; the object misses its delta until the \
3427 epoch boundary re-seeds the mirror (digest: {:?}, status: {:?})",
3428 transaction.digest(),
3429 effects.status(),
3430 );
3431 }
3432
3433 #[instrument(level = "error", skip_all)]
3434 pub async fn reconfigure(
3435 &self,
3436 cur_epoch_store: &AuthorityPerEpochStore,
3437 supported_protocol_versions: SupportedProtocolVersions,
3438 new_committee: Committee,
3439 epoch_start_configuration: EpochStartConfiguration,
3440 state_hasher: Arc<GlobalStateHasher>,
3441 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3442 epoch_supply_change: i64,
3443 epoch_last_checkpoint: CheckpointSequenceNumber,
3444 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
3445 Self::check_protocol_version(
3446 supported_protocol_versions,
3447 epoch_start_configuration
3448 .epoch_start_state()
3449 .protocol_version(),
3450 );
3451 self.metrics.reset_on_reconfigure();
3452 self.committee_store.insert_new_committee(&new_committee)?;
3453
3454 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3456
3457 cur_epoch_store.epoch_terminated().await;
3459
3460 let highest_locally_built_checkpoint_seq = self
3461 .checkpoint_store
3462 .get_latest_locally_computed_checkpoint()?
3463 .map(|c| c.sequence_number())
3464 .unwrap_or(0);
3465
3466 assert!(
3467 epoch_last_checkpoint >= highest_locally_built_checkpoint_seq,
3468 "expected {epoch_last_checkpoint} >= {highest_locally_built_checkpoint_seq}"
3469 );
3470
3471 self.revert_uncommitted_epoch_transactions(cur_epoch_store)
3477 .await?;
3478 self.get_reconfig_api()
3479 .clear_state_end_of_epoch(&execution_lock);
3480 self.check_system_consistency(
3481 cur_epoch_store,
3482 state_hasher,
3483 expensive_safety_check_config,
3484 epoch_supply_change,
3485 )?;
3486 self.check_transaction_deny_rules_consistency(cur_epoch_store, &epoch_start_configuration);
3487
3488 self.get_reconfig_api()
3489 .try_set_epoch_start_configuration(&epoch_start_configuration)?;
3490 if self
3494 .config
3495 .state_snapshot_write_config
3496 .object_store_config
3497 .is_some()
3498 {
3499 let current_epoch = cur_epoch_store.epoch();
3500 let epoch_checkpoint_path = self
3501 .config
3502 .db_checkpoint_path()
3503 .join(format!("epoch_{current_epoch}"));
3504 self.checkpoint_perpetual_db(&epoch_checkpoint_path, cur_epoch_store)?;
3505 }
3506
3507 let new_epoch = new_committee.epoch;
3508 let new_epoch_store = self
3509 .reopen_epoch_db(
3510 cur_epoch_store,
3511 new_committee,
3512 epoch_start_configuration,
3513 expensive_safety_check_config,
3514 epoch_last_checkpoint,
3515 )
3516 .await?;
3517 assert_eq!(new_epoch_store.epoch(), new_epoch);
3518 match self.execution_scheduler.as_ref() {
3519 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3520 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3521 tm.reconfigure(new_epoch);
3522 }
3523 }
3524 *execution_lock = new_epoch;
3525 Ok(new_epoch_store)
3529 }
3530
3531 pub async fn reconfigure_for_testing(&self) {
3536 self.reconfigure_for_testing_impl(None).await;
3537 }
3538
3539 pub async fn reconfigure_for_testing_with_protocol_config(
3542 &self,
3543 protocol_config: ProtocolConfig,
3544 ) {
3545 self.reconfigure_for_testing_impl(Some(protocol_config))
3546 .await;
3547 }
3548
3549 async fn reconfigure_for_testing_impl(&self, protocol_config: Option<ProtocolConfig>) {
3550 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3551 let epoch_store = self.epoch_store_for_testing().clone();
3552 let protocol_config =
3556 protocol_config.unwrap_or_else(|| epoch_store.protocol_config().clone());
3557 let _guard =
3558 ProtocolConfig::apply_overrides_for_testing(move |_, _| protocol_config.clone());
3559 let new_epoch_store = epoch_store.new_at_next_epoch_for_testing(
3560 self.get_backing_package_store().clone(),
3561 &self.config.expensive_safety_check_config,
3562 self.checkpoint_store
3563 .get_epoch_last_checkpoint(epoch_store.epoch())
3564 .unwrap()
3565 .map(|c| c.sequence_number())
3566 .unwrap_or_default(),
3567 );
3568 let new_epoch = new_epoch_store.epoch();
3569 match self.execution_scheduler.as_ref() {
3570 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3571 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3572 tm.reconfigure(new_epoch);
3573 }
3574 }
3575 self.epoch_store.store(new_epoch_store);
3576 epoch_store.epoch_terminated().await;
3577 *execution_lock = new_epoch;
3578 }
3579
3580 #[instrument(level = "error", skip_all)]
3581 fn check_system_consistency(
3582 &self,
3583 cur_epoch_store: &AuthorityPerEpochStore,
3584 state_hasher: Arc<GlobalStateHasher>,
3585 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3586 epoch_supply_change: i64,
3587 ) -> IotaResult<()> {
3588 info!(
3589 "Performing iota conservation consistency check for epoch {}",
3590 cur_epoch_store.epoch()
3591 );
3592
3593 if cfg!(debug_assertions) {
3594 cur_epoch_store.check_all_executed_transactions_in_checkpoint();
3595 }
3596
3597 self.get_reconfig_api()
3598 .try_expensive_check_iota_conservation(cur_epoch_store, Some(epoch_supply_change))?;
3599
3600 if expensive_safety_check_config.enable_state_consistency_check() {
3602 info!(
3603 "Performing state consistency check for epoch {}",
3604 cur_epoch_store.epoch()
3605 );
3606 self.expensive_check_is_consistent_state(state_hasher, cur_epoch_store);
3607 }
3608
3609 if expensive_safety_check_config.enable_secondary_index_checks() {
3610 if let Some(indexes) = self.indexes.clone() {
3611 verify_indexes(self.get_global_state_hash_store().as_ref(), indexes)
3612 .expect("secondary indexes are inconsistent");
3613 }
3614 }
3615
3616 Ok(())
3617 }
3618
3619 fn expensive_check_is_consistent_state(
3620 &self,
3621 state_hasher: Arc<GlobalStateHasher>,
3622 cur_epoch_store: &AuthorityPerEpochStore,
3623 ) {
3624 let live_object_set_hash = state_hasher.digest_live_object_set();
3625
3626 let root_state_hash: ECMHLiveObjectSetDigest = self
3627 .get_global_state_hash_store()
3628 .get_root_state_hash_for_epoch(cur_epoch_store.epoch())
3629 .expect("Retrieving root state hash cannot fail")
3630 .expect("Root state hash for epoch must exist")
3631 .1
3632 .digest()
3633 .into();
3634
3635 let is_inconsistent = root_state_hash != live_object_set_hash;
3636 if is_inconsistent {
3637 debug_fatal!(
3638 "Inconsistent state detected: root state hash: {:?}, live object set hash: {:?}",
3639 root_state_hash,
3640 live_object_set_hash
3641 );
3642 } else {
3643 info!("State consistency check passed");
3644 }
3645
3646 state_hasher.set_inconsistent_state(is_inconsistent);
3647 }
3648
3649 pub fn current_epoch_for_testing(&self) -> EpochId {
3650 self.epoch_store_for_testing().epoch()
3651 }
3652
3653 #[instrument(level = "error", skip_all)]
3657 fn checkpoint_perpetual_db(
3658 &self,
3659 checkpoint_path: &Path,
3660 cur_epoch_store: &AuthorityPerEpochStore,
3661 ) -> IotaResult {
3662 let _metrics_guard = self.metrics.db_checkpoint_latency.start_timer();
3663 let current_epoch = cur_epoch_store.epoch();
3664
3665 if checkpoint_path.exists() {
3666 info!("Skipping db checkpoint as it already exists for epoch: {current_epoch}");
3667 return Ok(());
3668 }
3669
3670 let checkpoint_path_tmp = checkpoint_path.with_extension("tmp");
3671 let store_checkpoint_path_tmp = checkpoint_path_tmp.join("store");
3672
3673 if checkpoint_path_tmp.exists() {
3674 fs::remove_dir_all(&checkpoint_path_tmp)
3675 .map_err(|e| IotaError::FileIO(e.to_string()))?;
3676 }
3677
3678 fs::create_dir_all(&checkpoint_path_tmp).map_err(|e| IotaError::FileIO(e.to_string()))?;
3679 fs::create_dir(&store_checkpoint_path_tmp).map_err(|e| IotaError::FileIO(e.to_string()))?;
3680
3681 self.get_reconfig_api()
3682 .try_checkpoint_db(&store_checkpoint_path_tmp.join("perpetual"))?;
3683
3684 fs::rename(checkpoint_path_tmp, checkpoint_path)
3685 .map_err(|e| IotaError::FileIO(e.to_string()))?;
3686 Ok(())
3687 }
3688
3689 pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3696 self.epoch_store.load()
3697 }
3698
3699 pub fn epoch_store_for_testing(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3701 self.load_epoch_store_one_call_per_task()
3702 }
3703
3704 pub fn clone_committee_for_testing(&self) -> Committee {
3705 Committee::clone(self.epoch_store_for_testing().committee())
3706 }
3707
3708 #[instrument(level = "trace", skip_all)]
3709 pub fn try_get_object(&self, object_id: &ObjectId) -> IotaResult<Option<Object>> {
3710 self.get_object_store()
3711 .try_get_object(object_id)
3712 .map_err(Into::into)
3713 }
3714
3715 pub fn get_object(&self, object_id: &ObjectId) -> Option<Object> {
3717 self.try_get_object(object_id)
3718 .expect("storage access failed")
3719 }
3720
3721 pub fn get_iota_system_package_object_ref(&self) -> IotaResult<ObjectReference> {
3722 Ok(self
3723 .try_get_object(&ObjectId::SYSTEM)?
3724 .expect("system package should always exist")
3725 .object_ref())
3726 }
3727
3728 pub fn get_iota_system_state_object_for_testing(&self) -> IotaResult<IotaSystemState> {
3730 self.get_object_cache_reader()
3731 .try_get_iota_system_state_object_unsafe()
3732 }
3733
3734 #[instrument(level = "trace", skip_all)]
3735 pub fn get_checkpoint_by_sequence_number(
3736 &self,
3737 sequence_number: CheckpointSequenceNumber,
3738 ) -> IotaResult<Option<VerifiedCheckpoint>> {
3739 Ok(self
3740 .checkpoint_store
3741 .get_checkpoint_by_sequence_number(sequence_number)?)
3742 }
3743
3744 pub async fn wait_for_checkpoint_inclusion(
3755 &self,
3756 digests: &[TransactionDigest],
3757 timeout: Duration,
3758 ) -> IotaResult<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>> {
3759 let deadline = tokio::time::Instant::now() + timeout;
3760 let mut checkpoint_timestamp_cache = HashMap::<CheckpointSequenceNumber, u64>::new();
3761 let mut results = BTreeMap::new();
3762 let mut remaining = digests.to_vec();
3763 let mut epoch_store = self.load_epoch_store_one_call_per_task().clone();
3764
3765 loop {
3766 let wait = epoch_store.wait_for_transactions_in_checkpoint_with_timeout(
3767 &remaining,
3768 deadline.saturating_duration_since(tokio::time::Instant::now()),
3769 |seq| self.checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache),
3770 );
3771 tokio::select! {
3772 wait_results = wait => {
3773 for (digest, seq_and_ts) in remaining.iter().zip(wait_results?) {
3774 if let Some(seq_and_ts) = seq_and_ts {
3775 results.insert(*digest, seq_and_ts);
3776 }
3777 }
3778 return Ok(results);
3779 }
3780 _ = epoch_store.wait_epoch_terminated() => {}
3781 }
3782
3783 let found = match epoch_store.multi_get_transaction_checkpoint(&remaining) {
3790 Ok(found) => found,
3791 Err(IotaError::EpochEnded(_)) => vec![None; remaining.len()],
3796 Err(err) => return Err(err),
3797 };
3798 let mut still_uncheckpointed = Vec::new();
3799 for (digest, found_seq) in remaining.iter().zip(found) {
3800 match found_seq {
3801 Some(seq) => {
3802 let ts = self
3803 .checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache);
3804 results.insert(*digest, (seq, ts));
3805 }
3806 None => still_uncheckpointed.push(*digest),
3807 }
3808 }
3809 remaining = still_uncheckpointed;
3810 if remaining.is_empty() {
3811 return Ok(results);
3812 }
3813
3814 match self
3815 .wait_for_next_epoch_store(epoch_store.epoch(), deadline)
3816 .await
3817 {
3818 Some(next) => epoch_store = next,
3819 None => return Ok(results),
3820 }
3821 }
3822 }
3823
3824 async fn wait_for_next_epoch_store(
3827 &self,
3828 prev_epoch: EpochId,
3829 deadline: tokio::time::Instant,
3830 ) -> Option<Arc<AuthorityPerEpochStore>> {
3831 const EPOCH_STORE_SWAP_POLL_INTERVAL: Duration = Duration::from_millis(100);
3836
3837 loop {
3838 let current = self.load_epoch_store_one_call_per_task().clone();
3841 if current.epoch() > prev_epoch {
3842 return Some(current);
3843 }
3844 if tokio::time::Instant::now() >= deadline {
3845 return None;
3846 }
3847 tokio::time::sleep(EPOCH_STORE_SWAP_POLL_INTERVAL).await;
3848 }
3849 }
3850
3851 fn checkpoint_timestamp_ms_cached(
3855 &self,
3856 seq: CheckpointSequenceNumber,
3857 cache: &mut HashMap<CheckpointSequenceNumber, u64>,
3858 ) -> u64 {
3859 *cache.entry(seq).or_insert_with(|| {
3860 self.get_checkpoint_by_sequence_number(seq)
3861 .ok()
3862 .flatten()
3863 .map(|c| c.timestamp_ms)
3864 .unwrap_or(0)
3865 })
3866 }
3867
3868 #[instrument(level = "trace", skip_all)]
3869 pub fn get_transaction_checkpoint_for_tests(
3870 &self,
3871 digest: &TransactionDigest,
3872 epoch_store: &AuthorityPerEpochStore,
3873 ) -> IotaResult<Option<VerifiedCheckpoint>> {
3874 let checkpoint = epoch_store.get_transaction_checkpoint(digest)?;
3875 let Some(checkpoint) = checkpoint else {
3876 return Ok(None);
3877 };
3878 let checkpoint = self
3879 .checkpoint_store
3880 .get_checkpoint_by_sequence_number(checkpoint)?;
3881 Ok(checkpoint)
3882 }
3883
3884 #[instrument(level = "trace", skip_all)]
3885 pub fn get_object_read(&self, object_id: &ObjectId) -> IotaResult<ObjectRead> {
3886 Ok(
3887 match self
3888 .get_object_cache_reader()
3889 .try_get_latest_object_or_tombstone(*object_id)?
3890 {
3891 Some((_, ObjectOrTombstone::Object(object))) => {
3892 let layout = self.get_object_layout(&object)?;
3893 ObjectRead::Exists(object.object_ref(), object, layout)
3894 }
3895 Some((_, ObjectOrTombstone::Tombstone(objref))) => ObjectRead::Deleted(objref),
3896 None => ObjectRead::NotExists(*object_id),
3897 },
3898 )
3899 }
3900
3901 pub fn get_chain_identifier(&self) -> ChainIdentifier {
3903 self.chain_identifier
3904 }
3905
3906 #[instrument(level = "trace", skip_all)]
3907 pub fn get_move_object<T>(&self, object_id: &ObjectId) -> IotaResult<T>
3908 where
3909 T: DeserializeOwned,
3910 {
3911 let o = self.get_object_read(object_id)?.into_object()?;
3912 if let Some(move_object) = o.data.as_opt_struct() {
3913 Ok(bcs::from_bytes(move_object.contents()).map_err(|e| {
3914 IotaError::ObjectDeserialization {
3915 error: format!("{e}"),
3916 }
3917 })?)
3918 } else {
3919 Err(IotaError::ObjectDeserialization {
3920 error: format!("Provided object : [{object_id}] is not a Move object."),
3921 })
3922 }
3923 }
3924
3925 #[instrument(level = "trace", skip_all)]
3931 pub fn get_past_object_read(
3932 &self,
3933 object_id: &ObjectId,
3934 version: Version,
3935 ) -> IotaResult<PastObjectRead> {
3936 let Some(obj_ref) = self
3938 .get_object_cache_reader()
3939 .try_get_latest_object_ref_or_tombstone(*object_id)?
3940 else {
3941 return Ok(PastObjectRead::ObjectNotExists(*object_id));
3942 };
3943
3944 if version > obj_ref.version {
3945 return Ok(PastObjectRead::VersionTooHigh {
3946 object_id: *object_id,
3947 asked_version: version,
3948 latest_version: obj_ref.version,
3949 });
3950 }
3951
3952 if version < obj_ref.version {
3953 return Ok(match self.read_object_at_version(object_id, version)? {
3955 Some((object, layout)) => {
3956 let obj_ref = object.object_ref();
3957 PastObjectRead::VersionFound(obj_ref, object, layout)
3958 }
3959
3960 None => PastObjectRead::VersionNotFound(*object_id, version),
3961 });
3962 }
3963
3964 if !obj_ref.digest.is_alive() {
3965 return Ok(PastObjectRead::ObjectDeleted(obj_ref));
3966 }
3967
3968 match self.read_object_at_version(object_id, obj_ref.version)? {
3969 Some((object, layout)) => Ok(PastObjectRead::VersionFound(obj_ref, object, layout)),
3970 None => {
3971 debug_fatal!(
3972 "Object with in parent_entry is missing from object store, datastore is \
3973 inconsistent",
3974 );
3975 Err(UserInputError::ObjectNotFound {
3976 object_id: *object_id,
3977 version: Some(obj_ref.version),
3978 }
3979 .into())
3980 }
3981 }
3982 }
3983
3984 #[instrument(level = "trace", skip_all)]
3985 fn read_object_at_version(
3986 &self,
3987 object_id: &ObjectId,
3988 version: Version,
3989 ) -> IotaResult<Option<(Object, Option<MoveStructLayout>)>> {
3990 let Some(object) = self
3991 .get_object_cache_reader()
3992 .try_get_object_by_key(object_id, version)?
3993 else {
3994 return Ok(None);
3995 };
3996
3997 let layout = self.get_object_layout(&object)?;
3998 Ok(Some((object, layout)))
3999 }
4000
4001 fn get_object_layout(&self, object: &Object) -> IotaResult<Option<MoveStructLayout>> {
4002 let layout = object
4003 .data
4004 .as_opt_struct()
4005 .map(|object| {
4006 into_struct_layout(
4007 self.load_epoch_store_one_call_per_task()
4008 .executor()
4009 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
4011 .get_annotated_layout(object.struct_tag())?,
4012 )
4013 })
4014 .transpose()?;
4015 Ok(layout)
4016 }
4017
4018 fn get_owner_at_version(&self, object_id: &ObjectId, version: Version) -> IotaResult<Owner> {
4019 self.get_object_store()
4020 .try_get_object_by_key(object_id, version)?
4021 .ok_or_else(|| {
4022 IotaError::from(UserInputError::ObjectNotFound {
4023 object_id: *object_id,
4024 version: Some(version),
4025 })
4026 })
4027 .map(|o| o.owner)
4028 }
4029
4030 #[instrument(level = "trace", skip_all)]
4031 pub fn get_owner_objects(
4032 &self,
4033 owner: Address,
4034 cursor: Option<ObjectId>,
4036 limit: usize,
4037 filter: Option<IotaObjectDataFilter>,
4038 ) -> IotaResult<Vec<ObjectInfo>> {
4039 if let Some(indexes) = &self.indexes {
4040 indexes.get_owner_objects(owner, cursor, limit, filter)
4041 } else {
4042 Err(IotaError::IndexStoreNotAvailable)
4043 }
4044 }
4045
4046 #[instrument(level = "trace", skip_all)]
4047 pub fn get_owned_coins_iterator_with_cursor(
4048 &self,
4049 owner: Address,
4050 cursor: (String, ObjectId),
4052 limit: usize,
4053 one_coin_type_only: bool,
4054 ) -> IotaResult<impl Iterator<Item = (String, ObjectId, CoinInfo)> + '_> {
4055 if let Some(indexes) = &self.indexes {
4056 indexes.get_owned_coins_iterator_with_cursor(owner, cursor, limit, one_coin_type_only)
4057 } else {
4058 Err(IotaError::IndexStoreNotAvailable)
4059 }
4060 }
4061
4062 #[instrument(level = "trace", skip_all)]
4063 pub fn get_owner_objects_iterator(
4064 &self,
4065 owner: Address,
4066 cursor: Option<ObjectId>,
4068 filter: Option<IotaObjectDataFilter>,
4069 ) -> IotaResult<impl Iterator<Item = ObjectInfo> + '_> {
4070 if let Some(indexes) = &self.indexes {
4071 indexes.get_owner_objects_iterator(owner, cursor, filter)
4072 } else {
4073 Err(IotaError::IndexStoreNotAvailable)
4074 }
4075 }
4076
4077 #[instrument(level = "trace", skip_all)]
4078 pub fn get_move_objects<T>(&self, owner: Address, tag: StructTag) -> IotaResult<Vec<T>>
4079 where
4080 T: DeserializeOwned,
4081 {
4082 let object_ids = self
4083 .get_owner_objects_iterator(owner, None, None)?
4084 .filter(|o| match &o.object_type {
4085 ObjectType::Struct(s) => *s == tag,
4086 ObjectType::Package => false,
4087 })
4088 .map(|info| ObjectKey(info.object_id, info.version))
4089 .collect::<Vec<_>>();
4090 let mut move_objects = vec![];
4091
4092 let objects = self
4093 .get_object_store()
4094 .try_multi_get_objects_by_key(&object_ids)?;
4095
4096 for (o, id) in objects.into_iter().zip(object_ids) {
4097 let object = o.ok_or_else(|| {
4098 IotaError::from(UserInputError::ObjectNotFound {
4099 object_id: id.0,
4100 version: Some(id.1),
4101 })
4102 })?;
4103 let move_object = object.data.as_opt_struct().ok_or_else(|| {
4104 IotaError::from(UserInputError::MovePackageAsObject { object_id: id.0 })
4105 })?;
4106 move_objects.push(bcs::from_bytes(move_object.contents()).map_err(|e| {
4107 IotaError::ObjectDeserialization {
4108 error: format!("{e}"),
4109 }
4110 })?);
4111 }
4112 Ok(move_objects)
4113 }
4114
4115 #[instrument(level = "trace", skip_all)]
4116 pub fn get_dynamic_fields(
4117 &self,
4118 owner: ObjectId,
4119 cursor: Option<ObjectId>,
4121 limit: usize,
4122 ) -> IotaResult<Vec<(ObjectId, DynamicFieldInfo)>> {
4123 Ok(self
4124 .get_dynamic_fields_iterator(owner, cursor)?
4125 .take(limit)
4126 .collect::<Result<Vec<_>, _>>()?)
4127 }
4128
4129 fn get_dynamic_fields_iterator(
4130 &self,
4131 owner: ObjectId,
4132 cursor: Option<ObjectId>,
4134 ) -> IotaResult<impl Iterator<Item = Result<(ObjectId, DynamicFieldInfo), TypedStoreError>> + '_>
4135 {
4136 if let Some(indexes) = &self.indexes {
4137 indexes.get_dynamic_fields_iterator(owner, cursor)
4138 } else {
4139 Err(IotaError::IndexStoreNotAvailable)
4140 }
4141 }
4142
4143 #[instrument(level = "trace", skip_all)]
4144 pub fn get_dynamic_field_object_id(
4145 &self,
4146 owner: ObjectId,
4147 name_type: TypeTag,
4148 name_bcs_bytes: &[u8],
4149 ) -> IotaResult<Option<ObjectId>> {
4150 if let Some(indexes) = &self.indexes {
4151 indexes.get_dynamic_field_object_id(owner, name_type, name_bcs_bytes)
4152 } else {
4153 Err(IotaError::IndexStoreNotAvailable)
4154 }
4155 }
4156
4157 #[instrument(level = "trace", skip_all)]
4158 pub fn get_total_transaction_blocks(&self) -> IotaResult<u64> {
4159 Ok(self.get_indexes()?.next_sequence_number())
4160 }
4161
4162 #[instrument(level = "trace", skip_all)]
4163 pub async fn get_executed_transaction_and_effects(
4164 &self,
4165 digest: TransactionDigest,
4166 kv_store: Arc<TransactionKeyValueStore>,
4167 ) -> IotaResult<(TransactionEnvelope, TransactionEffects)> {
4168 let transaction = kv_store.get_tx(digest).await?;
4169 let effects = kv_store.get_fx_by_tx_digest(digest).await?;
4170 Ok((transaction, effects))
4171 }
4172
4173 #[instrument(level = "trace", skip_all)]
4174 pub fn multi_get_checkpoint_by_sequence_number(
4175 &self,
4176 sequence_numbers: &[CheckpointSequenceNumber],
4177 ) -> IotaResult<Vec<Option<VerifiedCheckpoint>>> {
4178 Ok(self
4179 .checkpoint_store
4180 .multi_get_checkpoint_by_sequence_number(sequence_numbers)?)
4181 }
4182
4183 #[instrument(level = "trace", skip_all)]
4184 pub fn get_transaction_events(
4185 &self,
4186 digest: &TransactionDigest,
4187 ) -> IotaResult<TransactionEvents> {
4188 self.get_transaction_cache_reader()
4189 .try_get_events(digest)?
4190 .ok_or(IotaError::TransactionEventsNotFound { digest: *digest })
4191 }
4192
4193 pub fn get_transaction_input_objects(
4194 &self,
4195 effects: &TransactionEffects,
4196 ) -> anyhow::Result<Vec<Object>> {
4197 iota_types::storage::get_transaction_input_objects(self.get_object_store(), effects)
4198 .map_err(Into::into)
4199 }
4200
4201 pub fn get_transaction_output_objects(
4202 &self,
4203 effects: &TransactionEffects,
4204 ) -> anyhow::Result<Vec<Object>> {
4205 iota_types::storage::get_transaction_output_objects(self.get_object_store(), effects)
4206 .map_err(Into::into)
4207 }
4208
4209 fn get_indexes(&self) -> IotaResult<Arc<IndexStore>> {
4210 match &self.indexes {
4211 Some(i) => Ok(i.clone()),
4212 None => Err(IotaError::UnsupportedFeature {
4213 error: "extended object indexing is not enabled on this server".into(),
4214 }),
4215 }
4216 }
4217
4218 pub async fn get_transactions_for_tests(
4219 self: &Arc<Self>,
4220 filter: Option<TransactionFilter>,
4221 cursor: Option<TransactionDigest>,
4222 limit: Option<usize>,
4223 reverse: bool,
4224 ) -> IotaResult<Vec<TransactionDigest>> {
4225 let metrics = KeyValueStoreMetrics::new_for_tests();
4226 let kv_store = Arc::new(TransactionKeyValueStore::new(
4227 "rocksdb",
4228 metrics,
4229 self.clone(),
4230 ));
4231 self.get_transactions(&kv_store, filter, cursor, limit, reverse)
4232 .await
4233 }
4234
4235 #[instrument(level = "trace", skip_all)]
4236 pub async fn get_transactions(
4237 &self,
4238 kv_store: &Arc<TransactionKeyValueStore>,
4239 filter: Option<TransactionFilter>,
4240 cursor: Option<TransactionDigest>,
4242 limit: Option<usize>,
4243 reverse: bool,
4244 ) -> IotaResult<Vec<TransactionDigest>> {
4245 if let Some(TransactionFilter::Checkpoint(sequence_number)) = filter {
4246 let checkpoint_contents = kv_store.get_checkpoint_contents(sequence_number).await?;
4247 let iter = checkpoint_contents.iter().map(|c| c.transaction);
4248 if reverse {
4249 let iter = iter
4250 .rev()
4251 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4252 .skip(usize::from(cursor.is_some()));
4253 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4254 } else {
4255 let iter = iter
4256 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4257 .skip(usize::from(cursor.is_some()));
4258 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4259 }
4260 }
4261 self.get_indexes()?
4262 .get_transactions(filter, cursor, limit, reverse)
4263 }
4264
4265 pub fn get_checkpoint_store(&self) -> &Arc<CheckpointStore> {
4266 &self.checkpoint_store
4267 }
4268
4269 pub fn pruner(&self) -> &AuthorityStorePruner {
4272 &self.pruner
4273 }
4274
4275 pub fn get_latest_checkpoint_sequence_number(&self) -> IotaResult<CheckpointSequenceNumber> {
4276 self.get_checkpoint_store()
4277 .get_highest_executed_checkpoint_seq_number()?
4278 .ok_or(IotaError::UserInput {
4279 error: UserInputError::LatestCheckpointSequenceNumberNotFound,
4280 })
4281 }
4282
4283 #[cfg(msim)]
4284 pub fn get_highest_pruned_checkpoint_for_testing(
4285 &self,
4286 ) -> IotaResult<CheckpointSequenceNumber> {
4287 self.database_for_testing()
4288 .perpetual_tables
4289 .get_highest_pruned_checkpoint()
4290 .map(|c| c.unwrap_or(0))
4291 .map_err(Into::into)
4292 }
4293
4294 #[instrument(level = "trace", skip_all)]
4295 pub fn get_checkpoint_summary_by_sequence_number(
4296 &self,
4297 sequence_number: CheckpointSequenceNumber,
4298 ) -> IotaResult<CheckpointSummary> {
4299 let verified_checkpoint = self
4300 .get_checkpoint_store()
4301 .get_checkpoint_by_sequence_number(sequence_number)?;
4302 match verified_checkpoint {
4303 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4304 None => Err(IotaError::UserInput {
4305 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4306 }),
4307 }
4308 }
4309
4310 #[instrument(level = "trace", skip_all)]
4311 pub fn get_checkpoint_summary_by_digest(
4312 &self,
4313 digest: CheckpointDigest,
4314 ) -> IotaResult<CheckpointSummary> {
4315 let verified_checkpoint = self
4316 .get_checkpoint_store()
4317 .get_checkpoint_by_digest(&digest)?;
4318 match verified_checkpoint {
4319 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4320 None => Err(IotaError::UserInput {
4321 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4322 }),
4323 }
4324 }
4325
4326 #[instrument(level = "trace", skip_all)]
4327 pub fn find_publish_txn_digest(&self, package_id: ObjectId) -> IotaResult<TransactionDigest> {
4328 if package_id.is_system_package() {
4329 return self.find_genesis_txn_digest();
4330 }
4331 Ok(self
4332 .get_object_read(&package_id)?
4333 .into_object()?
4334 .previous_transaction)
4335 }
4336
4337 #[instrument(level = "trace", skip_all)]
4338 pub fn find_genesis_txn_digest(&self) -> IotaResult<TransactionDigest> {
4339 let summary = self
4340 .get_verified_checkpoint_by_sequence_number(0)?
4341 .into_message();
4342 let content = self.get_checkpoint_contents(summary.contents_digest)?;
4343 let genesis_transaction = content.enumerate_transactions(&summary).next();
4344 Ok(genesis_transaction
4345 .ok_or(IotaError::UserInput {
4346 error: UserInputError::GenesisTransactionNotFound,
4347 })?
4348 .1
4349 .transaction)
4350 }
4351
4352 #[instrument(level = "trace", skip_all)]
4353 pub fn get_verified_checkpoint_by_sequence_number(
4354 &self,
4355 sequence_number: CheckpointSequenceNumber,
4356 ) -> IotaResult<VerifiedCheckpoint> {
4357 let verified_checkpoint = self
4358 .get_checkpoint_store()
4359 .get_checkpoint_by_sequence_number(sequence_number)?;
4360 match verified_checkpoint {
4361 Some(verified_checkpoint) => Ok(verified_checkpoint),
4362 None => Err(IotaError::UserInput {
4363 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4364 }),
4365 }
4366 }
4367
4368 #[instrument(level = "trace", skip_all)]
4369 pub fn get_verified_checkpoint_summary_by_digest(
4370 &self,
4371 digest: CheckpointDigest,
4372 ) -> IotaResult<VerifiedCheckpoint> {
4373 let verified_checkpoint = self
4374 .get_checkpoint_store()
4375 .get_checkpoint_by_digest(&digest)?;
4376 match verified_checkpoint {
4377 Some(verified_checkpoint) => Ok(verified_checkpoint),
4378 None => Err(IotaError::UserInput {
4379 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4380 }),
4381 }
4382 }
4383
4384 #[instrument(level = "trace", skip_all)]
4385 pub fn get_checkpoint_contents(
4386 &self,
4387 digest: CheckpointContentsDigest,
4388 ) -> IotaResult<CheckpointContents> {
4389 self.get_checkpoint_store()
4390 .get_checkpoint_contents(&digest)?
4391 .ok_or(IotaError::UserInput {
4392 error: UserInputError::CheckpointContentsNotFound(digest),
4393 })
4394 }
4395
4396 #[instrument(level = "trace", skip_all)]
4397 pub fn get_checkpoint_contents_by_sequence_number(
4398 &self,
4399 sequence_number: CheckpointSequenceNumber,
4400 ) -> IotaResult<CheckpointContents> {
4401 let verified_checkpoint = self
4402 .get_checkpoint_store()
4403 .get_checkpoint_by_sequence_number(sequence_number)?;
4404 match verified_checkpoint {
4405 Some(verified_checkpoint) => {
4406 let contents_digest = verified_checkpoint.into_inner().contents_digest;
4407 self.get_checkpoint_contents(contents_digest)
4408 }
4409 None => Err(IotaError::UserInput {
4410 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4411 }),
4412 }
4413 }
4414
4415 #[instrument(level = "trace", skip_all)]
4416 pub async fn query_events(
4417 &self,
4418 kv_store: &Arc<TransactionKeyValueStore>,
4419 query: EventFilter,
4420 cursor: Option<EventID>,
4422 limit: usize,
4423 descending: bool,
4424 ) -> IotaResult<Vec<IotaEvent>> {
4425 let index_store = self.get_indexes()?;
4426
4427 let (tx_num, event_num) = if let Some(cursor) = cursor.as_ref() {
4429 let tx_seq = index_store.get_transaction_seq(&cursor.tx_digest)?.ok_or(
4430 IotaError::TransactionNotFound {
4431 digest: cursor.tx_digest,
4432 },
4433 )?;
4434 (tx_seq, cursor.event_seq as usize)
4435 } else if descending {
4436 (u64::MAX, usize::MAX)
4437 } else {
4438 (0, 0)
4439 };
4440
4441 let limit = limit + 1;
4442 let mut event_keys = match query {
4443 EventFilter::All(filters) => {
4444 if filters.is_empty() {
4445 index_store.all_events(tx_num, event_num, limit, descending)?
4446 } else {
4447 return Err(IotaError::UserInput {
4448 error: UserInputError::Unsupported(
4449 "This query type does not currently support filter combinations"
4450 .to_string(),
4451 ),
4452 });
4453 }
4454 }
4455 EventFilter::Transaction(digest) => {
4456 index_store.events_by_transaction(&digest, tx_num, event_num, limit, descending)?
4457 }
4458 EventFilter::MoveModule { package, module } => {
4459 let module_id = ModuleId::new(
4460 AccountAddress::new(package.into_bytes()),
4461 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4462 );
4463 index_store.events_by_module_id(&module_id, tx_num, event_num, limit, descending)?
4464 }
4465 EventFilter::MoveEventType(struct_name) => index_store
4466 .events_by_move_event_struct_name(
4467 &struct_name,
4468 tx_num,
4469 event_num,
4470 limit,
4471 descending,
4472 )?,
4473 EventFilter::Sender(sender) => {
4474 index_store.events_by_sender(&sender, tx_num, event_num, limit, descending)?
4475 }
4476 EventFilter::TimeRange {
4477 start_time,
4478 end_time,
4479 } => index_store
4480 .event_iterator(start_time, end_time, tx_num, event_num, limit, descending)?,
4481 EventFilter::MoveEventModule { package, module } => index_store
4482 .events_by_move_event_module(
4483 &ModuleId::new(
4484 AccountAddress::new(package.into_bytes()),
4485 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4486 ),
4487 tx_num,
4488 event_num,
4489 limit,
4490 descending,
4491 )?,
4492 EventFilter::Package(_)
4494 | EventFilter::MoveEventField { .. }
4495 | EventFilter::Any(_)
4496 | EventFilter::And(_, _)
4497 | EventFilter::Or(_, _) => {
4498 return Err(IotaError::UserInput {
4499 error: UserInputError::Unsupported(
4500 "This query type is not supported by the full node.".to_string(),
4501 ),
4502 });
4503 }
4504 };
4505
4506 if cursor.is_some() {
4509 if !event_keys.is_empty() {
4510 event_keys.remove(0);
4511 }
4512 } else {
4513 event_keys.truncate(limit - 1);
4514 }
4515
4516 let transaction_digests = event_keys
4518 .iter()
4519 .map(|(_, digest, _, _)| *digest)
4520 .collect::<HashSet<_>>()
4521 .into_iter()
4522 .collect::<Vec<_>>();
4523
4524 let events = kv_store
4525 .multi_get_events_by_tx_digests(&transaction_digests)
4526 .await?;
4527
4528 let events_map: HashMap<_, _> =
4529 transaction_digests.iter().zip(events.into_iter()).collect();
4530
4531 let stored_events = event_keys
4532 .into_iter()
4533 .map(|k| {
4534 (
4535 k,
4536 events_map
4537 .get(&k.1)
4538 .expect("fetched digest is missing")
4539 .clone()
4540 .and_then(|e| e.get(k.2).cloned()),
4541 )
4542 })
4543 .map(
4544 |((_event_digest, tx_digest, event_seq, timestamp), event)| {
4545 event
4546 .map(|e| (e, tx_digest, event_seq, timestamp))
4547 .ok_or(IotaError::TransactionEventsNotFound { digest: tx_digest })
4548 },
4549 )
4550 .collect::<Result<Vec<_>, _>>()?;
4551
4552 let epoch_store = self.load_epoch_store_one_call_per_task();
4553 let backing_store = self.get_backing_package_store().as_ref();
4554 let mut layout_resolver = epoch_store
4555 .executor()
4556 .type_layout_resolver(Box::new(backing_store));
4557 let mut events = vec![];
4558 for (e, tx_digest, event_seq, timestamp) in stored_events.into_iter() {
4559 events.push(IotaEvent::try_from(
4560 e.clone(),
4561 tx_digest,
4562 event_seq as u64,
4563 Some(timestamp),
4564 layout_resolver.get_annotated_layout(&e.struct_tag)?,
4565 )?)
4566 }
4567 Ok(events)
4568 }
4569
4570 pub fn insert_genesis_object(&self, object: Object) {
4571 self.get_reconfig_api()
4572 .try_insert_genesis_object(object)
4573 .expect("Cannot insert genesis object")
4574 }
4575
4576 pub fn insert_genesis_objects(&self, objects: &[Object]) {
4577 for o in objects {
4578 self.insert_genesis_object(o.clone());
4579 }
4580 }
4581
4582 #[instrument(level = "trace", skip_all)]
4584 pub fn get_transaction_status(
4585 &self,
4586 transaction_digest: &TransactionDigest,
4587 epoch_store: &Arc<AuthorityPerEpochStore>,
4588 ) -> IotaResult<Option<(SenderSignedTransaction, TransactionStatus)>> {
4589 if let Some(effects) =
4591 self.get_signed_effects_and_maybe_resign(transaction_digest, epoch_store)?
4592 {
4593 if let Some(transaction) = self
4594 .get_transaction_cache_reader()
4595 .try_get_transaction_block(transaction_digest)?
4596 {
4597 let cert_sig = epoch_store.get_transaction_cert_sig(transaction_digest)?;
4598 let events = if effects.events_digest().is_some() {
4599 self.get_transaction_events(effects.transaction_digest())?
4600 } else {
4601 TransactionEvents::default()
4602 };
4603 return Ok(Some((
4604 (*transaction).clone().into_message(),
4605 TransactionStatus::Executed(cert_sig, effects.into_inner(), events),
4606 )));
4607 } else {
4608 debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
4613 }
4614 }
4615 if let Some(signed) = epoch_store.get_signed_transaction(transaction_digest)? {
4616 self.metrics.tx_already_processed.inc();
4617 let (transaction, sig) = signed.into_inner().into_data_and_sig();
4618 Ok(Some((transaction, TransactionStatus::Signed(sig))))
4619 } else {
4620 Ok(None)
4621 }
4622 }
4623
4624 #[instrument(level = "trace", skip_all)]
4628 pub fn get_signed_effects_and_maybe_resign(
4629 &self,
4630 transaction_digest: &TransactionDigest,
4631 epoch_store: &Arc<AuthorityPerEpochStore>,
4632 ) -> IotaResult<Option<VerifiedSignedTransactionEffects>> {
4633 let effects = self
4634 .get_transaction_cache_reader()
4635 .try_get_executed_effects(transaction_digest)?;
4636 match effects {
4637 Some(effects) => {
4638 if effects.epoch() != epoch_store.epoch() {
4661 debug!(
4662 tx_digest=?transaction_digest,
4663 effects_epoch=?effects.epoch(),
4664 epoch=?epoch_store.epoch(),
4665 "Re-signing the effects with the current epoch"
4666 );
4667 }
4668 Ok(Some(self.sign_effects(effects, epoch_store)?))
4669 }
4670 None => Ok(None),
4671 }
4672 }
4673
4674 pub fn check_effects_against_previously_signed(
4684 &self,
4685 epoch_store: &AuthorityPerEpochStore,
4686 tx_digest: &TransactionDigest,
4687 effects_digest: &TransactionEffectsDigest,
4688 surface: &'static str,
4689 ) -> IotaResult<()> {
4690 if let Some(previously_signed_digest) = epoch_store.get_signed_effects_digest(tx_digest)? {
4691 if previously_signed_digest != *effects_digest {
4692 self.metrics
4693 .signed_effects_equivocation_prevented
4694 .with_label_values(&[surface])
4695 .inc();
4696 error!(
4697 ?tx_digest,
4698 ?previously_signed_digest,
4699 executed_digest = ?effects_digest,
4700 surface,
4701 "refusing to report effects that differ from previously signed effects"
4702 );
4703 return Err(IotaError::GenericAuthority {
4704 error: format!(
4705 "Refusing to report effects for transaction {tx_digest}: effects digest \
4706 {effects_digest} differs from previously signed effects digest \
4707 {previously_signed_digest}"
4708 ),
4709 });
4710 }
4711 }
4712 Ok(())
4713 }
4714
4715 #[instrument(level = "trace", skip_all)]
4716 pub(crate) fn sign_effects(
4717 &self,
4718 effects: TransactionEffects,
4719 epoch_store: &Arc<AuthorityPerEpochStore>,
4720 ) -> IotaResult<VerifiedSignedTransactionEffects> {
4721 let tx_digest = *effects.transaction_digest();
4722
4723 self.check_effects_against_previously_signed(
4724 epoch_store,
4725 &tx_digest,
4726 &effects.digest(),
4727 "sign_effects",
4728 )?;
4729
4730 let signed_effects = match epoch_store.get_effects_signature(&tx_digest)? {
4731 Some(sig) => {
4732 debug_assert!(sig.epoch == epoch_store.epoch());
4733 SignedTransactionEffects::new_from_data_and_sig(effects, sig)
4734 }
4735 _ => {
4736 let sig = AuthoritySignInfo::new(
4737 epoch_store.epoch(),
4738 &effects,
4739 Intent::iota_app(IntentScope::TransactionEffects),
4740 self.name,
4741 &*self.secret,
4742 );
4743
4744 let effects = SignedTransactionEffects::new_from_data_and_sig(effects, sig.clone());
4745
4746 epoch_store.insert_effects_digest_and_signature(
4747 &tx_digest,
4748 effects.digest(),
4749 &sig,
4750 )?;
4751
4752 effects
4753 }
4754 };
4755
4756 Ok(VerifiedSignedTransactionEffects::new_unchecked(
4757 signed_effects,
4758 ))
4759 }
4760
4761 #[instrument(level = "trace", skip_all)]
4763 fn fullnode_only_get_tx_coins_for_indexing(
4764 &self,
4765 effects: &TransactionEffects,
4766 inner_temporary_store: &InnerTemporaryStore,
4767 epoch_store: &Arc<AuthorityPerEpochStore>,
4768 ) -> Option<TxCoins> {
4769 if self.indexes.is_none() || self.is_committee_validator(epoch_store) {
4770 return None;
4771 }
4772 let written_coin_objects = inner_temporary_store
4773 .written
4774 .iter()
4775 .filter_map(|(k, v)| {
4776 if v.is_coin() {
4777 Some((*k, v.clone()))
4778 } else {
4779 None
4780 }
4781 })
4782 .collect();
4783 let mut input_coin_objects = inner_temporary_store
4784 .input_objects
4785 .iter()
4786 .filter_map(|(k, v)| {
4787 if v.is_coin() {
4788 Some((*k, v.clone()))
4789 } else {
4790 None
4791 }
4792 })
4793 .collect::<ObjectMap>();
4794
4795 for modified in effects.modified_at_versions() {
4800 let (object_id, version) = (*modified.object_id(), modified.version());
4801 if inner_temporary_store
4802 .loaded_runtime_objects
4803 .contains_key(&object_id)
4804 {
4805 if let Some(object) = self
4806 .get_object_store()
4807 .get_object_by_key(&object_id, version)
4808 {
4809 if object.is_coin() {
4810 input_coin_objects.insert(object_id, object);
4811 }
4812 }
4813 }
4814 }
4815
4816 Some((input_coin_objects, written_coin_objects))
4817 }
4818
4819 #[instrument(level = "trace", skip_all)]
4831 pub fn get_transaction_lock(
4832 &self,
4833 object_ref: &ObjectReference,
4834 epoch_store: &AuthorityPerEpochStore,
4835 ) -> IotaResult<Option<VerifiedSignedTransaction>> {
4836 let lock_info = self
4837 .get_object_cache_reader()
4838 .try_get_lock(*object_ref, epoch_store)?;
4839 let lock_info = match lock_info {
4840 ObjectLockStatus::LockedAtDifferentVersion { locked_ref } => {
4841 return Err(UserInputError::ObjectVersionUnavailableForConsumption {
4842 provided_obj_ref: *object_ref,
4843 current_version: locked_ref.version,
4844 }
4845 .into());
4846 }
4847 ObjectLockStatus::Initialized => {
4848 return Ok(None);
4849 }
4850 ObjectLockStatus::LockedToTx { locked_by_tx } => locked_by_tx,
4851 };
4852
4853 epoch_store.get_signed_transaction(&lock_info)
4854 }
4855
4856 pub fn try_get_objects(&self, objects: &[ObjectId]) -> IotaResult<Vec<Option<Object>>> {
4857 self.get_object_cache_reader().try_get_objects(objects)
4858 }
4859
4860 pub fn get_objects(&self, objects: &[ObjectId]) -> Vec<Option<Object>> {
4862 self.try_get_objects(objects)
4863 .expect("storage access failed")
4864 }
4865
4866 pub fn try_get_object_or_tombstone(
4867 &self,
4868 object_id: ObjectId,
4869 ) -> IotaResult<Option<ObjectReference>> {
4870 self.get_object_cache_reader()
4871 .try_get_latest_object_ref_or_tombstone(object_id)
4872 }
4873
4874 pub fn get_object_or_tombstone(&self, object_id: ObjectId) -> Option<ObjectReference> {
4876 self.try_get_object_or_tombstone(object_id)
4877 .expect("storage access failed")
4878 }
4879
4880 pub fn set_override_protocol_upgrade_buffer_stake(
4890 &self,
4891 expected_epoch: EpochId,
4892 buffer_stake_bps: u64,
4893 ) -> IotaResult {
4894 let epoch_store = self.load_epoch_store_one_call_per_task();
4895 let actual_epoch = epoch_store.epoch();
4896 if actual_epoch != expected_epoch {
4897 return Err(IotaError::WrongEpoch {
4898 expected_epoch,
4899 actual_epoch,
4900 });
4901 }
4902
4903 epoch_store.set_override_protocol_upgrade_buffer_stake(buffer_stake_bps)
4904 }
4905
4906 pub fn clear_override_protocol_upgrade_buffer_stake(
4907 &self,
4908 expected_epoch: EpochId,
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.clear_override_protocol_upgrade_buffer_stake()
4920 }
4921
4922 pub async fn get_available_system_packages(
4926 &self,
4927 binary_config: &BinaryConfig,
4928 ) -> Vec<ObjectReference> {
4929 let mut results = vec![];
4930
4931 let system_packages = BuiltInFramework::iter_system_packages();
4932
4933 #[cfg(msim)]
4935 let extra_packages = framework_injection::get_extra_packages(self.name);
4936 #[cfg(msim)]
4937 let system_packages = {
4938 let mut packages: Vec<_> = system_packages.collect();
4939 packages.extend(extra_packages.iter());
4940 packages
4941 };
4942
4943 for system_package in system_packages {
4944 let modules = system_package.modules().to_vec();
4945 #[cfg(msim)]
4947 let modules = framework_injection::get_override_modules(&system_package.id, self.name)
4948 .unwrap_or(modules);
4949
4950 let Some(obj_ref) = iota_framework::compare_system_package(
4951 &self.get_object_store(),
4952 &system_package.id,
4953 &modules,
4954 system_package.dependencies.to_vec(),
4955 binary_config,
4956 )
4957 .await
4958 else {
4959 return vec![];
4960 };
4961 results.push(obj_ref);
4962 }
4963
4964 results
4965 }
4966
4967 async fn get_system_package_bytes(
4991 &self,
4992 system_packages: Vec<ObjectReference>,
4993 binary_config: &BinaryConfig,
4994 ) -> Option<Vec<SystemPackage>> {
4995 let object_store = self.get_object_cache_reader();
4996
4997 let mut res = Vec::with_capacity(system_packages.len());
4998 for system_package_ref in system_packages {
4999 if object_store
5000 .get_object_by_key(&system_package_ref.object_id, system_package_ref.version)
5001 .is_some_and(|object| object.object_ref() == system_package_ref)
5002 {
5003 info!(
5005 "Framework {} does not need updating",
5006 system_package_ref.object_id
5007 );
5008 continue;
5009 }
5010
5011 let prev_transaction = if system_package_ref.version == Version::OBJECT_START {
5016 TransactionDigest::GENESIS_MARKER
5017 } else {
5018 let prev_version = system_package_ref
5019 .version
5020 .previous()
5021 .expect("version is greater than Version::OBJECT_START");
5022 let Some(prev_object) =
5023 object_store.get_object_by_key(&system_package_ref.object_id, prev_version)
5024 else {
5025 error!(
5026 "Framework {} not available locally at version {prev_version:?}, cannot \
5027 derive upgrade to {system_package_ref:?}",
5028 system_package_ref.object_id
5029 );
5030 return None;
5031 };
5032 prev_object.previous_transaction
5033 };
5034
5035 #[cfg(msim)]
5036 let FrameworkSystemPackage {
5037 id: _,
5038 bytes,
5039 dependencies,
5040 } = framework_injection::get_override_system_package(
5041 &system_package_ref.object_id,
5042 self.name,
5043 )
5044 .unwrap_or_else(|| {
5045 BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone()
5046 });
5047
5048 #[cfg(not(msim))]
5049 let FrameworkSystemPackage {
5050 id: _,
5051 bytes,
5052 dependencies,
5053 } = BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone();
5054
5055 let modules: Vec<_> = bytes
5056 .iter()
5057 .map(|m| CompiledModule::deserialize_with_config(m, binary_config).unwrap())
5058 .collect();
5059
5060 let new_object = Object::new_system_package(
5061 &modules,
5062 system_package_ref.version,
5063 dependencies.clone(),
5064 prev_transaction,
5065 );
5066
5067 let new_ref = new_object.object_ref();
5068 if new_ref != system_package_ref {
5069 debug_fatal!(
5070 "Framework mismatch -- binary: {new_ref:?}\n upgrade: {system_package_ref:?}"
5071 );
5072 return None;
5073 }
5074
5075 res.push(SystemPackage {
5076 version: system_package_ref.version,
5077 modules: bytes,
5078 dependencies,
5079 });
5080 }
5081
5082 Some(res)
5083 }
5084
5085 fn is_protocol_version_supported_v1(
5089 proposed_protocol_version: ProtocolVersion,
5090 committee: &Committee,
5091 capabilities: Vec<AuthorityCapabilitiesV1>,
5092 mut buffer_stake_bps: u64,
5093 ) -> Option<(ProtocolVersion, Digest, Vec<ObjectReference>)> {
5094 if buffer_stake_bps > 10000 {
5095 warn!("clamping buffer_stake_bps to 10000");
5096 buffer_stake_bps = 10000;
5097 }
5098
5099 let mut desired_upgrades: Vec<_> = capabilities
5102 .into_iter()
5103 .filter_map(|mut cap| {
5104 if cap.available_system_packages.is_empty() {
5106 return None;
5107 }
5108
5109 cap.available_system_packages.sort();
5110
5111 info!(
5112 "validator {:?} supports {:?} with system packages: {:?}",
5113 cap.authority.concise(),
5114 cap.supported_protocol_versions,
5115 cap.available_system_packages,
5116 );
5117
5118 cap.supported_protocol_versions
5122 .get_version_digest(proposed_protocol_version)
5123 .map(|digest| (digest, cap.available_system_packages, cap.authority))
5124 })
5125 .collect();
5126
5127 desired_upgrades.sort();
5130 desired_upgrades
5131 .into_iter()
5132 .chunk_by(|(digest, packages, _authority)| (*digest, packages.clone()))
5133 .into_iter()
5134 .find_map(|((digest, packages), group)| {
5135 assert!(!packages.is_empty());
5137
5138 let mut stake_aggregator: StakeAggregator<(), true> =
5139 StakeAggregator::new(Arc::new(committee.clone()));
5140
5141 for (_, _, authority) in group {
5142 stake_aggregator.insert_generic(authority, ());
5143 }
5144
5145 let total_votes = stake_aggregator.total_votes();
5146 let quorum_threshold = committee.quorum_threshold();
5147 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5148
5149 info!(
5150 protocol_config_digest = ?digest,
5151 ?total_votes,
5152 ?quorum_threshold,
5153 ?buffer_stake_bps,
5154 ?effective_threshold,
5155 ?proposed_protocol_version,
5156 ?packages,
5157 "support for upgrade"
5158 );
5159
5160 let has_support = total_votes >= effective_threshold;
5161 has_support.then_some((proposed_protocol_version, digest, packages))
5162 })
5163 }
5164
5165 fn choose_protocol_version_and_system_packages_v1(
5169 current_protocol_version: ProtocolVersion,
5170 current_protocol_digest: Digest,
5171 committee: &Committee,
5172 capabilities: Vec<AuthorityCapabilitiesV1>,
5173 buffer_stake_bps: u64,
5174 ) -> (ProtocolVersion, Digest, Vec<ObjectReference>) {
5175 let mut next_protocol_version = current_protocol_version;
5176 let mut system_packages = vec![];
5177 let mut protocol_version_digest = current_protocol_digest;
5178
5179 while let Some((version, digest, packages)) = Self::is_protocol_version_supported_v1(
5183 next_protocol_version + 1,
5184 committee,
5185 capabilities.clone(),
5186 buffer_stake_bps,
5187 ) {
5188 next_protocol_version = version;
5189 protocol_version_digest = digest;
5190 system_packages = packages;
5191 }
5192
5193 (
5194 next_protocol_version,
5195 protocol_version_digest,
5196 system_packages,
5197 )
5198 }
5199
5200 fn get_validators_supporting_protocol_version(
5205 target_protocol_version: ProtocolVersion,
5206 target_digest: Digest,
5207 active_validators: &[AuthorityPublicKey],
5208 capabilities: &[AuthorityCapabilitiesV1],
5209 ) -> Vec<u64> {
5210 let mut eligible_validators = Vec::new();
5211
5212 for capability in capabilities {
5213 if let Some(digest) = capability
5215 .supported_protocol_versions
5216 .get_version_digest(target_protocol_version)
5217 {
5218 if digest == target_digest {
5219 if let Some(index) = active_validators
5221 .iter()
5222 .position(|name| AuthorityName::from(name) == capability.authority)
5223 {
5224 eligible_validators.push(index as u64);
5225 }
5226 }
5227 }
5228 }
5229
5230 eligible_validators.sort();
5232 eligible_validators
5233 }
5234
5235 fn calculate_eligible_validators_weight(
5240 eligible_validator_indices: &[u64],
5241 active_validators: &[AuthorityPublicKey],
5242 committee: &Committee,
5243 ) -> u64 {
5244 let mut total_weight = 0u64;
5245
5246 for &index in eligible_validator_indices {
5247 let authority_pubkey = &active_validators[index as usize];
5248 if let Some((_, weight)) = committee
5250 .members()
5251 .find(|(name, _)| *name == AuthorityName::from(authority_pubkey))
5252 {
5253 total_weight += weight;
5254 }
5255 }
5256
5257 total_weight
5258 }
5259
5260 #[instrument(level = "error", skip_all)]
5273 pub async fn create_and_execute_advance_epoch_tx(
5274 &self,
5275 epoch_store: &Arc<AuthorityPerEpochStore>,
5276 gas_cost_summary: &GasCostSummary,
5277 checkpoint: CheckpointSequenceNumber,
5278 epoch_start_timestamp_ms: CheckpointTimestamp,
5279 scores: Vec<u64>,
5280 ) -> CheckpointBuilderResult<(
5281 IotaSystemState,
5282 Option<SystemEpochInfoEvent>,
5283 TransactionEffects,
5284 )> {
5285 let mut txns = Vec::new();
5286
5287 if epoch_store
5293 .protocol_config()
5294 .deny_rule_governance_on_chain()
5295 && epoch_store
5296 .epoch_start_config()
5297 .transaction_deny_rules_obj_initial_shared_version()
5298 .is_none()
5299 {
5300 txns.push(EndOfEpochTransactionKind::TransactionDenyRulesCreate);
5301 }
5302
5303 let next_epoch = epoch_store.epoch() + 1;
5304
5305 let buffer_stake_bps = epoch_store.get_effective_buffer_stake_bps();
5306 let authority_capabilities = epoch_store
5307 .get_capabilities_v1()
5308 .expect("read capabilities from db cannot fail");
5309 let (next_epoch_protocol_version, next_epoch_protocol_digest, next_epoch_system_packages) =
5310 Self::choose_protocol_version_and_system_packages_v1(
5311 epoch_store.protocol_version(),
5312 SupportedProtocolVersionsWithHashes::protocol_config_digest(
5313 epoch_store.protocol_config(),
5314 ),
5315 epoch_store.committee(),
5316 authority_capabilities.clone(),
5317 buffer_stake_bps,
5318 );
5319
5320 let config = epoch_store.protocol_config();
5324 let binary_config = to_binary_config(config);
5325 let Some(next_epoch_system_package_bytes) = self
5326 .get_system_package_bytes(next_epoch_system_packages.clone(), &binary_config)
5327 .await
5328 else {
5329 debug_fatal!(
5330 "upgraded system packages {:?} are not locally available, cannot create \
5331 ChangeEpochTx. validator binary must be upgraded to the correct version!",
5332 next_epoch_system_packages
5333 );
5334 return Err(CheckpointBuilderError::SystemPackagesMissing);
5344 };
5345
5346 if config.select_committee_from_eligible_validators() {
5349 let active_validators = epoch_store.epoch_start_state().get_active_validators();
5351
5352 let mut eligible_active_validators = (0..active_validators.len() as u64).collect();
5353
5354 if config.select_committee_supporting_next_epoch_version() {
5358 eligible_active_validators = Self::get_validators_supporting_protocol_version(
5359 next_epoch_protocol_version,
5360 next_epoch_protocol_digest,
5361 &active_validators,
5362 &authority_capabilities,
5363 );
5364
5365 let eligible_validators_weight = Self::calculate_eligible_validators_weight(
5367 &eligible_active_validators,
5368 &active_validators,
5369 epoch_store.committee(),
5370 );
5371
5372 let committee = epoch_store.committee();
5376 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5377
5378 if eligible_validators_weight < effective_threshold {
5379 error!(
5380 "Eligible validators weight {eligible_validators_weight} is less than effective threshold {effective_threshold}. \
5381 This could indicate a bug in validator selection logic or inconsistency with protocol version decision.",
5382 );
5383 eligible_active_validators = (0..active_validators.len() as u64).collect();
5386 }
5387 }
5388
5389 if config.pass_validator_scores_to_advance_epoch() {
5392 txns.push(EndOfEpochTransactionKind::new_change_epoch_v4(
5393 next_epoch,
5394 next_epoch_protocol_version.as_u64(),
5395 gas_cost_summary.storage_cost,
5396 gas_cost_summary.computation_cost,
5397 gas_cost_summary.computation_cost_burned,
5398 gas_cost_summary.storage_rebate,
5399 gas_cost_summary.non_refundable_storage_fee,
5400 epoch_start_timestamp_ms,
5401 next_epoch_system_package_bytes,
5402 eligible_active_validators,
5403 scores,
5404 config.adjust_rewards_by_score(),
5405 ));
5406 } else {
5407 txns.push(EndOfEpochTransactionKind::new_change_epoch_v3(
5408 next_epoch,
5409 next_epoch_protocol_version.as_u64(),
5410 gas_cost_summary.storage_cost,
5411 gas_cost_summary.computation_cost,
5412 gas_cost_summary.computation_cost_burned,
5413 gas_cost_summary.storage_rebate,
5414 gas_cost_summary.non_refundable_storage_fee,
5415 epoch_start_timestamp_ms,
5416 next_epoch_system_package_bytes,
5417 eligible_active_validators,
5418 ));
5419 }
5420 } else if config.protocol_defined_base_fee()
5421 && config.max_committee_members_count_as_option().is_some()
5422 {
5423 txns.push(EndOfEpochTransactionKind::new_change_epoch_v2(
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 ));
5434 } else {
5435 txns.push(EndOfEpochTransactionKind::new_change_epoch(
5436 next_epoch,
5437 next_epoch_protocol_version.as_u64(),
5438 gas_cost_summary.storage_cost,
5439 gas_cost_summary.computation_cost,
5440 gas_cost_summary.storage_rebate,
5441 gas_cost_summary.non_refundable_storage_fee,
5442 epoch_start_timestamp_ms,
5443 next_epoch_system_package_bytes,
5444 ));
5445 }
5446
5447 let tx = VerifiedTransaction::new_end_of_epoch_transaction(txns);
5448
5449 let executable_tx = VerifiedExecutableTransaction::new_from_checkpoint(
5450 tx.clone(),
5451 epoch_store.epoch(),
5452 checkpoint,
5453 );
5454
5455 let tx_digest = executable_tx.digest();
5456
5457 info!(
5458 ?next_epoch,
5459 ?next_epoch_protocol_version,
5460 ?next_epoch_system_packages,
5461 computation_cost=?gas_cost_summary.computation_cost,
5462 computation_cost_burned=?gas_cost_summary.computation_cost_burned,
5463 storage_cost=?gas_cost_summary.storage_cost,
5464 storage_rebate=?gas_cost_summary.storage_rebate,
5465 non_refundable_storage_fee=?gas_cost_summary.non_refundable_storage_fee,
5466 ?tx_digest,
5467 "Creating advance epoch transaction"
5468 );
5469
5470 fail_point_async!("change_epoch_tx_delay");
5471 let tx_lock = epoch_store.acquire_tx_lock(tx_digest);
5472
5473 if self
5477 .get_transaction_cache_reader()
5478 .try_is_tx_already_executed(tx_digest)?
5479 {
5480 warn!("change epoch tx has already been executed via state sync");
5481 return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
5482 }
5483
5484 let execution_guard = self.execution_lock_for_executable_transaction(&executable_tx)?;
5485
5486 let assigned_versions = epoch_store.assign_shared_object_versions_idempotent(
5490 self.get_object_cache_reader().as_ref(),
5491 std::iter::once(&Schedulable::Transaction(&executable_tx)),
5492 )?;
5493
5494 assert_eq!(assigned_versions.0.len(), 1);
5495 let assigned_versions = assigned_versions.0.into_iter().next().unwrap().1;
5496
5497 let (input_objects, _) = self.read_objects_for_execution(
5498 &tx_lock,
5499 &executable_tx,
5500 assigned_versions,
5501 epoch_store,
5502 )?;
5503
5504 let (temporary_store, effects, _execution_error_opt) = self.execute_transaction(
5505 &execution_guard,
5506 &executable_tx,
5507 input_objects,
5508 vec![],
5509 epoch_store,
5510 )?;
5511 let system_obj = get_iota_system_state(&temporary_store.written)
5512 .expect("change epoch tx must write to system object");
5513 let system_epoch_info_event = temporary_store
5515 .events
5516 .0
5517 .into_iter()
5518 .find(|event| event.is_system_epoch_info_event())
5519 .map(SystemEpochInfoEvent::from);
5520 assert!(system_epoch_info_event.is_some() || system_obj.safe_mode());
5523
5524 self.get_state_sync_store()
5528 .try_insert_transaction_and_effects(&tx, &effects)?;
5529
5530 info!(
5531 "Effects summary of the change epoch transaction: {:?}",
5532 effects.summary_for_debug()
5533 );
5534 epoch_store.record_checkpoint_builder_is_safe_mode_metric(system_obj.safe_mode());
5535 assert!(effects.status().is_success());
5537 Ok((system_obj, system_epoch_info_event, effects))
5538 }
5539
5540 #[instrument(level = "error", skip_all)]
5544 async fn revert_uncommitted_epoch_transactions(
5545 &self,
5546 epoch_store: &AuthorityPerEpochStore,
5547 ) -> IotaResult {
5548 {
5549 let state = epoch_store.get_reconfig_state_write_lock_guard();
5550 if state.should_accept_user_certs() {
5551 epoch_store.close_user_certs(state);
5560 }
5561 }
5563
5564 if !epoch_store.protocol_config().enable_pcool_flow() {
5567 let pending_certificates = epoch_store.pending_consensus_certificates();
5568 info!(
5569 "Reverting {} locally executed transactions that was not included in the epoch: \
5570 {:?}",
5571 pending_certificates.len(),
5572 pending_certificates,
5573 );
5574 for digest in pending_certificates {
5575 if epoch_store.is_transaction_executed_in_checkpoint(&digest)? {
5576 info!(
5577 "Not reverting pending consensus transaction {:?} - it was included in \
5578 checkpoint",
5579 digest
5580 );
5581 continue;
5582 }
5583 info!("Reverting {:?} at the end of epoch", digest);
5584 epoch_store.revert_executed_transaction(&digest)?;
5585 self.get_reconfig_api().try_revert_state_update(&digest)?;
5586 }
5587 info!("All uncommitted local transactions reverted");
5588 } else {
5589 info!("P-COOL mode: skipping revert of uncommitted epoch transactions");
5590 }
5591
5592 Ok(())
5593 }
5594
5595 #[instrument(level = "error", skip_all)]
5596 async fn reopen_epoch_db(
5597 &self,
5598 cur_epoch_store: &AuthorityPerEpochStore,
5599 new_committee: Committee,
5600 epoch_start_configuration: EpochStartConfiguration,
5601 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
5602 epoch_last_checkpoint: CheckpointSequenceNumber,
5603 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
5604 let new_epoch = new_committee.epoch;
5605 info!(new_epoch = ?new_epoch, "re-opening AuthorityEpochTables for new epoch");
5606 assert_eq!(
5607 epoch_start_configuration.epoch_start_state().epoch(),
5608 new_committee.epoch
5609 );
5610 fail_point!("before-open-new-epoch-store");
5611 let new_epoch_store = cur_epoch_store.new_at_next_epoch(
5612 self.name,
5613 new_committee,
5614 epoch_start_configuration,
5615 self.get_backing_package_store().clone(),
5616 expensive_safety_check_config,
5617 epoch_last_checkpoint,
5618 )?;
5619 self.epoch_store.store(new_epoch_store.clone());
5620 Ok(new_epoch_store)
5621 }
5622
5623 fn check_move_account_for_execution(
5631 &self,
5632 auth_account_object_id: ObjectId,
5633 auth_account_object_seq_number: Option<Version>,
5634 auth_account_object_digest: Option<ObjectDigest>,
5635 account_object: ObjectReadResult,
5636 signer: &Address,
5637 ) -> AuthenticatorFunctionRefForExecution {
5638 self.check_move_account(
5639 auth_account_object_id,
5640 auth_account_object_seq_number,
5641 auth_account_object_digest,
5642 account_object,
5643 signer,
5644 true,
5645 )
5646 .expect("move account checks cannot fail during execution")
5647 }
5648
5649 fn check_move_account_for_validation(
5653 &self,
5654 auth_account_object_id: ObjectId,
5655 auth_account_object_seq_number: Option<Version>,
5656 auth_account_object_digest: Option<ObjectDigest>,
5657 account_object: ObjectReadResult,
5658 signer: &Address,
5659 ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
5660 self.check_move_account(
5661 auth_account_object_id,
5662 auth_account_object_seq_number,
5663 auth_account_object_digest,
5664 account_object,
5665 signer,
5666 false,
5667 )
5668 }
5669
5670 fn check_move_account(
5677 &self,
5678 auth_account_object_id: ObjectId,
5679 auth_account_object_seq_number: Option<Version>,
5680 auth_account_object_digest: Option<ObjectDigest>,
5681 account_object: ObjectReadResult,
5682 signer: &Address,
5683 is_execution: bool,
5684 ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
5685 let auth_account_object_seq_number = match (&account_object.object, is_execution) {
5686 (ObjectReadResultKind::Object(object), _) => {
5690 let account_object_addr = Address::from(auth_account_object_id);
5691 fp_ensure!(
5692 signer == &account_object_addr,
5693 UserInputError::IncorrectUserSignature {
5694 error: format!("Move authenticator is trying to unlock {account_object_addr:?}, but given signer address is {signer:?}")
5695 }
5696 .into()
5697 );
5698
5699 fp_ensure!(
5700 object.is_shared() || object.is_immutable(),
5701 UserInputError::AccountObjectNotSupported {
5702 object_id: auth_account_object_id
5703 }
5704 .into()
5705 );
5706
5707 let auth_account_object_seq_number =
5708 if let Some(auth_account_object_seq_number) = auth_account_object_seq_number {
5709 let account_object_version = object.version();
5710
5711 fp_ensure!(
5712 account_object_version == auth_account_object_seq_number,
5713 UserInputError::AccountObjectVersionMismatch {
5714 object_id: auth_account_object_id,
5715 expected_version: auth_account_object_seq_number,
5716 actual_version: account_object_version,
5717 }
5718 .into()
5719 );
5720
5721 auth_account_object_seq_number
5722 } else {
5723 object.version()
5724 };
5725
5726 if let Some(auth_account_object_digest) = auth_account_object_digest {
5727 let expected_digest = object.digest();
5728 fp_ensure!(
5729 expected_digest == auth_account_object_digest,
5730 UserInputError::InvalidAccountObjectDigest {
5731 object_id: auth_account_object_id,
5732 expected_digest,
5733 actual_digest: auth_account_object_digest,
5734 }
5735 .into()
5736 );
5737 }
5738
5739 Ok(auth_account_object_seq_number)
5740 }
5741 (ObjectReadResultKind::DeletedSharedObject(version, digest), false) => {
5744 Err(UserInputError::AccountObjectDeleted {
5745 account_id: account_object.id(),
5746 account_version: *version,
5747 transaction_digest: *digest,
5748 })
5749 }
5750 (ObjectReadResultKind::CancelledTransactionObject(version), false) => {
5754 Err(UserInputError::AccountObjectInCanceledTransaction {
5755 account_id: account_object.id(),
5756 account_version: *version,
5757 })
5758 }
5759 (ObjectReadResultKind::DeletedSharedObject(version, _), true) => Ok(*version),
5764 (ObjectReadResultKind::CancelledTransactionObject(version), true) => Ok(*version),
5770 }?;
5771
5772 let authenticator_function_ref_field_id =
5773 derive_authenticator_function_ref_v1_dynamic_field_id(auth_account_object_id)?;
5774
5775 let authenticator_function_ref_field = self
5776 .get_object_cache_reader()
5777 .try_find_object_lt_or_eq_version(
5778 authenticator_function_ref_field_id,
5779 auth_account_object_seq_number,
5780 )?;
5781
5782 if let Some(authenticator_function_ref_field_obj) = authenticator_function_ref_field {
5783 Ok(authenticator_function_ref_v1_from_dynamic_field_object(
5784 auth_account_object_id,
5785 &authenticator_function_ref_field_obj,
5786 )?)
5787 } else {
5788 Err(UserInputError::MoveAuthenticatorNotFound {
5789 authenticator_function_ref_id: authenticator_function_ref_field_id,
5790 account_object_id: auth_account_object_id,
5791 account_object_version: auth_account_object_seq_number,
5792 }
5793 .into())
5794 }
5795 }
5796
5797 #[allow(clippy::type_complexity)]
5798 fn read_objects_for_validation(
5799 &self,
5800 transaction: &VerifiedTransaction,
5801 epoch: u64,
5802 ) -> IotaResult<(
5803 InputObjects,
5804 ReceivingObjects,
5805 Vec<(InputObjects, ObjectReadResult)>,
5806 )> {
5807 let (input_objects, tx_receiving_objects) = self.input_loader.read_objects_for_signing(
5808 Some(transaction.digest()),
5809 &transaction.collect_all_input_object_kind_for_reading()?,
5810 &transaction.data().transaction().receiving_objects(),
5811 epoch,
5812 )?;
5813
5814 transaction
5815 .split_input_objects_into_groups_for_reading(input_objects)
5816 .map(|(tx_input_objects, per_authenticator_inputs)| {
5817 (
5818 tx_input_objects,
5819 tx_receiving_objects,
5820 per_authenticator_inputs,
5821 )
5822 })
5823 }
5824
5825 #[allow(clippy::type_complexity)]
5826 fn check_transaction_inputs_for_validation(
5827 &self,
5828 protocol_config: &ProtocolConfig,
5829 reference_gas_price: u64,
5830 tx: &Transaction,
5831 tx_input_objects: InputObjects,
5832 tx_receiving_objects: &ReceivingObjects,
5833 move_authenticators: &Vec<&MoveAuthenticator>,
5834 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
5835 verifier_limits_source: VerifierLimitsSource<'_>,
5836 ) -> IotaResult<(
5837 IotaGasStatus,
5838 CheckedInputObjects,
5839 Vec<(CheckedInputObjects, AuthenticatorFunctionRef)>,
5840 )> {
5841 let authenticator_gas_budget = if move_authenticators.is_empty() {
5842 0
5843 } else {
5844 protocol_config.max_auth_gas()
5847 };
5848
5849 debug_assert_eq!(
5850 move_authenticators.len(),
5851 per_authenticator_inputs.len(),
5852 "Move authenticators amount must match the number of authenticator inputs"
5853 );
5854
5855 let per_authenticator_checked_inputs = move_authenticators
5856 .iter()
5857 .zip(per_authenticator_inputs)
5858 .map(
5859 |(move_authenticator, (authenticator_input_objects, account_object))| {
5860 let (
5862 auth_account_object_id,
5863 auth_account_object_seq_number,
5864 auth_account_object_digest,
5865 ) = move_authenticator.object_to_authenticate_components()?;
5866
5867 let signer = move_authenticator.address();
5868
5869 let AuthenticatorFunctionRefForExecution {
5871 authenticator_function_ref,
5872 ..
5873 } = self.check_move_account_for_validation(
5874 auth_account_object_id,
5875 auth_account_object_seq_number,
5876 auth_account_object_digest,
5877 account_object,
5878 &signer,
5879 )?;
5880
5881 let authenticator_checked_input_objects =
5883 iota_transaction_checks::check_move_authenticator_input_for_validation(
5884 authenticator_input_objects,
5885 )?;
5886
5887 Ok((
5888 authenticator_checked_input_objects,
5889 authenticator_function_ref,
5890 ))
5891 },
5892 )
5893 .collect::<IotaResult<Vec<_>>>()?;
5894
5895 let (gas_status, tx_checked_input_objects) =
5897 iota_transaction_checks::check_transaction_input(
5898 protocol_config,
5899 reference_gas_price,
5900 tx,
5901 tx_input_objects,
5902 tx_receiving_objects,
5903 &self.metrics.bytecode_verifier_metrics,
5904 verifier_limits_source,
5905 authenticator_gas_budget,
5906 )?;
5907
5908 Ok((
5909 gas_status,
5910 tx_checked_input_objects,
5911 per_authenticator_checked_inputs,
5912 ))
5913 }
5914
5915 #[cfg(test)]
5916 pub(crate) fn iter_live_object_set_for_testing(
5917 &self,
5918 ) -> impl Iterator<Item = authority_store_tables::LiveObject> + '_ {
5919 self.get_global_state_hash_store()
5920 .iter_cached_live_object_set_for_testing()
5921 }
5922
5923 #[cfg(test)]
5924 pub(crate) fn shutdown_execution_for_test(&self) {
5925 self.tx_execution_shutdown
5926 .lock()
5927 .take()
5928 .unwrap()
5929 .send(())
5930 .unwrap();
5931 }
5932
5933 pub async fn insert_objects_unsafe_for_testing_only(&self, objects: &[Object]) {
5936 self.get_reconfig_api().bulk_insert_genesis_objects(objects);
5937 self.get_object_cache_reader()
5938 .force_reload_system_packages(&BuiltInFramework::all_package_ids());
5939 self.get_reconfig_api()
5940 .clear_state_end_of_epoch(&self.execution_lock_for_reconfiguration().await);
5941 }
5942}
5943
5944pub struct RandomnessRoundReceiver {
5945 authority_state: Arc<AuthorityState>,
5946 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
5947}
5948
5949impl RandomnessRoundReceiver {
5950 pub fn spawn(
5951 authority_state: Arc<AuthorityState>,
5952 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
5953 ) -> JoinHandle<()> {
5954 let rrr = RandomnessRoundReceiver {
5955 authority_state,
5956 randomness_rx,
5957 };
5958 spawn_monitored_task!(rrr.run())
5959 }
5960
5961 async fn run(mut self) {
5962 info!("RandomnessRoundReceiver event loop started");
5963
5964 loop {
5965 tokio::select! {
5966 maybe_recv = self.randomness_rx.recv() => {
5967 if let Some((epoch, round, bytes)) = maybe_recv {
5968 self.handle_new_randomness(epoch, round, bytes).await;
5969 } else {
5970 break;
5971 }
5972 },
5973 }
5974 }
5975
5976 info!("RandomnessRoundReceiver event loop ended");
5977 }
5978
5979 #[instrument(level = "debug", skip_all, fields(?epoch, ?round))]
5980 async fn handle_new_randomness(&self, epoch: EpochId, round: RandomnessRound, bytes: Vec<u8>) {
5981 fail_point_async!("randomness-delay");
5982
5983 let epoch_store = self.authority_state.load_epoch_store_one_call_per_task();
5984 if epoch_store.epoch() != epoch {
5985 warn!(
5986 "dropping randomness for epoch {epoch}, round {round}, because we are in epoch {}",
5987 epoch_store.epoch()
5988 );
5989 return;
5990 }
5991 let key = TransactionKey::RandomnessRound(epoch, round);
5992 let transaction = VerifiedTransaction::new_randomness_state_update(
5993 epoch,
5994 round,
5995 bytes,
5996 epoch_store
5997 .epoch_start_config()
5998 .randomness_obj_initial_shared_version(),
5999 );
6000 debug!(
6001 "created randomness state update transaction with digest: {:?}",
6002 transaction.digest()
6003 );
6004 let transaction = VerifiedExecutableTransaction::new_system(transaction, epoch);
6005 let digest = *transaction.digest();
6006
6007 self.authority_state
6012 .get_cache_commit()
6013 .persist_transaction(&transaction);
6014
6015 if epoch_store.insert_tx_key(key, digest).is_err() {
6017 warn!("epoch ended while handling new randomness");
6018 }
6019
6020 match self.authority_state.execution_scheduler().as_ref() {
6022 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
6023 ExecutionSchedulerWrapper::TransactionManager(manager) => {
6024 manager.notify_transaction_key(&epoch_store, key, digest);
6028 }
6029 }
6030
6031 let authority_state = self.authority_state.clone();
6032 spawn_monitored_task!(async move {
6033 const RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT: Duration = Duration::from_secs(300);
6042 let result = tokio::time::timeout(
6043 RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT,
6044 authority_state
6045 .get_transaction_cache_reader()
6046 .try_notify_read_executed_effects(
6047 "RandomnessRoundReceiver::notify_read_executed_effects_first",
6048 &[digest],
6049 ),
6050 )
6051 .await;
6052 let result = match result {
6053 Ok(result) => result,
6054 Err(_) => {
6055 if cfg!(debug_assertions) {
6056 panic!(
6058 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6059 );
6060 }
6061 warn!(
6062 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6063 );
6064 authority_state
6066 .get_transaction_cache_reader()
6067 .try_notify_read_executed_effects(
6068 "RandomnessRoundReceiver::notify_read_executed_effects_second",
6069 &[digest],
6070 )
6071 .await
6072 }
6073 };
6074
6075 let mut effects = result.unwrap_or_else(|_| panic!("failed to get effects for randomness state update transaction at epoch {epoch}, round {round}"));
6076 let effects = effects.pop().expect("should return effects");
6077 if *effects.status() != ExecutionStatus::Success {
6078 fatal!(
6079 "failed to execute randomness state update transaction at epoch {epoch}, round {round}: {effects:?}"
6080 );
6081 }
6082 debug!(
6083 "successfully executed randomness state update transaction at epoch {epoch}, round {round}"
6084 );
6085 });
6086 }
6087}
6088
6089#[async_trait]
6090impl TransactionKeyValueStoreTrait for AuthorityState {
6091 async fn multi_get(
6092 &self,
6093 transaction_keys: &[TransactionDigest],
6094 effects_keys: &[TransactionDigest],
6095 ) -> IotaResult<KVStoreTransactionData> {
6096 let txns = if !transaction_keys.is_empty() {
6097 self.get_transaction_cache_reader()
6098 .try_multi_get_transaction_blocks(transaction_keys)?
6099 .into_iter()
6100 .map(|t| t.map(|t| (*t).clone().into_inner()))
6101 .collect()
6102 } else {
6103 vec![]
6104 };
6105
6106 let fx = if !effects_keys.is_empty() {
6107 self.get_transaction_cache_reader()
6108 .try_multi_get_executed_effects(effects_keys)?
6109 } else {
6110 vec![]
6111 };
6112
6113 Ok((txns, fx))
6114 }
6115
6116 async fn multi_get_checkpoints(
6117 &self,
6118 checkpoint_summaries: &[CheckpointSequenceNumber],
6119 checkpoint_contents: &[CheckpointSequenceNumber],
6120 checkpoint_summaries_by_digest: &[CheckpointDigest],
6121 ) -> IotaResult<(
6122 Vec<Option<CertifiedCheckpointSummary>>,
6123 Vec<Option<CheckpointContents>>,
6124 Vec<Option<CertifiedCheckpointSummary>>,
6125 )> {
6126 let mut summaries = Vec::with_capacity(checkpoint_summaries.len());
6128 let store = self.get_checkpoint_store();
6129 for seq in checkpoint_summaries {
6130 let checkpoint = store
6131 .get_checkpoint_by_sequence_number(*seq)?
6132 .map(|c| c.into_inner());
6133
6134 summaries.push(checkpoint);
6135 }
6136
6137 let mut contents = Vec::with_capacity(checkpoint_contents.len());
6138 for seq in checkpoint_contents {
6139 let checkpoint = store
6140 .get_checkpoint_by_sequence_number(*seq)?
6141 .and_then(|summary| {
6142 store
6143 .get_checkpoint_contents(&summary.contents_digest)
6144 .expect("db read cannot fail")
6145 });
6146 contents.push(checkpoint);
6147 }
6148
6149 let mut summaries_by_digest = Vec::with_capacity(checkpoint_summaries_by_digest.len());
6150 for digest in checkpoint_summaries_by_digest {
6151 let checkpoint = store
6152 .get_checkpoint_by_digest(digest)?
6153 .map(|c| c.into_inner());
6154 summaries_by_digest.push(checkpoint);
6155 }
6156
6157 Ok((summaries, contents, summaries_by_digest))
6158 }
6159
6160 async fn get_transaction_perpetual_checkpoint(
6161 &self,
6162 digest: TransactionDigest,
6163 ) -> IotaResult<Option<CheckpointSequenceNumber>> {
6164 self.get_checkpoint_cache()
6165 .try_get_transaction_perpetual_checkpoint(&digest)
6166 .map(|res| res.map(|(_epoch, checkpoint)| checkpoint))
6167 }
6168
6169 async fn get_object(
6170 &self,
6171 object_id: ObjectId,
6172 version: VersionNumber,
6173 ) -> IotaResult<Option<Object>> {
6174 self.get_object_cache_reader()
6175 .try_get_object_by_key(&object_id, version)
6176 }
6177
6178 #[instrument(skip_all)]
6179 async fn multi_get_objects(
6180 &self,
6181 object_keys: &[ObjectKey],
6182 ) -> IotaResult<Vec<Option<Object>>> {
6183 Ok(self
6184 .get_object_cache_reader()
6185 .multi_get_objects_by_key(object_keys))
6186 }
6187
6188 async fn multi_get_transactions_perpetual_checkpoints(
6189 &self,
6190 digests: &[TransactionDigest],
6191 ) -> IotaResult<Vec<Option<CheckpointSequenceNumber>>> {
6192 let res = self
6193 .get_checkpoint_cache()
6194 .try_multi_get_transactions_perpetual_checkpoints(digests)?;
6195
6196 Ok(res
6197 .into_iter()
6198 .map(|maybe| maybe.map(|(_epoch, checkpoint)| checkpoint))
6199 .collect())
6200 }
6201
6202 #[instrument(skip(self, digests), fields(digests = digests.iter().map(|d| d.to_string()).collect::<Vec<String>>().join(", ")))]
6203 async fn multi_get_events_by_tx_digests(
6204 &self,
6205 digests: &[TransactionDigest],
6206 ) -> IotaResult<Vec<Option<TransactionEvents>>> {
6207 if digests.is_empty() {
6208 return Ok(vec![]);
6209 }
6210
6211 Ok(self
6212 .get_transaction_cache_reader()
6213 .multi_get_events(digests))
6214 }
6215}
6216
6217#[cfg(msim)]
6218pub mod framework_injection {
6219 use std::{
6220 cell::RefCell,
6221 collections::{BTreeMap, BTreeSet},
6222 };
6223
6224 use iota_framework::{BuiltInFramework, SystemPackage};
6225 use iota_sdk_types::ObjectId;
6226 use iota_types::base_types::AuthorityName;
6227 use move_binary_format::CompiledModule;
6228
6229 type FrameworkOverrideConfig = BTreeMap<ObjectId, PackageOverrideConfig>;
6230
6231 thread_local! {
6233 static OVERRIDE: RefCell<FrameworkOverrideConfig> = RefCell::new(FrameworkOverrideConfig::default());
6234 }
6235
6236 type Framework = Vec<CompiledModule>;
6237
6238 pub type PackageUpgradeCallback =
6239 Box<dyn Fn(AuthorityName) -> Option<Framework> + Send + Sync + 'static>;
6240
6241 enum PackageOverrideConfig {
6242 Global(Framework),
6243 PerValidator(PackageUpgradeCallback),
6244 }
6245
6246 fn compiled_modules_to_bytes(modules: &[CompiledModule]) -> Vec<Vec<u8>> {
6247 modules
6248 .iter()
6249 .map(|m| {
6250 let mut buf = Vec::new();
6251 m.serialize_with_version(m.version, &mut buf).unwrap();
6252 buf
6253 })
6254 .collect()
6255 }
6256
6257 pub fn set_override(package_id: ObjectId, modules: Vec<CompiledModule>) {
6258 OVERRIDE.with(|bs| {
6259 bs.borrow_mut()
6260 .insert(package_id, PackageOverrideConfig::Global(modules))
6261 });
6262 }
6263
6264 pub fn set_override_cb(package_id: ObjectId, func: PackageUpgradeCallback) {
6265 OVERRIDE.with(|bs| {
6266 bs.borrow_mut()
6267 .insert(package_id, PackageOverrideConfig::PerValidator(func))
6268 });
6269 }
6270
6271 pub fn get_override_bytes(package_id: &ObjectId, name: AuthorityName) -> Option<Vec<Vec<u8>>> {
6272 OVERRIDE.with(|cfg| {
6273 cfg.borrow().get(package_id).and_then(|entry| match entry {
6274 PackageOverrideConfig::Global(framework) => {
6275 Some(compiled_modules_to_bytes(framework))
6276 }
6277 PackageOverrideConfig::PerValidator(func) => {
6278 func(name).map(|fw| compiled_modules_to_bytes(&fw))
6279 }
6280 })
6281 })
6282 }
6283
6284 pub fn get_override_modules(
6285 package_id: &ObjectId,
6286 name: AuthorityName,
6287 ) -> Option<Vec<CompiledModule>> {
6288 OVERRIDE.with(|cfg| {
6289 cfg.borrow().get(package_id).and_then(|entry| match entry {
6290 PackageOverrideConfig::Global(framework) => Some(framework.clone()),
6291 PackageOverrideConfig::PerValidator(func) => func(name),
6292 })
6293 })
6294 }
6295
6296 pub fn get_override_system_package(
6297 package_id: &ObjectId,
6298 name: AuthorityName,
6299 ) -> Option<SystemPackage> {
6300 let bytes = get_override_bytes(package_id, name)?;
6301 let dependencies = if package_id.is_system_package() {
6302 BuiltInFramework::get_package_by_id(package_id)
6303 .dependencies
6304 .to_vec()
6305 } else {
6306 BuiltInFramework::all_package_ids()
6309 };
6310 Some(SystemPackage {
6311 id: *package_id,
6312 bytes,
6313 dependencies,
6314 })
6315 }
6316
6317 pub fn get_extra_packages(name: AuthorityName) -> Vec<SystemPackage> {
6318 let built_in = BTreeSet::from_iter(BuiltInFramework::all_package_ids());
6319 let extra: Vec<ObjectId> = OVERRIDE.with(|cfg| {
6320 cfg.borrow()
6321 .keys()
6322 .filter_map(|package| (!built_in.contains(package)).then_some(*package))
6323 .collect()
6324 });
6325
6326 extra
6327 .into_iter()
6328 .map(|package| SystemPackage {
6329 id: package,
6330 bytes: get_override_bytes(&package, name).unwrap(),
6331 dependencies: BuiltInFramework::all_package_ids(),
6332 })
6333 .collect()
6334 }
6335}
6336
6337#[derive(Debug, Serialize, Deserialize, Clone)]
6338pub struct ObjDumpFormat {
6339 pub id: ObjectId,
6340 pub version: VersionNumber,
6341 pub digest: ObjectDigest,
6342 pub object: Object,
6343}
6344
6345impl ObjDumpFormat {
6346 fn new(object: Object) -> Self {
6347 let oref = object.object_ref();
6348 Self {
6349 id: oref.object_id,
6350 version: oref.version,
6351 digest: oref.digest,
6352 object,
6353 }
6354 }
6355}
6356
6357#[derive(Debug, Serialize, Deserialize, Clone)]
6358pub struct NodeStateDump {
6359 pub tx_digest: TransactionDigest,
6360 pub sender_signed_data: SenderSignedTransaction,
6361 pub executed_epoch: u64,
6362 pub reference_gas_price: u64,
6363 pub protocol_version: u64,
6364 pub epoch_start_timestamp_ms: u64,
6365 pub computed_effects: TransactionEffects,
6366 pub expected_effects_digest: TransactionEffectsDigest,
6367 pub relevant_system_packages: Vec<ObjDumpFormat>,
6368 pub shared_objects: Vec<ObjDumpFormat>,
6369 pub loaded_child_objects: Vec<ObjDumpFormat>,
6370 pub modified_at_versions: Vec<ObjDumpFormat>,
6371 pub runtime_reads: Vec<ObjDumpFormat>,
6372 pub input_objects: Vec<ObjDumpFormat>,
6373}
6374
6375impl NodeStateDump {
6376 pub fn new(
6377 tx_digest: &TransactionDigest,
6378 effects: &TransactionEffects,
6379 expected_effects_digest: TransactionEffectsDigest,
6380 object_store: &dyn ObjectStore,
6381 epoch_store: &Arc<AuthorityPerEpochStore>,
6382 inner_temporary_store: &InnerTemporaryStore,
6383 transaction: &VerifiedExecutableTransaction,
6384 ) -> IotaResult<Self> {
6385 let executed_epoch = epoch_store.epoch();
6387 let reference_gas_price = epoch_store.reference_gas_price();
6388 let epoch_start_config = epoch_store.epoch_start_config();
6389 let protocol_version = epoch_store.protocol_version().as_u64();
6390 let epoch_start_timestamp_ms = epoch_start_config.epoch_data().epoch_start_timestamp();
6391
6392 let mut relevant_system_packages = Vec::new();
6394 for sys_package_id in BuiltInFramework::all_package_ids() {
6395 if let Some(w) = object_store.try_get_object(&sys_package_id)? {
6396 relevant_system_packages.push(ObjDumpFormat::new(w))
6397 }
6398 }
6399
6400 let mut shared_objects = Vec::new();
6402 for kind in effects.input_shared_objects() {
6403 match kind {
6404 InputSharedObject::Mutate(obj_ref) | InputSharedObject::ReadOnly(obj_ref) => {
6405 if let Some(w) =
6406 object_store.try_get_object_by_key(&obj_ref.object_id, obj_ref.version)?
6407 {
6408 shared_objects.push(ObjDumpFormat::new(w))
6409 }
6410 }
6411 InputSharedObject::ReadDeleted(..)
6412 | InputSharedObject::MutateDeleted(..)
6413 | InputSharedObject::Canceled(..) => (),
6415 _ => unimplemented!(
6416 "a new InputSharedObject enum variant was added and needs to be handled"
6417 ),
6418 }
6419 }
6420
6421 let mut loaded_child_objects = Vec::new();
6424 for (id, meta) in &inner_temporary_store.loaded_runtime_objects {
6425 if let Some(w) = object_store.try_get_object_by_key(id, meta.version)? {
6426 loaded_child_objects.push(ObjDumpFormat::new(w))
6427 }
6428 }
6429
6430 let mut modified_at_versions = Vec::new();
6432 for modified in effects.modified_at_versions() {
6433 let (id, ver) = (modified.object_id(), modified.version());
6434 if let Some(w) = object_store.try_get_object_by_key(id, ver)? {
6435 modified_at_versions.push(ObjDumpFormat::new(w))
6436 }
6437 }
6438
6439 let mut runtime_reads = Vec::new();
6443 for obj in inner_temporary_store
6444 .runtime_packages_loaded_from_db
6445 .values()
6446 {
6447 runtime_reads.push(ObjDumpFormat::new(obj.object().clone()));
6448 }
6449
6450 Ok(Self {
6453 tx_digest: *tx_digest,
6454 executed_epoch,
6455 reference_gas_price,
6456 epoch_start_timestamp_ms,
6457 protocol_version,
6458 relevant_system_packages,
6459 shared_objects,
6460 loaded_child_objects,
6461 modified_at_versions,
6462 runtime_reads,
6463 sender_signed_data: transaction.clone().into_message(),
6464 input_objects: inner_temporary_store
6465 .input_objects
6466 .values()
6467 .map(|o| ObjDumpFormat::new(o.clone()))
6468 .collect(),
6469 computed_effects: effects.clone(),
6470 expected_effects_digest,
6471 })
6472 }
6473
6474 pub fn all_objects(&self) -> Vec<ObjDumpFormat> {
6475 let mut objects = Vec::new();
6476 objects.extend(self.relevant_system_packages.clone());
6477 objects.extend(self.shared_objects.clone());
6478 objects.extend(self.loaded_child_objects.clone());
6479 objects.extend(self.modified_at_versions.clone());
6480 objects.extend(self.runtime_reads.clone());
6481 objects.extend(self.input_objects.clone());
6482 objects
6483 }
6484
6485 pub fn write_to_file(&self, path: &Path) -> Result<PathBuf, anyhow::Error> {
6486 let file_name = format!(
6487 "{}_{}_NODE_DUMP.json",
6488 self.tx_digest,
6489 AuthorityState::unixtime_now_ms()
6490 );
6491 let mut path = path.to_path_buf();
6492 path.push(&file_name);
6493 let mut file = File::create(path.clone())?;
6494 file.write_all(serde_json::to_string_pretty(self)?.as_bytes())?;
6495 Ok(path)
6496 }
6497
6498 pub fn read_from_file(path: &PathBuf) -> Result<Self, anyhow::Error> {
6499 let file = File::open(path)?;
6500 serde_json::from_reader(file).map_err(|e| anyhow::anyhow!(e))
6501 }
6502}
6503
6504fn pre_consensus_move_authenticators<'a>(
6516 tx: &'a VerifiedTransaction,
6517 protocol_config: &ProtocolConfig,
6518) -> Vec<&'a MoveAuthenticator> {
6519 if protocol_config.pre_consensus_sponsor_only_move_authentication() {
6520 if tx.transaction().is_sponsored_tx() {
6521 if let Some(sponsor_move_authenticator) = tx.sponsor_move_authenticator() {
6522 vec![sponsor_move_authenticator]
6523 } else {
6524 vec![]
6525 }
6526 } else {
6527 tx.move_authenticators()
6528 }
6529 } else {
6530 tx.move_authenticators()
6531 }
6532}