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