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