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