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