1use std::{
7 collections::{BTreeMap, HashMap, HashSet},
8 fs::File,
9 io::Write,
10 path::{Path, PathBuf},
11 pin::Pin,
12 sync::{Arc, atomic::Ordering},
13 time::{Duration, SystemTime, UNIX_EPOCH},
14 vec,
15};
16
17use arc_swap::{ArcSwap, Guard};
18use async_trait::async_trait;
19use authority_per_epoch_store::TxLockGuard;
20pub use authority_store::{AuthorityStore, ResolverWrapper, UpdateType};
21use fastcrypto::{
22 encoding::{Base58, Encoding},
23 hash::MultisetHash,
24};
25use iota_common::{debug_fatal, fatal};
26use iota_config::{
27 NodeConfig,
28 genesis::Genesis,
29 node::{AuthorityOverloadConfig, ExpensiveSafetyCheckConfig, StateDebugDumpConfig},
30};
31use iota_framework::{BuiltInFramework, SystemPackage as FrameworkSystemPackage};
32use iota_json_rpc_types::{
33 EventFilter, IotaEvent, IotaMoveValue, IotaObjectDataFilter, IotaTransactionBlockEffects,
34 IotaTransactionBlockEvents, TransactionFilter,
35};
36use iota_macros::{fail_point, fail_point_async, fail_point_if};
37use iota_metrics::{
38 TX_TYPE_SHARED_OBJ_TX, TX_TYPE_SINGLE_WRITER_TX, monitored_scope, spawn_monitored_task,
39};
40use iota_sdk_types::{
41 Address, CheckpointCommitment, CheckpointContents, CheckpointContentsDigest, CheckpointDigest,
42 CheckpointSummary, Digest, EndOfEpochTransactionKind, ExecutionStatus, GasCostSummary,
43 InputSharedObject, MoveAuthenticator, ObjectDigest, ObjectId, ObjectReference, Owner,
44 RandomnessRound, SenderSignedTransaction, StructTag, SystemPackage, Transaction,
45 TransactionDigest, TransactionEffects, TransactionEffectsDigest, TransactionEvents,
46 TransactionKind, TypeTag, Version, WriteKind,
47 crypto::{Intent, IntentScope},
48};
49use iota_storage::{
50 key_value_store::{
51 KVStoreTransactionData, TransactionKeyValueStore, TransactionKeyValueStoreTrait,
52 },
53 key_value_store_metrics::KeyValueStoreMetrics,
54};
55use iota_traffic_controller::{TrafficController, metrics::TrafficControllerMetrics};
56use iota_transaction_checks::VerifierLimitsSource;
57#[cfg(msim)]
58use iota_types::committee::CommitteeTrait;
59use iota_types::{
60 account_abstraction::authenticator_function::{
61 AuthenticatorFunctionRef, AuthenticatorFunctionRefForExecution,
62 MoveAuthenticatorForExecution, MoveAuthenticatorsForExecution,
63 authenticator_function_ref_v1_from_dynamic_field_object,
64 derive_authenticator_function_ref_v1_dynamic_field_id, extract_auth_fun_refs,
65 },
66 auth_context::AuthContextData,
67 base_types::{AuthorityName, ConciseableName, ObjectInfo, ObjectType, VersionNumber},
68 committee::{Committee, EpochId, ProtocolVersion},
69 crypto::{AggregateAuthorityPublicKey, AuthoritySignInfo, AuthoritySignature, Signer},
70 deny_list_v1::{check_coin_deny_list_v1, coin_types_for_denylist_check},
71 deny_rule_governance::DenyRuleConfig,
72 digests::ChainIdentifier,
73 dynamic_field::{DynamicFieldInfo, DynamicFieldName, visitor as DFV},
74 effects::{
75 SignedTransactionEffects, TransactionEffectsAPI, TransactionEffectsExt,
76 VerifiedSignedTransactionEffects,
77 },
78 error::{ExecutionError, ExecutionErrorKind, IotaError, IotaResult, UserInputError},
79 event::{EventID, SystemEpochInfoEvent},
80 executable_transaction::VerifiedExecutableTransaction,
81 execution_config_utils::to_binary_config,
82 fp_ensure,
83 gas::IotaGasStatus,
84 gas_coin::mock_simulation_gas_coin,
85 inner_temporary_store::{
86 InnerTemporaryStore, ObjectMap, PackageStoreWithFallback, TxCoins, WrittenObjects,
87 },
88 iota_sdk_types_conversions::type_tag_core_to_sdk,
89 iota_system_state::{
90 IotaSystemState, IotaSystemStateTrait,
91 epoch_start_iota_system_state::EpochStartSystemStateTrait, get_iota_system_state,
92 },
93 layout_resolver::{LayoutResolver, into_struct_layout},
94 message_envelope::Message,
95 messages_checkpoint::{
96 CertifiedCheckpointSummary, CheckpointContentsExt, CheckpointRequest, CheckpointResponse,
97 CheckpointSequenceNumber, CheckpointSummaryResponse, CheckpointTimestamp,
98 ECMHLiveObjectSetDigest, VerifiedCheckpoint,
99 },
100 messages_consensus::AuthorityCapabilitiesV1,
101 messages_grpc::{
102 HandleTransactionResponse, LayoutGenerationOption, ObjectInfoRequest,
103 ObjectInfoRequestKind, ObjectInfoResponse, TransactionInfoRequest, TransactionInfoResponse,
104 TransactionStatus,
105 },
106 metrics::{BytecodeVerifierMetrics, LimitsMetrics},
107 move_authenticator::MoveAuthenticatorExt,
108 object::{Object, ObjectRead, PastObjectRead, bounded_visitor::BoundedVisitor},
109 storage::{BackingPackageStore, BackingStore, ObjectKey, ObjectOrTombstone, ObjectStore},
110 supported_protocol_versions::{
111 ProtocolConfig, SupportedProtocolVersions, SupportedProtocolVersionsWithHashes,
112 },
113 traffic_control::{PolicyConfig, TrafficControlReconfigParams},
114 transaction::*,
115 transaction_executor::{SimulateTransactionResult, VmChecks},
116};
117use itertools::Itertools;
118use move_binary_format::{CompiledModule, binary_config::BinaryConfig};
119use move_core_types::{
120 account_address::AccountAddress, annotated_value::MoveStructLayout, language_storage::ModuleId,
121};
122use parking_lot::Mutex;
123use prometheus_filtered::{
124 Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, MetricLevel,
125 Registry, register_histogram_vec_with_registry, register_histogram_with_registry,
126 register_int_counter_vec_with_registry, register_int_counter_with_registry,
127 register_int_gauge_vec_with_registry, register_int_gauge_with_registry,
128};
129use serde::{Deserialize, Serialize, de::DeserializeOwned};
130use tap::TapFallible;
131use tokio::{
132 sync::{RwLock, mpsc, mpsc::unbounded_channel, oneshot},
133 task::JoinHandle,
134};
135use tracing::{debug, error, info, instrument, trace, warn};
136use typed_store::TypedStoreError;
137
138use self::{
139 authority_store::ExecutionLockWriteGuard, authority_store_pruner::AuthorityStorePruningMetrics,
140};
141#[cfg(msim)]
142pub use crate::checkpoints::checkpoint_executor::utils::{
143 CheckpointTimeoutConfig, init_checkpoint_timeout_config,
144};
145use crate::{
146 authority::{
147 authority_per_epoch_store::{AuthorityPerEpochStore, TxGuard},
148 authority_per_epoch_store_pruner::AuthorityPerEpochStorePruner,
149 authority_store::{ExecutionLockReadGuard, ObjectLockStatus},
150 authority_store_pruner::{
151 AuthorityStorePruner, EPOCH_DURATION_MS_FOR_TESTING, ObjectRetentionGuard,
152 },
153 epoch_start_configuration::{EpochStartConfigTrait, EpochStartConfiguration},
154 shared_object_version_manager::{AssignedVersions, Schedulable},
155 },
156 authority_client::NetworkAuthorityClient,
157 checkpoint_progress_tracker::CheckpointProgressTracker,
158 checkpoints::{CheckpointBuilderError, CheckpointBuilderResult, CheckpointStore},
159 congestion_tracker::CongestionTracker,
160 consensus_adapter::ConsensusAdapter,
161 epoch::committee_store::CommitteeStore,
162 epoch_end_db_snapshot::{EpochEndDbSnapshotHandle, HandOver},
163 execution_cache::{
164 CheckpointCache, ExecutionCacheCommit, ExecutionCacheReconfigAPI,
165 ExecutionCacheTraitPointers, ExecutionCacheWrite, ObjectCacheRead, StateSyncAPI,
166 TransactionCacheRead,
167 },
168 execution_driver::execution_process,
169 execution_scheduler::{ExecutionSchedulerAPI, ExecutionSchedulerWrapper},
170 global_state_hasher::{GlobalStateHashStore, GlobalStateHasher},
171 grpc_indexes::GrpcIndexesStore,
172 jsonrpc_index::{CoinInfo, IndexStore, ObjectIndexChanges},
173 metrics::{LatencyObserver, RateTracker},
174 module_cache_metrics::ResolverMetrics,
175 overload_monitor::{
176 AuthorityOverloadInfo, compute_graduated_load_shedding_percentage,
177 overload_monitor_accept_tx,
178 },
179 post_consensus_input_reader::{
180 AccountVerdict, InputResolution, ReceivingObjectsResolution, ValidationAtCommit,
181 ValidationInputsAtCommit,
182 reader::{CommitIndexedReader, DenyListAtCommit},
183 },
184 stake_aggregator::StakeAggregator,
185 subscription_handler::SubscriptionHandler,
186 transaction_input_loader::TransactionInputLoader,
187 transaction_outputs::TransactionOutputs,
188 validator_tx_finalizer::ValidatorTxFinalizer,
189 verify_indexes::verify_indexes,
190};
191
192#[cfg(test)]
193#[path = "unit_tests/authority_tests.rs"]
194pub mod authority_tests;
195
196#[cfg(test)]
197#[path = "unit_tests/transaction_tests.rs"]
198pub mod transaction_tests;
199
200#[cfg(test)]
201#[path = "unit_tests/batch_transaction_tests.rs"]
202mod batch_transaction_tests;
203
204#[cfg(test)]
205#[path = "unit_tests/move_integration_tests.rs"]
206pub mod move_integration_tests;
207
208#[cfg(test)]
209#[path = "unit_tests/gas_tests.rs"]
210mod gas_tests;
211
212#[cfg(test)]
213#[path = "unit_tests/batch_verification_tests.rs"]
214mod batch_verification_tests;
215
216#[cfg(test)]
217#[path = "unit_tests/coin_deny_list_tests.rs"]
218mod coin_deny_list_tests;
219
220#[cfg(test)]
221#[path = "unit_tests/pre_execution_failure_tests.rs"]
222mod pre_execution_failure_tests;
223
224#[cfg(test)]
225#[path = "unit_tests/cancelled_move_authenticator_tests.rs"]
226mod cancelled_move_authenticator_tests;
227
228#[cfg(test)]
229#[path = "unit_tests/auth_unit_test_utils.rs"]
230pub mod auth_unit_test_utils;
231
232#[cfg(any(test, feature = "test-utils"))]
233pub mod authority_test_utils;
234
235pub mod authority_per_epoch_store;
236pub mod authority_per_epoch_store_pruner;
237
238pub mod authority_store_pruner;
239pub mod authority_store_tables;
240pub mod authority_store_types;
241pub mod epoch_start_configuration;
242pub mod shared_object_congestion_tracker;
243pub mod shared_object_version_manager;
244pub mod suggested_gas_price_calculator;
245#[cfg(any(test, feature = "test-utils"))]
246pub mod test_authority_builder;
247pub mod transaction_deferral;
248
249pub(crate) mod authority_store;
250pub mod backpressure;
251pub(crate) mod dropped_tx_status_cache;
252
253pub struct AuthorityMetrics {
255 tx_orders: IntCounter,
256 total_certs: IntCounter,
257 total_cert_attempts: IntCounter,
258 total_effects: IntCounter,
259 pub shared_obj_tx: IntCounter,
260 sponsored_tx: IntCounter,
261 tx_already_processed: IntCounter,
262 num_input_objs: Histogram,
263 num_shared_objects: Histogram,
264 batch_size: Histogram,
265
266 authority_state_handle_transaction_latency: Histogram,
267
268 execute_certificate_latency_single_writer: Histogram,
269 execute_certificate_latency_shared_object: Histogram,
270
271 internal_execution_latency: Histogram,
272 signed_effects_equivocation_prevented: IntCounterVec,
276 execution_load_input_objects_latency: Histogram,
277 prepare_certificate_latency: Histogram,
278 commit_certificate_latency: Histogram,
279 epoch_end_db_snapshot_handover_latency: Histogram,
280 epoch_end_db_snapshots_skipped: IntCounter,
281
282 pub(crate) transaction_manager_num_enqueued_certificates: IntCounterVec,
283 pub(crate) transaction_manager_num_missing_objects: IntGauge,
284 pub(crate) transaction_manager_num_pending_certificates: IntGauge,
285 pub(crate) transaction_manager_num_executing_certificates: IntGauge,
286 pub(crate) transaction_manager_num_ready: IntGauge,
287 pub(crate) transaction_manager_object_cache_size: IntGauge,
288 pub(crate) transaction_manager_object_cache_hits: IntCounter,
289 pub(crate) transaction_manager_object_cache_misses: IntCounter,
290 pub(crate) transaction_manager_object_cache_evictions: IntCounter,
291 pub(crate) transaction_manager_package_cache_size: IntGauge,
292 pub(crate) transaction_manager_package_cache_hits: IntCounter,
293 pub(crate) transaction_manager_package_cache_misses: IntCounter,
294 pub(crate) transaction_manager_package_cache_evictions: IntCounter,
295 pub(crate) transaction_manager_transaction_queue_age_s: Histogram,
296
297 pub(crate) execution_driver_executed_transactions: IntCounter,
298 pub(crate) execution_driver_dispatch_queue: IntGauge,
299 pub(crate) execution_queueing_delay_s: Histogram,
300 pub(crate) prepare_cert_gas_latency_ratio: Histogram,
301 pub(crate) execution_gas_latency_ratio: Histogram,
302
303 pub(crate) skipped_consensus_txns: IntCounter,
304 pub(crate) skipped_consensus_txns_cache_hit: IntCounter,
305
306 pub(crate) authority_overload_status: IntGauge,
307 pub(crate) consensus_queue_load_shedding_percentage: IntGauge,
309 pub(crate) local_post_consensus_load_shedding_percentage: IntGauge,
313
314 pub(crate) transaction_overload_sources: IntCounterVec,
315
316 post_processing_total_events_emitted: IntCounter,
318 post_processing_total_tx_indexed: IntCounter,
319 post_processing_total_tx_had_event_processed: IntCounter,
320 post_processing_total_failures: IntCounter,
321
322 pub consensus_handler_processed: IntCounterVec,
324 pub consensus_handler_transaction_sizes: HistogramVec,
325 pub consensus_handler_num_low_scoring_authorities: IntGauge,
326 pub consensus_handler_scores: IntGaugeVec,
327 pub consensus_handler_deferred_transactions: IntCounter,
328 pub consensus_handler_congested_transactions: IntCounter,
329 pub consensus_handler_cancelled_transactions: IntCounter,
330 pub consensus_handler_validation_dropped_transactions: IntCounter,
334 pub consensus_handler_validation_reader_verdicts: IntCounterVec,
338 pub consensus_handler_commit_execution_lag: IntGauge,
341 pub consensus_handler_load_shedding_dropped_transactions: IntCounter,
345 pub consensus_handler_load_shedding_percentage: IntGauge,
351 pub consensus_handler_max_object_costs: IntGaugeVec,
352 pub consensus_committed_subdags: IntCounterVec,
353 pub consensus_committed_messages: IntGaugeVec,
354 pub consensus_committed_user_transactions: IntGaugeVec,
355 pub consensus_handler_leader_round: IntGauge,
356 pub consensus_calculated_throughput: IntGauge,
357 pub consensus_calculated_throughput_profile: IntGauge,
358
359 pub validator_scoreboard_scores: IntGaugeVec,
360 pub invalid_misbehavior_reports_by_authority: IntGaugeVec,
361
362 pub limits_metrics: Arc<LimitsMetrics>,
363
364 pub bytecode_verifier_metrics: Arc<BytecodeVerifierMetrics>,
366
367 pub multisig_sig_count: IntCounter,
369
370 pub execution_queueing_latency: LatencyObserver,
373
374 pub txn_ready_rate_tracker: Arc<Mutex<RateTracker>>,
381
382 pub execution_rate_tracker: Arc<Mutex<RateTracker>>,
385}
386
387const POSITIVE_INT_BUCKETS: &[f64] = &[
389 1., 2., 5., 7., 10., 20., 50., 70., 100., 200., 500., 700., 1000., 2000., 5000., 7000., 10000.,
390 20000., 50000., 70000., 100000., 200000., 500000., 700000., 1000000., 2000000., 5000000.,
391 7000000., 10000000.,
392];
393
394const LATENCY_SEC_BUCKETS: &[f64] = &[
395 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.,
396 10., 20., 30., 60., 90.,
397];
398
399const LOW_LATENCY_SEC_BUCKETS: &[f64] = &[
401 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,
402 0.2, 0.5, 1., 2., 5., 10., 20., 50., 100.,
403];
404
405const GAS_LATENCY_RATIO_BUCKETS: &[f64] = &[
406 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,
407 3000.0, 4000.0, 5000.0, 6000.0, 7000.0, 8000.0, 9000.0, 10000.0, 50000.0, 100000.0, 1000000.0,
408];
409
410impl AuthorityMetrics {
411 pub fn new(registry: &prometheus_filtered::Registry) -> AuthorityMetrics {
412 let execute_certificate_latency = register_histogram_vec_with_registry!(
413 "authority_state_execute_certificate_latency",
414 "Latency of executing certificates, including waiting for inputs",
415 &["tx_type"],
416 LATENCY_SEC_BUCKETS.to_vec(),
417 registry;
418 MetricLevel::Info,
419 )
420 .unwrap();
421
422 let execute_certificate_latency_single_writer =
423 execute_certificate_latency.with_label_values(&[TX_TYPE_SINGLE_WRITER_TX]);
424 let execute_certificate_latency_shared_object =
425 execute_certificate_latency.with_label_values(&[TX_TYPE_SHARED_OBJ_TX]);
426
427 Self {
428 tx_orders: register_int_counter_with_registry!(
429 "total_transaction_orders",
430 "Total number of transaction orders",
431 registry;
432 MetricLevel::Warn,
433 )
434 .unwrap(),
435 total_certs: register_int_counter_with_registry!(
436 "total_transaction_certificates",
437 "Total number of transaction certificates handled",
438 registry;
439 MetricLevel::Warn,
440 )
441 .unwrap(),
442 total_cert_attempts: register_int_counter_with_registry!(
443 "total_handle_certificate_attempts",
444 "Number of calls to handle_certificate",
445 registry,
446 )
447 .unwrap(),
448 total_effects: register_int_counter_with_registry!(
450 "total_transaction_effects",
451 "Total number of transaction effects produced",
452 registry;
453 MetricLevel::Warn,
454 )
455 .unwrap(),
456
457 shared_obj_tx: register_int_counter_with_registry!(
458 "num_shared_obj_tx",
459 "Number of transactions involving shared objects",
460 registry;
461 MetricLevel::Warn,
462 )
463 .unwrap(),
464
465 sponsored_tx: register_int_counter_with_registry!(
466 "num_sponsored_tx",
467 "Number of sponsored transactions",
468 registry,
469 )
470 .unwrap(),
471
472 tx_already_processed: register_int_counter_with_registry!(
473 "num_tx_already_processed",
474 "Number of transaction orders already processed previously",
475 registry,
476 )
477 .unwrap(),
478 num_input_objs: register_histogram_with_registry!(
479 "num_input_objects",
480 "Distribution of number of input TX objects per TX",
481 POSITIVE_INT_BUCKETS.to_vec(),
482 registry;
483 MetricLevel::Warn,
484 )
485 .unwrap(),
486 num_shared_objects: register_histogram_with_registry!(
487 "num_shared_objects",
488 "Number of shared input objects per TX",
489 POSITIVE_INT_BUCKETS.to_vec(),
490 registry,
491 )
492 .unwrap(),
493 batch_size: register_histogram_with_registry!(
494 "batch_size",
495 "Distribution of size of transaction batch",
496 POSITIVE_INT_BUCKETS.to_vec(),
497 registry,
498 )
499 .unwrap(),
500 authority_state_handle_transaction_latency: register_histogram_with_registry!(
501 "authority_state_handle_transaction_latency",
502 "Latency of handling transactions",
503 LATENCY_SEC_BUCKETS.to_vec(),
504 registry,
505 )
506 .unwrap(),
507 execute_certificate_latency_single_writer,
508 execute_certificate_latency_shared_object,
509 internal_execution_latency: register_histogram_with_registry!(
510 "authority_state_internal_execution_latency",
511 "Latency of actual certificate executions",
512 LATENCY_SEC_BUCKETS.to_vec(),
513 registry,
514 )
515 .unwrap(),
516 signed_effects_equivocation_prevented: register_int_counter_vec_with_registry!(
517 "authority_state_signed_effects_equivocation_prevented",
518 "Number of times the validator refused to report effects that differ from previously signed effects for the same transaction, by RPC surface",
519 &["surface"],
520 registry,
521 )
522 .unwrap(),
523 execution_load_input_objects_latency: register_histogram_with_registry!(
524 "authority_state_execution_load_input_objects_latency",
525 "Latency of loading input objects for execution",
526 LOW_LATENCY_SEC_BUCKETS.to_vec(),
527 registry,
528 )
529 .unwrap(),
530 prepare_certificate_latency: register_histogram_with_registry!(
531 "authority_state_prepare_certificate_latency",
532 "Latency of executing certificates, before committing the results",
533 LATENCY_SEC_BUCKETS.to_vec(),
534 registry,
535 )
536 .unwrap(),
537 commit_certificate_latency: register_histogram_with_registry!(
538 "authority_state_commit_certificate_latency",
539 "Latency of committing certificate execution results",
540 LATENCY_SEC_BUCKETS.to_vec(),
541 registry,
542 )
543 .unwrap(),
544 epoch_end_db_snapshot_handover_latency: register_histogram_with_registry!(
545 "epoch_end_db_snapshot_handover_latency",
546 "Time the epoch boundary waits for the consumer to take its database \
547 snapshot of the perpetual store",
548 LATENCY_SEC_BUCKETS.to_vec(),
549 registry,
550 ).unwrap(),
551 epoch_end_db_snapshots_skipped: register_int_counter_with_registry!(
552 "epoch_end_db_snapshots_skipped",
553 "Epoch boundaries whose database snapshot was not taken, because the \
554 consumer was busy or did not take it in time",
555 registry,
556 ).unwrap(),
557 transaction_manager_num_enqueued_certificates: register_int_counter_vec_with_registry!(
558 "transaction_manager_num_enqueued_certificates",
559 "Current number of certificates enqueued to TransactionManager",
560 &["result"],
561 registry,
562 )
563 .unwrap(),
564 transaction_manager_num_missing_objects: register_int_gauge_with_registry!(
565 "transaction_manager_num_missing_objects",
566 "Current number of missing objects in TransactionManager",
567 registry,
568 )
569 .unwrap(),
570 transaction_manager_num_pending_certificates: register_int_gauge_with_registry!(
571 "transaction_manager_num_pending_certificates",
572 "Number of certificates pending in TransactionManager, with at least 1 missing input object",
573 registry;
574 MetricLevel::Warn,
575 )
576 .unwrap(),
577 transaction_manager_num_executing_certificates: register_int_gauge_with_registry!(
578 "transaction_manager_num_executing_certificates",
579 "Number of executing certificates, including queued and actually running certificates",
580 registry;
581 MetricLevel::Warn,
582 )
583 .unwrap(),
584 transaction_manager_num_ready: register_int_gauge_with_registry!(
585 "transaction_manager_num_ready",
586 "Number of ready transactions in TransactionManager",
587 registry,
588 )
589 .unwrap(),
590 transaction_manager_object_cache_size: register_int_gauge_with_registry!(
591 "transaction_manager_object_cache_size",
592 "Current size of object-availability cache in TransactionManager",
593 registry,
594 )
595 .unwrap(),
596 transaction_manager_object_cache_hits: register_int_counter_with_registry!(
597 "transaction_manager_object_cache_hits",
598 "Number of object-availability cache hits in TransactionManager",
599 registry,
600 )
601 .unwrap(),
602 authority_overload_status: register_int_gauge_with_registry!(
603 "authority_overload_status",
604 "Whether authority is current experiencing overload and enters load shedding mode.",
605 registry;
606 MetricLevel::Warn,)
607 .unwrap(),
608 local_post_consensus_load_shedding_percentage: register_int_gauge_with_registry!(
609 "authority_load_shedding_percentage",
610 "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).",
611 registry;
612 MetricLevel::Info,)
613 .unwrap(),
614 consensus_queue_load_shedding_percentage: register_int_gauge_with_registry!(
615 "consensus_queue_load_shedding_percentage",
616 "Percentage of transactions shed due to consensus queue length. Separate admission-control signal, not an input to authority_load_shedding_percentage.",
617 registry)
618 .unwrap(),
619 transaction_manager_object_cache_misses: register_int_counter_with_registry!(
620 "transaction_manager_object_cache_misses",
621 "Number of object-availability cache misses in TransactionManager",
622 registry,
623 )
624 .unwrap(),
625 transaction_manager_object_cache_evictions: register_int_counter_with_registry!(
626 "transaction_manager_object_cache_evictions",
627 "Number of object-availability cache evictions in TransactionManager",
628 registry,
629 )
630 .unwrap(),
631 transaction_manager_package_cache_size: register_int_gauge_with_registry!(
632 "transaction_manager_package_cache_size",
633 "Current size of package-availability cache in TransactionManager",
634 registry,
635 )
636 .unwrap(),
637 transaction_manager_package_cache_hits: register_int_counter_with_registry!(
638 "transaction_manager_package_cache_hits",
639 "Number of package-availability cache hits in TransactionManager",
640 registry,
641 )
642 .unwrap(),
643 transaction_manager_package_cache_misses: register_int_counter_with_registry!(
644 "transaction_manager_package_cache_misses",
645 "Number of package-availability cache misses in TransactionManager",
646 registry,
647 )
648 .unwrap(),
649 transaction_manager_package_cache_evictions: register_int_counter_with_registry!(
650 "transaction_manager_package_cache_evictions",
651 "Number of package-availability cache evictions in TransactionManager",
652 registry,
653 )
654 .unwrap(),
655 transaction_manager_transaction_queue_age_s: register_histogram_with_registry!(
656 "transaction_manager_transaction_queue_age_s",
657 "Time spent in waiting for transaction in the queue",
658 LATENCY_SEC_BUCKETS.to_vec(),
659 registry;
660 MetricLevel::Warn,
661 )
662 .unwrap(),
663 transaction_overload_sources: register_int_counter_vec_with_registry!(
664 "transaction_overload_sources",
665 "Number of times each source indicates transaction overload.",
666 &["source"],
667 registry)
668 .unwrap(),
669 execution_driver_executed_transactions: register_int_counter_with_registry!(
670 "execution_driver_executed_transactions",
671 "Cumulative number of transaction executed by execution driver",
672 registry;
673 MetricLevel::Warn,
674 )
675 .unwrap(),
676 execution_driver_dispatch_queue: register_int_gauge_with_registry!(
677 "execution_driver_dispatch_queue",
678 "Number of transaction pending in execution driver dispatch queue",
679 registry,
680 )
681 .unwrap(),
682 execution_queueing_delay_s: register_histogram_with_registry!(
683 "execution_queueing_delay_s",
684 "Queueing delay between a transaction is ready for execution until it starts executing.",
685 LATENCY_SEC_BUCKETS.to_vec(),
686 registry
687 )
688 .unwrap(),
689 prepare_cert_gas_latency_ratio: register_histogram_with_registry!(
690 "prepare_cert_gas_latency_ratio",
691 "The ratio of computation gas divided by VM execution latency.",
692 GAS_LATENCY_RATIO_BUCKETS.to_vec(),
693 registry
694 )
695 .unwrap(),
696 execution_gas_latency_ratio: register_histogram_with_registry!(
697 "execution_gas_latency_ratio",
698 "The ratio of computation gas divided by certificate execution latency, include committing certificate.",
699 GAS_LATENCY_RATIO_BUCKETS.to_vec(),
700 registry
701 )
702 .unwrap(),
703 skipped_consensus_txns: register_int_counter_with_registry!(
704 "skipped_consensus_txns",
705 "Total number of consensus transactions skipped",
706 registry,
707 )
708 .unwrap(),
709 skipped_consensus_txns_cache_hit: register_int_counter_with_registry!(
710 "skipped_consensus_txns_cache_hit",
711 "Total number of consensus transactions skipped because of local cache hit",
712 registry,
713 )
714 .unwrap(),
715 post_processing_total_events_emitted: register_int_counter_with_registry!(
716 "post_processing_total_events_emitted",
717 "Total number of events emitted in post processing",
718 registry,
719 )
720 .unwrap(),
721 post_processing_total_tx_indexed: register_int_counter_with_registry!(
722 "post_processing_total_tx_indexed",
723 "Total number of txes indexed in post processing",
724 registry,
725 )
726 .unwrap(),
727 post_processing_total_tx_had_event_processed: register_int_counter_with_registry!(
728 "post_processing_total_tx_had_event_processed",
729 "Total number of txes finished event processing in post processing",
730 registry,
731 )
732 .unwrap(),
733 post_processing_total_failures: register_int_counter_with_registry!(
734 "post_processing_total_failures",
735 "Total number of failure in post processing",
736 registry,
737 )
738 .unwrap(),
739 consensus_handler_processed: register_int_counter_vec_with_registry!(
740 "consensus_handler_processed",
741 "Number of transactions processed by consensus handler",
742 &["class"],
743 registry
744 ).unwrap(),
745 consensus_handler_transaction_sizes: register_histogram_vec_with_registry!(
746 "consensus_handler_transaction_sizes",
747 "Sizes of each type of transactions processed by consensus handler",
748 &["class"],
749 POSITIVE_INT_BUCKETS.to_vec(),
750 registry;
751 MetricLevel::Warn,
752 ).unwrap(),
753 consensus_handler_num_low_scoring_authorities: register_int_gauge_with_registry!(
754 "consensus_handler_num_low_scoring_authorities",
755 "Number of low scoring authorities based on reputation scores from consensus",
756 registry
757 ).unwrap(),
758 consensus_handler_scores: register_int_gauge_vec_with_registry!(
759 "consensus_handler_scores",
760 "scores from consensus for each authority",
761 &["authority"],
762 registry,
763 ).unwrap(),
764 validator_scoreboard_scores: register_int_gauge_vec_with_registry!(
765 "validator_scoreboard_scores",
766 "Per-authority validator scores published by the local Scoreboard after each consensus commit. Range [0, MAX_SCORE].",
767 &["authority"],
768 registry;
769 MetricLevel::Warn,
770 ).unwrap(),
771 invalid_misbehavior_reports_by_authority: register_int_gauge_vec_with_registry!(
772 "invalid_misbehavior_reports_by_authority",
773 "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.",
774 &["authority"],
775 registry;
776 MetricLevel::Warn,
777 ).unwrap(),
778 consensus_handler_deferred_transactions: register_int_counter_with_registry!(
779 "consensus_handler_deferred_transactions",
780 "Number of transactions deferred by consensus handler",
781 registry,
782 ).unwrap(),
783 consensus_handler_congested_transactions: register_int_counter_with_registry!(
784 "consensus_handler_congested_transactions",
785 "Number of transactions deferred by consensus handler due to congestion",
786 registry,
787 ).unwrap(),
788 consensus_handler_cancelled_transactions: register_int_counter_with_registry!(
789 "consensus_handler_cancelled_transactions",
790 "Number of transactions cancelled by consensus handler",
791 registry,
792 ).unwrap(),
793 consensus_handler_validation_dropped_transactions: register_int_counter_with_registry!(
794 "consensus_handler_validation_dropped_transactions",
795 "Number of UserTransactionV1 transactions dropped by post-consensus validation",
796 registry,
797 ).unwrap(),
798 consensus_handler_validation_reader_verdicts: register_int_counter_vec_with_registry!(
799 "consensus_handler_validation_reader_verdicts",
800 "Verdicts of the commit-indexed reader in post-consensus validation, by verdict and deciding reason",
801 &["verdict", "reason"],
802 registry,
803 ).unwrap(),
804 consensus_handler_commit_execution_lag: register_int_gauge_with_registry!(
805 "consensus_handler_commit_execution_lag",
806 "The consensus commit being validated minus the highest fully executed commit",
807 registry,
808 ).unwrap(),
809 consensus_handler_load_shedding_dropped_transactions: register_int_counter_with_registry!(
810 "consensus_handler_load_shedding_dropped_transactions",
811 "Number of user transactions dropped by post-consensus load shedding, based on the quorum load shedding percentage",
812 registry,
813 ).unwrap(),
814 consensus_handler_load_shedding_percentage: register_int_gauge_with_registry!(
815 "consensus_handler_load_shedding_percentage",
816 "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.",
817 registry,
818 ).unwrap(),
819 consensus_handler_max_object_costs: register_int_gauge_vec_with_registry!(
820 "consensus_handler_max_congestion_control_object_costs",
821 "Max object costs for congestion control in the current consensus commit",
822 &["commit_type"],
823 registry,
824 ).unwrap(),
825 consensus_committed_subdags: register_int_counter_vec_with_registry!(
826 "consensus_committed_subdags",
827 "Number of committed subdags, sliced by leader",
828 &["authority"],
829 registry,
830 ).unwrap(),
831 consensus_committed_messages: register_int_gauge_vec_with_registry!(
832 "consensus_committed_messages",
833 "Total number of committed consensus messages, sliced by author",
834 &["authority"],
835 registry;
836 MetricLevel::Warn,
837 ).unwrap(),
838 consensus_committed_user_transactions: register_int_gauge_vec_with_registry!(
839 "consensus_committed_user_transactions",
840 "Number of committed user transactions, sliced by submitter",
841 &["authority"],
842 registry,
843 ).unwrap(),
844 consensus_handler_leader_round: register_int_gauge_with_registry!(
845 "consensus_handler_leader_round",
846 "The leader round of the current consensus output being processed in the consensus handler",
847 registry;
848 MetricLevel::Warn,
849 ).unwrap(),
850 limits_metrics: Arc::new(LimitsMetrics::new(registry)),
851 bytecode_verifier_metrics: Arc::new(BytecodeVerifierMetrics::new(registry)),
852 multisig_sig_count: register_int_counter_with_registry!(
853 "multisig_sig_count",
854 "Count of multisig signatures",
855 registry,
856 )
857 .unwrap(),
858 consensus_calculated_throughput: register_int_gauge_with_registry!(
859 "consensus_calculated_throughput",
860 "The calculated throughput from consensus output. Result is calculated based on unique transactions.",
861 registry,
862 ).unwrap(),
863 consensus_calculated_throughput_profile: register_int_gauge_with_registry!(
864 "consensus_calculated_throughput_profile",
865 "The current active calculated throughput profile",
866 registry
867 ).unwrap(),
868 execution_queueing_latency: LatencyObserver::new(),
869 txn_ready_rate_tracker: Arc::new(Mutex::new(RateTracker::new(Duration::from_secs(10)))),
870 execution_rate_tracker: Arc::new(Mutex::new(RateTracker::new(Duration::from_secs(10)))),
871 }
872 }
873
874 pub fn reset_on_reconfigure(&self) {
878 self.consensus_committed_messages.reset();
879 self.consensus_handler_scores.reset();
880 self.validator_scoreboard_scores.reset();
881 self.invalid_misbehavior_reports_by_authority.reset();
882 self.consensus_committed_user_transactions.reset();
883 }
884}
885
886pub type StableSyncAuthoritySigner = Pin<Arc<dyn Signer<AuthoritySignature> + Send + Sync>>;
892
893type CheckedValidationInputs = (CheckedInputObjects, Vec<CheckedInputObjects>);
895
896#[derive(Debug, Clone, Default)]
900pub struct ExecutionEnv {
901 pub assigned_versions: AssignedVersions,
903 pub expected_effects_digest: Option<TransactionEffectsDigest>,
906}
907
908impl ExecutionEnv {
909 pub fn new() -> Self {
910 Default::default()
911 }
912
913 pub fn with_expected_effects_digest(
914 mut self,
915 expected_effects_digest: TransactionEffectsDigest,
916 ) -> Self {
917 self.expected_effects_digest = Some(expected_effects_digest);
918 self
919 }
920
921 pub fn with_assigned_versions(mut self, assigned_versions: AssignedVersions) -> Self {
922 if !assigned_versions.is_empty() {
923 self.assigned_versions = assigned_versions;
924 }
925 self
926 }
927}
928
929pub struct AuthorityState {
930 pub name: AuthorityName,
933 pub secret: StableSyncAuthoritySigner,
935
936 input_loader: TransactionInputLoader,
938 execution_cache_trait_pointers: ExecutionCacheTraitPointers,
939
940 epoch_store: ArcSwap<AuthorityPerEpochStore>,
941
942 execution_lock: RwLock<EpochId>,
948
949 pub indexes: Option<Arc<IndexStore>>,
950 pub grpc_indexes_store: Option<Arc<GrpcIndexesStore>>,
951
952 pub subscription_handler: Arc<SubscriptionHandler>,
953 pub checkpoint_store: Arc<CheckpointStore>,
954
955 committee_store: Arc<CommitteeStore>,
956
957 execution_scheduler: Arc<ExecutionSchedulerWrapper>,
959
960 #[cfg_attr(not(test), expect(unused))]
962 tx_execution_shutdown: Mutex<Option<oneshot::Sender<()>>>,
963
964 pub metrics: Arc<AuthorityMetrics>,
965 pruner: AuthorityStorePruner,
968 authority_per_epoch_pruner: AuthorityPerEpochStorePruner,
969 checkpoint_progress_tracker: Option<Arc<CheckpointProgressTracker>>,
970
971 pub config: NodeConfig,
972
973 pub overload_info: AuthorityOverloadInfo,
975
976 pub validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
977
978 chain_identifier: ChainIdentifier,
981
982 pub(crate) congestion_tracker: Arc<CongestionTracker>,
983
984 pub traffic_controller: Option<Arc<TrafficController>>,
986 epoch_end_db_snapshots: Option<EpochEndDbSnapshotHandle>,
989}
990
991impl AuthorityState {
1000 pub fn is_committee_validator(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1001 epoch_store.committee().authority_exists(&self.name)
1002 }
1003
1004 pub fn is_active_validator(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1005 epoch_store
1006 .active_validators()
1007 .iter()
1008 .any(|a| AuthorityName::from(a) == self.name)
1009 }
1010
1011 pub fn is_fullnode(&self, epoch_store: &AuthorityPerEpochStore) -> bool {
1012 !self.is_committee_validator(epoch_store)
1013 }
1014
1015 pub fn committee_store(&self) -> &Arc<CommitteeStore> {
1016 &self.committee_store
1017 }
1018
1019 pub fn clone_committee_store(&self) -> Arc<CommitteeStore> {
1020 self.committee_store.clone()
1021 }
1022
1023 pub fn overload_config(&self) -> &AuthorityOverloadConfig {
1024 &self.config.authority_overload_config
1025 }
1026
1027 pub fn get_epoch_state_commitments(
1028 &self,
1029 epoch: EpochId,
1030 ) -> IotaResult<Option<Vec<CheckpointCommitment>>> {
1031 self.checkpoint_store.get_epoch_state_commitments(epoch)
1032 }
1033
1034 #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1080 pub(crate) async fn handle_transaction_validation_checks(
1081 &self,
1082 transaction: &VerifiedTransaction,
1083 epoch_store: &Arc<AuthorityPerEpochStore>,
1084 deny_config: &dyn DenyRuleConfig,
1085 epoch_gated_coin_deny_list: bool,
1086 verifier_limits_source: VerifierLimitsSource<'_>,
1087 ) -> IotaResult<Vec<ObjectReference>> {
1088 let protocol_config = epoch_store.protocol_config();
1089 let reference_gas_price = epoch_store.reference_gas_price();
1090
1091 let epoch = epoch_store.epoch();
1092
1093 let tx = transaction.data().transaction();
1094
1095 iota_transaction_checks::deny::check_transaction_for_validation(
1099 tx,
1100 transaction.signatures(),
1101 &transaction.input_objects()?,
1102 &tx.receiving_objects(),
1103 deny_config,
1104 self.get_backing_package_store().as_ref(),
1105 )?;
1106
1107 let (tx_input_objects, tx_receiving_objects, per_authenticator_inputs) =
1112 self.read_objects_for_validation(transaction, epoch)?;
1113
1114 let move_authenticators = transaction.move_authenticators();
1115
1116 let (gas_status, tx_checked_input_objects, per_authenticator_checked_inputs) = self
1122 .check_transaction_inputs_for_validation(
1123 protocol_config,
1124 reference_gas_price,
1125 tx,
1126 tx_input_objects,
1127 &tx_receiving_objects,
1128 &move_authenticators,
1129 per_authenticator_inputs,
1130 verifier_limits_source,
1131 )?;
1132
1133 let per_authenticator_checked_input_objects: Vec<_> = per_authenticator_checked_inputs
1136 .iter()
1137 .map(|i| &i.0)
1138 .collect();
1139
1140 debug_assert!(
1143 per_authenticator_checked_input_objects
1144 .iter()
1145 .all(|objects| objects.inner().filter_owned_objects().is_empty()),
1146 "Move authenticator input objects must not contain owned objects"
1147 );
1148
1149 if protocol_config.deny_authenticator_packages() {
1156 iota_transaction_checks::deny::check_authenticator_packages(
1157 deny_config,
1158 per_authenticator_checked_inputs
1159 .iter()
1160 .map(|(_, authenticator_function_ref)| authenticator_function_ref),
1161 self.get_backing_package_store().as_ref(),
1162 )?;
1163 }
1164
1165 check_coin_deny_list_v1(
1169 tx.sender(),
1170 &tx_checked_input_objects,
1171 &tx_receiving_objects,
1172 &per_authenticator_checked_input_objects,
1173 &self.get_object_store(),
1174 epoch_gated_coin_deny_list.then_some(epoch),
1175 )?;
1176
1177 let (kind, signer, gas_data) = tx.execution_parts();
1178
1179 let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) =
1180 extract_auth_fun_refs(signer, gas_data.owner, |address| {
1181 move_authenticators
1182 .iter()
1183 .zip(per_authenticator_checked_inputs.iter())
1184 .find(|(move_authenticator, _)| move_authenticator.address() == address)
1185 .map(|(_, (_, auth_fun_ref))| auth_fun_ref.clone())
1186 });
1187
1188 let pre_consensus_move_authenticators =
1193 pre_consensus_move_authenticators(transaction, protocol_config);
1194 debug_assert_eq!(
1197 move_authenticators.len(),
1198 per_authenticator_checked_inputs.len(),
1199 "Move authenticators amount must match the number of checked authenticator inputs"
1200 );
1201 let (move_authenticators, per_authenticator_checked_inputs): (Vec<_>, Vec<_>) =
1202 move_authenticators
1203 .into_iter()
1204 .zip(per_authenticator_checked_inputs)
1205 .filter(|(a, _)| pre_consensus_move_authenticators.contains(a))
1206 .unzip();
1207 let per_authenticator_checked_input_objects: Vec<_> = per_authenticator_checked_inputs
1208 .iter()
1209 .map(|i| &i.0)
1210 .collect();
1211
1212 if !move_authenticators.is_empty() {
1215 let aggregated_authenticator_input_objects =
1216 iota_transaction_checks::aggregate_authenticator_input_objects(
1217 &per_authenticator_checked_input_objects,
1218 )?;
1219
1220 let move_authenticators = move_authenticators
1221 .into_iter()
1222 .zip(per_authenticator_checked_inputs)
1223 .map(
1224 |(
1225 move_authenticator,
1226 (authenticator_checked_input_objects, authenticator_function_ref),
1227 )| {
1228 (
1229 move_authenticator.to_owned(),
1230 authenticator_function_ref,
1231 authenticator_checked_input_objects,
1232 )
1233 },
1234 )
1235 .collect();
1236
1237 let tx_bytes = bcs::to_bytes(tx).expect("Transaction serialization cannot fail");
1242
1243 let (sender_auth_digest, sponsor_auth_digest) =
1244 transaction.data().compute_auth_digests()?;
1245
1246 let auth_context_data = AuthContextData {
1247 transaction_data_bytes: tx_bytes,
1248 sender_auth_digest,
1249 sponsor_auth_digest,
1250 sender_authenticator_function_ref,
1251 sponsor_authenticator_function_ref,
1252 };
1253
1254 let validation_result = epoch_store.executor().authenticate_transaction(
1256 self.get_backing_store().as_ref(),
1257 protocol_config,
1258 self.metrics.limits_metrics.clone(),
1259 &epoch_store.epoch_start_config().epoch_data().epoch_id(),
1260 epoch_store
1261 .epoch_start_config()
1262 .epoch_data()
1263 .epoch_start_timestamp(),
1264 gas_data,
1265 gas_status,
1266 move_authenticators,
1267 aggregated_authenticator_input_objects,
1268 kind,
1269 signer,
1270 transaction.digest().to_owned(),
1271 auth_context_data,
1272 &mut None,
1273 );
1274
1275 if let Err(validation_error) = validation_result {
1276 return Err(IotaError::MoveAuthenticatorExecutionFailure {
1277 error: validation_error.to_string(),
1278 });
1279 }
1280 }
1281
1282 Ok(tx_checked_input_objects.inner().filter_owned_objects())
1283 }
1284
1285 #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1302 pub(crate) fn handle_transaction_validation_checks_at_commit(
1303 &self,
1304 reader: &CommitIndexedReader,
1305 transaction: &VerifiedTransaction,
1306 epoch_store: &Arc<AuthorityPerEpochStore>,
1307 deny_config: &dyn DenyRuleConfig,
1308 verifier_limits_source: VerifierLimitsSource<'_>,
1309 ) -> IotaResult<ValidationAtCommit> {
1310 let protocol_config = epoch_store.protocol_config();
1311 let reference_gas_price = epoch_store.reference_gas_price();
1312
1313 let tx = transaction.data().transaction();
1314
1315 let (tx_input_objects, tx_receiving_objects, per_authenticator_inputs) =
1316 match self.read_objects_for_validation_at_commit(reader, transaction)? {
1317 ValidationInputsAtCommit::Loaded {
1318 tx_input_objects,
1319 tx_receiving_objects,
1320 per_authenticator_inputs,
1321 } => (
1322 tx_input_objects,
1323 tx_receiving_objects,
1324 per_authenticator_inputs,
1325 ),
1326 ValidationInputsAtCommit::Drop(kind, reason) => {
1327 return Ok(ValidationAtCommit::Drop(kind, reason));
1328 }
1329 ValidationInputsAtCommit::Missing(kind, reason) => {
1330 return Ok(ValidationAtCommit::Missing(kind, reason));
1331 }
1332 };
1333
1334 iota_transaction_checks::deny::check_transaction_for_validation(
1339 tx,
1340 transaction.signatures(),
1341 &transaction.input_objects()?,
1342 &tx.receiving_objects(),
1343 deny_config,
1344 reader,
1345 )?;
1346
1347 let move_authenticators = transaction.move_authenticators();
1348
1349 let (tx_checked_input_objects, per_authenticator_checked_inputs) = self
1361 .check_transaction_inputs_at_commit(
1362 protocol_config,
1363 reference_gas_price,
1364 tx,
1365 tx_input_objects,
1366 &tx_receiving_objects,
1367 &move_authenticators,
1368 per_authenticator_inputs,
1369 verifier_limits_source,
1370 )?;
1371
1372 let per_authenticator_checked_input_objects =
1373 per_authenticator_checked_inputs.iter().collect::<Vec<_>>();
1374
1375 debug_assert!(
1376 per_authenticator_checked_input_objects
1377 .iter()
1378 .all(|objects| objects.inner().filter_owned_objects().is_empty()),
1379 "Move authenticator input objects must not contain owned objects"
1380 );
1381
1382 let accounts = move_authenticators
1386 .iter()
1387 .map(|move_authenticator| {
1388 let account_kind = move_authenticator
1389 .object_to_authenticate()
1390 .input_object_kind()
1391 .expect("the object to authenticate is validated before consensus");
1392 Ok((account_kind, reader.read_account(account_kind.object_id())?))
1393 })
1394 .collect::<IotaResult<Vec<_>>>()?;
1395
1396 if protocol_config.deny_authenticator_packages() && deny_config.has_denied_packages() {
1400 let mut function_refs = Vec::new();
1401 for (account_kind, verdict) in &accounts {
1402 if let AccountVerdict::Account(field) = verdict {
1403 function_refs.extend(
1404 reader
1405 .visible_authenticator_function_ref(account_kind.object_id(), field)?,
1406 );
1407 }
1408 }
1409 if let Err(error) = iota_transaction_checks::deny::check_authenticator_packages(
1410 deny_config,
1411 &function_refs,
1412 reader,
1413 ) {
1414 if error.is_storage_or_epoch_error() {
1415 return Err(error);
1416 }
1417 return Ok(ValidationAtCommit::AuthenticatorPackageDenied(error));
1418 }
1419 }
1420
1421 let mut shared_objects = Vec::new();
1429 for input in tx_checked_input_objects.inner().iter().chain(
1430 per_authenticator_checked_input_objects
1431 .iter()
1432 .flat_map(|objects| objects.inner().iter()),
1433 ) {
1434 if let (
1435 InputObjectKind::SharedMoveObject {
1436 id,
1437 initial_shared_version,
1438 ..
1439 },
1440 None,
1441 ) = (input.input_object_kind, input.as_object())
1442 {
1443 shared_objects
1444 .push(reader.read_shared_object_for_type(id, initial_shared_version)?);
1445 }
1446 }
1447 let coin_types = coin_types_for_denylist_check(
1448 tx_checked_input_objects
1449 .inner()
1450 .iter_objects()
1451 .chain(
1452 per_authenticator_checked_input_objects
1453 .iter()
1454 .flat_map(|objects| objects.inner().iter_objects()),
1455 )
1456 .chain(&shared_objects)
1457 .chain(tx_receiving_objects.iter_objects()),
1458 );
1459 if let Some(denial) = DenyListAtCommit::new(reader).denial(tx.sender(), coin_types)? {
1460 return Err(denial.into());
1461 }
1462
1463 for (account_kind, verdict) in accounts {
1466 if let AccountVerdict::Missing(reason) = verdict {
1467 return Ok(ValidationAtCommit::Missing(account_kind, reason));
1468 }
1469 }
1470
1471 Ok(ValidationAtCommit::Keep(
1472 tx_checked_input_objects.inner().filter_owned_objects(),
1473 ))
1474 }
1475
1476 async fn handle_transaction_impl(
1480 &self,
1481 transaction: VerifiedTransaction,
1482 epoch_store: &Arc<AuthorityPerEpochStore>,
1483 ) -> IotaResult<VerifiedSignedTransaction> {
1484 let _execution_lock = self.execution_lock_for_signing()?;
1486
1487 let owned_objects = self
1488 .handle_transaction_validation_checks(
1489 &transaction,
1490 epoch_store,
1491 &self.config.transaction_deny_config,
1492 false,
1497 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
1498 )
1499 .await?;
1500
1501 let epoch = epoch_store.epoch();
1502 let signed_transaction =
1503 VerifiedSignedTransaction::new(epoch, transaction, self.name, &*self.secret);
1504
1505 self.get_cache_writer().try_acquire_transaction_locks(
1510 epoch_store,
1511 &owned_objects,
1512 signed_transaction.clone(),
1513 )?;
1514
1515 Ok(signed_transaction)
1516 }
1517
1518 #[instrument(name = "handle_transaction", level = "trace", skip_all, fields(tx_digest = ?transaction.digest(), sender = transaction.data().transaction().gas_owner().to_string()
1520 ))]
1521 pub async fn handle_transaction(
1522 &self,
1523 epoch_store: &Arc<AuthorityPerEpochStore>,
1524 transaction: VerifiedTransaction,
1525 ) -> IotaResult<HandleTransactionResponse> {
1526 let tx_digest = *transaction.digest();
1527 debug!("handle_transaction");
1528
1529 if let Some((_, status)) = self.get_transaction_status(&tx_digest, epoch_store)? {
1531 return Ok(HandleTransactionResponse { status });
1532 }
1533
1534 let _metrics_guard = self
1535 .metrics
1536 .authority_state_handle_transaction_latency
1537 .start_timer();
1538 self.metrics.tx_orders.inc();
1539
1540 let signed = self.handle_transaction_impl(transaction, epoch_store).await;
1541 match signed {
1542 Ok(s) => {
1543 if self.is_committee_validator(epoch_store) {
1544 if let Some(validator_tx_finalizer) = &self.validator_tx_finalizer {
1545 let tx = s.clone();
1546 let validator_tx_finalizer = validator_tx_finalizer.clone();
1547 let cache_reader = self.get_transaction_cache_reader().clone();
1548 let epoch_store = epoch_store.clone();
1549 spawn_monitored_task!(epoch_store.within_alive_epoch(
1550 validator_tx_finalizer.track_signed_tx(cache_reader, &epoch_store, tx)
1551 ));
1552 }
1553 }
1554 Ok(HandleTransactionResponse {
1555 status: TransactionStatus::Signed(s.into_inner().into_sig()),
1556 })
1557 }
1558 Err(err) => Ok(HandleTransactionResponse {
1562 status: self
1563 .get_transaction_status(&tx_digest, epoch_store)?
1564 .ok_or(err)?
1565 .1,
1566 }),
1567 }
1568 }
1569
1570 pub fn check_system_overload_at_signing(&self) -> bool {
1571 self.config
1572 .authority_overload_config
1573 .check_system_overload_at_signing
1574 }
1575
1576 pub fn check_system_overload_at_execution(&self) -> bool {
1577 self.config
1578 .authority_overload_config
1579 .check_system_overload_at_execution
1580 }
1581
1582 pub(crate) fn check_system_overload(
1592 &self,
1593 consensus_adapter: &Arc<ConsensusAdapter>,
1594 tx: &SenderSignedTransaction,
1595 do_authority_overload_check: bool,
1596 pcool_flow_enabled: bool,
1597 ) -> IotaResult {
1598 if pcool_flow_enabled {
1599 self.check_consensus_queue_graduated_limits(consensus_adapter, tx)
1602 .tap_err(|_| {
1603 self.update_overload_metrics("consensus");
1604 })?;
1605
1606 consensus_adapter.check_consensus_overload().tap_err(|_| {
1613 self.update_overload_metrics("consensus");
1614 })?;
1615 } else {
1616 if do_authority_overload_check {
1617 self.check_authority_overload(tx).tap_err(|_| {
1618 self.update_overload_metrics("execution_queue");
1619 })?;
1620 }
1621 self.execution_scheduler
1622 .check_execution_overload(self.overload_config(), tx)
1623 .tap_err(|_| {
1624 self.update_overload_metrics("execution_pending");
1625 })?;
1626 consensus_adapter.check_consensus_overload().tap_err(|_| {
1627 self.update_overload_metrics("consensus");
1628 })?;
1629
1630 let pending_tx_count = self
1631 .get_cache_commit()
1632 .approximate_pending_transaction_count();
1633 if pending_tx_count
1634 > self
1635 .config
1636 .execution_cache_config
1637 .writeback_cache
1638 .backpressure_threshold_for_rpc()
1639 {
1640 return Err(IotaError::ValidatorOverloadedRetryAfter {
1641 retry_after_secs: 10,
1642 });
1643 }
1644 }
1645
1646 Ok(())
1647 }
1648
1649 fn check_consensus_queue_graduated_limits(
1657 &self,
1658 consensus_adapter: &Arc<ConsensusAdapter>,
1659 tx: &SenderSignedTransaction,
1660 ) -> IotaResult {
1661 let num_inflight_txs = consensus_adapter.num_inflight_transactions() as usize;
1662
1663 let shedding_pct = compute_graduated_load_shedding_percentage(
1664 num_inflight_txs,
1665 consensus_adapter.max_pending_transactions(),
1666 consensus_adapter.graduated_load_shedding_soft_limit_pct(),
1667 );
1668
1669 self.metrics
1670 .consensus_queue_load_shedding_percentage
1671 .set(shedding_pct as i64);
1672
1673 if shedding_pct == 0 {
1674 return Ok(());
1675 }
1676
1677 if shedding_pct >= 100 {
1682 return Err(IotaError::TooManyTransactionsPendingConsensus);
1683 }
1684
1685 overload_monitor_accept_tx(shedding_pct, tx.digest())
1686 }
1687
1688 fn check_authority_overload(&self, tx: &SenderSignedTransaction) -> IotaResult {
1689 if !self.overload_info.is_overload.load(Ordering::Relaxed) {
1690 return Ok(());
1691 }
1692
1693 let load_shedding_percentage = self
1694 .overload_info
1695 .local_load_shedding_percentage
1696 .load(Ordering::Relaxed);
1697 overload_monitor_accept_tx(load_shedding_percentage, tx.digest())
1698 }
1699
1700 fn update_overload_metrics(&self, source: &str) {
1701 self.metrics
1702 .transaction_overload_sources
1703 .with_label_values(&[source])
1704 .inc();
1705 }
1706
1707 #[instrument(level = "trace", skip_all)]
1712 pub async fn wait_for_certificate_execution(
1713 &self,
1714 certificate: &VerifiedCertificate,
1715 epoch_store: &Arc<AuthorityPerEpochStore>,
1716 ) -> IotaResult<TransactionEffects> {
1717 let _metrics_guard = if certificate.contains_shared_object() {
1718 self.metrics
1719 .execute_certificate_latency_shared_object
1720 .start_timer()
1721 } else {
1722 self.metrics
1723 .execute_certificate_latency_single_writer
1724 .start_timer()
1725 };
1726 trace!("wait_for_certificate_execution");
1727
1728 self.metrics.total_cert_attempts.inc();
1729
1730 if !certificate.contains_shared_object() {
1731 self.execution_scheduler.enqueue(
1736 vec![(
1737 Schedulable::Transaction(VerifiedExecutableTransaction::new_from_certificate(
1738 certificate.clone(),
1739 )),
1740 ExecutionEnv::new(),
1741 )],
1742 epoch_store,
1743 );
1744 }
1745
1746 epoch_store
1749 .within_alive_epoch(self.notify_read_effects(
1750 "AuthorityState::wait_for_certificate_execution",
1751 certificate,
1752 ))
1753 .await
1754 .and_then(|r| r)
1755 }
1756
1757 #[instrument(level = "trace", skip_all, fields(tx_digest = ?transaction.digest()))]
1771 pub fn try_execute_immediately(
1772 &self,
1773 transaction: &VerifiedExecutableTransaction,
1774 execution_env: ExecutionEnv,
1775 epoch_store: &Arc<AuthorityPerEpochStore>,
1776 ) -> IotaResult<(TransactionEffects, Option<ExecutionError>)> {
1777 let _scope = monitored_scope("Execution::try_execute_immediately");
1778 let _metrics_guard = self.metrics.internal_execution_latency.start_timer();
1779
1780 let tx_digest = transaction.digest();
1781
1782 let tx_guard = epoch_store.acquire_tx_guard(transaction)?;
1784
1785 if let Some(effects) = self
1788 .get_transaction_cache_reader()
1789 .try_get_executed_effects(tx_digest)?
1790 {
1791 if let Some(expected_effects_digest_inner) = execution_env.expected_effects_digest {
1792 assert_eq!(
1793 effects.digest(),
1794 expected_effects_digest_inner,
1795 "Unexpected effects digest for transaction {tx_digest}"
1796 );
1797 }
1798 tx_guard.release();
1799 return Ok((effects, None));
1800 }
1801
1802 let (tx_input_objects, per_authenticator_inputs) = self.read_objects_for_execution(
1803 tx_guard.as_lock_guard(),
1804 transaction,
1805 execution_env.assigned_versions,
1806 epoch_store,
1807 )?;
1808
1809 self.process_transaction(
1810 tx_guard,
1811 transaction,
1812 tx_input_objects,
1813 per_authenticator_inputs,
1814 execution_env.expected_effects_digest,
1815 epoch_store,
1816 )
1817 .tap_err(|e| info!(?tx_digest, "process_transaction failed: {e}"))
1818 .tap_ok(
1819 |(fx, _)| debug!(?tx_digest, fx_digest=?fx.digest(), "process_transaction succeeded"),
1820 )
1821 }
1822
1823 pub fn read_objects_for_execution(
1824 &self,
1825 tx_lock: &TxLockGuard,
1826 transaction: &VerifiedExecutableTransaction,
1827 assigned_shared_object_versions: AssignedVersions,
1828 epoch_store: &Arc<AuthorityPerEpochStore>,
1829 ) -> IotaResult<(InputObjects, Vec<(InputObjects, ObjectReadResult)>)> {
1830 let _scope = monitored_scope("Execution::load_input_objects");
1831 let _metrics_guard = self
1832 .metrics
1833 .execution_load_input_objects_latency
1834 .start_timer();
1835
1836 let input_objects = transaction.collect_all_input_object_kind_for_reading()?;
1837
1838 let input_objects = self.input_loader.read_objects_for_execution(
1839 &transaction.key(),
1840 tx_lock,
1841 &input_objects,
1842 &assigned_shared_object_versions,
1843 epoch_store.epoch(),
1844 )?;
1845
1846 transaction.split_input_objects_into_groups_for_reading(input_objects)
1847 }
1848
1849 pub fn try_execute_for_test(
1856 &self,
1857 certificate: &VerifiedCertificate,
1858 execution_env: ExecutionEnv,
1859 ) -> IotaResult<(VerifiedSignedTransactionEffects, Option<ExecutionError>)> {
1860 let epoch_store = self.epoch_store_for_testing();
1861 epoch_store.assign_to_a_new_commit_for_testing(&[certificate.key()]);
1862 let (effects, execution_error_opt) = self.try_execute_immediately(
1863 &VerifiedExecutableTransaction::new_from_certificate(certificate.clone()),
1864 execution_env,
1865 &epoch_store,
1866 )?;
1867 let signed_effects = self.sign_effects(effects, &epoch_store)?;
1868 Ok((signed_effects, execution_error_opt))
1869 }
1870
1871 pub fn execute_for_test(
1873 &self,
1874 certificate: &VerifiedCertificate,
1875 execution_env: ExecutionEnv,
1876 ) -> (VerifiedSignedTransactionEffects, Option<ExecutionError>) {
1877 self.try_execute_for_test(certificate, execution_env)
1878 .expect("try_execute_for_test should not fail")
1879 }
1880
1881 pub async fn notify_read_effects(
1882 &self,
1883 task_name: &'static str,
1884 certificate: &VerifiedCertificate,
1885 ) -> IotaResult<TransactionEffects> {
1886 self.get_transaction_cache_reader()
1887 .try_notify_read_executed_effects(task_name, &[*certificate.digest()])
1888 .await
1889 .map(|mut r| r.pop().expect("must return correct number of effects"))
1890 }
1891
1892 fn check_owned_locks(&self, owned_object_refs: &[ObjectReference]) -> IotaResult {
1893 self.get_object_cache_reader()
1894 .try_check_owned_objects_are_live(owned_object_refs)
1895 }
1896
1897 pub(crate) fn debug_dump_transaction_state(
1902 &self,
1903 tx_digest: &TransactionDigest,
1904 effects: &TransactionEffects,
1905 expected_effects_digest: TransactionEffectsDigest,
1906 inner_temporary_store: &InnerTemporaryStore,
1907 transaction: &VerifiedExecutableTransaction,
1908 debug_dump_config: &StateDebugDumpConfig,
1909 ) -> IotaResult<PathBuf> {
1910 let dump_dir = debug_dump_config
1913 .dump_file_directory
1914 .as_ref()
1915 .cloned()
1916 .unwrap_or(std::env::temp_dir());
1917 let epoch_store = self.load_epoch_store_one_call_per_task();
1918
1919 NodeStateDump::new(
1920 tx_digest,
1921 effects,
1922 expected_effects_digest,
1923 self.get_object_store().as_ref(),
1924 &epoch_store,
1925 inner_temporary_store,
1926 transaction,
1927 )?
1928 .write_to_file(&dump_dir)
1929 .map_err(|e| IotaError::FileIO(e.to_string()))
1930 }
1931
1932 #[instrument(name = "process_certificate", level = "trace", skip_all, fields(tx_digest = ?transaction.digest(), sender = ?transaction.data().transaction().gas_owner().to_string()))]
1933 pub(crate) fn process_transaction(
1934 &self,
1935 tx_guard: TxGuard,
1936 transaction: &VerifiedExecutableTransaction,
1937 tx_input_objects: InputObjects,
1938 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
1939 expected_effects_digest: Option<TransactionEffectsDigest>,
1940 epoch_store: &Arc<AuthorityPerEpochStore>,
1941 ) -> IotaResult<(TransactionEffects, Option<ExecutionError>)> {
1942 let process_transaction_start_time = tokio::time::Instant::now();
1943 let digest = *transaction.digest();
1944
1945 let _scope = monitored_scope("Execution::process_certificate");
1946
1947 fail_point_if!("correlated-crash-process-transaction", || {
1948 if iota_simulator::random::deterministic_probability_once(digest, 0.01) {
1949 iota_simulator::task::kill_current_node(None);
1950 }
1951 });
1952
1953 let execution_guard = self.execution_lock_for_executable_transaction(transaction);
1954 let execution_guard = match execution_guard {
1960 Ok(execution_guard) => execution_guard,
1961 Err(err) => {
1962 tx_guard.release();
1963 return Err(err);
1964 }
1965 };
1966 if *execution_guard != epoch_store.epoch() {
1970 tx_guard.release();
1971 info!("The epoch of the execution_guard doesn't match the epoch store");
1972 return Err(IotaError::WrongEpoch {
1973 expected_epoch: epoch_store.epoch(),
1974 actual_epoch: *execution_guard,
1975 });
1976 }
1977
1978 let (inner_temporary_store, effects, execution_error_opt) = match self.execute_transaction(
1984 &execution_guard,
1985 transaction,
1986 tx_input_objects,
1987 per_authenticator_inputs,
1988 epoch_store,
1989 ) {
1990 Err(e) => {
1991 info!(name = ?self.name, ?digest, "Error preparing transaction: {e}");
1992 tx_guard.release();
1993 return Err(e);
1994 }
1995 Ok(res) => res,
1996 };
1997
1998 if let Some(expected_effects_digest) = expected_effects_digest {
1999 if effects.digest() != expected_effects_digest {
2000 match self.debug_dump_transaction_state(
2002 &digest,
2003 &effects,
2004 expected_effects_digest,
2005 &inner_temporary_store,
2006 transaction,
2007 &self.config.state_debug_dump_config,
2008 ) {
2009 Ok(out_path) => {
2010 info!(
2011 "Dumped node state for transaction {} to {}",
2012 digest,
2013 out_path.as_path().display().to_string()
2014 );
2015 }
2016 Err(e) => {
2017 error!("Error dumping state for transaction {}: {e}", digest);
2018 }
2019 }
2020 error!(
2021 tx_digest = ?digest,
2022 ?expected_effects_digest,
2023 actual_effects = ?effects,
2024 "fork detected!"
2025 );
2026 panic!(
2027 "Transaction {} is expected to have effects digest {}, but got {}!",
2028 digest,
2029 expected_effects_digest,
2030 effects.digest(),
2031 );
2032 }
2033 }
2034
2035 fail_point!("crash");
2036
2037 self.commit_transaction(
2038 transaction,
2039 inner_temporary_store,
2040 &effects,
2041 tx_guard,
2042 execution_guard,
2043 expected_effects_digest,
2044 epoch_store,
2045 )?;
2046
2047 let elapsed = process_transaction_start_time.elapsed().as_micros() as f64;
2048 if elapsed > 0.0 {
2049 self.metrics
2050 .execution_gas_latency_ratio
2051 .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed);
2052 };
2053 Ok((effects, execution_error_opt))
2054 }
2055
2056 pub async fn reconfigure_traffic_control(
2057 &self,
2058 params: TrafficControlReconfigParams,
2059 ) -> Result<TrafficControlReconfigParams, IotaError> {
2060 if let Some(traffic_controller) = self.traffic_controller.as_ref() {
2061 traffic_controller.admin_reconfigure(params)
2062 } else {
2063 Err(IotaError::InvalidAdminRequest(
2064 "Traffic controller is not configured on this node".to_string(),
2065 ))
2066 }
2067 }
2068
2069 #[instrument(level = "trace", skip_all)]
2070 fn commit_transaction(
2071 &self,
2072 transaction: &VerifiedExecutableTransaction,
2073 inner_temporary_store: InnerTemporaryStore,
2074 effects: &TransactionEffects,
2075 tx_guard: TxGuard,
2076 _execution_guard: ExecutionLockReadGuard<'_>,
2077 expected_effects_digest: Option<TransactionEffectsDigest>,
2078 epoch_store: &Arc<AuthorityPerEpochStore>,
2079 ) -> IotaResult {
2080 let _scope: Option<iota_metrics::MonitoredScopeGuard> =
2081 monitored_scope("Execution::commit_certificate");
2082 let _metrics_guard = self.metrics.commit_certificate_latency.start_timer();
2083
2084 let tx_digest = transaction.digest();
2085 let input_object_count = inner_temporary_store.input_objects.len();
2086 let shared_object_count = effects.input_shared_objects().len();
2087
2088 let output_keys = inner_temporary_store.get_output_keys(effects);
2089
2090 let _ = self
2092 .post_process_one_tx(transaction, effects, &inner_temporary_store, epoch_store)
2093 .tap_err(|e| {
2094 self.metrics.post_processing_total_failures.inc();
2095 error!(?tx_digest, "tx post processing failed: {e}");
2096 });
2097
2098 epoch_store.insert_executed_in_epoch(tx_digest);
2102
2103 let key = transaction.key();
2104 if !matches!(key, TransactionKey::Digest(_)) {
2105 epoch_store.insert_tx_key(key, *tx_digest)?;
2106 }
2107
2108 if epoch_store.pcool_bookkeeping_enabled()
2117 && !transaction.transaction().is_genesis_tx()
2118 && !transaction.transaction().is_end_of_epoch_tx()
2119 {
2120 epoch_store.record_executed_transaction(&key, effects);
2121 }
2122
2123 fail_point!("crash");
2125
2126 let transaction_outputs = TransactionOutputs::build_transaction_outputs(
2127 transaction.clone().into_unsigned(),
2128 effects.clone(),
2129 inner_temporary_store,
2130 );
2131 self.get_cache_writer()
2132 .try_write_transaction_outputs(epoch_store.epoch(), transaction_outputs.into())?;
2133
2134 self.report_failed_deny_rule_update_execution(
2135 transaction,
2136 effects,
2137 expected_effects_digest,
2138 epoch_store,
2139 );
2140
2141 if transaction.transaction().is_end_of_epoch_tx() {
2142 self.get_object_cache_reader()
2145 .force_reload_system_packages(&BuiltInFramework::all_package_ids());
2146 }
2147
2148 tx_guard.commit_tx();
2150
2151 match self.execution_scheduler.as_ref() {
2152 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
2153 ExecutionSchedulerWrapper::TransactionManager(tm) => {
2154 tm.notify_commit(tx_digest, output_keys, epoch_store);
2158 if let Some(key) = transaction.non_digest_key() {
2164 tm.notify_transaction_key(epoch_store, key, *tx_digest);
2165 }
2166 }
2167 }
2168
2169 self.update_metrics(transaction, input_object_count, shared_object_count);
2170
2171 Ok(())
2172 }
2173
2174 fn update_metrics(
2175 &self,
2176 transaction: &VerifiedExecutableTransaction,
2177 input_object_count: usize,
2178 shared_object_count: usize,
2179 ) {
2180 if transaction.has_multisig() {
2182 self.metrics.multisig_sig_count.inc();
2183 }
2184
2185 self.metrics.total_effects.inc();
2186 self.metrics.total_certs.inc();
2187
2188 if shared_object_count > 0 {
2189 self.metrics.shared_obj_tx.inc();
2190 }
2191
2192 if transaction.is_sponsored_tx() {
2193 self.metrics.sponsored_tx.inc();
2194 }
2195
2196 self.metrics
2197 .num_input_objs
2198 .observe(input_object_count as f64);
2199 self.metrics
2200 .num_shared_objects
2201 .observe(shared_object_count as f64);
2202 self.metrics
2203 .batch_size
2204 .observe(transaction.data().transaction().kind().num_commands() as f64);
2205 }
2206
2207 #[instrument(level = "trace", skip_all)]
2219 fn execute_transaction(
2220 &self,
2221 _execution_guard: &ExecutionLockReadGuard<'_>,
2222 transaction: &VerifiedExecutableTransaction,
2223 tx_input_objects: InputObjects,
2224 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
2225 epoch_store: &Arc<AuthorityPerEpochStore>,
2226 ) -> IotaResult<(
2227 InnerTemporaryStore,
2228 TransactionEffects,
2229 Option<ExecutionError>,
2230 )> {
2231 let _scope = monitored_scope("Execution::execute_certificate");
2232 let _metrics_guard = self.metrics.prepare_certificate_latency.start_timer();
2233 let prepare_transaction_start_time = tokio::time::Instant::now();
2234
2235 let protocol_config = epoch_store.protocol_config();
2236
2237 let reference_gas_price = epoch_store.reference_gas_price();
2238
2239 let epoch_id = epoch_store.epoch_start_config().epoch_data().epoch_id();
2240 let epoch_start_timestamp = epoch_store
2241 .epoch_start_config()
2242 .epoch_data()
2243 .epoch_start_timestamp();
2244
2245 let backing_store = self.get_backing_store().as_ref();
2246
2247 let tx_digest = *transaction.digest();
2248
2249 let tx = transaction.data().transaction();
2252 tx.validity_check(protocol_config)?;
2253
2254 let (kind, signer, gas_data) = tx.execution_parts();
2255
2256 let move_authenticators = transaction.move_authenticators();
2257
2258 #[cfg_attr(not(any(msim, fail_points)), expect(unused_mut))]
2259 let (inner_temp_store, _, mut effects, _, execution_error_opt) = if move_authenticators
2260 .is_empty()
2261 {
2262 let (tx_gas_status, tx_checked_input_objects) =
2267 iota_transaction_checks::check_certificate_input(
2268 transaction,
2269 tx_input_objects,
2270 protocol_config,
2271 reference_gas_price,
2272 )?;
2273
2274 let owned_object_refs = tx_checked_input_objects.inner().filter_owned_objects();
2275 self.check_owned_locks(&owned_object_refs)?;
2276 epoch_store.executor().execute_transaction_to_effects(
2277 backing_store,
2278 protocol_config,
2279 self.metrics.limits_metrics.clone(),
2280 self.config
2283 .expensive_safety_check_config
2284 .enable_deep_per_tx_iota_conservation_check(),
2285 self.config.certificate_deny_config.certificate_deny_set(),
2286 &epoch_id,
2287 epoch_start_timestamp,
2288 tx_checked_input_objects,
2289 gas_data,
2290 tx_gas_status,
2291 kind,
2292 signer,
2293 tx_digest,
2294 &mut None,
2295 )
2296 } else {
2297 debug_assert_eq!(
2303 move_authenticators.len(),
2304 per_authenticator_inputs.len(),
2305 "Move authenticators amount must match the number of authenticator inputs"
2306 );
2307
2308 let mut per_authenticator_input_objects = Vec::with_capacity(move_authenticators.len());
2312 let mut resolutions = Vec::with_capacity(move_authenticators.len());
2313 for (move_authenticator, (authenticator_input_objects, account_object)) in
2314 move_authenticators.iter().zip(per_authenticator_inputs)
2315 {
2316 let (account_object_id, account_object_version, account_object_digest) =
2320 move_authenticator
2321 .object_to_authenticate_components()
2322 .expect(
2323 "the object to authenticate is validated before consensus and cannot \
2324 be invalid during execution",
2325 );
2326
2327 resolutions.push(self.check_move_account_for_execution(
2332 account_object_id,
2333 account_object_version,
2334 account_object_digest,
2335 account_object,
2336 &move_authenticator.address(),
2337 protocol_config,
2338 ));
2339
2340 per_authenticator_input_objects.push(authenticator_input_objects);
2341 }
2342
2343 let tx_bytes = bcs::to_bytes(tx).expect("Transaction serialization cannot fail");
2345
2346 let (sender_auth_digest, sponsor_auth_digest) =
2347 transaction.data().compute_auth_digests()?;
2348
2349 let authenticator_gas_budget = protocol_config.max_auth_gas();
2354 let (
2355 gas_status,
2356 per_authenticator_checked_input_objects,
2357 authenticator_and_tx_checked_input_objects,
2358 ) = iota_transaction_checks::check_certificate_and_move_authenticator_input(
2359 transaction,
2360 tx_input_objects,
2361 per_authenticator_input_objects,
2362 authenticator_gas_budget,
2363 protocol_config,
2364 reference_gas_price,
2365 )?;
2366
2367 let owned_object_refs = authenticator_and_tx_checked_input_objects
2368 .inner()
2369 .filter_owned_objects();
2370 self.check_owned_locks(&owned_object_refs)?;
2371
2372 let (sender_authenticator_function_ref, sponsor_authenticator_function_ref) =
2376 extract_auth_fun_refs(signer, gas_data.owner, |address| {
2377 move_authenticators
2378 .iter()
2379 .zip(&resolutions)
2380 .find(|(move_authenticator, _)| move_authenticator.address() == address)
2381 .and_then(|(_, resolution)| resolution.as_ref().ok())
2382 .map(|function_ref| function_ref.authenticator_function_ref.clone())
2383 });
2384
2385 let accounts = move_authenticators
2386 .iter()
2387 .map(|move_authenticator| move_authenticator.address())
2388 .collect::<Vec<_>>();
2389 debug_assert_eq!(
2390 move_authenticators.len(),
2391 per_authenticator_checked_input_objects.len(),
2392 "Move authenticators amount must match the number of checked authenticator inputs"
2393 );
2394 let deterministic_validation = protocol_config.enable_pcool_flow();
2398 let mut first_resolution_error = None;
2399 let mut gas_owner_resolution_error = None;
2400 let mut resolved_authenticators = Vec::with_capacity(move_authenticators.len());
2401 for ((move_authenticator, resolution), authenticator_checked_input_objects) in
2402 move_authenticators
2403 .into_iter()
2404 .zip(resolutions)
2405 .zip(per_authenticator_checked_input_objects)
2406 {
2407 match resolution {
2408 Ok(function_ref) => {
2409 resolved_authenticators.push(MoveAuthenticatorForExecution {
2410 authenticator: move_authenticator.to_owned(),
2411 function_ref,
2412 input_objects: authenticator_checked_input_objects,
2413 })
2414 }
2415 Err(error)
2416 if deterministic_validation
2417 && move_authenticator.address() == gas_data.owner =>
2418 {
2419 gas_owner_resolution_error = Some(error);
2420 }
2421 Err(error) => {
2422 first_resolution_error.get_or_insert(error);
2423 }
2424 }
2425 }
2426
2427 let auth_context_data = AuthContextData {
2428 transaction_data_bytes: tx_bytes,
2429 sender_auth_digest,
2430 sponsor_auth_digest,
2431 sender_authenticator_function_ref,
2432 sponsor_authenticator_function_ref,
2433 };
2434
2435 let authenticators = match gas_owner_resolution_error.or(first_resolution_error) {
2440 Some(error) => MoveAuthenticatorsForExecution::ResolutionFailed {
2441 error,
2442 accounts,
2443 gas_owner: if deterministic_validation {
2444 resolved_authenticators
2445 .into_iter()
2446 .find(|resolved| resolved.authenticator.address() == gas_data.owner)
2447 .map(Box::new)
2448 } else {
2449 None
2450 },
2451 },
2452 None => MoveAuthenticatorsForExecution::Resolved(resolved_authenticators),
2453 };
2454
2455 epoch_store
2456 .executor()
2457 .authenticate_then_execute_transaction_to_effects(
2458 backing_store,
2459 protocol_config,
2460 self.metrics.limits_metrics.clone(),
2461 self.config
2462 .expensive_safety_check_config
2463 .enable_deep_per_tx_iota_conservation_check(),
2464 self.config.certificate_deny_config.certificate_deny_set(),
2465 &epoch_id,
2466 epoch_start_timestamp,
2467 gas_data,
2468 gas_status,
2469 authenticators,
2470 authenticator_and_tx_checked_input_objects,
2471 kind,
2472 signer,
2473 tx_digest,
2474 auth_context_data,
2475 &mut None,
2476 )
2477 };
2478
2479 fail_point_if!("cp_execution_nondeterminism", || {
2480 #[cfg(msim)]
2481 self.create_fail_state(transaction, epoch_store, &mut effects);
2482 });
2483
2484 let elapsed = prepare_transaction_start_time.elapsed().as_micros() as f64;
2485 if elapsed > 0.0 {
2486 self.metrics
2487 .prepare_cert_gas_latency_ratio
2488 .observe(effects.gas_cost_summary().computation_cost as f64 / elapsed);
2489 }
2490
2491 Ok((inner_temp_store, effects, execution_error_opt.err()))
2492 }
2493
2494 pub fn prepare_transaction_for_benchmark(
2495 &self,
2496 transaction: &VerifiedExecutableTransaction,
2497 input_objects: InputObjects,
2498 epoch_store: &Arc<AuthorityPerEpochStore>,
2499 ) -> IotaResult<(
2500 InnerTemporaryStore,
2501 TransactionEffects,
2502 Option<ExecutionError>,
2503 )> {
2504 let lock = RwLock::new(epoch_store.epoch());
2505 let execution_guard = lock.try_read().unwrap();
2506
2507 self.execute_transaction(
2508 &execution_guard,
2509 transaction,
2510 input_objects,
2511 vec![],
2512 epoch_store,
2513 )
2514 }
2515
2516 pub fn simulate_transaction(
2549 &self,
2550 transaction: Transaction,
2551 checks: VmChecks,
2552 ) -> IotaResult<SimulateTransactionResult> {
2553 let epoch_store = self.load_epoch_store_one_call_per_task();
2554 self.simulate_transaction_in_epoch(&epoch_store, transaction, checks)
2555 }
2556
2557 #[instrument("simulate_tx", level = "trace", skip_all)]
2571 pub fn simulate_transaction_in_epoch(
2572 &self,
2573 epoch_store: &AuthorityPerEpochStore,
2574 transaction: Transaction,
2575 checks: VmChecks,
2576 ) -> IotaResult<SimulateTransactionResult> {
2577 if !self.is_fullnode(epoch_store) {
2578 return Err(IotaError::UnsupportedFeature {
2579 error: "simulate is only supported on fullnodes".to_string(),
2580 });
2581 }
2582
2583 self.simulate_transaction_inner(epoch_store, transaction, checks)
2584 }
2585
2586 pub fn simulate_transaction_for_benchmark(
2590 &self,
2591 transaction: Transaction,
2592 checks: VmChecks,
2593 ) -> IotaResult<SimulateTransactionResult> {
2594 let epoch_store = self.load_epoch_store_one_call_per_task();
2595 self.simulate_transaction_inner(&epoch_store, transaction, checks)
2596 }
2597
2598 #[instrument(level = "trace", skip_all)]
2599 fn simulate_transaction_inner(
2600 &self,
2601 epoch_store: &AuthorityPerEpochStore,
2602 mut transaction: Transaction,
2603 checks: VmChecks,
2604 ) -> IotaResult<SimulateTransactionResult> {
2605 if transaction.kind().is_system() {
2606 return Err(IotaError::UnsupportedFeature {
2607 error: "simulate does not support system transactions".to_string(),
2608 });
2609 }
2610
2611 transaction.check_serialized_size(epoch_store.protocol_config())?;
2612
2613 transaction.validity_check_no_gas_check(epoch_store.protocol_config())?;
2617
2618 transaction.check_gas_payment_size(epoch_store.protocol_config())?;
2622
2623 let input_object_kinds = transaction.input_objects()?;
2624 let receiving_object_refs = transaction.receiving_objects();
2625
2626 iota_transaction_checks::deny::check_transaction_for_validation(
2629 &transaction,
2630 &[],
2631 &input_object_kinds,
2632 &receiving_object_refs,
2633 &self.config.transaction_deny_config,
2634 self.get_backing_package_store().as_ref(),
2635 )?;
2636
2637 let (mut input_objects, receiving_objects) = self.input_loader.read_objects_for_signing(
2639 None,
2641 &input_object_kinds,
2642 &receiving_object_refs,
2643 epoch_store.epoch(),
2644 )?;
2645
2646 let mock_gas_id = if transaction.gas().is_empty() {
2648 let mock_gas_object = mock_simulation_gas_coin(transaction.gas_data().owner);
2649 let mock_gas_object_ref = mock_gas_object.object_ref();
2650 transaction.gas_data_mut().objects = vec![mock_gas_object_ref];
2651 input_objects.push(ObjectReadResult::new_from_gas_object(&mock_gas_object));
2652 Some(mock_gas_object.id())
2653 } else {
2654 None
2655 };
2656
2657 let protocol_config = epoch_store.protocol_config();
2658
2659 iota_types::gas::fill_in_unset_simulation_gas(
2660 &mut transaction,
2661 &input_objects,
2662 epoch_store.reference_gas_price(),
2663 protocol_config,
2664 );
2665
2666 let authenticator_gas_budget = 0;
2669
2670 let (gas_status, checked_input_objects) = if checks.enabled() {
2673 iota_transaction_checks::check_transaction_input(
2674 protocol_config,
2675 epoch_store.reference_gas_price(),
2676 &transaction,
2677 input_objects,
2678 &receiving_objects,
2679 &self.metrics.bytecode_verifier_metrics,
2680 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2681 authenticator_gas_budget,
2682 )?
2683 } else {
2684 iota_types::gas::check_gas_coins_cover_budget_in_simulation(
2690 &input_objects,
2691 transaction.gas(),
2692 transaction.gas_budget(),
2693 )?;
2694
2695 let checked_input_objects = iota_transaction_checks::check_simulation_input(
2696 protocol_config,
2697 transaction.kind(),
2698 input_objects,
2699 receiving_objects,
2700 )?;
2701
2702 iota_transaction_checks::check_non_system_packages_to_be_published(
2708 &transaction,
2709 protocol_config,
2710 &self.metrics.bytecode_verifier_metrics,
2711 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2712 )?;
2713
2714 let gas_status = IotaGasStatus::new(
2715 transaction.gas_budget(),
2716 transaction.gas_price(),
2717 epoch_store.reference_gas_price(),
2718 protocol_config,
2719 )?;
2720
2721 (gas_status, checked_input_objects)
2722 };
2723
2724 let executor = iota_execution::executor(
2726 protocol_config,
2727 true, None,
2729 )
2730 .expect("Creating an executor should not fail here");
2731
2732 let (kind, signer, gas_data) = transaction.execution_parts();
2734 let (inner_temp_store, _, effects, execution_result) = executor.dev_inspect_transaction(
2735 self.get_backing_store().as_ref(),
2736 protocol_config,
2737 self.metrics.limits_metrics.clone(),
2738 false, self.config.certificate_deny_config.certificate_deny_set(),
2740 &epoch_store.epoch_start_config().epoch_data().epoch_id(),
2741 epoch_store
2742 .epoch_start_config()
2743 .epoch_data()
2744 .epoch_start_timestamp(),
2745 checked_input_objects,
2746 gas_data,
2747 gas_status,
2748 kind,
2749 signer,
2750 transaction.digest(),
2751 checks.disabled(),
2752 );
2753
2754 let mut input_objects = inner_temp_store.input_objects;
2755 iota_types::storage::extend_input_objects_with_loaded_runtime_objects(
2756 &mut input_objects,
2757 &effects,
2758 &inner_temp_store.loaded_runtime_objects,
2759 self.get_backing_store().as_object_store(),
2760 );
2761
2762 Ok(SimulateTransactionResult {
2763 input_objects,
2764 output_objects: inner_temp_store.written,
2765 events: effects.events_digest().map(|_| inner_temp_store.events),
2766 effects,
2767 execution_result,
2768 suggested_gas_price: self
2769 .congestion_tracker
2770 .get_prediction_suggested_gas_price(&transaction),
2771 mock_gas_id,
2772 gas_data: transaction.gas_data().clone(),
2773 })
2774 }
2775
2776 pub fn reference_gas_price_for_testing(&self) -> Result<u64, anyhow::Error> {
2778 let epoch_store = self.epoch_store_for_testing();
2779 Ok(epoch_store.reference_gas_price())
2780 }
2781
2782 #[instrument(level = "trace", skip_all)]
2783 pub fn try_is_tx_already_executed(&self, digest: &TransactionDigest) -> IotaResult<bool> {
2784 self.get_transaction_cache_reader()
2785 .try_is_tx_already_executed(digest)
2786 }
2787
2788 pub fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
2790 self.try_is_tx_already_executed(digest)
2791 .expect("storage access failed")
2792 }
2793
2794 #[instrument(level = "debug", skip_all, err)]
2796 fn index_tx(
2797 &self,
2798 indexes: &IndexStore,
2799 digest: &TransactionDigest,
2800 transaction: &VerifiedExecutableTransaction,
2802 effects: &TransactionEffects,
2803 events: &TransactionEvents,
2804 timestamp_ms: u64,
2805 tx_coins: Option<TxCoins>,
2806 written: &WrittenObjects,
2807 inner_temporary_store: &InnerTemporaryStore,
2808 epoch_store: &Arc<AuthorityPerEpochStore>,
2809 ) -> IotaResult<u64> {
2810 let changes = self
2811 .process_object_index(effects, written, inner_temporary_store, epoch_store)
2812 .tap_err(|e| warn!(tx_digest=?digest, "Failed to process object index, index_tx is skipped: {e}"))?;
2813
2814 indexes.index_tx(
2815 transaction.data().transaction().sender(),
2816 transaction
2817 .data()
2818 .transaction()
2819 .input_objects()?
2820 .iter()
2821 .map(|o| o.object_id()),
2822 effects
2823 .all_changed_objects()
2824 .into_iter()
2825 .map(|(changed, _kind)| (*changed.reference(), *changed.owner())),
2826 transaction
2827 .data()
2828 .transaction()
2829 .move_calls()
2830 .into_iter()
2831 .map(|(package, module, function)| {
2832 (*package, module.to_owned(), function.to_owned())
2833 }),
2834 events,
2835 changes,
2836 digest,
2837 timestamp_ms,
2838 tx_coins,
2839 )
2840 }
2841
2842 #[cfg(msim)]
2843 fn create_fail_state(
2844 &self,
2845 transaction: &VerifiedExecutableTransaction,
2846 epoch_store: &Arc<AuthorityPerEpochStore>,
2847 effects: &mut TransactionEffects,
2848 ) {
2849 use std::cell::RefCell;
2850
2851 use iota_types::effects::TransactionEffectsAPIForTesting;
2852 thread_local! {
2853 static FAIL_STATE: RefCell<(u64, HashSet<AuthorityName>)> = RefCell::new((0, HashSet::new()));
2854 }
2855 if !transaction.data().transaction().is_system_tx() {
2856 let committee = epoch_store.committee();
2857 let cur_stake = (**committee).weight(&self.name);
2858 if cur_stake > 0 {
2859 FAIL_STATE.with_borrow_mut(|fail_state| {
2860 if fail_state.0 < committee.validity_threshold() {
2862 fail_state.0 += cur_stake;
2863 fail_state.1.insert(self.name);
2864 }
2865
2866 if fail_state.1.contains(&self.name) {
2867 info!("cp_exec failing tx");
2868 effects.gas_cost_summary_mut_for_testing().computation_cost += 1;
2869 }
2870 });
2871 }
2872 }
2873 }
2874
2875 fn process_object_index(
2876 &self,
2877 effects: &TransactionEffects,
2878 written: &WrittenObjects,
2879 inner_temporary_store: &InnerTemporaryStore,
2880 epoch_store: &Arc<AuthorityPerEpochStore>,
2881 ) -> IotaResult<ObjectIndexChanges> {
2882 let mut layout_resolver =
2883 epoch_store
2884 .executor()
2885 .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
2886 inner_temporary_store,
2887 self.get_backing_package_store(),
2888 )));
2889
2890 let modified_at_version = effects
2891 .modified_at_versions()
2892 .into_iter()
2893 .map(|modified| (*modified.object_id(), modified.version()))
2894 .collect::<HashMap<_, _>>();
2895
2896 let tx_digest = effects.transaction_digest();
2897 let mut deleted_owners = vec![];
2898 let mut deleted_dynamic_fields = vec![];
2899 for object_ref in effects.deleted().into_iter().chain(effects.wrapped()) {
2900 let old_version = modified_at_version.get(&object_ref.object_id).unwrap();
2901 match self.get_owner_at_version(&object_ref.object_id, *old_version).unwrap_or_else(
2904 |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)
2905 ) {
2906 Owner::Address(addr) => deleted_owners.push((addr, object_ref.object_id)),
2907 Owner::Object(object_id) => {
2908 deleted_dynamic_fields.push((object_id, object_ref.object_id))
2909 }
2910 _ => {}
2911 }
2912 }
2913
2914 let mut new_owners = vec![];
2915 let mut new_dynamic_fields = vec![];
2916
2917 for (changed, kind) in effects.all_changed_objects() {
2918 let (oref, owner) = (*changed.reference(), *changed.owner());
2919 let id = &oref.object_id;
2920 if let WriteKind::Mutate = kind {
2923 let Some(old_version) = modified_at_version.get(id) else {
2924 panic!(
2925 "tx_digest={tx_digest}, error processing object owner index, cannot find modified at version for mutated object [{id}]."
2926 );
2927 };
2928 let Some(old_object) = self
2931 .get_object_store()
2932 .try_get_object_by_key(id, *old_version)?
2933 else {
2934 panic!(
2935 "tx_digest={tx_digest}, error processing object owner index, cannot find owner for object {id} at version {old_version:?}"
2936 );
2937 };
2938 if old_object.owner != owner {
2939 match old_object.owner {
2940 Owner::Address(addr) => {
2941 deleted_owners.push((addr, *id));
2942 }
2943 Owner::Object(object_id) => deleted_dynamic_fields.push((object_id, *id)),
2944 _ => {}
2945 }
2946 }
2947 }
2948
2949 match owner {
2950 Owner::Address(addr) => {
2951 let new_object = written.get(id).unwrap_or_else(
2954 || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2955 );
2956 assert_eq!(
2957 new_object.version(),
2958 oref.version,
2959 "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2960 tx_digest,
2961 id,
2962 new_object.version(),
2963 oref.version
2964 );
2965
2966 let object_type = new_object
2967 .data
2968 .opt_object_type()
2969 .map(|ty| ObjectType::Struct(ty.clone()))
2970 .unwrap_or(ObjectType::Package);
2971
2972 new_owners.push((
2973 (addr, *id),
2974 ObjectInfo {
2975 object_id: *id,
2976 version: oref.version,
2977 digest: oref.digest,
2978 object_type,
2979 owner,
2980 previous_transaction: *effects.transaction_digest(),
2981 },
2982 ));
2983 }
2984 Owner::Object(owner) => {
2985 let new_object = written.get(id).unwrap_or_else(
2986 || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2987 );
2988 assert_eq!(
2989 new_object.version(),
2990 oref.version,
2991 "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2992 tx_digest,
2993 id,
2994 new_object.version(),
2995 oref.version
2996 );
2997
2998 let Some(df_info) = self
2999 .try_create_dynamic_field_info(new_object, written, layout_resolver.as_mut())
3000 .unwrap_or_else(|e| {
3001 error!(
3002 "try_create_dynamic_field_info should not fail, {}, new_object={}, new_object_type={}",
3003 e,
3004 new_object.id(),
3005 ObjectType::from(new_object)
3006 );
3007 None
3008 }
3009 )
3010 else {
3011 continue;
3013 };
3014 new_dynamic_fields.push(((owner, *id), df_info))
3015 }
3016 _ => {}
3017 }
3018 }
3019
3020 Ok(ObjectIndexChanges {
3021 deleted_owners,
3022 deleted_dynamic_fields,
3023 new_owners,
3024 new_dynamic_fields,
3025 })
3026 }
3027
3028 fn try_create_dynamic_field_info(
3029 &self,
3030 o: &Object,
3031 written: &WrittenObjects,
3032 resolver: &mut dyn LayoutResolver,
3033 ) -> IotaResult<Option<DynamicFieldInfo>> {
3034 let Some(move_object) = o.data.as_opt_struct().cloned() else {
3036 return Ok(None);
3037 };
3038
3039 if !move_object.struct_tag().is_dynamic_field() {
3041 return Ok(None);
3042 }
3043
3044 let layout = match resolver.get_annotated_layout(move_object.struct_tag()) {
3045 Ok(annotated_layout) => annotated_layout.into_layout(),
3046 Err(e) => {
3047 error!(
3048 "unable to load layout for type `{:?}`: {e}",
3049 move_object.struct_tag()
3050 );
3051 return Ok(None);
3052 }
3053 };
3054
3055 let field =
3056 DFV::FieldVisitor::deserialize(move_object.contents(), &layout).map_err(|e| {
3057 IotaError::ObjectDeserialization {
3058 error: e.to_string(),
3059 }
3060 })?;
3061
3062 let type_ = field.kind;
3063 let name_type: TypeTag = type_tag_core_to_sdk(&field.name_layout.into());
3064 let bcs_name = field.name_bytes.to_owned();
3065
3066 let name_value = BoundedVisitor::deserialize_value(field.name_bytes, field.name_layout)
3067 .map_err(|e| {
3068 warn!("{e}");
3069 IotaError::ObjectDeserialization {
3070 error: e.to_string(),
3071 }
3072 })?;
3073
3074 let name = DynamicFieldName {
3075 type_tag: name_type,
3076 value: IotaMoveValue::from(name_value).to_json_value(),
3077 };
3078
3079 let value_metadata = field.value_metadata().map_err(|e| {
3080 warn!("{e}");
3081 IotaError::ObjectDeserialization {
3082 error: e.to_string(),
3083 }
3084 })?;
3085
3086 Ok(Some(match value_metadata {
3087 DFV::ValueMetadata::DynamicField(object_type) => DynamicFieldInfo {
3088 name,
3089 bcs_name,
3090 type_,
3091 object_type: object_type.to_canonical_string(true),
3092 object_id: o.id(),
3093 version: o.version(),
3094 digest: o.digest(),
3095 },
3096
3097 DFV::ValueMetadata::DynamicObjectField(object_id) => {
3098 let (version, digest, object_type) = if let Some(object) = written.get(&object_id) {
3103 (
3104 object.version(),
3105 object.digest(),
3106 object.data.opt_object_type().unwrap().clone(),
3107 )
3108 } else {
3109 let object = self
3111 .get_object_store()
3112 .try_get_object_by_key(&object_id, o.version())?
3113 .ok_or_else(|| UserInputError::ObjectNotFound {
3114 object_id,
3115 version: Some(o.version()),
3116 })?;
3117 let version = object.version();
3118 let digest = object.digest();
3119 let object_type = object.data.opt_object_type().unwrap().clone();
3120 (version, digest, object_type)
3121 };
3122
3123 DynamicFieldInfo {
3124 name,
3125 bcs_name,
3126 type_,
3127 object_type: object_type.to_string(),
3128 object_id,
3129 version,
3130 digest,
3131 }
3132 }
3133 }))
3134 }
3135
3136 #[instrument(level = "trace", skip_all, err)]
3137 fn post_process_one_tx(
3138 &self,
3139 transaction: &VerifiedExecutableTransaction,
3140 effects: &TransactionEffects,
3141 inner_temporary_store: &InnerTemporaryStore,
3142 epoch_store: &Arc<AuthorityPerEpochStore>,
3143 ) -> IotaResult {
3144 if self.indexes.is_none() {
3145 return Ok(());
3146 }
3147
3148 let _scope = monitored_scope("Execution::post_process_one_tx");
3149
3150 let tx_digest = transaction.digest();
3151 let timestamp_ms = Self::unixtime_now_ms();
3152 let events = &inner_temporary_store.events;
3153 let written = &inner_temporary_store.written;
3154 let tx_coins = self.fullnode_only_get_tx_coins_for_indexing(
3155 effects,
3156 inner_temporary_store,
3157 epoch_store,
3158 );
3159
3160 if let Some(indexes) = &self.indexes {
3162 let _ = self
3163 .index_tx(
3164 indexes.as_ref(),
3165 tx_digest,
3166 transaction,
3167 effects,
3168 events,
3169 timestamp_ms,
3170 tx_coins,
3171 written,
3172 inner_temporary_store,
3173 epoch_store,
3174 )
3175 .tap_ok(|_| self.metrics.post_processing_total_tx_indexed.inc())
3176 .tap_err(|e| error!(?tx_digest, "Post processing - Couldn't index tx: {e}"))
3177 .expect("Indexing tx should not fail");
3178
3179 let effects: IotaTransactionBlockEffects = effects.clone().try_into()?;
3180 let events = self.make_transaction_block_events(
3181 events.clone(),
3182 *tx_digest,
3183 timestamp_ms,
3184 epoch_store,
3185 inner_temporary_store,
3186 )?;
3187 self.subscription_handler
3189 .process_tx(transaction.data().transaction(), &effects, &events)
3190 .tap_ok(|_| {
3191 self.metrics
3192 .post_processing_total_tx_had_event_processed
3193 .inc()
3194 })
3195 .tap_err(|e| {
3196 warn!(
3197 ?tx_digest,
3198 "Post processing - Couldn't process events for tx: {}", e
3199 )
3200 })?;
3201
3202 self.metrics
3203 .post_processing_total_events_emitted
3204 .inc_by(events.data.len() as u64);
3205 };
3206 Ok(())
3207 }
3208
3209 fn make_transaction_block_events(
3210 &self,
3211 transaction_events: TransactionEvents,
3212 digest: TransactionDigest,
3213 timestamp_ms: u64,
3214 epoch_store: &Arc<AuthorityPerEpochStore>,
3215 inner_temporary_store: &InnerTemporaryStore,
3216 ) -> IotaResult<IotaTransactionBlockEvents> {
3217 let mut layout_resolver =
3218 epoch_store
3219 .executor()
3220 .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
3221 inner_temporary_store,
3222 self.get_backing_package_store(),
3223 )));
3224 IotaTransactionBlockEvents::try_from(
3225 transaction_events,
3226 digest,
3227 Some(timestamp_ms),
3228 layout_resolver.as_mut(),
3229 )
3230 }
3231
3232 pub fn unixtime_now_ms() -> u64 {
3233 let now = SystemTime::now()
3234 .duration_since(UNIX_EPOCH)
3235 .expect("Time went backwards")
3236 .as_millis();
3237 u64::try_from(now).expect("Travelling in time machine")
3238 }
3239
3240 #[instrument(level = "trace", skip_all)]
3241 pub async fn handle_transaction_info_request(
3242 &self,
3243 request: TransactionInfoRequest,
3244 ) -> IotaResult<TransactionInfoResponse> {
3245 let epoch_store = self.load_epoch_store_one_call_per_task();
3246 let (transaction, status) = self
3247 .get_transaction_status(&request.transaction_digest, &epoch_store)?
3248 .ok_or(IotaError::TransactionNotFound {
3249 digest: request.transaction_digest,
3250 })?;
3251 Ok(TransactionInfoResponse {
3252 transaction,
3253 status,
3254 })
3255 }
3256
3257 #[instrument(level = "trace", skip_all)]
3258 pub async fn handle_object_info_request(
3259 &self,
3260 request: ObjectInfoRequest,
3261 ) -> IotaResult<ObjectInfoResponse> {
3262 let epoch_store = self.load_epoch_store_one_call_per_task();
3263
3264 let requested_object_seq = match request.request_kind {
3265 ObjectInfoRequestKind::LatestObjectInfo => {
3266 self.try_get_object_or_tombstone(request.object_id)?
3267 .ok_or_else(|| {
3268 IotaError::from(UserInputError::ObjectNotFound {
3269 object_id: request.object_id,
3270 version: None,
3271 })
3272 })?
3273 .version
3274 }
3275 ObjectInfoRequestKind::PastObjectInfoDebug(seq) => seq,
3276 };
3277
3278 let object = self
3279 .get_object_store()
3280 .try_get_object_by_key(&request.object_id, requested_object_seq)?
3281 .ok_or_else(|| {
3282 IotaError::from(UserInputError::ObjectNotFound {
3283 object_id: request.object_id,
3284 version: Some(requested_object_seq),
3285 })
3286 })?;
3287
3288 let layout = if let (LayoutGenerationOption::Generate, Some(move_obj)) =
3289 (request.generate_layout, object.data.as_opt_struct())
3290 {
3291 Some(into_struct_layout(
3292 epoch_store
3293 .executor()
3294 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
3295 .get_annotated_layout(move_obj.struct_tag())?,
3296 )?)
3297 } else {
3298 None
3299 };
3300
3301 let lock = if !object.is_address_owned() {
3302 None
3304 } else {
3305 self.get_transaction_lock(&object.object_ref(), &epoch_store)?
3306 .map(|s| s.into_inner())
3307 };
3308
3309 Ok(ObjectInfoResponse {
3310 object,
3311 layout,
3312 lock_for_debugging: lock,
3313 })
3314 }
3315
3316 #[instrument(level = "trace", skip_all)]
3317 pub fn handle_checkpoint_request(
3318 &self,
3319 request: &CheckpointRequest,
3320 ) -> IotaResult<CheckpointResponse> {
3321 let summary = if request.certified {
3322 let summary = match request.sequence_number {
3323 Some(seq) => self
3324 .checkpoint_store
3325 .get_checkpoint_by_sequence_number(seq)?,
3326 None => self.checkpoint_store.get_latest_certified_checkpoint()?,
3327 }
3328 .map(|v| v.into_inner());
3329 summary.map(CheckpointSummaryResponse::Certified)
3330 } else {
3331 let summary = match request.sequence_number {
3332 Some(seq) => self.checkpoint_store.get_locally_computed_checkpoint(seq)?,
3333 None => self
3334 .checkpoint_store
3335 .get_latest_locally_computed_checkpoint()?,
3336 };
3337 summary.map(CheckpointSummaryResponse::Pending)
3338 };
3339 let contents = match &summary {
3340 Some(s) => self
3341 .checkpoint_store
3342 .get_checkpoint_contents(&s.contents_digest())?,
3343 None => None,
3344 };
3345 Ok(CheckpointResponse {
3346 checkpoint: summary,
3347 contents,
3348 })
3349 }
3350
3351 fn check_protocol_version(
3352 supported_protocol_versions: SupportedProtocolVersions,
3353 current_version: ProtocolVersion,
3354 ) {
3355 info!("current protocol version is now {:?}", current_version);
3356 info!("supported versions are: {:?}", supported_protocol_versions);
3357 if !supported_protocol_versions.is_version_supported(current_version) {
3358 let msg = format!(
3359 "Unsupported protocol version. The network is at {current_version:?}, but this IotaNode only supports: {supported_protocol_versions:?}. Shutting down.",
3360 );
3361
3362 error!("{}", msg);
3363 eprintln!("{msg}");
3364
3365 #[cfg(not(msim))]
3366 std::process::exit(1);
3367
3368 #[cfg(msim)]
3369 iota_simulator::task::shutdown_current_node();
3370 }
3371 }
3372
3373 #[expect(clippy::disallowed_methods)] pub async fn new(
3375 name: AuthorityName,
3376 secret: StableSyncAuthoritySigner,
3377 supported_protocol_versions: SupportedProtocolVersions,
3378 store: Arc<AuthorityStore>,
3379 execution_cache_trait_pointers: ExecutionCacheTraitPointers,
3380 epoch_store: Arc<AuthorityPerEpochStore>,
3381 committee_store: Arc<CommitteeStore>,
3382 indexes: Option<Arc<IndexStore>>,
3383 grpc_indexes_store: Option<Arc<GrpcIndexesStore>>,
3384 checkpoint_store: Arc<CheckpointStore>,
3385 prometheus_registry: &Registry,
3386 genesis_objects: &[Object],
3387 config: NodeConfig,
3388 validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
3389 chain_identifier: ChainIdentifier,
3390 checkpoint_progress_tracker: Option<Arc<CheckpointProgressTracker>>,
3391 policy_config: Option<PolicyConfig>,
3392 epoch_end_db_snapshots: Option<EpochEndDbSnapshotHandle>,
3393 ) -> Arc<Self> {
3394 Self::check_protocol_version(supported_protocol_versions, epoch_store.protocol_version());
3395
3396 epoch_store.set_effects_store(
3399 execution_cache_trait_pointers
3400 .transaction_cache_reader
3401 .clone(),
3402 );
3403
3404 let metrics = Arc::new(AuthorityMetrics::new(prometheus_registry));
3405 let (tx_ready_transactions, rx_ready_transactions) = unbounded_channel();
3406 let execution_scheduler = Arc::new(ExecutionSchedulerWrapper::new(
3407 execution_cache_trait_pointers.object_cache_reader.clone(),
3408 execution_cache_trait_pointers
3409 .transaction_cache_reader
3410 .clone(),
3411 tx_ready_transactions,
3412 &epoch_store,
3413 metrics.clone(),
3414 ));
3415 let (tx_execution_shutdown, rx_execution_shutdown) = oneshot::channel();
3416
3417 let authority_per_epoch_pruner = AuthorityPerEpochStorePruner::new(
3418 epoch_store.get_parent_path(),
3419 config
3420 .authority_store_pruning_config
3421 .num_latest_epoch_dbs_to_retain,
3422 )
3423 .await;
3424 let pruner = AuthorityStorePruner::new(
3425 store.perpetual_tables.clone(),
3426 checkpoint_store.clone(),
3427 grpc_indexes_store.clone(),
3428 indexes.clone(),
3429 config.authority_store_pruning_config.clone(),
3430 epoch_store.committee().authority_exists(&name),
3431 epoch_store.epoch_start_state().epoch_duration_ms(),
3432 prometheus_registry,
3433 checkpoint_progress_tracker.clone(),
3434 epoch_store.object_pruning_limit(),
3435 );
3436 let input_loader =
3437 TransactionInputLoader::new(execution_cache_trait_pointers.object_cache_reader.clone());
3438 let epoch = epoch_store.epoch();
3439 let rgp = epoch_store.reference_gas_price();
3440 let traffic_controller_metrics =
3441 Arc::new(TrafficControllerMetrics::new(prometheus_registry));
3442 let traffic_controller = policy_config.map(|policy_config| {
3443 Arc::new(TrafficController::init(
3444 policy_config,
3445 traffic_controller_metrics,
3446 ))
3447 });
3448 let state = Arc::new(AuthorityState {
3449 name,
3450 secret,
3451 execution_lock: RwLock::new(epoch),
3452 epoch_store: ArcSwap::new(epoch_store.clone()),
3453 input_loader,
3454 execution_cache_trait_pointers,
3455 indexes,
3456 grpc_indexes_store,
3457 subscription_handler: Arc::new(SubscriptionHandler::new(prometheus_registry)),
3458 checkpoint_store,
3459 committee_store,
3460 execution_scheduler,
3461 tx_execution_shutdown: Mutex::new(Some(tx_execution_shutdown)),
3462 metrics,
3463 pruner,
3464 authority_per_epoch_pruner,
3465 checkpoint_progress_tracker,
3466 config,
3467 overload_info: AuthorityOverloadInfo::default(),
3468 validator_tx_finalizer,
3469 chain_identifier,
3470 congestion_tracker: Arc::new(CongestionTracker::new(rgp)),
3471 traffic_controller,
3472 epoch_end_db_snapshots,
3473 });
3474
3475 let authority_state = Arc::downgrade(&state);
3477 spawn_monitored_task!(execution_process(
3478 authority_state,
3479 rx_ready_transactions,
3480 rx_execution_shutdown,
3481 ));
3482 state
3484 .create_owner_index_if_empty(genesis_objects, &epoch_store)
3485 .expect("Error indexing genesis objects.");
3486
3487 state
3488 }
3489
3490 pub fn epoch_db_pruner(&self) -> &AuthorityPerEpochStorePruner {
3491 &self.authority_per_epoch_pruner
3492 }
3493
3494 pub fn get_object_cache_reader(&self) -> &Arc<dyn ObjectCacheRead> {
3496 &self.execution_cache_trait_pointers.object_cache_reader
3497 }
3498
3499 pub fn get_transaction_cache_reader(&self) -> &Arc<dyn TransactionCacheRead> {
3500 &self.execution_cache_trait_pointers.transaction_cache_reader
3501 }
3502
3503 pub fn get_cache_writer(&self) -> &Arc<dyn ExecutionCacheWrite> {
3504 &self.execution_cache_trait_pointers.cache_writer
3505 }
3506
3507 pub fn get_backing_store(&self) -> &Arc<dyn BackingStore + Send + Sync> {
3508 &self.execution_cache_trait_pointers.backing_store
3509 }
3510
3511 pub fn get_backing_package_store(&self) -> &Arc<dyn BackingPackageStore + Send + Sync> {
3512 &self.execution_cache_trait_pointers.backing_package_store
3513 }
3514
3515 pub fn get_object_store(&self) -> &Arc<dyn ObjectStore + Send + Sync> {
3516 &self.execution_cache_trait_pointers.object_store
3517 }
3518
3519 pub fn get_reconfig_api(&self) -> &Arc<dyn ExecutionCacheReconfigAPI> {
3520 &self.execution_cache_trait_pointers.reconfig_api
3521 }
3522
3523 pub fn get_global_state_hash_store(&self) -> &Arc<dyn GlobalStateHashStore> {
3524 &self.execution_cache_trait_pointers.global_state_hash_store
3525 }
3526
3527 pub fn get_checkpoint_cache(&self) -> &Arc<dyn CheckpointCache> {
3528 &self.execution_cache_trait_pointers.checkpoint_cache
3529 }
3530
3531 pub fn get_state_sync_store(&self) -> &Arc<dyn StateSyncAPI> {
3532 &self.execution_cache_trait_pointers.state_sync_store
3533 }
3534
3535 pub fn get_cache_commit(&self) -> &Arc<dyn ExecutionCacheCommit> {
3536 &self.execution_cache_trait_pointers.cache_commit
3537 }
3538
3539 pub fn database_for_testing(&self) -> Arc<AuthorityStore> {
3540 self.execution_cache_trait_pointers
3541 .testing_api
3542 .database_for_testing()
3543 }
3544
3545 #[cfg(test)]
3548 pub fn evict_committed_object_for_testing(&self, id: &ObjectId) {
3549 self.execution_cache_trait_pointers
3550 .testing_api
3551 .evict_committed_object_for_testing(id)
3552 }
3553
3554 pub async fn prune_checkpoints_for_eligible_epochs_for_testing(
3555 &self,
3556 config: NodeConfig,
3557 metrics: Arc<AuthorityStorePruningMetrics>,
3558 ) -> anyhow::Result<()> {
3559 AuthorityStorePruner::prune_checkpoints_for_eligible_epochs(
3560 &self.database_for_testing().perpetual_tables,
3561 &self.checkpoint_store,
3562 self.grpc_indexes_store.as_deref(),
3563 config.authority_store_pruning_config,
3564 metrics,
3565 EPOCH_DURATION_MS_FOR_TESTING,
3566 self.checkpoint_progress_tracker.as_ref(),
3567 )
3568 .await
3569 }
3570
3571 pub fn execution_scheduler(&self) -> &Arc<ExecutionSchedulerWrapper> {
3572 &self.execution_scheduler
3573 }
3574
3575 pub fn uses_execution_scheduler(&self) -> bool {
3578 self.execution_scheduler.uses_execution_scheduler()
3579 }
3580
3581 fn create_owner_index_if_empty(
3582 &self,
3583 genesis_objects: &[Object],
3584 epoch_store: &Arc<AuthorityPerEpochStore>,
3585 ) -> IotaResult {
3586 let Some(index_store) = &self.indexes else {
3587 return Ok(());
3588 };
3589 if !index_store.is_empty() {
3590 return Ok(());
3591 }
3592
3593 let mut new_owners = vec![];
3594 let mut new_dynamic_fields = vec![];
3595 let mut layout_resolver = epoch_store
3596 .executor()
3597 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()));
3598 for o in genesis_objects.iter() {
3599 match o.owner {
3600 Owner::Address(addr) => {
3601 new_owners.push(((addr, o.id()), ObjectInfo::new(&o.object_ref(), o)))
3602 }
3603 Owner::Object(object_id) => {
3604 let id = o.id();
3605 let info = match self.try_create_dynamic_field_info(
3606 o,
3607 &BTreeMap::new(),
3608 layout_resolver.as_mut(),
3609 ) {
3610 Ok(Some(info)) => info,
3611 Ok(None) => continue,
3612 Err(IotaError::UserInput {
3613 error:
3614 UserInputError::ObjectNotFound {
3615 object_id: not_found_id,
3616 version,
3617 },
3618 }) => {
3619 warn!(
3620 ?not_found_id,
3621 ?version,
3622 object_owner=?object_id,
3623 field=?id,
3624 "Skipping dynamic field: referenced genesis object not found"
3625 );
3626 continue;
3627 }
3628 Err(e) => return Err(e),
3629 };
3630 new_dynamic_fields.push(((object_id, id), info));
3631 }
3632 _ => {}
3633 }
3634 }
3635
3636 index_store.insert_genesis_objects(ObjectIndexChanges {
3637 deleted_owners: vec![],
3638 deleted_dynamic_fields: vec![],
3639 new_owners,
3640 new_dynamic_fields,
3641 })
3642 }
3643
3644 pub fn execution_lock_for_executable_transaction(
3648 &self,
3649 transaction: &VerifiedExecutableTransaction,
3650 ) -> IotaResult<ExecutionLockReadGuard<'_>> {
3651 let lock = self
3652 .execution_lock
3653 .try_read()
3654 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)?;
3655 if *lock == transaction.auth_sig().epoch() {
3656 Ok(lock)
3657 } else {
3658 Err(IotaError::WrongEpoch {
3659 expected_epoch: *lock,
3660 actual_epoch: transaction.auth_sig().epoch(),
3661 })
3662 }
3663 }
3664
3665 pub fn execution_lock_for_signing(&self) -> IotaResult<ExecutionLockReadGuard<'_>> {
3671 self.execution_lock
3672 .try_read()
3673 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)
3674 }
3675
3676 pub async fn execution_lock_for_reconfiguration(&self) -> ExecutionLockWriteGuard<'_> {
3677 self.execution_lock.write().await
3678 }
3679
3680 pub(crate) fn check_transaction_deny_rules_consistency(
3690 &self,
3691 cur_epoch_store: &AuthorityPerEpochStore,
3692 epoch_start_configuration: &EpochStartConfiguration,
3693 ) {
3694 if self.is_fullnode(cur_epoch_store) {
3695 return;
3696 }
3697 let Some(walked_deny_rules) = epoch_start_configuration.transaction_deny_rules_state()
3698 else {
3699 if cur_epoch_store
3700 .epoch_start_config()
3701 .transaction_deny_rules_obj_initial_shared_version()
3702 .is_some()
3703 {
3704 fatal!(
3705 "TransactionDenyRules object existed in epoch {} but is missing from the \
3706 state walked for the next epoch — the local store is corrupted; restore or \
3707 state-sync before rejoining",
3708 cur_epoch_store.epoch(),
3709 );
3710 }
3711 return;
3712 };
3713 if cur_epoch_store
3717 .get_reconfig_state_read_lock_guard()
3718 .should_accept_tx()
3719 {
3720 info!(
3721 "skipping the deny-rule mirror comparison: consensus did not close epoch {} on \
3722 this node",
3723 cur_epoch_store.epoch(),
3724 );
3725 return;
3726 }
3727 let mirrored_deny_rules = cur_epoch_store.get_mirrored_transaction_deny_rules();
3728 if *walked_deny_rules != *mirrored_deny_rules {
3729 debug_fatal!(
3730 "TransactionDenyRules object diverged from the mirrored state at the end of \
3731 epoch {}; continuing from the object (walked: {walked_deny_rules:?}, mirrored: \
3732 {mirrored_deny_rules:?})",
3733 cur_epoch_store.epoch(),
3734 );
3735 cur_epoch_store.metrics.deny_rule_mirror_divergence.set(1);
3736 }
3737 }
3738
3739 pub(crate) fn report_failed_deny_rule_update_execution(
3751 &self,
3752 transaction: &VerifiedExecutableTransaction,
3753 effects: &TransactionEffects,
3754 expected_effects_digest: Option<TransactionEffectsDigest>,
3755 epoch_store: &AuthorityPerEpochStore,
3756 ) {
3757 if !matches!(
3758 transaction.transaction().kind(),
3759 TransactionKind::TransactionDenyRulesUpdate(_)
3760 ) || effects.status().is_success()
3761 {
3762 return;
3763 }
3764 epoch_store
3765 .metrics
3766 .deny_rule_update_execution_failures
3767 .inc();
3768 if expected_effects_digest.is_some() {
3769 error!(
3770 digest = ?transaction.digest(),
3771 status = ?effects.status(),
3772 "TransactionDenyRulesUpdate failed execution; the object misses its delta until \
3773 the epoch boundary re-seeds the mirror"
3774 );
3775 return;
3776 }
3777 debug_fatal!(
3778 "TransactionDenyRulesUpdate failed execution; the object misses its delta until the \
3779 epoch boundary re-seeds the mirror (digest: {:?}, status: {:?})",
3780 transaction.digest(),
3781 effects.status(),
3782 );
3783 }
3784
3785 #[instrument(level = "error", skip_all)]
3786 pub async fn reconfigure(
3787 &self,
3788 cur_epoch_store: &AuthorityPerEpochStore,
3789 supported_protocol_versions: SupportedProtocolVersions,
3790 new_committee: Committee,
3791 epoch_start_configuration: EpochStartConfiguration,
3792 state_hasher: Arc<GlobalStateHasher>,
3793 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3794 epoch_supply_change: i64,
3795 epoch_last_checkpoint: CheckpointSequenceNumber,
3796 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
3797 Self::check_protocol_version(
3798 supported_protocol_versions,
3799 epoch_start_configuration
3800 .epoch_start_state()
3801 .protocol_version(),
3802 );
3803 self.metrics.reset_on_reconfigure();
3804 self.committee_store.insert_new_committee(&new_committee)?;
3805
3806 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3808
3809 cur_epoch_store.epoch_terminated().await;
3811
3812 let highest_locally_built_checkpoint_seq = self
3813 .checkpoint_store
3814 .get_latest_locally_computed_checkpoint()?
3815 .map(|c| c.sequence_number())
3816 .unwrap_or(0);
3817
3818 assert!(
3819 epoch_last_checkpoint >= highest_locally_built_checkpoint_seq,
3820 "expected {epoch_last_checkpoint} >= {highest_locally_built_checkpoint_seq}"
3821 );
3822
3823 self.revert_uncommitted_epoch_transactions(cur_epoch_store)
3829 .await?;
3830 self.get_reconfig_api()
3831 .clear_state_end_of_epoch(&execution_lock);
3832 self.check_system_consistency(
3833 cur_epoch_store,
3834 state_hasher,
3835 expensive_safety_check_config,
3836 epoch_supply_change,
3837 )?;
3838 self.check_transaction_deny_rules_consistency(cur_epoch_store, &epoch_start_configuration);
3839
3840 self.get_reconfig_api()
3841 .try_set_epoch_start_configuration(&epoch_start_configuration)?;
3842 self.hand_over_epoch_end_db_snapshot(cur_epoch_store.epoch())
3843 .await;
3844
3845 let new_epoch = new_committee.epoch;
3846 let new_epoch_store = self
3847 .reopen_epoch_db(
3848 cur_epoch_store,
3849 new_committee,
3850 epoch_start_configuration,
3851 expensive_safety_check_config,
3852 epoch_last_checkpoint,
3853 )
3854 .await?;
3855 assert_eq!(new_epoch_store.epoch(), new_epoch);
3856 match self.execution_scheduler.as_ref() {
3857 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3858 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3859 tm.reconfigure(new_epoch);
3860 }
3861 }
3862 *execution_lock = new_epoch;
3863 Ok(new_epoch_store)
3867 }
3868
3869 pub async fn reconfigure_for_testing(&self) {
3874 self.reconfigure_for_testing_impl(None).await;
3875 }
3876
3877 pub async fn reconfigure_for_testing_with_protocol_config(
3880 &self,
3881 protocol_config: ProtocolConfig,
3882 ) {
3883 self.reconfigure_for_testing_impl(Some(protocol_config))
3884 .await;
3885 }
3886
3887 async fn reconfigure_for_testing_impl(&self, protocol_config: Option<ProtocolConfig>) {
3888 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3889 let epoch_store = self.epoch_store_for_testing().clone();
3890 let protocol_config =
3894 protocol_config.unwrap_or_else(|| epoch_store.protocol_config().clone());
3895 let _guard =
3896 ProtocolConfig::apply_overrides_for_testing(move |_, _| protocol_config.clone());
3897 let new_epoch_store = epoch_store.new_at_next_epoch_for_testing(
3898 self.get_backing_package_store().clone(),
3899 &self.config.expensive_safety_check_config,
3900 self.checkpoint_store
3901 .get_epoch_last_checkpoint(epoch_store.epoch())
3902 .unwrap()
3903 .map(|c| c.sequence_number())
3904 .unwrap_or_default(),
3905 );
3906 let new_epoch = new_epoch_store.epoch();
3907 match self.execution_scheduler.as_ref() {
3908 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3909 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3910 tm.reconfigure(new_epoch);
3911 }
3912 }
3913 self.epoch_store.store(new_epoch_store);
3914 epoch_store.epoch_terminated().await;
3915 *execution_lock = new_epoch;
3916 }
3917
3918 #[instrument(level = "error", skip_all)]
3919 fn check_system_consistency(
3920 &self,
3921 cur_epoch_store: &AuthorityPerEpochStore,
3922 state_hasher: Arc<GlobalStateHasher>,
3923 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3924 epoch_supply_change: i64,
3925 ) -> IotaResult<()> {
3926 info!(
3927 "Performing iota conservation consistency check for epoch {}",
3928 cur_epoch_store.epoch()
3929 );
3930
3931 if cfg!(debug_assertions) {
3932 cur_epoch_store.check_all_executed_transactions_in_checkpoint();
3933 }
3934
3935 self.get_reconfig_api()
3936 .try_expensive_check_iota_conservation(cur_epoch_store, Some(epoch_supply_change))?;
3937
3938 if expensive_safety_check_config.enable_state_consistency_check() {
3940 info!(
3941 "Performing state consistency check for epoch {}",
3942 cur_epoch_store.epoch()
3943 );
3944 self.expensive_check_is_consistent_state(state_hasher, cur_epoch_store);
3945 }
3946
3947 if expensive_safety_check_config.enable_secondary_index_checks() {
3948 if let Some(indexes) = self.indexes.clone() {
3949 verify_indexes(self.get_global_state_hash_store().as_ref(), indexes)
3950 .expect("secondary indexes are inconsistent");
3951 }
3952 }
3953
3954 Ok(())
3955 }
3956
3957 fn expensive_check_is_consistent_state(
3958 &self,
3959 state_hasher: Arc<GlobalStateHasher>,
3960 cur_epoch_store: &AuthorityPerEpochStore,
3961 ) {
3962 let live_object_set_hash = state_hasher.digest_live_object_set();
3963
3964 let root_state_hash: ECMHLiveObjectSetDigest = self
3965 .get_global_state_hash_store()
3966 .get_root_state_hash_for_epoch(cur_epoch_store.epoch())
3967 .expect("Retrieving root state hash cannot fail")
3968 .expect("Root state hash for epoch must exist")
3969 .1
3970 .digest()
3971 .into();
3972
3973 let is_inconsistent = root_state_hash != live_object_set_hash;
3974 if is_inconsistent {
3975 debug_fatal!(
3976 "Inconsistent state detected: root state hash: {:?}, live object set hash: {:?}",
3977 root_state_hash,
3978 live_object_set_hash
3979 );
3980 } else {
3981 info!("State consistency check passed");
3982 }
3983
3984 state_hasher.set_inconsistent_state(is_inconsistent);
3985 }
3986
3987 pub fn current_epoch_for_testing(&self) -> EpochId {
3988 self.epoch_store_for_testing().epoch()
3989 }
3990
3991 #[instrument(level = "error", skip_all)]
3995 async fn hand_over_epoch_end_db_snapshot(&self, epoch: EpochId) {
3996 let Some(handle) = &self.epoch_end_db_snapshots else {
3997 return;
3998 };
3999 let _metrics_guard = self
4000 .metrics
4001 .epoch_end_db_snapshot_handover_latency
4002 .start_timer();
4003 if handle.hand_over(epoch).await == HandOver::Skipped {
4004 self.metrics.epoch_end_db_snapshots_skipped.inc();
4005 }
4006 }
4007
4008 pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
4015 self.epoch_store.load()
4016 }
4017
4018 pub fn epoch_store_for_testing(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
4020 self.load_epoch_store_one_call_per_task()
4021 }
4022
4023 pub fn clone_committee_for_testing(&self) -> Committee {
4024 Committee::clone(self.epoch_store_for_testing().committee())
4025 }
4026
4027 #[instrument(level = "trace", skip_all)]
4028 pub fn try_get_object(&self, object_id: &ObjectId) -> IotaResult<Option<Object>> {
4029 self.get_object_store()
4030 .try_get_object(object_id)
4031 .map_err(Into::into)
4032 }
4033
4034 pub fn get_object(&self, object_id: &ObjectId) -> Option<Object> {
4036 self.try_get_object(object_id)
4037 .expect("storage access failed")
4038 }
4039
4040 pub fn get_iota_system_package_object_ref(&self) -> IotaResult<ObjectReference> {
4041 Ok(self
4042 .try_get_object(&ObjectId::SYSTEM)?
4043 .expect("system package should always exist")
4044 .object_ref())
4045 }
4046
4047 pub fn get_iota_system_state_object_for_testing(&self) -> IotaResult<IotaSystemState> {
4049 self.get_object_cache_reader()
4050 .try_get_iota_system_state_object_unsafe()
4051 }
4052
4053 #[instrument(level = "trace", skip_all)]
4054 pub fn get_checkpoint_by_sequence_number(
4055 &self,
4056 sequence_number: CheckpointSequenceNumber,
4057 ) -> IotaResult<Option<VerifiedCheckpoint>> {
4058 Ok(self
4059 .checkpoint_store
4060 .get_checkpoint_by_sequence_number(sequence_number)?)
4061 }
4062
4063 pub async fn wait_for_checkpoint_inclusion(
4074 &self,
4075 digests: &[TransactionDigest],
4076 timeout: Duration,
4077 ) -> IotaResult<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>> {
4078 let deadline = tokio::time::Instant::now() + timeout;
4079 let mut checkpoint_timestamp_cache = HashMap::<CheckpointSequenceNumber, u64>::new();
4080 let mut results = BTreeMap::new();
4081 let mut remaining = digests.to_vec();
4082 let mut epoch_store = self.load_epoch_store_one_call_per_task().clone();
4083
4084 loop {
4085 let wait = epoch_store.wait_for_transactions_in_checkpoint_with_timeout(
4086 &remaining,
4087 deadline.saturating_duration_since(tokio::time::Instant::now()),
4088 |seq| self.checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache),
4089 );
4090 tokio::select! {
4091 wait_results = wait => {
4092 for (digest, seq_and_ts) in remaining.iter().zip(wait_results?) {
4093 if let Some(seq_and_ts) = seq_and_ts {
4094 results.insert(*digest, seq_and_ts);
4095 }
4096 }
4097 return Ok(results);
4098 }
4099 _ = epoch_store.wait_epoch_terminated() => {}
4100 }
4101
4102 let found = match epoch_store.multi_get_transaction_checkpoint(&remaining) {
4109 Ok(found) => found,
4110 Err(IotaError::EpochEnded(_)) => vec![None; remaining.len()],
4115 Err(err) => return Err(err),
4116 };
4117 let mut still_uncheckpointed = Vec::new();
4118 for (digest, found_seq) in remaining.iter().zip(found) {
4119 match found_seq {
4120 Some(seq) => {
4121 let ts = self
4122 .checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache);
4123 results.insert(*digest, (seq, ts));
4124 }
4125 None => still_uncheckpointed.push(*digest),
4126 }
4127 }
4128 remaining = still_uncheckpointed;
4129 if remaining.is_empty() {
4130 return Ok(results);
4131 }
4132
4133 match self
4134 .wait_for_next_epoch_store(epoch_store.epoch(), deadline)
4135 .await
4136 {
4137 Some(next) => epoch_store = next,
4138 None => return Ok(results),
4139 }
4140 }
4141 }
4142
4143 async fn wait_for_next_epoch_store(
4146 &self,
4147 prev_epoch: EpochId,
4148 deadline: tokio::time::Instant,
4149 ) -> Option<Arc<AuthorityPerEpochStore>> {
4150 const EPOCH_STORE_SWAP_POLL_INTERVAL: Duration = Duration::from_millis(100);
4155
4156 loop {
4157 let current = self.load_epoch_store_one_call_per_task().clone();
4160 if current.epoch() > prev_epoch {
4161 return Some(current);
4162 }
4163 if tokio::time::Instant::now() >= deadline {
4164 return None;
4165 }
4166 tokio::time::sleep(EPOCH_STORE_SWAP_POLL_INTERVAL).await;
4167 }
4168 }
4169
4170 fn checkpoint_timestamp_ms_cached(
4174 &self,
4175 seq: CheckpointSequenceNumber,
4176 cache: &mut HashMap<CheckpointSequenceNumber, u64>,
4177 ) -> u64 {
4178 *cache.entry(seq).or_insert_with(|| {
4179 self.get_checkpoint_by_sequence_number(seq)
4180 .ok()
4181 .flatten()
4182 .map(|c| c.timestamp_ms)
4183 .unwrap_or(0)
4184 })
4185 }
4186
4187 #[instrument(level = "trace", skip_all)]
4188 pub fn get_transaction_checkpoint_for_tests(
4189 &self,
4190 digest: &TransactionDigest,
4191 epoch_store: &AuthorityPerEpochStore,
4192 ) -> IotaResult<Option<VerifiedCheckpoint>> {
4193 let checkpoint = epoch_store.get_transaction_checkpoint(digest)?;
4194 let Some(checkpoint) = checkpoint else {
4195 return Ok(None);
4196 };
4197 let checkpoint = self
4198 .checkpoint_store
4199 .get_checkpoint_by_sequence_number(checkpoint)?;
4200 Ok(checkpoint)
4201 }
4202
4203 #[instrument(level = "trace", skip_all)]
4204 pub fn get_object_read(&self, object_id: &ObjectId) -> IotaResult<ObjectRead> {
4205 Ok(
4206 match self
4207 .get_object_cache_reader()
4208 .try_get_latest_object_or_tombstone(*object_id)?
4209 {
4210 Some((_, ObjectOrTombstone::Object(object))) => {
4211 let layout = self.get_object_layout(&object)?;
4212 ObjectRead::Exists(object.object_ref(), object, layout)
4213 }
4214 Some((_, ObjectOrTombstone::Tombstone(objref))) => ObjectRead::Deleted(objref),
4215 None => ObjectRead::NotExists(*object_id),
4216 },
4217 )
4218 }
4219
4220 pub fn get_chain_identifier(&self) -> ChainIdentifier {
4222 self.chain_identifier
4223 }
4224
4225 #[instrument(level = "trace", skip_all)]
4226 pub fn get_move_object<T>(&self, object_id: &ObjectId) -> IotaResult<T>
4227 where
4228 T: DeserializeOwned,
4229 {
4230 let o = self.get_object_read(object_id)?.into_object()?;
4231 if let Some(move_object) = o.data.as_opt_struct() {
4232 Ok(bcs::from_bytes(move_object.contents()).map_err(|e| {
4233 IotaError::ObjectDeserialization {
4234 error: format!("{e}"),
4235 }
4236 })?)
4237 } else {
4238 Err(IotaError::ObjectDeserialization {
4239 error: format!("Provided object : [{object_id}] is not a Move object."),
4240 })
4241 }
4242 }
4243
4244 #[instrument(level = "trace", skip_all)]
4250 pub fn get_past_object_read(
4251 &self,
4252 object_id: &ObjectId,
4253 version: Version,
4254 ) -> IotaResult<PastObjectRead> {
4255 let Some(obj_ref) = self
4257 .get_object_cache_reader()
4258 .try_get_latest_object_ref_or_tombstone(*object_id)?
4259 else {
4260 return Ok(PastObjectRead::ObjectNotExists(*object_id));
4261 };
4262
4263 if version > obj_ref.version {
4264 return Ok(PastObjectRead::VersionTooHigh {
4265 object_id: *object_id,
4266 asked_version: version,
4267 latest_version: obj_ref.version,
4268 });
4269 }
4270
4271 if version < obj_ref.version {
4272 return Ok(match self.read_object_at_version(object_id, version)? {
4274 Some((object, layout)) => {
4275 let obj_ref = object.object_ref();
4276 PastObjectRead::VersionFound(obj_ref, object, layout)
4277 }
4278
4279 None => PastObjectRead::VersionNotFound(*object_id, version),
4280 });
4281 }
4282
4283 if !obj_ref.digest.is_alive() {
4284 return Ok(PastObjectRead::ObjectDeleted(obj_ref));
4285 }
4286
4287 match self.read_object_at_version(object_id, obj_ref.version)? {
4288 Some((object, layout)) => Ok(PastObjectRead::VersionFound(obj_ref, object, layout)),
4289 None => {
4290 debug_fatal!(
4291 "Object with in parent_entry is missing from object store, datastore is \
4292 inconsistent",
4293 );
4294 Err(UserInputError::ObjectNotFound {
4295 object_id: *object_id,
4296 version: Some(obj_ref.version),
4297 }
4298 .into())
4299 }
4300 }
4301 }
4302
4303 #[instrument(level = "trace", skip_all)]
4304 fn read_object_at_version(
4305 &self,
4306 object_id: &ObjectId,
4307 version: Version,
4308 ) -> IotaResult<Option<(Object, Option<MoveStructLayout>)>> {
4309 let Some(object) = self
4310 .get_object_cache_reader()
4311 .try_get_object_by_key(object_id, version)?
4312 else {
4313 return Ok(None);
4314 };
4315
4316 let layout = self.get_object_layout(&object)?;
4317 Ok(Some((object, layout)))
4318 }
4319
4320 fn get_object_layout(&self, object: &Object) -> IotaResult<Option<MoveStructLayout>> {
4321 let layout = object
4322 .data
4323 .as_opt_struct()
4324 .map(|object| {
4325 into_struct_layout(
4326 self.load_epoch_store_one_call_per_task()
4327 .executor()
4328 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
4330 .get_annotated_layout(object.struct_tag())?,
4331 )
4332 })
4333 .transpose()?;
4334 Ok(layout)
4335 }
4336
4337 fn get_owner_at_version(&self, object_id: &ObjectId, version: Version) -> IotaResult<Owner> {
4338 self.get_object_store()
4339 .try_get_object_by_key(object_id, version)?
4340 .ok_or_else(|| {
4341 IotaError::from(UserInputError::ObjectNotFound {
4342 object_id: *object_id,
4343 version: Some(version),
4344 })
4345 })
4346 .map(|o| o.owner)
4347 }
4348
4349 #[instrument(level = "trace", skip_all)]
4350 pub fn get_owner_objects(
4351 &self,
4352 owner: Address,
4353 cursor: Option<ObjectId>,
4355 limit: usize,
4356 filter: Option<IotaObjectDataFilter>,
4357 ) -> IotaResult<Vec<ObjectInfo>> {
4358 if let Some(indexes) = &self.indexes {
4359 indexes.get_owner_objects(owner, cursor, limit, filter)
4360 } else {
4361 Err(IotaError::IndexStoreNotAvailable)
4362 }
4363 }
4364
4365 #[instrument(level = "trace", skip_all)]
4366 pub fn get_owned_coins_iterator_with_cursor(
4367 &self,
4368 owner: Address,
4369 cursor: (String, ObjectId),
4371 limit: usize,
4372 one_coin_type_only: bool,
4373 ) -> IotaResult<impl Iterator<Item = (String, ObjectId, CoinInfo)> + '_> {
4374 if let Some(indexes) = &self.indexes {
4375 indexes.get_owned_coins_iterator_with_cursor(owner, cursor, limit, one_coin_type_only)
4376 } else {
4377 Err(IotaError::IndexStoreNotAvailable)
4378 }
4379 }
4380
4381 #[instrument(level = "trace", skip_all)]
4382 pub fn get_owner_objects_iterator(
4383 &self,
4384 owner: Address,
4385 cursor: Option<ObjectId>,
4387 filter: Option<IotaObjectDataFilter>,
4388 ) -> IotaResult<impl Iterator<Item = ObjectInfo> + '_> {
4389 if let Some(indexes) = &self.indexes {
4390 indexes.get_owner_objects_iterator(owner, cursor, filter)
4391 } else {
4392 Err(IotaError::IndexStoreNotAvailable)
4393 }
4394 }
4395
4396 #[instrument(level = "trace", skip_all)]
4397 pub fn get_move_objects<T>(&self, owner: Address, tag: StructTag) -> IotaResult<Vec<T>>
4398 where
4399 T: DeserializeOwned,
4400 {
4401 let object_ids = self
4402 .get_owner_objects_iterator(owner, None, None)?
4403 .filter(|o| match &o.object_type {
4404 ObjectType::Struct(s) => *s == tag,
4405 ObjectType::Package => false,
4406 })
4407 .map(|info| ObjectKey(info.object_id, info.version))
4408 .collect::<Vec<_>>();
4409 let mut move_objects = vec![];
4410
4411 let objects = self
4412 .get_object_store()
4413 .try_multi_get_objects_by_key(&object_ids)?;
4414
4415 for (o, id) in objects.into_iter().zip(object_ids) {
4416 let object = o.ok_or_else(|| {
4417 IotaError::from(UserInputError::ObjectNotFound {
4418 object_id: id.0,
4419 version: Some(id.1),
4420 })
4421 })?;
4422 let move_object = object.data.as_opt_struct().ok_or_else(|| {
4423 IotaError::from(UserInputError::MovePackageAsObject { object_id: id.0 })
4424 })?;
4425 move_objects.push(bcs::from_bytes(move_object.contents()).map_err(|e| {
4426 IotaError::ObjectDeserialization {
4427 error: format!("{e}"),
4428 }
4429 })?);
4430 }
4431 Ok(move_objects)
4432 }
4433
4434 #[instrument(level = "trace", skip_all)]
4435 pub fn get_dynamic_fields(
4436 &self,
4437 owner: ObjectId,
4438 cursor: Option<ObjectId>,
4440 limit: usize,
4441 ) -> IotaResult<Vec<(ObjectId, DynamicFieldInfo)>> {
4442 Ok(self
4443 .get_dynamic_fields_iterator(owner, cursor)?
4444 .take(limit)
4445 .collect::<Result<Vec<_>, _>>()?)
4446 }
4447
4448 fn get_dynamic_fields_iterator(
4449 &self,
4450 owner: ObjectId,
4451 cursor: Option<ObjectId>,
4453 ) -> IotaResult<impl Iterator<Item = Result<(ObjectId, DynamicFieldInfo), TypedStoreError>> + '_>
4454 {
4455 if let Some(indexes) = &self.indexes {
4456 indexes.get_dynamic_fields_iterator(owner, cursor)
4457 } else {
4458 Err(IotaError::IndexStoreNotAvailable)
4459 }
4460 }
4461
4462 #[instrument(level = "trace", skip_all)]
4463 pub fn get_dynamic_field_object_id(
4464 &self,
4465 owner: ObjectId,
4466 name_type: TypeTag,
4467 name_bcs_bytes: &[u8],
4468 ) -> IotaResult<Option<ObjectId>> {
4469 if let Some(indexes) = &self.indexes {
4470 indexes.get_dynamic_field_object_id(owner, name_type, name_bcs_bytes)
4471 } else {
4472 Err(IotaError::IndexStoreNotAvailable)
4473 }
4474 }
4475
4476 #[instrument(level = "trace", skip_all)]
4477 pub fn get_total_transaction_blocks(&self) -> IotaResult<u64> {
4478 Ok(self.get_indexes()?.next_sequence_number())
4479 }
4480
4481 #[instrument(level = "trace", skip_all)]
4482 pub async fn get_executed_transaction_and_effects(
4483 &self,
4484 digest: TransactionDigest,
4485 kv_store: Arc<TransactionKeyValueStore>,
4486 ) -> IotaResult<(TransactionEnvelope, TransactionEffects)> {
4487 let transaction = kv_store.get_tx(digest).await?;
4488 let effects = kv_store.get_fx_by_tx_digest(digest).await?;
4489 Ok((transaction, effects))
4490 }
4491
4492 #[instrument(level = "trace", skip_all)]
4493 pub fn multi_get_checkpoint_by_sequence_number(
4494 &self,
4495 sequence_numbers: &[CheckpointSequenceNumber],
4496 ) -> IotaResult<Vec<Option<VerifiedCheckpoint>>> {
4497 Ok(self
4498 .checkpoint_store
4499 .multi_get_checkpoint_by_sequence_number(sequence_numbers)?)
4500 }
4501
4502 #[instrument(level = "trace", skip_all)]
4503 pub fn get_transaction_events(
4504 &self,
4505 digest: &TransactionDigest,
4506 ) -> IotaResult<TransactionEvents> {
4507 self.get_transaction_cache_reader()
4508 .try_get_events(digest)?
4509 .ok_or(IotaError::TransactionEventsNotFound { digest: *digest })
4510 }
4511
4512 pub fn get_transaction_input_objects(
4513 &self,
4514 effects: &TransactionEffects,
4515 ) -> anyhow::Result<Vec<Object>> {
4516 iota_types::storage::get_transaction_input_objects(self.get_object_store(), effects)
4517 .map_err(Into::into)
4518 }
4519
4520 pub fn get_transaction_output_objects(
4521 &self,
4522 effects: &TransactionEffects,
4523 ) -> anyhow::Result<Vec<Object>> {
4524 iota_types::storage::get_transaction_output_objects(self.get_object_store(), effects)
4525 .map_err(Into::into)
4526 }
4527
4528 fn get_indexes(&self) -> IotaResult<Arc<IndexStore>> {
4529 match &self.indexes {
4530 Some(i) => Ok(i.clone()),
4531 None => Err(IotaError::UnsupportedFeature {
4532 error: "extended object indexing is not enabled on this server".into(),
4533 }),
4534 }
4535 }
4536
4537 pub async fn get_transactions_for_tests(
4538 self: &Arc<Self>,
4539 filter: Option<TransactionFilter>,
4540 cursor: Option<TransactionDigest>,
4541 limit: Option<usize>,
4542 reverse: bool,
4543 ) -> IotaResult<Vec<TransactionDigest>> {
4544 let metrics = KeyValueStoreMetrics::new_for_tests();
4545 let kv_store = Arc::new(TransactionKeyValueStore::new(
4546 "rocksdb",
4547 metrics,
4548 self.clone(),
4549 ));
4550 self.get_transactions(&kv_store, filter, cursor, limit, reverse)
4551 .await
4552 }
4553
4554 #[instrument(level = "trace", skip_all)]
4555 pub async fn get_transactions(
4556 &self,
4557 kv_store: &Arc<TransactionKeyValueStore>,
4558 filter: Option<TransactionFilter>,
4559 cursor: Option<TransactionDigest>,
4561 limit: Option<usize>,
4562 reverse: bool,
4563 ) -> IotaResult<Vec<TransactionDigest>> {
4564 if let Some(TransactionFilter::Checkpoint(sequence_number)) = filter {
4565 let checkpoint_contents = kv_store.get_checkpoint_contents(sequence_number).await?;
4566 let iter = checkpoint_contents.iter().map(|c| c.transaction);
4567 if reverse {
4568 let iter = iter
4569 .rev()
4570 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4571 .skip(usize::from(cursor.is_some()));
4572 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4573 } else {
4574 let iter = iter
4575 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4576 .skip(usize::from(cursor.is_some()));
4577 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4578 }
4579 }
4580 self.get_indexes()?
4581 .get_transactions(filter, cursor, limit, reverse)
4582 }
4583
4584 pub fn get_checkpoint_store(&self) -> &Arc<CheckpointStore> {
4585 &self.checkpoint_store
4586 }
4587
4588 pub fn pruner(&self) -> &AuthorityStorePruner {
4591 &self.pruner
4592 }
4593
4594 pub fn retain_objects(&self) -> ObjectRetentionGuard {
4600 self.pruner.retain_objects()
4601 }
4602
4603 pub fn get_latest_checkpoint_sequence_number(&self) -> IotaResult<CheckpointSequenceNumber> {
4604 self.get_checkpoint_store()
4605 .get_highest_executed_checkpoint_seq_number()?
4606 .ok_or(IotaError::UserInput {
4607 error: UserInputError::LatestCheckpointSequenceNumberNotFound,
4608 })
4609 }
4610
4611 #[cfg(msim)]
4612 pub fn get_highest_pruned_checkpoint_for_testing(
4613 &self,
4614 ) -> IotaResult<CheckpointSequenceNumber> {
4615 self.database_for_testing()
4616 .perpetual_tables
4617 .get_highest_pruned_checkpoint()
4618 .map(|c| c.unwrap_or(0))
4619 .map_err(Into::into)
4620 }
4621
4622 #[instrument(level = "trace", skip_all)]
4623 pub fn get_checkpoint_summary_by_sequence_number(
4624 &self,
4625 sequence_number: CheckpointSequenceNumber,
4626 ) -> IotaResult<CheckpointSummary> {
4627 let verified_checkpoint = self
4628 .get_checkpoint_store()
4629 .get_checkpoint_by_sequence_number(sequence_number)?;
4630 match verified_checkpoint {
4631 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4632 None => Err(IotaError::UserInput {
4633 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4634 }),
4635 }
4636 }
4637
4638 #[instrument(level = "trace", skip_all)]
4639 pub fn get_checkpoint_summary_by_digest(
4640 &self,
4641 digest: CheckpointDigest,
4642 ) -> IotaResult<CheckpointSummary> {
4643 let verified_checkpoint = self
4644 .get_checkpoint_store()
4645 .get_checkpoint_by_digest(&digest)?;
4646 match verified_checkpoint {
4647 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4648 None => Err(IotaError::UserInput {
4649 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4650 }),
4651 }
4652 }
4653
4654 #[instrument(level = "trace", skip_all)]
4655 pub fn find_publish_txn_digest(&self, package_id: ObjectId) -> IotaResult<TransactionDigest> {
4656 if package_id.is_system_package() {
4657 return self.find_genesis_txn_digest();
4658 }
4659 Ok(self
4660 .get_object_read(&package_id)?
4661 .into_object()?
4662 .previous_transaction)
4663 }
4664
4665 #[instrument(level = "trace", skip_all)]
4666 pub fn find_genesis_txn_digest(&self) -> IotaResult<TransactionDigest> {
4667 let summary = self
4668 .get_verified_checkpoint_by_sequence_number(0)?
4669 .into_message();
4670 let content = self.get_checkpoint_contents(summary.contents_digest)?;
4671 let genesis_transaction = content.enumerate_transactions(&summary).next();
4672 Ok(genesis_transaction
4673 .ok_or(IotaError::UserInput {
4674 error: UserInputError::GenesisTransactionNotFound,
4675 })?
4676 .1
4677 .transaction)
4678 }
4679
4680 #[instrument(level = "trace", skip_all)]
4681 pub fn get_verified_checkpoint_by_sequence_number(
4682 &self,
4683 sequence_number: CheckpointSequenceNumber,
4684 ) -> IotaResult<VerifiedCheckpoint> {
4685 let verified_checkpoint = self
4686 .get_checkpoint_store()
4687 .get_checkpoint_by_sequence_number(sequence_number)?;
4688 match verified_checkpoint {
4689 Some(verified_checkpoint) => Ok(verified_checkpoint),
4690 None => Err(IotaError::UserInput {
4691 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4692 }),
4693 }
4694 }
4695
4696 #[instrument(level = "trace", skip_all)]
4697 pub fn get_verified_checkpoint_summary_by_digest(
4698 &self,
4699 digest: CheckpointDigest,
4700 ) -> IotaResult<VerifiedCheckpoint> {
4701 let verified_checkpoint = self
4702 .get_checkpoint_store()
4703 .get_checkpoint_by_digest(&digest)?;
4704 match verified_checkpoint {
4705 Some(verified_checkpoint) => Ok(verified_checkpoint),
4706 None => Err(IotaError::UserInput {
4707 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4708 }),
4709 }
4710 }
4711
4712 #[instrument(level = "trace", skip_all)]
4713 pub fn get_checkpoint_contents(
4714 &self,
4715 digest: CheckpointContentsDigest,
4716 ) -> IotaResult<CheckpointContents> {
4717 self.get_checkpoint_store()
4718 .get_checkpoint_contents(&digest)?
4719 .ok_or(IotaError::UserInput {
4720 error: UserInputError::CheckpointContentsNotFound(digest),
4721 })
4722 }
4723
4724 #[instrument(level = "trace", skip_all)]
4725 pub fn get_checkpoint_contents_by_sequence_number(
4726 &self,
4727 sequence_number: CheckpointSequenceNumber,
4728 ) -> IotaResult<CheckpointContents> {
4729 let verified_checkpoint = self
4730 .get_checkpoint_store()
4731 .get_checkpoint_by_sequence_number(sequence_number)?;
4732 match verified_checkpoint {
4733 Some(verified_checkpoint) => {
4734 let contents_digest = verified_checkpoint.into_inner().contents_digest;
4735 self.get_checkpoint_contents(contents_digest)
4736 }
4737 None => Err(IotaError::UserInput {
4738 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4739 }),
4740 }
4741 }
4742
4743 #[instrument(level = "trace", skip_all)]
4744 pub async fn query_events(
4745 &self,
4746 kv_store: &Arc<TransactionKeyValueStore>,
4747 query: EventFilter,
4748 cursor: Option<EventID>,
4750 limit: usize,
4751 descending: bool,
4752 ) -> IotaResult<Vec<IotaEvent>> {
4753 let index_store = self.get_indexes()?;
4754
4755 let (tx_num, event_num) = if let Some(cursor) = cursor.as_ref() {
4757 let tx_seq = index_store.get_transaction_seq(&cursor.tx_digest)?.ok_or(
4758 IotaError::TransactionNotFound {
4759 digest: cursor.tx_digest,
4760 },
4761 )?;
4762 (tx_seq, cursor.event_seq as usize)
4763 } else if descending {
4764 (u64::MAX, usize::MAX)
4765 } else {
4766 (0, 0)
4767 };
4768
4769 let limit = limit + 1;
4770 let mut event_keys = match query {
4771 EventFilter::All(filters) => {
4772 if filters.is_empty() {
4773 index_store.all_events(tx_num, event_num, limit, descending)?
4774 } else {
4775 return Err(IotaError::UserInput {
4776 error: UserInputError::Unsupported(
4777 "This query type does not currently support filter combinations"
4778 .to_string(),
4779 ),
4780 });
4781 }
4782 }
4783 EventFilter::Transaction(digest) => {
4784 index_store.events_by_transaction(&digest, tx_num, event_num, limit, descending)?
4785 }
4786 EventFilter::MoveModule { package, module } => {
4787 let module_id = ModuleId::new(
4788 AccountAddress::new(package.into_bytes()),
4789 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4790 );
4791 index_store.events_by_module_id(&module_id, tx_num, event_num, limit, descending)?
4792 }
4793 EventFilter::MoveEventType(struct_name) => index_store
4794 .events_by_move_event_struct_name(
4795 &struct_name,
4796 tx_num,
4797 event_num,
4798 limit,
4799 descending,
4800 )?,
4801 EventFilter::Sender(sender) => {
4802 index_store.events_by_sender(&sender, tx_num, event_num, limit, descending)?
4803 }
4804 EventFilter::TimeRange {
4805 start_time,
4806 end_time,
4807 } => index_store
4808 .event_iterator(start_time, end_time, tx_num, event_num, limit, descending)?,
4809 EventFilter::MoveEventModule { package, module } => index_store
4810 .events_by_move_event_module(
4811 &ModuleId::new(
4812 AccountAddress::new(package.into_bytes()),
4813 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4814 ),
4815 tx_num,
4816 event_num,
4817 limit,
4818 descending,
4819 )?,
4820 EventFilter::Package(_)
4822 | EventFilter::MoveEventField { .. }
4823 | EventFilter::Any(_)
4824 | EventFilter::And(_, _)
4825 | EventFilter::Or(_, _) => {
4826 return Err(IotaError::UserInput {
4827 error: UserInputError::Unsupported(
4828 "This query type is not supported by the full node.".to_string(),
4829 ),
4830 });
4831 }
4832 };
4833
4834 if cursor.is_some() {
4837 if !event_keys.is_empty() {
4838 event_keys.remove(0);
4839 }
4840 } else {
4841 event_keys.truncate(limit - 1);
4842 }
4843
4844 let transaction_digests = event_keys
4846 .iter()
4847 .map(|(_, digest, _, _)| *digest)
4848 .collect::<HashSet<_>>()
4849 .into_iter()
4850 .collect::<Vec<_>>();
4851
4852 let events = kv_store
4853 .multi_get_events_by_tx_digests(&transaction_digests)
4854 .await?;
4855
4856 let events_map: HashMap<_, _> =
4857 transaction_digests.iter().zip(events.into_iter()).collect();
4858
4859 let stored_events = event_keys
4860 .into_iter()
4861 .map(|k| {
4862 (
4863 k,
4864 events_map
4865 .get(&k.1)
4866 .expect("fetched digest is missing")
4867 .clone()
4868 .and_then(|e| e.get(k.2).cloned()),
4869 )
4870 })
4871 .map(
4872 |((_event_digest, tx_digest, event_seq, timestamp), event)| {
4873 event
4874 .map(|e| (e, tx_digest, event_seq, timestamp))
4875 .ok_or(IotaError::TransactionEventsNotFound { digest: tx_digest })
4876 },
4877 )
4878 .collect::<Result<Vec<_>, _>>()?;
4879
4880 let epoch_store = self.load_epoch_store_one_call_per_task();
4881 let backing_store = self.get_backing_package_store().as_ref();
4882 let mut layout_resolver = epoch_store
4883 .executor()
4884 .type_layout_resolver(Box::new(backing_store));
4885 let mut events = vec![];
4886 for (e, tx_digest, event_seq, timestamp) in stored_events.into_iter() {
4887 events.push(IotaEvent::try_from(
4888 e.clone(),
4889 tx_digest,
4890 event_seq as u64,
4891 Some(timestamp),
4892 layout_resolver.get_annotated_layout(&e.struct_tag)?,
4893 )?)
4894 }
4895 Ok(events)
4896 }
4897
4898 pub fn insert_genesis_object(&self, object: Object) {
4899 self.get_reconfig_api()
4900 .try_insert_genesis_object(object)
4901 .expect("Cannot insert genesis object")
4902 }
4903
4904 pub fn insert_genesis_objects(&self, objects: &[Object]) {
4905 for o in objects {
4906 self.insert_genesis_object(o.clone());
4907 }
4908 }
4909
4910 #[instrument(level = "trace", skip_all)]
4912 pub fn get_transaction_status(
4913 &self,
4914 transaction_digest: &TransactionDigest,
4915 epoch_store: &Arc<AuthorityPerEpochStore>,
4916 ) -> IotaResult<Option<(SenderSignedTransaction, TransactionStatus)>> {
4917 if let Some(effects) =
4919 self.get_signed_effects_and_maybe_resign(transaction_digest, epoch_store)?
4920 {
4921 if let Some(transaction) = self
4922 .get_transaction_cache_reader()
4923 .try_get_transaction_block(transaction_digest)?
4924 {
4925 let cert_sig = epoch_store.get_transaction_cert_sig(transaction_digest)?;
4926 let events = if effects.events_digest().is_some() {
4927 self.get_transaction_events(effects.transaction_digest())?
4928 } else {
4929 TransactionEvents::default()
4930 };
4931 return Ok(Some((
4932 (*transaction).clone().into_message(),
4933 TransactionStatus::Executed(cert_sig, effects.into_inner(), events),
4934 )));
4935 } else {
4936 debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
4941 }
4942 }
4943 if let Some(signed) = epoch_store.get_signed_transaction(transaction_digest)? {
4944 self.metrics.tx_already_processed.inc();
4945 let (transaction, sig) = signed.into_inner().into_data_and_sig();
4946 Ok(Some((transaction, TransactionStatus::Signed(sig))))
4947 } else {
4948 Ok(None)
4949 }
4950 }
4951
4952 #[instrument(level = "trace", skip_all)]
4956 pub fn get_signed_effects_and_maybe_resign(
4957 &self,
4958 transaction_digest: &TransactionDigest,
4959 epoch_store: &Arc<AuthorityPerEpochStore>,
4960 ) -> IotaResult<Option<VerifiedSignedTransactionEffects>> {
4961 let effects = self
4962 .get_transaction_cache_reader()
4963 .try_get_executed_effects(transaction_digest)?;
4964 match effects {
4965 Some(effects) => {
4966 if effects.epoch() != epoch_store.epoch() {
4987 debug!(
4988 tx_digest=?transaction_digest,
4989 effects_epoch=?effects.epoch(),
4990 epoch=?epoch_store.epoch(),
4991 "Re-signing the effects with the current epoch"
4992 );
4993 }
4994 Ok(Some(self.sign_effects(effects, epoch_store)?))
4995 }
4996 None => Ok(None),
4997 }
4998 }
4999
5000 pub fn check_effects_against_previously_signed(
5010 &self,
5011 epoch_store: &AuthorityPerEpochStore,
5012 tx_digest: &TransactionDigest,
5013 effects_digest: &TransactionEffectsDigest,
5014 surface: &'static str,
5015 ) -> IotaResult<()> {
5016 if let Some(previously_signed_digest) = epoch_store.get_signed_effects_digest(tx_digest)? {
5017 if previously_signed_digest != *effects_digest {
5018 self.metrics
5019 .signed_effects_equivocation_prevented
5020 .with_label_values(&[surface])
5021 .inc();
5022 error!(
5023 ?tx_digest,
5024 ?previously_signed_digest,
5025 executed_digest = ?effects_digest,
5026 surface,
5027 "refusing to report effects that differ from previously signed effects"
5028 );
5029 return Err(IotaError::GenericAuthority {
5030 error: format!(
5031 "Refusing to report effects for transaction {tx_digest}: effects digest \
5032 {effects_digest} differs from previously signed effects digest \
5033 {previously_signed_digest}"
5034 ),
5035 });
5036 }
5037 }
5038 Ok(())
5039 }
5040
5041 #[instrument(level = "trace", skip_all)]
5042 pub(crate) fn sign_effects(
5043 &self,
5044 effects: TransactionEffects,
5045 epoch_store: &Arc<AuthorityPerEpochStore>,
5046 ) -> IotaResult<VerifiedSignedTransactionEffects> {
5047 let tx_digest = *effects.transaction_digest();
5048
5049 self.check_effects_against_previously_signed(
5050 epoch_store,
5051 &tx_digest,
5052 &effects.digest(),
5053 "sign_effects",
5054 )?;
5055
5056 let signed_effects = match epoch_store.get_effects_signature(&tx_digest)? {
5057 Some(sig) => {
5058 debug_assert!(sig.epoch == epoch_store.epoch());
5059 SignedTransactionEffects::new_from_data_and_sig(effects, sig)
5060 }
5061 _ => {
5062 let sig = AuthoritySignInfo::new(
5063 epoch_store.epoch(),
5064 &effects,
5065 Intent::iota_app(IntentScope::TransactionEffects),
5066 self.name,
5067 &*self.secret,
5068 );
5069
5070 let effects = SignedTransactionEffects::new_from_data_and_sig(effects, sig.clone());
5071
5072 epoch_store.insert_effects_digest_and_signature(
5073 &tx_digest,
5074 effects.digest(),
5075 &sig,
5076 )?;
5077
5078 effects
5079 }
5080 };
5081
5082 Ok(VerifiedSignedTransactionEffects::new_unchecked(
5083 signed_effects,
5084 ))
5085 }
5086
5087 #[instrument(level = "trace", skip_all)]
5089 fn fullnode_only_get_tx_coins_for_indexing(
5090 &self,
5091 effects: &TransactionEffects,
5092 inner_temporary_store: &InnerTemporaryStore,
5093 epoch_store: &Arc<AuthorityPerEpochStore>,
5094 ) -> Option<TxCoins> {
5095 if self.indexes.is_none() || self.is_committee_validator(epoch_store) {
5096 return None;
5097 }
5098 let written_coin_objects = inner_temporary_store
5099 .written
5100 .iter()
5101 .filter_map(|(k, v)| {
5102 if v.is_coin() {
5103 Some((*k, v.clone()))
5104 } else {
5105 None
5106 }
5107 })
5108 .collect();
5109 let mut input_coin_objects = inner_temporary_store
5110 .input_objects
5111 .iter()
5112 .filter_map(|(k, v)| {
5113 if v.is_coin() {
5114 Some((*k, v.clone()))
5115 } else {
5116 None
5117 }
5118 })
5119 .collect::<ObjectMap>();
5120
5121 for modified in effects.modified_at_versions() {
5126 let (object_id, version) = (*modified.object_id(), modified.version());
5127 if inner_temporary_store
5128 .loaded_runtime_objects
5129 .contains_key(&object_id)
5130 {
5131 if let Some(object) = self
5132 .get_object_store()
5133 .get_object_by_key(&object_id, version)
5134 {
5135 if object.is_coin() {
5136 input_coin_objects.insert(object_id, object);
5137 }
5138 }
5139 }
5140 }
5141
5142 Some((input_coin_objects, written_coin_objects))
5143 }
5144
5145 #[instrument(level = "trace", skip_all)]
5157 pub fn get_transaction_lock(
5158 &self,
5159 object_ref: &ObjectReference,
5160 epoch_store: &AuthorityPerEpochStore,
5161 ) -> IotaResult<Option<VerifiedSignedTransaction>> {
5162 let lock_info = self
5163 .get_object_cache_reader()
5164 .try_get_lock(*object_ref, epoch_store)?;
5165 let lock_info = match lock_info {
5166 ObjectLockStatus::LockedAtDifferentVersion { locked_ref } => {
5167 return Err(UserInputError::ObjectVersionUnavailableForConsumption {
5168 provided_obj_ref: *object_ref,
5169 current_version: locked_ref.version,
5170 }
5171 .into());
5172 }
5173 ObjectLockStatus::Initialized => {
5174 return Ok(None);
5175 }
5176 ObjectLockStatus::LockedToTx { locked_by_tx } => locked_by_tx,
5177 };
5178
5179 epoch_store.get_signed_transaction(&lock_info)
5180 }
5181
5182 pub fn try_get_objects(&self, objects: &[ObjectId]) -> IotaResult<Vec<Option<Object>>> {
5183 self.get_object_cache_reader().try_get_objects(objects)
5184 }
5185
5186 pub fn get_objects(&self, objects: &[ObjectId]) -> Vec<Option<Object>> {
5188 self.try_get_objects(objects)
5189 .expect("storage access failed")
5190 }
5191
5192 pub fn try_get_object_or_tombstone(
5193 &self,
5194 object_id: ObjectId,
5195 ) -> IotaResult<Option<ObjectReference>> {
5196 self.get_object_cache_reader()
5197 .try_get_latest_object_ref_or_tombstone(object_id)
5198 }
5199
5200 pub fn get_object_or_tombstone(&self, object_id: ObjectId) -> Option<ObjectReference> {
5202 self.try_get_object_or_tombstone(object_id)
5203 .expect("storage access failed")
5204 }
5205
5206 pub fn set_override_protocol_upgrade_buffer_stake(
5216 &self,
5217 expected_epoch: EpochId,
5218 buffer_stake_bps: u64,
5219 ) -> IotaResult {
5220 let epoch_store = self.load_epoch_store_one_call_per_task();
5221 let actual_epoch = epoch_store.epoch();
5222 if actual_epoch != expected_epoch {
5223 return Err(IotaError::WrongEpoch {
5224 expected_epoch,
5225 actual_epoch,
5226 });
5227 }
5228
5229 epoch_store.set_override_protocol_upgrade_buffer_stake(buffer_stake_bps)
5230 }
5231
5232 pub fn clear_override_protocol_upgrade_buffer_stake(
5233 &self,
5234 expected_epoch: EpochId,
5235 ) -> IotaResult {
5236 let epoch_store = self.load_epoch_store_one_call_per_task();
5237 let actual_epoch = epoch_store.epoch();
5238 if actual_epoch != expected_epoch {
5239 return Err(IotaError::WrongEpoch {
5240 expected_epoch,
5241 actual_epoch,
5242 });
5243 }
5244
5245 epoch_store.clear_override_protocol_upgrade_buffer_stake()
5246 }
5247
5248 pub async fn get_available_system_packages(
5252 &self,
5253 protocol_config: &ProtocolConfig,
5254 ) -> Vec<ObjectReference> {
5255 let mut results = vec![];
5256
5257 let system_packages = BuiltInFramework::iter_system_packages();
5258
5259 #[cfg(msim)]
5261 let extra_packages = framework_injection::get_extra_packages(self.name);
5262 #[cfg(msim)]
5263 let system_packages = {
5264 let mut packages: Vec<_> = system_packages.collect();
5265 packages.extend(extra_packages.iter());
5266 packages
5267 };
5268
5269 for system_package in system_packages {
5270 let modules = system_package.modules().to_vec();
5271 #[cfg(msim)]
5273 let modules = framework_injection::get_override_modules(&system_package.id, self.name)
5274 .unwrap_or(modules);
5275
5276 let Some(obj_ref) = iota_framework::compare_system_package(
5277 &self.get_object_store(),
5278 &system_package.id,
5279 &modules,
5280 system_package.dependencies.to_vec(),
5281 protocol_config,
5282 )
5283 .await
5284 else {
5285 return vec![];
5286 };
5287 results.push(obj_ref);
5288 }
5289
5290 results
5291 }
5292
5293 async fn get_system_package_bytes(
5316 &self,
5317 system_packages: Vec<ObjectReference>,
5318 binary_config: &BinaryConfig,
5319 ) -> Option<Vec<SystemPackage>> {
5320 let object_store = self.get_object_cache_reader();
5321
5322 let mut res = Vec::with_capacity(system_packages.len());
5323 for system_package_ref in system_packages {
5324 if object_store
5325 .get_object_by_key(&system_package_ref.object_id, system_package_ref.version)
5326 .is_some_and(|object| object.object_ref() == system_package_ref)
5327 {
5328 info!(
5330 "Framework {} does not need updating",
5331 system_package_ref.object_id
5332 );
5333 continue;
5334 }
5335
5336 let prev_transaction = if system_package_ref.version == Version::OBJECT_START {
5341 TransactionDigest::GENESIS_MARKER
5342 } else {
5343 let prev_version = system_package_ref
5344 .version
5345 .previous()
5346 .expect("version is greater than Version::OBJECT_START");
5347 let Some(prev_object) =
5348 object_store.get_object_by_key(&system_package_ref.object_id, prev_version)
5349 else {
5350 error!(
5351 "Framework {} not available locally at version {prev_version:?}, cannot \
5352 derive upgrade to {system_package_ref:?}",
5353 system_package_ref.object_id
5354 );
5355 return None;
5356 };
5357 prev_object.previous_transaction
5358 };
5359
5360 #[cfg(msim)]
5361 let FrameworkSystemPackage {
5362 id: _,
5363 bytes,
5364 dependencies,
5365 } = framework_injection::get_override_system_package(
5366 &system_package_ref.object_id,
5367 self.name,
5368 )
5369 .unwrap_or_else(|| {
5370 BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone()
5371 });
5372
5373 #[cfg(not(msim))]
5374 let FrameworkSystemPackage {
5375 id: _,
5376 bytes,
5377 dependencies,
5378 } = BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone();
5379
5380 let modules: Vec<_> = bytes
5381 .iter()
5382 .map(|m| CompiledModule::deserialize_with_config(m, binary_config).unwrap())
5383 .collect();
5384
5385 let new_object = Object::new_system_package(
5386 &modules,
5387 system_package_ref.version,
5388 dependencies.clone(),
5389 prev_transaction,
5390 );
5391
5392 let new_ref = new_object.object_ref();
5393 if new_ref != system_package_ref {
5394 debug_fatal!(
5395 "Framework mismatch -- binary: {new_ref:?}\n upgrade: {system_package_ref:?}"
5396 );
5397 return None;
5398 }
5399
5400 res.push(SystemPackage {
5401 version: system_package_ref.version,
5402 modules: bytes,
5403 dependencies,
5404 });
5405 }
5406
5407 Some(res)
5408 }
5409
5410 fn is_protocol_version_supported_v1(
5414 proposed_protocol_version: ProtocolVersion,
5415 committee: &Committee,
5416 capabilities: Vec<AuthorityCapabilitiesV1>,
5417 mut buffer_stake_bps: u64,
5418 ) -> Option<(ProtocolVersion, Digest, Vec<ObjectReference>)> {
5419 if buffer_stake_bps > 10000 {
5420 warn!("clamping buffer_stake_bps to 10000");
5421 buffer_stake_bps = 10000;
5422 }
5423
5424 let mut desired_upgrades: Vec<_> = capabilities
5427 .into_iter()
5428 .filter_map(|mut cap| {
5429 if cap.available_system_packages.is_empty() {
5431 return None;
5432 }
5433
5434 cap.available_system_packages.sort();
5435
5436 info!(
5437 "validator {:?} supports {:?} with system packages: {:?}",
5438 cap.authority.concise(),
5439 cap.supported_protocol_versions,
5440 cap.available_system_packages,
5441 );
5442
5443 cap.supported_protocol_versions
5447 .get_version_digest(proposed_protocol_version)
5448 .map(|digest| (digest, cap.available_system_packages, cap.authority))
5449 })
5450 .collect();
5451
5452 desired_upgrades.sort();
5455 desired_upgrades
5456 .into_iter()
5457 .chunk_by(|(digest, packages, _authority)| (*digest, packages.clone()))
5458 .into_iter()
5459 .find_map(|((digest, packages), group)| {
5460 assert!(!packages.is_empty());
5462
5463 let mut stake_aggregator: StakeAggregator<(), true> =
5464 StakeAggregator::new(Arc::new(committee.clone()));
5465
5466 for (_, _, authority) in group {
5467 stake_aggregator.insert_generic(authority, ());
5468 }
5469
5470 let total_votes = stake_aggregator.total_votes();
5471 let quorum_threshold = committee.quorum_threshold();
5472 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5473
5474 info!(
5475 protocol_config_digest = ?digest,
5476 ?total_votes,
5477 ?quorum_threshold,
5478 ?buffer_stake_bps,
5479 ?effective_threshold,
5480 ?proposed_protocol_version,
5481 ?packages,
5482 "support for upgrade"
5483 );
5484
5485 let has_support = total_votes >= effective_threshold;
5486 has_support.then_some((proposed_protocol_version, digest, packages))
5487 })
5488 }
5489
5490 fn choose_protocol_version_and_system_packages_v1(
5494 current_protocol_version: ProtocolVersion,
5495 current_protocol_digest: Digest,
5496 committee: &Committee,
5497 capabilities: Vec<AuthorityCapabilitiesV1>,
5498 buffer_stake_bps: u64,
5499 ) -> (ProtocolVersion, Digest, Vec<ObjectReference>) {
5500 let mut next_protocol_version = current_protocol_version;
5501 let mut system_packages = vec![];
5502 let mut protocol_version_digest = current_protocol_digest;
5503
5504 while let Some((version, digest, packages)) = Self::is_protocol_version_supported_v1(
5508 next_protocol_version + 1,
5509 committee,
5510 capabilities.clone(),
5511 buffer_stake_bps,
5512 ) {
5513 next_protocol_version = version;
5514 protocol_version_digest = digest;
5515 system_packages = packages;
5516 }
5517
5518 (
5519 next_protocol_version,
5520 protocol_version_digest,
5521 system_packages,
5522 )
5523 }
5524
5525 fn get_validators_supporting_protocol_version(
5530 target_protocol_version: ProtocolVersion,
5531 target_digest: Digest,
5532 active_validators: &[AggregateAuthorityPublicKey],
5533 capabilities: &[AuthorityCapabilitiesV1],
5534 ) -> Vec<u64> {
5535 let mut eligible_validators = Vec::new();
5536
5537 for capability in capabilities {
5538 if let Some(digest) = capability
5540 .supported_protocol_versions
5541 .get_version_digest(target_protocol_version)
5542 {
5543 if digest == target_digest {
5544 if let Some(index) = active_validators
5546 .iter()
5547 .position(|name| AuthorityName::from(name) == capability.authority)
5548 {
5549 eligible_validators.push(index as u64);
5550 }
5551 }
5552 }
5553 }
5554
5555 eligible_validators.sort();
5557 eligible_validators
5558 }
5559
5560 fn calculate_eligible_validators_weight(
5565 eligible_validator_indices: &[u64],
5566 active_validators: &[AggregateAuthorityPublicKey],
5567 committee: &Committee,
5568 ) -> u64 {
5569 let mut total_weight = 0u64;
5570
5571 for &index in eligible_validator_indices {
5572 let authority_pubkey = &active_validators[index as usize];
5573 if let Some((_, weight)) = committee
5575 .members()
5576 .find(|(name, _)| *name == AuthorityName::from(authority_pubkey))
5577 {
5578 total_weight += weight;
5579 }
5580 }
5581
5582 total_weight
5583 }
5584
5585 #[instrument(level = "error", skip_all)]
5598 pub async fn create_and_execute_advance_epoch_tx(
5599 &self,
5600 epoch_store: &Arc<AuthorityPerEpochStore>,
5601 gas_cost_summary: &GasCostSummary,
5602 checkpoint: CheckpointSequenceNumber,
5603 epoch_start_timestamp_ms: CheckpointTimestamp,
5604 scores: Vec<u64>,
5605 ) -> CheckpointBuilderResult<(
5606 IotaSystemState,
5607 Option<SystemEpochInfoEvent>,
5608 TransactionEffects,
5609 )> {
5610 let mut txns = Vec::new();
5611
5612 if epoch_store.protocol_config().enable_pcool_flow()
5618 && epoch_store
5619 .epoch_start_config()
5620 .transaction_deny_rules_obj_initial_shared_version()
5621 .is_none()
5622 {
5623 txns.push(EndOfEpochTransactionKind::TransactionDenyRulesCreate);
5624 }
5625
5626 let next_epoch = epoch_store.epoch() + 1;
5627
5628 let buffer_stake_bps = epoch_store.get_effective_buffer_stake_bps();
5629 let authority_capabilities = epoch_store
5630 .get_capabilities_v1()
5631 .expect("read capabilities from db cannot fail");
5632 let (next_epoch_protocol_version, next_epoch_protocol_digest, next_epoch_system_packages) =
5633 Self::choose_protocol_version_and_system_packages_v1(
5634 epoch_store.protocol_version(),
5635 SupportedProtocolVersionsWithHashes::protocol_config_digest(
5636 epoch_store.protocol_config(),
5637 ),
5638 epoch_store.committee(),
5639 authority_capabilities.clone(),
5640 buffer_stake_bps,
5641 );
5642
5643 let config = epoch_store.protocol_config();
5647 let binary_config = to_binary_config(config, None);
5648 let Some(next_epoch_system_package_bytes) = self
5649 .get_system_package_bytes(next_epoch_system_packages.clone(), &binary_config)
5650 .await
5651 else {
5652 debug_fatal!(
5653 "upgraded system packages {:?} are not locally available, cannot create \
5654 ChangeEpochTx. validator binary must be upgraded to the correct version!",
5655 next_epoch_system_packages
5656 );
5657 return Err(CheckpointBuilderError::SystemPackagesMissing);
5666 };
5667
5668 if config.select_committee_from_eligible_validators() {
5671 let active_validators = epoch_store.epoch_start_state().get_active_validators();
5673
5674 let mut eligible_active_validators = (0..active_validators.len() as u64).collect();
5675
5676 if config.select_committee_supporting_next_epoch_version() {
5680 eligible_active_validators = Self::get_validators_supporting_protocol_version(
5681 next_epoch_protocol_version,
5682 next_epoch_protocol_digest,
5683 &active_validators,
5684 &authority_capabilities,
5685 );
5686
5687 let eligible_validators_weight = Self::calculate_eligible_validators_weight(
5689 &eligible_active_validators,
5690 &active_validators,
5691 epoch_store.committee(),
5692 );
5693
5694 let committee = epoch_store.committee();
5698 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5699
5700 if eligible_validators_weight < effective_threshold {
5701 error!(
5702 "Eligible validators weight {eligible_validators_weight} is less than effective threshold {effective_threshold}. \
5703 This could indicate a bug in validator selection logic or inconsistency with protocol version decision.",
5704 );
5705 eligible_active_validators = (0..active_validators.len() as u64).collect();
5708 }
5709 }
5710
5711 if config.pass_validator_scores_to_advance_epoch() {
5714 txns.push(EndOfEpochTransactionKind::new_change_epoch_v4(
5715 next_epoch,
5716 next_epoch_protocol_version.as_u64(),
5717 gas_cost_summary.storage_cost,
5718 gas_cost_summary.computation_cost,
5719 gas_cost_summary.computation_cost_burned,
5720 gas_cost_summary.storage_rebate,
5721 gas_cost_summary.non_refundable_storage_fee,
5722 epoch_start_timestamp_ms,
5723 next_epoch_system_package_bytes,
5724 eligible_active_validators,
5725 scores,
5726 config.adjust_rewards_by_score(),
5727 ));
5728 } else {
5729 txns.push(EndOfEpochTransactionKind::new_change_epoch_v3(
5730 next_epoch,
5731 next_epoch_protocol_version.as_u64(),
5732 gas_cost_summary.storage_cost,
5733 gas_cost_summary.computation_cost,
5734 gas_cost_summary.computation_cost_burned,
5735 gas_cost_summary.storage_rebate,
5736 gas_cost_summary.non_refundable_storage_fee,
5737 epoch_start_timestamp_ms,
5738 next_epoch_system_package_bytes,
5739 eligible_active_validators,
5740 ));
5741 }
5742 } else if config.protocol_defined_base_fee()
5743 && config.max_committee_members_count_as_option().is_some()
5744 {
5745 txns.push(EndOfEpochTransactionKind::new_change_epoch_v2(
5746 next_epoch,
5747 next_epoch_protocol_version.as_u64(),
5748 gas_cost_summary.storage_cost,
5749 gas_cost_summary.computation_cost,
5750 gas_cost_summary.computation_cost_burned,
5751 gas_cost_summary.storage_rebate,
5752 gas_cost_summary.non_refundable_storage_fee,
5753 epoch_start_timestamp_ms,
5754 next_epoch_system_package_bytes,
5755 ));
5756 } else {
5757 txns.push(EndOfEpochTransactionKind::new_change_epoch(
5758 next_epoch,
5759 next_epoch_protocol_version.as_u64(),
5760 gas_cost_summary.storage_cost,
5761 gas_cost_summary.computation_cost,
5762 gas_cost_summary.storage_rebate,
5763 gas_cost_summary.non_refundable_storage_fee,
5764 epoch_start_timestamp_ms,
5765 next_epoch_system_package_bytes,
5766 ));
5767 }
5768
5769 let tx = VerifiedTransaction::new_end_of_epoch_transaction(txns);
5770
5771 let executable_tx = VerifiedExecutableTransaction::new_from_checkpoint(
5772 tx.clone(),
5773 epoch_store.epoch(),
5774 checkpoint,
5775 );
5776
5777 let tx_digest = executable_tx.digest();
5778
5779 info!(
5780 ?next_epoch,
5781 ?next_epoch_protocol_version,
5782 ?next_epoch_system_packages,
5783 computation_cost=?gas_cost_summary.computation_cost,
5784 computation_cost_burned=?gas_cost_summary.computation_cost_burned,
5785 storage_cost=?gas_cost_summary.storage_cost,
5786 storage_rebate=?gas_cost_summary.storage_rebate,
5787 non_refundable_storage_fee=?gas_cost_summary.non_refundable_storage_fee,
5788 ?tx_digest,
5789 "Creating advance epoch transaction"
5790 );
5791
5792 fail_point_async!("change_epoch_tx_delay");
5793 let tx_lock = epoch_store.acquire_tx_lock(tx_digest);
5794
5795 if self
5799 .get_transaction_cache_reader()
5800 .try_is_tx_already_executed(tx_digest)?
5801 {
5802 warn!("change epoch tx has already been executed via state sync");
5803 return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
5804 }
5805
5806 let execution_guard = self.execution_lock_for_executable_transaction(&executable_tx)?;
5807
5808 let assigned_versions = epoch_store.assign_shared_object_versions_idempotent(
5812 self.get_object_cache_reader().as_ref(),
5813 std::iter::once(&Schedulable::Transaction(&executable_tx)),
5814 )?;
5815
5816 assert_eq!(assigned_versions.0.len(), 1);
5817 let assigned_versions = assigned_versions.0.into_iter().next().unwrap().1;
5818
5819 let (input_objects, _) = self.read_objects_for_execution(
5820 &tx_lock,
5821 &executable_tx,
5822 assigned_versions,
5823 epoch_store,
5824 )?;
5825
5826 let (temporary_store, effects, _execution_error_opt) = self.execute_transaction(
5827 &execution_guard,
5828 &executable_tx,
5829 input_objects,
5830 vec![],
5831 epoch_store,
5832 )?;
5833 let system_obj = get_iota_system_state(&temporary_store.written)
5834 .expect("change epoch tx must write to system object");
5835 let system_epoch_info_event = temporary_store
5837 .events
5838 .0
5839 .into_iter()
5840 .find(|event| event.is_system_epoch_info_event())
5841 .map(SystemEpochInfoEvent::from);
5842 assert!(system_epoch_info_event.is_some() || system_obj.safe_mode());
5845
5846 self.get_state_sync_store()
5850 .try_insert_transaction_and_effects(&tx, &effects)?;
5851
5852 info!(
5853 "Effects summary of the change epoch transaction: {:?}",
5854 effects.summary_for_debug()
5855 );
5856 epoch_store.record_checkpoint_builder_is_safe_mode_metric(system_obj.safe_mode());
5857 assert!(effects.status().is_success());
5859 Ok((system_obj, system_epoch_info_event, effects))
5860 }
5861
5862 #[instrument(level = "error", skip_all)]
5866 async fn revert_uncommitted_epoch_transactions(
5867 &self,
5868 epoch_store: &AuthorityPerEpochStore,
5869 ) -> IotaResult {
5870 {
5871 let state = epoch_store.get_reconfig_state_write_lock_guard();
5872 if state.should_accept_user_certs() {
5873 epoch_store.close_user_certs(state);
5882 }
5883 }
5885
5886 if !epoch_store.protocol_config().enable_pcool_flow() {
5889 let pending_certificates = epoch_store.pending_consensus_certificates();
5890 info!(
5891 "Reverting {} locally executed transactions that was not included in the epoch: \
5892 {:?}",
5893 pending_certificates.len(),
5894 pending_certificates,
5895 );
5896 for digest in pending_certificates {
5897 if epoch_store.is_transaction_executed_in_checkpoint(&digest)? {
5898 info!(
5899 "Not reverting pending consensus transaction {:?} - it was included in \
5900 checkpoint",
5901 digest
5902 );
5903 continue;
5904 }
5905 info!("Reverting {:?} at the end of epoch", digest);
5906 epoch_store.revert_executed_transaction(&digest)?;
5907 self.get_reconfig_api().try_revert_state_update(&digest)?;
5908 }
5909 info!("All uncommitted local transactions reverted");
5910 } else {
5911 info!("P-COOL mode: skipping revert of uncommitted epoch transactions");
5912 }
5913
5914 Ok(())
5915 }
5916
5917 #[instrument(level = "error", skip_all)]
5918 async fn reopen_epoch_db(
5919 &self,
5920 cur_epoch_store: &AuthorityPerEpochStore,
5921 new_committee: Committee,
5922 epoch_start_configuration: EpochStartConfiguration,
5923 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
5924 epoch_last_checkpoint: CheckpointSequenceNumber,
5925 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
5926 let new_epoch = new_committee.epoch;
5927 info!(new_epoch = ?new_epoch, "re-opening AuthorityEpochTables for new epoch");
5928 assert_eq!(
5929 epoch_start_configuration.epoch_start_state().epoch(),
5930 new_committee.epoch
5931 );
5932 fail_point!("before-open-new-epoch-store");
5933 let new_epoch_store = cur_epoch_store.new_at_next_epoch(
5934 self.name,
5935 new_committee,
5936 epoch_start_configuration,
5937 self.get_backing_package_store().clone(),
5938 expensive_safety_check_config,
5939 epoch_last_checkpoint,
5940 )?;
5941 self.epoch_store.store(new_epoch_store.clone());
5942 Ok(new_epoch_store)
5943 }
5944
5945 fn check_move_account_for_execution(
5967 &self,
5968 auth_account_object_id: ObjectId,
5969 auth_account_object_seq_number: Option<Version>,
5970 auth_account_object_digest: Option<ObjectDigest>,
5971 account_object: ObjectReadResult,
5972 signer: &Address,
5973 protocol_config: &ProtocolConfig,
5974 ) -> Result<AuthenticatorFunctionRefForExecution, ExecutionError> {
5975 match self.check_move_account(
5976 auth_account_object_id,
5977 auth_account_object_seq_number,
5978 auth_account_object_digest,
5979 account_object,
5980 signer,
5981 true,
5982 protocol_config,
5983 ) {
5984 Ok(function_ref) => Ok(function_ref),
5985 Err(MoveAccountCheckError::Input(input_error)) => {
5986 let status = match &input_error {
5987 UserInputError::MoveAuthenticatorNotFound {
5988 account_object_id, ..
5989 }
5990 | UserInputError::InvalidAuthenticatorFunctionRefField { account_object_id } => {
5991 ExecutionErrorKind::AuthenticatorFunctionNotFound {
5992 object_id: *account_object_id,
5993 }
5994 }
5995 UserInputError::AccountObjectNotSupported { object_id }
6000 | UserInputError::ImmutableAccountObjectNotSupported { object_id }
6001 | UserInputError::InvalidAccountObjectDigest { object_id, .. } => {
6002 ExecutionErrorKind::AccountNotSharedObject {
6003 object_id: *object_id,
6004 }
6005 }
6006 _ => ExecutionErrorKind::FunctionNotFound,
6009 };
6010 Err(ExecutionError::new_with_source(status, input_error))
6011 }
6012 Err(MoveAccountCheckError::Storage(storage_error)) => {
6013 panic!("failed to read the store while checking a Move account: {storage_error}")
6014 }
6015 }
6016 }
6017
6018 fn check_move_account_for_validation(
6022 &self,
6023 auth_account_object_id: ObjectId,
6024 auth_account_object_seq_number: Option<Version>,
6025 auth_account_object_digest: Option<ObjectDigest>,
6026 account_object: ObjectReadResult,
6027 signer: &Address,
6028 protocol_config: &ProtocolConfig,
6029 ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
6030 self.check_move_account(
6031 auth_account_object_id,
6032 auth_account_object_seq_number,
6033 auth_account_object_digest,
6034 account_object,
6035 signer,
6036 false,
6037 protocol_config,
6038 )
6039 .map_err(IotaError::from)
6040 }
6041
6042 fn check_move_account(
6059 &self,
6060 auth_account_object_id: ObjectId,
6061 auth_account_object_seq_number: Option<Version>,
6062 auth_account_object_digest: Option<ObjectDigest>,
6063 account_object: ObjectReadResult,
6064 signer: &Address,
6065 is_execution: bool,
6066 protocol_config: &ProtocolConfig,
6067 ) -> Result<AuthenticatorFunctionRefForExecution, MoveAccountCheckError> {
6068 let auth_account_object_seq_number = match (&account_object.object, is_execution) {
6069 (ObjectReadResultKind::Object(object), _) => {
6073 let account_object_addr = Address::from(auth_account_object_id);
6074 fp_ensure!(
6075 signer == &account_object_addr,
6076 UserInputError::IncorrectUserSignature {
6077 error: format!("Move authenticator is trying to unlock {account_object_addr:?}, but given signer address is {signer:?}")
6078 }
6079 .into()
6080 );
6081
6082 if protocol_config.reject_immutable_account_objects() {
6083 fp_ensure!(
6084 !object.is_immutable(),
6085 UserInputError::ImmutableAccountObjectNotSupported {
6086 object_id: auth_account_object_id
6087 }
6088 .into()
6089 );
6090 }
6091
6092 fp_ensure!(
6093 object.is_shared() || object.is_immutable(),
6094 UserInputError::AccountObjectNotSupported {
6095 object_id: auth_account_object_id
6096 }
6097 .into()
6098 );
6099
6100 let auth_account_object_seq_number =
6101 if let Some(expected_version) = auth_account_object_seq_number {
6102 let account_object_version = object.version();
6103
6104 fp_ensure!(
6105 account_object_version == expected_version,
6106 UserInputError::AccountObjectVersionMismatch {
6107 object_id: auth_account_object_id,
6108 expected_version,
6109 actual_version: account_object_version,
6110 }
6111 .into()
6112 );
6113
6114 expected_version
6115 } else {
6116 object.version()
6117 };
6118
6119 if let Some(expected_digest) = auth_account_object_digest {
6120 let account_object_digest = object.digest();
6121 fp_ensure!(
6122 account_object_digest == expected_digest,
6123 UserInputError::InvalidAccountObjectDigest {
6124 object_id: auth_account_object_id,
6125 expected_digest,
6126 actual_digest: account_object_digest,
6127 }
6128 .into()
6129 );
6130 }
6131
6132 Ok(auth_account_object_seq_number)
6133 }
6134 (ObjectReadResultKind::DeletedSharedObject(version, digest), false) => {
6137 Err(UserInputError::AccountObjectDeleted {
6138 account_id: account_object.id(),
6139 account_version: *version,
6140 transaction_digest: *digest,
6141 })
6142 }
6143 (ObjectReadResultKind::CancelledTransactionObject(version), false) => {
6147 Err(UserInputError::AccountObjectInCanceledTransaction {
6148 account_id: account_object.id(),
6149 account_version: *version,
6150 })
6151 }
6152 (ObjectReadResultKind::DeletedSharedObject(version, _), true) => Ok(*version),
6157 (ObjectReadResultKind::CancelledTransactionObject(version), true) => Ok(*version),
6163 (ObjectReadResultKind::UnreadSharedObject, _) => unreachable!(
6166 "only post-consensus validation at a commit lists an unread shared object, and \
6167 it leaves the account to execution"
6168 ),
6169 }?;
6170
6171 let authenticator_function_ref_field_id =
6172 derive_authenticator_function_ref_v1_dynamic_field_id(auth_account_object_id)?;
6173
6174 let authenticator_function_ref_field = self
6175 .get_object_cache_reader()
6176 .try_find_object_lt_or_eq_version(
6177 authenticator_function_ref_field_id,
6178 auth_account_object_seq_number,
6179 )
6180 .map_err(MoveAccountCheckError::Storage)?;
6181
6182 if let Some(authenticator_function_ref_field_obj) = authenticator_function_ref_field {
6183 Ok(authenticator_function_ref_v1_from_dynamic_field_object(
6184 auth_account_object_id,
6185 &authenticator_function_ref_field_obj,
6186 )?)
6187 } else {
6188 Err(UserInputError::MoveAuthenticatorNotFound {
6189 authenticator_function_ref_id: authenticator_function_ref_field_id,
6190 account_object_id: auth_account_object_id,
6191 account_object_version: auth_account_object_seq_number,
6192 }
6193 .into())
6194 }
6195 }
6196
6197 #[allow(clippy::type_complexity)]
6198 fn read_objects_for_validation(
6199 &self,
6200 transaction: &VerifiedTransaction,
6201 epoch: u64,
6202 ) -> IotaResult<(
6203 InputObjects,
6204 ReceivingObjects,
6205 Vec<(InputObjects, ObjectReadResult)>,
6206 )> {
6207 let (input_objects, tx_receiving_objects) = self.input_loader.read_objects_for_signing(
6208 Some(transaction.digest()),
6209 &transaction.collect_all_input_object_kind_for_reading()?,
6210 &transaction.data().transaction().receiving_objects(),
6211 epoch,
6212 )?;
6213
6214 transaction
6215 .split_input_objects_into_groups_for_reading(input_objects)
6216 .map(|(tx_input_objects, per_authenticator_inputs)| {
6217 (
6218 tx_input_objects,
6219 tx_receiving_objects,
6220 per_authenticator_inputs,
6221 )
6222 })
6223 }
6224
6225 fn read_objects_for_validation_at_commit(
6230 &self,
6231 reader: &CommitIndexedReader,
6232 transaction: &VerifiedTransaction,
6233 ) -> IotaResult<ValidationInputsAtCommit> {
6234 let input_objects = match self.input_loader.read_objects_at_commit(
6235 reader,
6236 &transaction.collect_all_input_object_kind_for_reading()?,
6237 )? {
6238 InputResolution::Loaded(input_objects) => input_objects,
6239 InputResolution::Drop(kind, reason) => {
6240 return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6241 }
6242 InputResolution::Missing(kind, reason) => {
6243 return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6244 }
6245 };
6246 let tx_receiving_objects = match self.input_loader.read_receiving_objects_at_commit(
6247 reader,
6248 &transaction.data().transaction().receiving_objects(),
6249 )? {
6250 ReceivingObjectsResolution::Loaded(receiving_objects) => receiving_objects,
6251 ReceivingObjectsResolution::Drop(kind, reason) => {
6252 return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6253 }
6254 ReceivingObjectsResolution::Missing(kind, reason) => {
6255 return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6256 }
6257 };
6258
6259 let (tx_input_objects, per_authenticator_inputs) =
6260 transaction.split_input_objects_into_groups_for_reading(input_objects)?;
6261 Ok(ValidationInputsAtCommit::Loaded {
6262 tx_input_objects,
6263 tx_receiving_objects,
6264 per_authenticator_inputs,
6265 })
6266 }
6267
6268 #[allow(clippy::type_complexity)]
6269 fn check_transaction_inputs_for_validation(
6270 &self,
6271 protocol_config: &ProtocolConfig,
6272 reference_gas_price: u64,
6273 tx: &Transaction,
6274 tx_input_objects: InputObjects,
6275 tx_receiving_objects: &ReceivingObjects,
6276 move_authenticators: &Vec<&MoveAuthenticator>,
6277 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6278 verifier_limits_source: VerifierLimitsSource<'_>,
6279 ) -> IotaResult<(
6280 IotaGasStatus,
6281 CheckedInputObjects,
6282 Vec<(CheckedInputObjects, AuthenticatorFunctionRef)>,
6283 )> {
6284 let authenticator_gas_budget = if move_authenticators.is_empty() {
6285 0
6286 } else {
6287 protocol_config.max_auth_gas()
6290 };
6291
6292 debug_assert_eq!(
6293 move_authenticators.len(),
6294 per_authenticator_inputs.len(),
6295 "Move authenticators amount must match the number of authenticator inputs"
6296 );
6297
6298 let per_authenticator_checked_inputs = move_authenticators
6299 .iter()
6300 .zip(per_authenticator_inputs)
6301 .map(
6302 |(move_authenticator, (authenticator_input_objects, account_object))| {
6303 let (
6305 auth_account_object_id,
6306 auth_account_object_seq_number,
6307 auth_account_object_digest,
6308 ) = move_authenticator.object_to_authenticate_components()?;
6309
6310 let signer = move_authenticator.address();
6311
6312 let AuthenticatorFunctionRefForExecution {
6314 authenticator_function_ref,
6315 ..
6316 } = self.check_move_account_for_validation(
6317 auth_account_object_id,
6318 auth_account_object_seq_number,
6319 auth_account_object_digest,
6320 account_object,
6321 &signer,
6322 protocol_config,
6323 )?;
6324
6325 let authenticator_checked_input_objects =
6327 iota_transaction_checks::check_move_authenticator_input_for_validation(
6328 authenticator_input_objects,
6329 )?;
6330
6331 Ok((
6332 authenticator_checked_input_objects,
6333 authenticator_function_ref,
6334 ))
6335 },
6336 )
6337 .collect::<IotaResult<Vec<_>>>()?;
6338
6339 let (gas_status, tx_checked_input_objects) =
6341 iota_transaction_checks::check_transaction_input(
6342 protocol_config,
6343 reference_gas_price,
6344 tx,
6345 tx_input_objects,
6346 tx_receiving_objects,
6347 &self.metrics.bytecode_verifier_metrics,
6348 verifier_limits_source,
6349 authenticator_gas_budget,
6350 )?;
6351
6352 Ok((
6353 gas_status,
6354 tx_checked_input_objects,
6355 per_authenticator_checked_inputs,
6356 ))
6357 }
6358
6359 fn check_transaction_inputs_at_commit(
6366 &self,
6367 protocol_config: &ProtocolConfig,
6368 reference_gas_price: u64,
6369 tx: &Transaction,
6370 tx_input_objects: InputObjects,
6371 tx_receiving_objects: &ReceivingObjects,
6372 move_authenticators: &[&MoveAuthenticator],
6373 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6374 verifier_limits_source: VerifierLimitsSource<'_>,
6375 ) -> IotaResult<CheckedValidationInputs> {
6376 let authenticator_gas_budget = if move_authenticators.is_empty() {
6377 0
6378 } else {
6379 protocol_config.max_auth_gas()
6380 };
6381
6382 debug_assert_eq!(
6383 move_authenticators.len(),
6384 per_authenticator_inputs.len(),
6385 "Move authenticators amount must match the number of authenticator inputs"
6386 );
6387
6388 let per_authenticator_checked_inputs = per_authenticator_inputs
6397 .into_iter()
6398 .map(|(authenticator_input_objects, _account_object)| {
6399 iota_transaction_checks::check_move_authenticator_input_for_validation(
6400 authenticator_input_objects,
6401 )
6402 })
6403 .collect::<IotaResult<Vec<_>>>()?;
6404
6405 let (_gas_status, tx_checked_input_objects) =
6407 iota_transaction_checks::check_transaction_input(
6408 protocol_config,
6409 reference_gas_price,
6410 tx,
6411 tx_input_objects,
6412 tx_receiving_objects,
6413 &self.metrics.bytecode_verifier_metrics,
6414 verifier_limits_source,
6415 authenticator_gas_budget,
6416 )?;
6417
6418 Ok((tx_checked_input_objects, per_authenticator_checked_inputs))
6419 }
6420
6421 #[cfg(test)]
6422 pub(crate) fn iter_live_object_set_for_testing(
6423 &self,
6424 ) -> impl Iterator<Item = authority_store_tables::LiveObject> + '_ {
6425 self.get_global_state_hash_store()
6426 .iter_cached_live_object_set_for_testing()
6427 }
6428
6429 #[cfg(test)]
6430 pub(crate) fn shutdown_execution_for_test(&self) {
6431 self.tx_execution_shutdown
6432 .lock()
6433 .take()
6434 .unwrap()
6435 .send(())
6436 .unwrap();
6437 }
6438
6439 pub async fn insert_objects_unsafe_for_testing_only(&self, objects: &[Object]) {
6442 self.get_reconfig_api().bulk_insert_genesis_objects(objects);
6443 self.get_object_cache_reader()
6444 .force_reload_system_packages(&BuiltInFramework::all_package_ids());
6445 self.get_reconfig_api()
6446 .clear_state_end_of_epoch(&self.execution_lock_for_reconfiguration().await);
6447 }
6448}
6449
6450pub struct RandomnessRoundReceiver {
6451 authority_state: Arc<AuthorityState>,
6452 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6453}
6454
6455impl RandomnessRoundReceiver {
6456 pub fn spawn(
6457 authority_state: Arc<AuthorityState>,
6458 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6459 ) -> JoinHandle<()> {
6460 let rrr = RandomnessRoundReceiver {
6461 authority_state,
6462 randomness_rx,
6463 };
6464 spawn_monitored_task!(rrr.run())
6465 }
6466
6467 async fn run(mut self) {
6468 info!("RandomnessRoundReceiver event loop started");
6469
6470 loop {
6471 tokio::select! {
6472 maybe_recv = self.randomness_rx.recv() => {
6473 if let Some((epoch, round, bytes)) = maybe_recv {
6474 self.handle_new_randomness(epoch, round, bytes).await;
6475 } else {
6476 break;
6477 }
6478 },
6479 }
6480 }
6481
6482 info!("RandomnessRoundReceiver event loop ended");
6483 }
6484
6485 #[instrument(level = "debug", skip_all, fields(?epoch, ?round))]
6486 async fn handle_new_randomness(&self, epoch: EpochId, round: RandomnessRound, bytes: Vec<u8>) {
6487 fail_point_async!("randomness-delay");
6488
6489 let epoch_store = self.authority_state.load_epoch_store_one_call_per_task();
6490 if epoch_store.epoch() != epoch {
6491 warn!(
6492 "dropping randomness for epoch {epoch}, round {round}, because we are in epoch {}",
6493 epoch_store.epoch()
6494 );
6495 return;
6496 }
6497 let key = TransactionKey::RandomnessRound(epoch, round);
6498 let transaction = VerifiedTransaction::new_randomness_state_update(
6499 epoch,
6500 round,
6501 bytes,
6502 epoch_store
6503 .epoch_start_config()
6504 .randomness_obj_initial_shared_version(),
6505 );
6506 debug!(
6507 "created randomness state update transaction with digest: {:?}",
6508 transaction.digest()
6509 );
6510 let transaction = VerifiedExecutableTransaction::new_system(transaction, epoch);
6511 let digest = *transaction.digest();
6512
6513 self.authority_state
6518 .get_cache_commit()
6519 .persist_transaction(&transaction);
6520
6521 if epoch_store.insert_tx_key(key, digest).is_err() {
6523 warn!("epoch ended while handling new randomness");
6524 }
6525
6526 match self.authority_state.execution_scheduler().as_ref() {
6528 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
6529 ExecutionSchedulerWrapper::TransactionManager(manager) => {
6530 manager.notify_transaction_key(&epoch_store, key, digest);
6534 }
6535 }
6536
6537 let authority_state = self.authority_state.clone();
6538 spawn_monitored_task!(async move {
6539 const RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT: Duration = Duration::from_secs(300);
6548 let result = tokio::time::timeout(
6549 RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT,
6550 authority_state
6551 .get_transaction_cache_reader()
6552 .try_notify_read_executed_effects(
6553 "RandomnessRoundReceiver::notify_read_executed_effects_first",
6554 &[digest],
6555 ),
6556 )
6557 .await;
6558 let result = match result {
6559 Ok(result) => result,
6560 Err(_) => {
6561 if cfg!(debug_assertions) {
6562 panic!(
6564 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6565 );
6566 }
6567 warn!(
6568 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6569 );
6570 authority_state
6572 .get_transaction_cache_reader()
6573 .try_notify_read_executed_effects(
6574 "RandomnessRoundReceiver::notify_read_executed_effects_second",
6575 &[digest],
6576 )
6577 .await
6578 }
6579 };
6580
6581 let mut effects = result.unwrap_or_else(|_| panic!("failed to get effects for randomness state update transaction at epoch {epoch}, round {round}"));
6582 let effects = effects.pop().expect("should return effects");
6583 if *effects.status() != ExecutionStatus::Success {
6584 fatal!(
6585 "failed to execute randomness state update transaction at epoch {epoch}, round {round}: {effects:?}"
6586 );
6587 }
6588 debug!(
6589 "successfully executed randomness state update transaction at epoch {epoch}, round {round}"
6590 );
6591 });
6592 }
6593}
6594
6595#[async_trait]
6596impl TransactionKeyValueStoreTrait for AuthorityState {
6597 async fn multi_get(
6598 &self,
6599 transaction_keys: &[TransactionDigest],
6600 effects_keys: &[TransactionDigest],
6601 ) -> IotaResult<KVStoreTransactionData> {
6602 let txns = if !transaction_keys.is_empty() {
6603 self.get_transaction_cache_reader()
6604 .try_multi_get_transaction_blocks(transaction_keys)?
6605 .into_iter()
6606 .map(|t| t.map(|t| (*t).clone().into_inner()))
6607 .collect()
6608 } else {
6609 vec![]
6610 };
6611
6612 let fx = if !effects_keys.is_empty() {
6613 self.get_transaction_cache_reader()
6614 .try_multi_get_executed_effects(effects_keys)?
6615 } else {
6616 vec![]
6617 };
6618
6619 Ok((txns, fx))
6620 }
6621
6622 async fn multi_get_checkpoints(
6623 &self,
6624 checkpoint_summaries: &[CheckpointSequenceNumber],
6625 checkpoint_contents: &[CheckpointSequenceNumber],
6626 checkpoint_summaries_by_digest: &[CheckpointDigest],
6627 ) -> IotaResult<(
6628 Vec<Option<CertifiedCheckpointSummary>>,
6629 Vec<Option<CheckpointContents>>,
6630 Vec<Option<CertifiedCheckpointSummary>>,
6631 )> {
6632 let mut summaries = Vec::with_capacity(checkpoint_summaries.len());
6634 let store = self.get_checkpoint_store();
6635 for seq in checkpoint_summaries {
6636 let checkpoint = store
6637 .get_checkpoint_by_sequence_number(*seq)?
6638 .map(|c| c.into_inner());
6639
6640 summaries.push(checkpoint);
6641 }
6642
6643 let mut contents = Vec::with_capacity(checkpoint_contents.len());
6644 for seq in checkpoint_contents {
6645 let checkpoint = store
6646 .get_checkpoint_by_sequence_number(*seq)?
6647 .and_then(|summary| {
6648 store
6649 .get_checkpoint_contents(&summary.contents_digest)
6650 .expect("db read cannot fail")
6651 });
6652 contents.push(checkpoint);
6653 }
6654
6655 let mut summaries_by_digest = Vec::with_capacity(checkpoint_summaries_by_digest.len());
6656 for digest in checkpoint_summaries_by_digest {
6657 let checkpoint = store
6658 .get_checkpoint_by_digest(digest)?
6659 .map(|c| c.into_inner());
6660 summaries_by_digest.push(checkpoint);
6661 }
6662
6663 Ok((summaries, contents, summaries_by_digest))
6664 }
6665
6666 async fn get_transaction_perpetual_checkpoint(
6667 &self,
6668 digest: TransactionDigest,
6669 ) -> IotaResult<Option<CheckpointSequenceNumber>> {
6670 self.get_checkpoint_cache()
6671 .try_get_transaction_perpetual_checkpoint(&digest)
6672 .map(|res| res.map(|(_epoch, checkpoint)| checkpoint))
6673 }
6674
6675 async fn get_object(
6676 &self,
6677 object_id: ObjectId,
6678 version: VersionNumber,
6679 ) -> IotaResult<Option<Object>> {
6680 self.get_object_cache_reader()
6681 .try_get_object_by_key(&object_id, version)
6682 }
6683
6684 #[instrument(skip_all)]
6685 async fn multi_get_objects(
6686 &self,
6687 object_keys: &[ObjectKey],
6688 ) -> IotaResult<Vec<Option<Object>>> {
6689 Ok(self
6690 .get_object_cache_reader()
6691 .multi_get_objects_by_key(object_keys))
6692 }
6693
6694 async fn multi_get_transactions_perpetual_checkpoints(
6695 &self,
6696 digests: &[TransactionDigest],
6697 ) -> IotaResult<Vec<Option<CheckpointSequenceNumber>>> {
6698 let res = self
6699 .get_checkpoint_cache()
6700 .try_multi_get_transactions_perpetual_checkpoints(digests)?;
6701
6702 Ok(res
6703 .into_iter()
6704 .map(|maybe| maybe.map(|(_epoch, checkpoint)| checkpoint))
6705 .collect())
6706 }
6707
6708 #[instrument(skip(self, digests), fields(digests = digests.iter().map(|d| d.to_string()).collect::<Vec<String>>().join(", ")))]
6709 async fn multi_get_events_by_tx_digests(
6710 &self,
6711 digests: &[TransactionDigest],
6712 ) -> IotaResult<Vec<Option<TransactionEvents>>> {
6713 if digests.is_empty() {
6714 return Ok(vec![]);
6715 }
6716
6717 Ok(self
6718 .get_transaction_cache_reader()
6719 .multi_get_events(digests))
6720 }
6721}
6722
6723#[cfg(msim)]
6724pub mod framework_injection {
6725 use std::{
6726 cell::RefCell,
6727 collections::{BTreeMap, BTreeSet},
6728 };
6729
6730 use iota_framework::{BuiltInFramework, SystemPackage};
6731 use iota_sdk_types::ObjectId;
6732 use iota_types::base_types::AuthorityName;
6733 use move_binary_format::CompiledModule;
6734
6735 type FrameworkOverrideConfig = BTreeMap<ObjectId, PackageOverrideConfig>;
6736
6737 thread_local! {
6739 static OVERRIDE: RefCell<FrameworkOverrideConfig> = RefCell::new(FrameworkOverrideConfig::default());
6740 }
6741
6742 type Framework = Vec<CompiledModule>;
6743
6744 pub type PackageUpgradeCallback =
6745 Box<dyn Fn(AuthorityName) -> Option<Framework> + Send + Sync + 'static>;
6746
6747 enum PackageOverrideConfig {
6748 Global(Framework),
6749 PerValidator(PackageUpgradeCallback),
6750 }
6751
6752 fn compiled_modules_to_bytes(modules: &[CompiledModule]) -> Vec<Vec<u8>> {
6753 modules
6754 .iter()
6755 .map(|m| {
6756 let mut buf = Vec::new();
6757 m.serialize_with_version(m.version, &mut buf).unwrap();
6758 buf
6759 })
6760 .collect()
6761 }
6762
6763 pub fn set_override(package_id: ObjectId, modules: Vec<CompiledModule>) {
6764 OVERRIDE.with(|bs| {
6765 bs.borrow_mut()
6766 .insert(package_id, PackageOverrideConfig::Global(modules))
6767 });
6768 }
6769
6770 pub fn set_override_cb(package_id: ObjectId, func: PackageUpgradeCallback) {
6771 OVERRIDE.with(|bs| {
6772 bs.borrow_mut()
6773 .insert(package_id, PackageOverrideConfig::PerValidator(func))
6774 });
6775 }
6776
6777 pub fn get_override_bytes(package_id: &ObjectId, name: AuthorityName) -> Option<Vec<Vec<u8>>> {
6778 OVERRIDE.with(|cfg| {
6779 cfg.borrow().get(package_id).and_then(|entry| match entry {
6780 PackageOverrideConfig::Global(framework) => {
6781 Some(compiled_modules_to_bytes(framework))
6782 }
6783 PackageOverrideConfig::PerValidator(func) => {
6784 func(name).map(|fw| compiled_modules_to_bytes(&fw))
6785 }
6786 })
6787 })
6788 }
6789
6790 pub fn get_override_modules(
6791 package_id: &ObjectId,
6792 name: AuthorityName,
6793 ) -> Option<Vec<CompiledModule>> {
6794 OVERRIDE.with(|cfg| {
6795 cfg.borrow().get(package_id).and_then(|entry| match entry {
6796 PackageOverrideConfig::Global(framework) => Some(framework.clone()),
6797 PackageOverrideConfig::PerValidator(func) => func(name),
6798 })
6799 })
6800 }
6801
6802 pub fn get_override_system_package(
6803 package_id: &ObjectId,
6804 name: AuthorityName,
6805 ) -> Option<SystemPackage> {
6806 let bytes = get_override_bytes(package_id, name)?;
6807 let dependencies = BuiltInFramework::try_get_package_by_id(package_id)
6811 .map_or_else(BuiltInFramework::all_package_ids, |package| {
6812 package.dependencies.to_vec()
6813 });
6814 Some(SystemPackage {
6815 id: *package_id,
6816 bytes,
6817 dependencies,
6818 })
6819 }
6820
6821 pub fn get_extra_packages(name: AuthorityName) -> Vec<SystemPackage> {
6822 let built_in = BTreeSet::from_iter(BuiltInFramework::all_package_ids());
6823 let extra: Vec<ObjectId> = OVERRIDE.with(|cfg| {
6824 cfg.borrow()
6825 .keys()
6826 .filter_map(|package| (!built_in.contains(package)).then_some(*package))
6827 .collect()
6828 });
6829
6830 extra
6831 .into_iter()
6832 .map(|package| SystemPackage {
6833 id: package,
6834 bytes: get_override_bytes(&package, name).unwrap(),
6835 dependencies: BuiltInFramework::all_package_ids(),
6836 })
6837 .collect()
6838 }
6839}
6840
6841#[derive(Debug, Serialize, Deserialize, Clone)]
6842pub struct ObjDumpFormat {
6843 pub id: ObjectId,
6844 pub version: VersionNumber,
6845 pub digest: ObjectDigest,
6846 pub object: Object,
6847}
6848
6849impl ObjDumpFormat {
6850 fn new(object: Object) -> Self {
6851 let oref = object.object_ref();
6852 Self {
6853 id: oref.object_id,
6854 version: oref.version,
6855 digest: oref.digest,
6856 object,
6857 }
6858 }
6859}
6860
6861#[derive(Debug, Serialize, Deserialize, Clone)]
6862pub struct NodeStateDump {
6863 pub tx_digest: TransactionDigest,
6864 pub sender_signed_data: SenderSignedTransaction,
6865 pub executed_epoch: u64,
6866 pub reference_gas_price: u64,
6867 pub protocol_version: u64,
6868 pub epoch_start_timestamp_ms: u64,
6869 pub computed_effects: TransactionEffects,
6870 pub expected_effects_digest: TransactionEffectsDigest,
6871 pub relevant_system_packages: Vec<ObjDumpFormat>,
6872 pub shared_objects: Vec<ObjDumpFormat>,
6873 pub loaded_child_objects: Vec<ObjDumpFormat>,
6874 pub modified_at_versions: Vec<ObjDumpFormat>,
6875 pub runtime_reads: Vec<ObjDumpFormat>,
6876 pub input_objects: Vec<ObjDumpFormat>,
6877}
6878
6879impl NodeStateDump {
6880 pub fn new(
6881 tx_digest: &TransactionDigest,
6882 effects: &TransactionEffects,
6883 expected_effects_digest: TransactionEffectsDigest,
6884 object_store: &dyn ObjectStore,
6885 epoch_store: &Arc<AuthorityPerEpochStore>,
6886 inner_temporary_store: &InnerTemporaryStore,
6887 transaction: &VerifiedExecutableTransaction,
6888 ) -> IotaResult<Self> {
6889 let executed_epoch = epoch_store.epoch();
6891 let reference_gas_price = epoch_store.reference_gas_price();
6892 let epoch_start_config = epoch_store.epoch_start_config();
6893 let protocol_version = epoch_store.protocol_version().as_u64();
6894 let epoch_start_timestamp_ms = epoch_start_config.epoch_data().epoch_start_timestamp();
6895
6896 let mut relevant_system_packages = Vec::new();
6898 for sys_package_id in BuiltInFramework::all_package_ids() {
6899 if let Some(w) = object_store.try_get_object(&sys_package_id)? {
6900 relevant_system_packages.push(ObjDumpFormat::new(w))
6901 }
6902 }
6903
6904 let mut shared_objects = Vec::new();
6906 for kind in effects.input_shared_objects() {
6907 match kind {
6908 InputSharedObject::Mutate(obj_ref) | InputSharedObject::ReadOnly(obj_ref) => {
6909 if let Some(w) =
6910 object_store.try_get_object_by_key(&obj_ref.object_id, obj_ref.version)?
6911 {
6912 shared_objects.push(ObjDumpFormat::new(w))
6913 }
6914 }
6915 InputSharedObject::ReadDeleted(..)
6916 | InputSharedObject::MutateDeleted(..)
6917 | InputSharedObject::Canceled(..) => (),
6919 _ => unimplemented!(
6920 "a new InputSharedObject enum variant was added and needs to be handled"
6921 ),
6922 }
6923 }
6924
6925 let mut loaded_child_objects = Vec::new();
6928 for (id, meta) in &inner_temporary_store.loaded_runtime_objects {
6929 if let Some(w) = object_store.try_get_object_by_key(id, meta.version)? {
6930 loaded_child_objects.push(ObjDumpFormat::new(w))
6931 }
6932 }
6933
6934 let mut modified_at_versions = Vec::new();
6936 for modified in effects.modified_at_versions() {
6937 let (id, ver) = (modified.object_id(), modified.version());
6938 if let Some(w) = object_store.try_get_object_by_key(id, ver)? {
6939 modified_at_versions.push(ObjDumpFormat::new(w))
6940 }
6941 }
6942
6943 let mut runtime_reads = Vec::new();
6947 for obj in inner_temporary_store
6948 .runtime_packages_loaded_from_db
6949 .values()
6950 {
6951 runtime_reads.push(ObjDumpFormat::new(obj.object().clone()));
6952 }
6953
6954 Ok(Self {
6957 tx_digest: *tx_digest,
6958 executed_epoch,
6959 reference_gas_price,
6960 epoch_start_timestamp_ms,
6961 protocol_version,
6962 relevant_system_packages,
6963 shared_objects,
6964 loaded_child_objects,
6965 modified_at_versions,
6966 runtime_reads,
6967 sender_signed_data: transaction.clone().into_message(),
6968 input_objects: inner_temporary_store
6969 .input_objects
6970 .values()
6971 .map(|o| ObjDumpFormat::new(o.clone()))
6972 .collect(),
6973 computed_effects: effects.clone(),
6974 expected_effects_digest,
6975 })
6976 }
6977
6978 pub fn all_objects(&self) -> Vec<ObjDumpFormat> {
6979 let mut objects = Vec::new();
6980 objects.extend(self.relevant_system_packages.clone());
6981 objects.extend(self.shared_objects.clone());
6982 objects.extend(self.loaded_child_objects.clone());
6983 objects.extend(self.modified_at_versions.clone());
6984 objects.extend(self.runtime_reads.clone());
6985 objects.extend(self.input_objects.clone());
6986 objects
6987 }
6988
6989 pub fn write_to_file(&self, path: &Path) -> Result<PathBuf, anyhow::Error> {
6990 let file_name = format!(
6991 "{}_{}_NODE_DUMP.json",
6992 self.tx_digest,
6993 AuthorityState::unixtime_now_ms()
6994 );
6995 let mut path = path.to_path_buf();
6996 path.push(&file_name);
6997 let mut file = File::create(path.clone())?;
6998 file.write_all(serde_json::to_string_pretty(self)?.as_bytes())?;
6999 Ok(path)
7000 }
7001
7002 pub fn read_from_file(path: &PathBuf) -> Result<Self, anyhow::Error> {
7003 let file = File::open(path)?;
7004 serde_json::from_reader(file).map_err(|e| anyhow::anyhow!(e))
7005 }
7006}
7007
7008enum MoveAccountCheckError {
7012 Input(UserInputError),
7014
7015 Storage(IotaError),
7017}
7018
7019impl From<UserInputError> for MoveAccountCheckError {
7020 fn from(error: UserInputError) -> Self {
7021 Self::Input(error)
7022 }
7023}
7024
7025impl From<MoveAccountCheckError> for IotaError {
7026 fn from(error: MoveAccountCheckError) -> Self {
7027 match error {
7028 MoveAccountCheckError::Input(error) => IotaError::UserInput { error },
7029 MoveAccountCheckError::Storage(error) => error,
7030 }
7031 }
7032}
7033
7034fn pre_consensus_move_authenticators<'a>(
7046 tx: &'a VerifiedTransaction,
7047 protocol_config: &ProtocolConfig,
7048) -> Vec<&'a MoveAuthenticator> {
7049 if protocol_config.pre_consensus_sponsor_only_move_authentication() {
7050 if tx.transaction().is_sponsored_tx() {
7051 if let Some(sponsor_move_authenticator) = tx.sponsor_move_authenticator() {
7052 vec![sponsor_move_authenticator]
7053 } else {
7054 vec![]
7055 }
7056 } else {
7057 tx.move_authenticators()
7058 }
7059 } else {
7060 tx.move_authenticators()
7061 }
7062}