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(
2544 &self,
2545 transaction: Transaction,
2546 checks: VmChecks,
2547 ) -> IotaResult<SimulateTransactionResult> {
2548 let epoch_store = self.load_epoch_store_one_call_per_task();
2549 self.simulate_transaction_in_epoch(&epoch_store, transaction, checks)
2550 }
2551
2552 #[instrument("simulate_tx", level = "trace", skip_all)]
2566 pub fn simulate_transaction_in_epoch(
2567 &self,
2568 epoch_store: &AuthorityPerEpochStore,
2569 transaction: Transaction,
2570 checks: VmChecks,
2571 ) -> IotaResult<SimulateTransactionResult> {
2572 if !self.is_fullnode(epoch_store) {
2573 return Err(IotaError::UnsupportedFeature {
2574 error: "simulate is only supported on fullnodes".to_string(),
2575 });
2576 }
2577
2578 self.simulate_transaction_inner(epoch_store, transaction, checks)
2579 }
2580
2581 pub fn simulate_transaction_for_benchmark(
2585 &self,
2586 transaction: Transaction,
2587 checks: VmChecks,
2588 ) -> IotaResult<SimulateTransactionResult> {
2589 let epoch_store = self.load_epoch_store_one_call_per_task();
2590 self.simulate_transaction_inner(&epoch_store, transaction, checks)
2591 }
2592
2593 #[instrument(level = "trace", skip_all)]
2594 fn simulate_transaction_inner(
2595 &self,
2596 epoch_store: &AuthorityPerEpochStore,
2597 mut transaction: Transaction,
2598 checks: VmChecks,
2599 ) -> IotaResult<SimulateTransactionResult> {
2600 if transaction.kind().is_system() {
2601 return Err(IotaError::UnsupportedFeature {
2602 error: "simulate does not support system transactions".to_string(),
2603 });
2604 }
2605
2606 transaction.check_serialized_size(epoch_store.protocol_config())?;
2607
2608 transaction.validity_check_no_gas_check(epoch_store.protocol_config())?;
2612
2613 transaction.check_gas_payment_size(epoch_store.protocol_config())?;
2617
2618 let input_object_kinds = transaction.input_objects()?;
2619 let receiving_object_refs = transaction.receiving_objects();
2620
2621 iota_transaction_checks::deny::check_transaction_for_validation(
2624 &transaction,
2625 &[],
2626 &input_object_kinds,
2627 &receiving_object_refs,
2628 &self.config.transaction_deny_config,
2629 self.get_backing_package_store().as_ref(),
2630 )?;
2631
2632 let (mut input_objects, receiving_objects) = self.input_loader.read_objects_for_signing(
2634 None,
2636 &input_object_kinds,
2637 &receiving_object_refs,
2638 epoch_store.epoch(),
2639 )?;
2640
2641 let mock_gas_id = if transaction.gas().is_empty() {
2643 let mock_gas_object = mock_simulation_gas_coin(transaction.gas_data().owner);
2644 let mock_gas_object_ref = mock_gas_object.object_ref();
2645 transaction.gas_data_mut().objects = vec![mock_gas_object_ref];
2646 input_objects.push(ObjectReadResult::new_from_gas_object(&mock_gas_object));
2647 Some(mock_gas_object.id())
2648 } else {
2649 None
2650 };
2651
2652 let protocol_config = epoch_store.protocol_config();
2653
2654 iota_types::gas::fill_in_unset_simulation_gas(
2655 &mut transaction,
2656 &input_objects,
2657 epoch_store.reference_gas_price(),
2658 protocol_config,
2659 );
2660
2661 let authenticator_gas_budget = 0;
2664
2665 let (gas_status, checked_input_objects) = if checks.enabled() {
2668 iota_transaction_checks::check_transaction_input(
2669 protocol_config,
2670 epoch_store.reference_gas_price(),
2671 &transaction,
2672 input_objects,
2673 &receiving_objects,
2674 &self.metrics.bytecode_verifier_metrics,
2675 VerifierLimitsSource::NodeConfig(&self.config.verifier_signing_config),
2676 authenticator_gas_budget,
2677 )?
2678 } else {
2679 iota_types::gas::check_gas_coins_cover_budget_in_simulation(
2685 &input_objects,
2686 transaction.gas(),
2687 transaction.gas_budget(),
2688 )?;
2689
2690 let checked_input_objects = iota_transaction_checks::check_simulation_input(
2691 protocol_config,
2692 transaction.kind(),
2693 input_objects,
2694 receiving_objects,
2695 )?;
2696 let gas_status = IotaGasStatus::new(
2697 transaction.gas_budget(),
2698 transaction.gas_price(),
2699 epoch_store.reference_gas_price(),
2700 protocol_config,
2701 )?;
2702
2703 (gas_status, checked_input_objects)
2704 };
2705
2706 let executor = iota_execution::executor(
2708 protocol_config,
2709 true, None,
2711 )
2712 .expect("Creating an executor should not fail here");
2713
2714 let (kind, signer, gas_data) = transaction.execution_parts();
2716 let (inner_temp_store, _, effects, execution_result) = executor.dev_inspect_transaction(
2717 self.get_backing_store().as_ref(),
2718 protocol_config,
2719 self.metrics.limits_metrics.clone(),
2720 false, self.config.certificate_deny_config.certificate_deny_set(),
2722 &epoch_store.epoch_start_config().epoch_data().epoch_id(),
2723 epoch_store
2724 .epoch_start_config()
2725 .epoch_data()
2726 .epoch_start_timestamp(),
2727 checked_input_objects,
2728 gas_data,
2729 gas_status,
2730 kind,
2731 signer,
2732 transaction.digest(),
2733 checks.disabled(),
2734 );
2735
2736 let mut input_objects = inner_temp_store.input_objects;
2737 iota_types::storage::extend_input_objects_with_loaded_runtime_objects(
2738 &mut input_objects,
2739 &effects,
2740 &inner_temp_store.loaded_runtime_objects,
2741 self.get_backing_store().as_object_store(),
2742 );
2743
2744 Ok(SimulateTransactionResult {
2745 input_objects,
2746 output_objects: inner_temp_store.written,
2747 events: effects.events_digest().map(|_| inner_temp_store.events),
2748 effects,
2749 execution_result,
2750 suggested_gas_price: self
2751 .congestion_tracker
2752 .get_prediction_suggested_gas_price(&transaction),
2753 mock_gas_id,
2754 gas_data: transaction.gas_data().clone(),
2755 })
2756 }
2757
2758 pub fn reference_gas_price_for_testing(&self) -> Result<u64, anyhow::Error> {
2760 let epoch_store = self.epoch_store_for_testing();
2761 Ok(epoch_store.reference_gas_price())
2762 }
2763
2764 #[instrument(level = "trace", skip_all)]
2765 pub fn try_is_tx_already_executed(&self, digest: &TransactionDigest) -> IotaResult<bool> {
2766 self.get_transaction_cache_reader()
2767 .try_is_tx_already_executed(digest)
2768 }
2769
2770 pub fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
2772 self.try_is_tx_already_executed(digest)
2773 .expect("storage access failed")
2774 }
2775
2776 #[instrument(level = "debug", skip_all, err)]
2778 fn index_tx(
2779 &self,
2780 indexes: &IndexStore,
2781 digest: &TransactionDigest,
2782 transaction: &VerifiedExecutableTransaction,
2784 effects: &TransactionEffects,
2785 events: &TransactionEvents,
2786 timestamp_ms: u64,
2787 tx_coins: Option<TxCoins>,
2788 written: &WrittenObjects,
2789 inner_temporary_store: &InnerTemporaryStore,
2790 epoch_store: &Arc<AuthorityPerEpochStore>,
2791 ) -> IotaResult<u64> {
2792 let changes = self
2793 .process_object_index(effects, written, inner_temporary_store, epoch_store)
2794 .tap_err(|e| warn!(tx_digest=?digest, "Failed to process object index, index_tx is skipped: {e}"))?;
2795
2796 indexes.index_tx(
2797 transaction.data().transaction().sender(),
2798 transaction
2799 .data()
2800 .transaction()
2801 .input_objects()?
2802 .iter()
2803 .map(|o| o.object_id()),
2804 effects
2805 .all_changed_objects()
2806 .into_iter()
2807 .map(|(changed, _kind)| (*changed.reference(), *changed.owner())),
2808 transaction
2809 .data()
2810 .transaction()
2811 .move_calls()
2812 .into_iter()
2813 .map(|(package, module, function)| {
2814 (*package, module.to_owned(), function.to_owned())
2815 }),
2816 events,
2817 changes,
2818 digest,
2819 timestamp_ms,
2820 tx_coins,
2821 )
2822 }
2823
2824 #[cfg(msim)]
2825 fn create_fail_state(
2826 &self,
2827 transaction: &VerifiedExecutableTransaction,
2828 epoch_store: &Arc<AuthorityPerEpochStore>,
2829 effects: &mut TransactionEffects,
2830 ) {
2831 use std::cell::RefCell;
2832
2833 use iota_types::effects::TransactionEffectsAPIForTesting;
2834 thread_local! {
2835 static FAIL_STATE: RefCell<(u64, HashSet<AuthorityName>)> = RefCell::new((0, HashSet::new()));
2836 }
2837 if !transaction.data().transaction().is_system_tx() {
2838 let committee = epoch_store.committee();
2839 let cur_stake = (**committee).weight(&self.name);
2840 if cur_stake > 0 {
2841 FAIL_STATE.with_borrow_mut(|fail_state| {
2842 if fail_state.0 < committee.validity_threshold() {
2844 fail_state.0 += cur_stake;
2845 fail_state.1.insert(self.name);
2846 }
2847
2848 if fail_state.1.contains(&self.name) {
2849 info!("cp_exec failing tx");
2850 effects.gas_cost_summary_mut_for_testing().computation_cost += 1;
2851 }
2852 });
2853 }
2854 }
2855 }
2856
2857 fn process_object_index(
2858 &self,
2859 effects: &TransactionEffects,
2860 written: &WrittenObjects,
2861 inner_temporary_store: &InnerTemporaryStore,
2862 epoch_store: &Arc<AuthorityPerEpochStore>,
2863 ) -> IotaResult<ObjectIndexChanges> {
2864 let mut layout_resolver =
2865 epoch_store
2866 .executor()
2867 .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
2868 inner_temporary_store,
2869 self.get_backing_package_store(),
2870 )));
2871
2872 let modified_at_version = effects
2873 .modified_at_versions()
2874 .into_iter()
2875 .map(|modified| (*modified.object_id(), modified.version()))
2876 .collect::<HashMap<_, _>>();
2877
2878 let tx_digest = effects.transaction_digest();
2879 let mut deleted_owners = vec![];
2880 let mut deleted_dynamic_fields = vec![];
2881 for object_ref in effects.deleted().into_iter().chain(effects.wrapped()) {
2882 let old_version = modified_at_version.get(&object_ref.object_id).unwrap();
2883 match self.get_owner_at_version(&object_ref.object_id, *old_version).unwrap_or_else(
2886 |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)
2887 ) {
2888 Owner::Address(addr) => deleted_owners.push((addr, object_ref.object_id)),
2889 Owner::Object(object_id) => {
2890 deleted_dynamic_fields.push((object_id, object_ref.object_id))
2891 }
2892 _ => {}
2893 }
2894 }
2895
2896 let mut new_owners = vec![];
2897 let mut new_dynamic_fields = vec![];
2898
2899 for (changed, kind) in effects.all_changed_objects() {
2900 let (oref, owner) = (*changed.reference(), *changed.owner());
2901 let id = &oref.object_id;
2902 if let WriteKind::Mutate = kind {
2905 let Some(old_version) = modified_at_version.get(id) else {
2906 panic!(
2907 "tx_digest={tx_digest}, error processing object owner index, cannot find modified at version for mutated object [{id}]."
2908 );
2909 };
2910 let Some(old_object) = self
2913 .get_object_store()
2914 .try_get_object_by_key(id, *old_version)?
2915 else {
2916 panic!(
2917 "tx_digest={tx_digest}, error processing object owner index, cannot find owner for object {id} at version {old_version:?}"
2918 );
2919 };
2920 if old_object.owner != owner {
2921 match old_object.owner {
2922 Owner::Address(addr) => {
2923 deleted_owners.push((addr, *id));
2924 }
2925 Owner::Object(object_id) => deleted_dynamic_fields.push((object_id, *id)),
2926 _ => {}
2927 }
2928 }
2929 }
2930
2931 match owner {
2932 Owner::Address(addr) => {
2933 let new_object = written.get(id).unwrap_or_else(
2936 || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2937 );
2938 assert_eq!(
2939 new_object.version(),
2940 oref.version,
2941 "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2942 tx_digest,
2943 id,
2944 new_object.version(),
2945 oref.version
2946 );
2947
2948 let object_type = new_object
2949 .data
2950 .opt_object_type()
2951 .map(|ty| ObjectType::Struct(ty.clone()))
2952 .unwrap_or(ObjectType::Package);
2953
2954 new_owners.push((
2955 (addr, *id),
2956 ObjectInfo {
2957 object_id: *id,
2958 version: oref.version,
2959 digest: oref.digest,
2960 object_type,
2961 owner,
2962 previous_transaction: *effects.transaction_digest(),
2963 },
2964 ));
2965 }
2966 Owner::Object(owner) => {
2967 let new_object = written.get(id).unwrap_or_else(
2968 || panic!("tx_digest={tx_digest}, error processing object owner index, written does not contain object {id}")
2969 );
2970 assert_eq!(
2971 new_object.version(),
2972 oref.version,
2973 "tx_digest={} error processing object owner index, object {} from written has mismatched version. Actual: {}, expected: {}",
2974 tx_digest,
2975 id,
2976 new_object.version(),
2977 oref.version
2978 );
2979
2980 let Some(df_info) = self
2981 .try_create_dynamic_field_info(new_object, written, layout_resolver.as_mut())
2982 .unwrap_or_else(|e| {
2983 error!(
2984 "try_create_dynamic_field_info should not fail, {}, new_object={}, new_object_type={}",
2985 e,
2986 new_object.id(),
2987 ObjectType::from(new_object)
2988 );
2989 None
2990 }
2991 )
2992 else {
2993 continue;
2995 };
2996 new_dynamic_fields.push(((owner, *id), df_info))
2997 }
2998 _ => {}
2999 }
3000 }
3001
3002 Ok(ObjectIndexChanges {
3003 deleted_owners,
3004 deleted_dynamic_fields,
3005 new_owners,
3006 new_dynamic_fields,
3007 })
3008 }
3009
3010 fn try_create_dynamic_field_info(
3011 &self,
3012 o: &Object,
3013 written: &WrittenObjects,
3014 resolver: &mut dyn LayoutResolver,
3015 ) -> IotaResult<Option<DynamicFieldInfo>> {
3016 let Some(move_object) = o.data.as_opt_struct().cloned() else {
3018 return Ok(None);
3019 };
3020
3021 if !move_object.struct_tag().is_dynamic_field() {
3023 return Ok(None);
3024 }
3025
3026 let layout = match resolver.get_annotated_layout(move_object.struct_tag()) {
3027 Ok(annotated_layout) => annotated_layout.into_layout(),
3028 Err(e) => {
3029 error!(
3030 "unable to load layout for type `{:?}`: {e}",
3031 move_object.struct_tag()
3032 );
3033 return Ok(None);
3034 }
3035 };
3036
3037 let field =
3038 DFV::FieldVisitor::deserialize(move_object.contents(), &layout).map_err(|e| {
3039 IotaError::ObjectDeserialization {
3040 error: e.to_string(),
3041 }
3042 })?;
3043
3044 let type_ = field.kind;
3045 let name_type: TypeTag = type_tag_core_to_sdk(&field.name_layout.into());
3046 let bcs_name = field.name_bytes.to_owned();
3047
3048 let name_value = BoundedVisitor::deserialize_value(field.name_bytes, field.name_layout)
3049 .map_err(|e| {
3050 warn!("{e}");
3051 IotaError::ObjectDeserialization {
3052 error: e.to_string(),
3053 }
3054 })?;
3055
3056 let name = DynamicFieldName {
3057 type_tag: name_type,
3058 value: IotaMoveValue::from(name_value).to_json_value(),
3059 };
3060
3061 let value_metadata = field.value_metadata().map_err(|e| {
3062 warn!("{e}");
3063 IotaError::ObjectDeserialization {
3064 error: e.to_string(),
3065 }
3066 })?;
3067
3068 Ok(Some(match value_metadata {
3069 DFV::ValueMetadata::DynamicField(object_type) => DynamicFieldInfo {
3070 name,
3071 bcs_name,
3072 type_,
3073 object_type: object_type.to_canonical_string(true),
3074 object_id: o.id(),
3075 version: o.version(),
3076 digest: o.digest(),
3077 },
3078
3079 DFV::ValueMetadata::DynamicObjectField(object_id) => {
3080 let (version, digest, object_type) = if let Some(object) = written.get(&object_id) {
3085 (
3086 object.version(),
3087 object.digest(),
3088 object.data.opt_object_type().unwrap().clone(),
3089 )
3090 } else {
3091 let object = self
3093 .get_object_store()
3094 .try_get_object_by_key(&object_id, o.version())?
3095 .ok_or_else(|| UserInputError::ObjectNotFound {
3096 object_id,
3097 version: Some(o.version()),
3098 })?;
3099 let version = object.version();
3100 let digest = object.digest();
3101 let object_type = object.data.opt_object_type().unwrap().clone();
3102 (version, digest, object_type)
3103 };
3104
3105 DynamicFieldInfo {
3106 name,
3107 bcs_name,
3108 type_,
3109 object_type: object_type.to_string(),
3110 object_id,
3111 version,
3112 digest,
3113 }
3114 }
3115 }))
3116 }
3117
3118 #[instrument(level = "trace", skip_all, err)]
3119 fn post_process_one_tx(
3120 &self,
3121 transaction: &VerifiedExecutableTransaction,
3122 effects: &TransactionEffects,
3123 inner_temporary_store: &InnerTemporaryStore,
3124 epoch_store: &Arc<AuthorityPerEpochStore>,
3125 ) -> IotaResult {
3126 if self.indexes.is_none() {
3127 return Ok(());
3128 }
3129
3130 let _scope = monitored_scope("Execution::post_process_one_tx");
3131
3132 let tx_digest = transaction.digest();
3133 let timestamp_ms = Self::unixtime_now_ms();
3134 let events = &inner_temporary_store.events;
3135 let written = &inner_temporary_store.written;
3136 let tx_coins = self.fullnode_only_get_tx_coins_for_indexing(
3137 effects,
3138 inner_temporary_store,
3139 epoch_store,
3140 );
3141
3142 if let Some(indexes) = &self.indexes {
3144 let _ = self
3145 .index_tx(
3146 indexes.as_ref(),
3147 tx_digest,
3148 transaction,
3149 effects,
3150 events,
3151 timestamp_ms,
3152 tx_coins,
3153 written,
3154 inner_temporary_store,
3155 epoch_store,
3156 )
3157 .tap_ok(|_| self.metrics.post_processing_total_tx_indexed.inc())
3158 .tap_err(|e| error!(?tx_digest, "Post processing - Couldn't index tx: {e}"))
3159 .expect("Indexing tx should not fail");
3160
3161 let effects: IotaTransactionBlockEffects = effects.clone().try_into()?;
3162 let events = self.make_transaction_block_events(
3163 events.clone(),
3164 *tx_digest,
3165 timestamp_ms,
3166 epoch_store,
3167 inner_temporary_store,
3168 )?;
3169 self.subscription_handler
3171 .process_tx(transaction.data().transaction(), &effects, &events)
3172 .tap_ok(|_| {
3173 self.metrics
3174 .post_processing_total_tx_had_event_processed
3175 .inc()
3176 })
3177 .tap_err(|e| {
3178 warn!(
3179 ?tx_digest,
3180 "Post processing - Couldn't process events for tx: {}", e
3181 )
3182 })?;
3183
3184 self.metrics
3185 .post_processing_total_events_emitted
3186 .inc_by(events.data.len() as u64);
3187 };
3188 Ok(())
3189 }
3190
3191 fn make_transaction_block_events(
3192 &self,
3193 transaction_events: TransactionEvents,
3194 digest: TransactionDigest,
3195 timestamp_ms: u64,
3196 epoch_store: &Arc<AuthorityPerEpochStore>,
3197 inner_temporary_store: &InnerTemporaryStore,
3198 ) -> IotaResult<IotaTransactionBlockEvents> {
3199 let mut layout_resolver =
3200 epoch_store
3201 .executor()
3202 .type_layout_resolver(Box::new(PackageStoreWithFallback::new(
3203 inner_temporary_store,
3204 self.get_backing_package_store(),
3205 )));
3206 IotaTransactionBlockEvents::try_from(
3207 transaction_events,
3208 digest,
3209 Some(timestamp_ms),
3210 layout_resolver.as_mut(),
3211 )
3212 }
3213
3214 pub fn unixtime_now_ms() -> u64 {
3215 let now = SystemTime::now()
3216 .duration_since(UNIX_EPOCH)
3217 .expect("Time went backwards")
3218 .as_millis();
3219 u64::try_from(now).expect("Travelling in time machine")
3220 }
3221
3222 #[instrument(level = "trace", skip_all)]
3223 pub async fn handle_transaction_info_request(
3224 &self,
3225 request: TransactionInfoRequest,
3226 ) -> IotaResult<TransactionInfoResponse> {
3227 let epoch_store = self.load_epoch_store_one_call_per_task();
3228 let (transaction, status) = self
3229 .get_transaction_status(&request.transaction_digest, &epoch_store)?
3230 .ok_or(IotaError::TransactionNotFound {
3231 digest: request.transaction_digest,
3232 })?;
3233 Ok(TransactionInfoResponse {
3234 transaction,
3235 status,
3236 })
3237 }
3238
3239 #[instrument(level = "trace", skip_all)]
3240 pub async fn handle_object_info_request(
3241 &self,
3242 request: ObjectInfoRequest,
3243 ) -> IotaResult<ObjectInfoResponse> {
3244 let epoch_store = self.load_epoch_store_one_call_per_task();
3245
3246 let requested_object_seq = match request.request_kind {
3247 ObjectInfoRequestKind::LatestObjectInfo => {
3248 self.try_get_object_or_tombstone(request.object_id)?
3249 .ok_or_else(|| {
3250 IotaError::from(UserInputError::ObjectNotFound {
3251 object_id: request.object_id,
3252 version: None,
3253 })
3254 })?
3255 .version
3256 }
3257 ObjectInfoRequestKind::PastObjectInfoDebug(seq) => seq,
3258 };
3259
3260 let object = self
3261 .get_object_store()
3262 .try_get_object_by_key(&request.object_id, requested_object_seq)?
3263 .ok_or_else(|| {
3264 IotaError::from(UserInputError::ObjectNotFound {
3265 object_id: request.object_id,
3266 version: Some(requested_object_seq),
3267 })
3268 })?;
3269
3270 let layout = if let (LayoutGenerationOption::Generate, Some(move_obj)) =
3271 (request.generate_layout, object.data.as_opt_struct())
3272 {
3273 Some(into_struct_layout(
3274 epoch_store
3275 .executor()
3276 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
3277 .get_annotated_layout(move_obj.struct_tag())?,
3278 )?)
3279 } else {
3280 None
3281 };
3282
3283 let lock = if !object.is_address_owned() {
3284 None
3286 } else {
3287 self.get_transaction_lock(&object.object_ref(), &epoch_store)?
3288 .map(|s| s.into_inner())
3289 };
3290
3291 Ok(ObjectInfoResponse {
3292 object,
3293 layout,
3294 lock_for_debugging: lock,
3295 })
3296 }
3297
3298 #[instrument(level = "trace", skip_all)]
3299 pub fn handle_checkpoint_request(
3300 &self,
3301 request: &CheckpointRequest,
3302 ) -> IotaResult<CheckpointResponse> {
3303 let summary = if request.certified {
3304 let summary = match request.sequence_number {
3305 Some(seq) => self
3306 .checkpoint_store
3307 .get_checkpoint_by_sequence_number(seq)?,
3308 None => self.checkpoint_store.get_latest_certified_checkpoint()?,
3309 }
3310 .map(|v| v.into_inner());
3311 summary.map(CheckpointSummaryResponse::Certified)
3312 } else {
3313 let summary = match request.sequence_number {
3314 Some(seq) => self.checkpoint_store.get_locally_computed_checkpoint(seq)?,
3315 None => self
3316 .checkpoint_store
3317 .get_latest_locally_computed_checkpoint()?,
3318 };
3319 summary.map(CheckpointSummaryResponse::Pending)
3320 };
3321 let contents = match &summary {
3322 Some(s) => self
3323 .checkpoint_store
3324 .get_checkpoint_contents(&s.contents_digest())?,
3325 None => None,
3326 };
3327 Ok(CheckpointResponse {
3328 checkpoint: summary,
3329 contents,
3330 })
3331 }
3332
3333 fn check_protocol_version(
3334 supported_protocol_versions: SupportedProtocolVersions,
3335 current_version: ProtocolVersion,
3336 ) {
3337 info!("current protocol version is now {:?}", current_version);
3338 info!("supported versions are: {:?}", supported_protocol_versions);
3339 if !supported_protocol_versions.is_version_supported(current_version) {
3340 let msg = format!(
3341 "Unsupported protocol version. The network is at {current_version:?}, but this IotaNode only supports: {supported_protocol_versions:?}. Shutting down.",
3342 );
3343
3344 error!("{}", msg);
3345 eprintln!("{msg}");
3346
3347 #[cfg(not(msim))]
3348 std::process::exit(1);
3349
3350 #[cfg(msim)]
3351 iota_simulator::task::shutdown_current_node();
3352 }
3353 }
3354
3355 #[expect(clippy::disallowed_methods)] pub async fn new(
3357 name: AuthorityName,
3358 secret: StableSyncAuthoritySigner,
3359 supported_protocol_versions: SupportedProtocolVersions,
3360 store: Arc<AuthorityStore>,
3361 execution_cache_trait_pointers: ExecutionCacheTraitPointers,
3362 epoch_store: Arc<AuthorityPerEpochStore>,
3363 committee_store: Arc<CommitteeStore>,
3364 indexes: Option<Arc<IndexStore>>,
3365 grpc_indexes_store: Option<Arc<GrpcIndexesStore>>,
3366 checkpoint_store: Arc<CheckpointStore>,
3367 prometheus_registry: &Registry,
3368 genesis_objects: &[Object],
3369 config: NodeConfig,
3370 validator_tx_finalizer: Option<Arc<ValidatorTxFinalizer<NetworkAuthorityClient>>>,
3371 chain_identifier: ChainIdentifier,
3372 checkpoint_progress_tracker: Option<Arc<CheckpointProgressTracker>>,
3373 policy_config: Option<PolicyConfig>,
3374 epoch_end_db_snapshots: Option<EpochEndDbSnapshotHandle>,
3375 ) -> Arc<Self> {
3376 Self::check_protocol_version(supported_protocol_versions, epoch_store.protocol_version());
3377
3378 epoch_store.set_effects_store(
3381 execution_cache_trait_pointers
3382 .transaction_cache_reader
3383 .clone(),
3384 );
3385
3386 let metrics = Arc::new(AuthorityMetrics::new(prometheus_registry));
3387 let (tx_ready_transactions, rx_ready_transactions) = unbounded_channel();
3388 let execution_scheduler = Arc::new(ExecutionSchedulerWrapper::new(
3389 execution_cache_trait_pointers.object_cache_reader.clone(),
3390 execution_cache_trait_pointers
3391 .transaction_cache_reader
3392 .clone(),
3393 tx_ready_transactions,
3394 &epoch_store,
3395 metrics.clone(),
3396 ));
3397 let (tx_execution_shutdown, rx_execution_shutdown) = oneshot::channel();
3398
3399 let authority_per_epoch_pruner = AuthorityPerEpochStorePruner::new(
3400 epoch_store.get_parent_path(),
3401 config
3402 .authority_store_pruning_config
3403 .num_latest_epoch_dbs_to_retain,
3404 )
3405 .await;
3406 let pruner = AuthorityStorePruner::new(
3407 store.perpetual_tables.clone(),
3408 checkpoint_store.clone(),
3409 grpc_indexes_store.clone(),
3410 indexes.clone(),
3411 config.authority_store_pruning_config.clone(),
3412 epoch_store.committee().authority_exists(&name),
3413 epoch_store.epoch_start_state().epoch_duration_ms(),
3414 prometheus_registry,
3415 checkpoint_progress_tracker.clone(),
3416 epoch_store.object_pruning_limit(),
3417 );
3418 let input_loader =
3419 TransactionInputLoader::new(execution_cache_trait_pointers.object_cache_reader.clone());
3420 let epoch = epoch_store.epoch();
3421 let rgp = epoch_store.reference_gas_price();
3422 let traffic_controller_metrics =
3423 Arc::new(TrafficControllerMetrics::new(prometheus_registry));
3424 let traffic_controller = policy_config.map(|policy_config| {
3425 Arc::new(TrafficController::init(
3426 policy_config,
3427 traffic_controller_metrics,
3428 ))
3429 });
3430 let state = Arc::new(AuthorityState {
3431 name,
3432 secret,
3433 execution_lock: RwLock::new(epoch),
3434 epoch_store: ArcSwap::new(epoch_store.clone()),
3435 input_loader,
3436 execution_cache_trait_pointers,
3437 indexes,
3438 grpc_indexes_store,
3439 subscription_handler: Arc::new(SubscriptionHandler::new(prometheus_registry)),
3440 checkpoint_store,
3441 committee_store,
3442 execution_scheduler,
3443 tx_execution_shutdown: Mutex::new(Some(tx_execution_shutdown)),
3444 metrics,
3445 pruner,
3446 authority_per_epoch_pruner,
3447 checkpoint_progress_tracker,
3448 config,
3449 overload_info: AuthorityOverloadInfo::default(),
3450 validator_tx_finalizer,
3451 chain_identifier,
3452 congestion_tracker: Arc::new(CongestionTracker::new(rgp)),
3453 traffic_controller,
3454 epoch_end_db_snapshots,
3455 });
3456
3457 let authority_state = Arc::downgrade(&state);
3459 spawn_monitored_task!(execution_process(
3460 authority_state,
3461 rx_ready_transactions,
3462 rx_execution_shutdown,
3463 ));
3464 state
3466 .create_owner_index_if_empty(genesis_objects, &epoch_store)
3467 .expect("Error indexing genesis objects.");
3468
3469 state
3470 }
3471
3472 pub fn epoch_db_pruner(&self) -> &AuthorityPerEpochStorePruner {
3473 &self.authority_per_epoch_pruner
3474 }
3475
3476 pub fn get_object_cache_reader(&self) -> &Arc<dyn ObjectCacheRead> {
3478 &self.execution_cache_trait_pointers.object_cache_reader
3479 }
3480
3481 pub fn get_transaction_cache_reader(&self) -> &Arc<dyn TransactionCacheRead> {
3482 &self.execution_cache_trait_pointers.transaction_cache_reader
3483 }
3484
3485 pub fn get_cache_writer(&self) -> &Arc<dyn ExecutionCacheWrite> {
3486 &self.execution_cache_trait_pointers.cache_writer
3487 }
3488
3489 pub fn get_backing_store(&self) -> &Arc<dyn BackingStore + Send + Sync> {
3490 &self.execution_cache_trait_pointers.backing_store
3491 }
3492
3493 pub fn get_backing_package_store(&self) -> &Arc<dyn BackingPackageStore + Send + Sync> {
3494 &self.execution_cache_trait_pointers.backing_package_store
3495 }
3496
3497 pub fn get_object_store(&self) -> &Arc<dyn ObjectStore + Send + Sync> {
3498 &self.execution_cache_trait_pointers.object_store
3499 }
3500
3501 pub fn get_reconfig_api(&self) -> &Arc<dyn ExecutionCacheReconfigAPI> {
3502 &self.execution_cache_trait_pointers.reconfig_api
3503 }
3504
3505 pub fn get_global_state_hash_store(&self) -> &Arc<dyn GlobalStateHashStore> {
3506 &self.execution_cache_trait_pointers.global_state_hash_store
3507 }
3508
3509 pub fn get_checkpoint_cache(&self) -> &Arc<dyn CheckpointCache> {
3510 &self.execution_cache_trait_pointers.checkpoint_cache
3511 }
3512
3513 pub fn get_state_sync_store(&self) -> &Arc<dyn StateSyncAPI> {
3514 &self.execution_cache_trait_pointers.state_sync_store
3515 }
3516
3517 pub fn get_cache_commit(&self) -> &Arc<dyn ExecutionCacheCommit> {
3518 &self.execution_cache_trait_pointers.cache_commit
3519 }
3520
3521 pub fn database_for_testing(&self) -> Arc<AuthorityStore> {
3522 self.execution_cache_trait_pointers
3523 .testing_api
3524 .database_for_testing()
3525 }
3526
3527 #[cfg(test)]
3530 pub fn evict_committed_object_for_testing(&self, id: &ObjectId) {
3531 self.execution_cache_trait_pointers
3532 .testing_api
3533 .evict_committed_object_for_testing(id)
3534 }
3535
3536 pub async fn prune_checkpoints_for_eligible_epochs_for_testing(
3537 &self,
3538 config: NodeConfig,
3539 metrics: Arc<AuthorityStorePruningMetrics>,
3540 ) -> anyhow::Result<()> {
3541 AuthorityStorePruner::prune_checkpoints_for_eligible_epochs(
3542 &self.database_for_testing().perpetual_tables,
3543 &self.checkpoint_store,
3544 self.grpc_indexes_store.as_deref(),
3545 config.authority_store_pruning_config,
3546 metrics,
3547 EPOCH_DURATION_MS_FOR_TESTING,
3548 self.checkpoint_progress_tracker.as_ref(),
3549 )
3550 .await
3551 }
3552
3553 pub fn execution_scheduler(&self) -> &Arc<ExecutionSchedulerWrapper> {
3554 &self.execution_scheduler
3555 }
3556
3557 pub fn uses_execution_scheduler(&self) -> bool {
3560 self.execution_scheduler.uses_execution_scheduler()
3561 }
3562
3563 fn create_owner_index_if_empty(
3564 &self,
3565 genesis_objects: &[Object],
3566 epoch_store: &Arc<AuthorityPerEpochStore>,
3567 ) -> IotaResult {
3568 let Some(index_store) = &self.indexes else {
3569 return Ok(());
3570 };
3571 if !index_store.is_empty() {
3572 return Ok(());
3573 }
3574
3575 let mut new_owners = vec![];
3576 let mut new_dynamic_fields = vec![];
3577 let mut layout_resolver = epoch_store
3578 .executor()
3579 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()));
3580 for o in genesis_objects.iter() {
3581 match o.owner {
3582 Owner::Address(addr) => {
3583 new_owners.push(((addr, o.id()), ObjectInfo::new(&o.object_ref(), o)))
3584 }
3585 Owner::Object(object_id) => {
3586 let id = o.id();
3587 let info = match self.try_create_dynamic_field_info(
3588 o,
3589 &BTreeMap::new(),
3590 layout_resolver.as_mut(),
3591 ) {
3592 Ok(Some(info)) => info,
3593 Ok(None) => continue,
3594 Err(IotaError::UserInput {
3595 error:
3596 UserInputError::ObjectNotFound {
3597 object_id: not_found_id,
3598 version,
3599 },
3600 }) => {
3601 warn!(
3602 ?not_found_id,
3603 ?version,
3604 object_owner=?object_id,
3605 field=?id,
3606 "Skipping dynamic field: referenced genesis object not found"
3607 );
3608 continue;
3609 }
3610 Err(e) => return Err(e),
3611 };
3612 new_dynamic_fields.push(((object_id, id), info));
3613 }
3614 _ => {}
3615 }
3616 }
3617
3618 index_store.insert_genesis_objects(ObjectIndexChanges {
3619 deleted_owners: vec![],
3620 deleted_dynamic_fields: vec![],
3621 new_owners,
3622 new_dynamic_fields,
3623 })
3624 }
3625
3626 pub fn execution_lock_for_executable_transaction(
3630 &self,
3631 transaction: &VerifiedExecutableTransaction,
3632 ) -> IotaResult<ExecutionLockReadGuard<'_>> {
3633 let lock = self
3634 .execution_lock
3635 .try_read()
3636 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)?;
3637 if *lock == transaction.auth_sig().epoch() {
3638 Ok(lock)
3639 } else {
3640 Err(IotaError::WrongEpoch {
3641 expected_epoch: *lock,
3642 actual_epoch: transaction.auth_sig().epoch(),
3643 })
3644 }
3645 }
3646
3647 pub fn execution_lock_for_signing(&self) -> IotaResult<ExecutionLockReadGuard<'_>> {
3653 self.execution_lock
3654 .try_read()
3655 .map_err(|_| IotaError::ValidatorHaltedAtEpochEnd)
3656 }
3657
3658 pub async fn execution_lock_for_reconfiguration(&self) -> ExecutionLockWriteGuard<'_> {
3659 self.execution_lock.write().await
3660 }
3661
3662 pub(crate) fn check_transaction_deny_rules_consistency(
3672 &self,
3673 cur_epoch_store: &AuthorityPerEpochStore,
3674 epoch_start_configuration: &EpochStartConfiguration,
3675 ) {
3676 if self.is_fullnode(cur_epoch_store) {
3677 return;
3678 }
3679 let Some(walked_deny_rules) = epoch_start_configuration.transaction_deny_rules_state()
3680 else {
3681 if cur_epoch_store
3682 .epoch_start_config()
3683 .transaction_deny_rules_obj_initial_shared_version()
3684 .is_some()
3685 {
3686 fatal!(
3687 "TransactionDenyRules object existed in epoch {} but is missing from the \
3688 state walked for the next epoch — the local store is corrupted; restore or \
3689 state-sync before rejoining",
3690 cur_epoch_store.epoch(),
3691 );
3692 }
3693 return;
3694 };
3695 if cur_epoch_store
3699 .get_reconfig_state_read_lock_guard()
3700 .should_accept_tx()
3701 {
3702 info!(
3703 "skipping the deny-rule mirror comparison: consensus did not close epoch {} on \
3704 this node",
3705 cur_epoch_store.epoch(),
3706 );
3707 return;
3708 }
3709 let mirrored_deny_rules = cur_epoch_store.get_mirrored_transaction_deny_rules();
3710 if *walked_deny_rules != *mirrored_deny_rules {
3711 debug_fatal!(
3712 "TransactionDenyRules object diverged from the mirrored state at the end of \
3713 epoch {}; continuing from the object (walked: {walked_deny_rules:?}, mirrored: \
3714 {mirrored_deny_rules:?})",
3715 cur_epoch_store.epoch(),
3716 );
3717 cur_epoch_store.metrics.deny_rule_mirror_divergence.set(1);
3718 }
3719 }
3720
3721 pub(crate) fn report_failed_deny_rule_update_execution(
3733 &self,
3734 transaction: &VerifiedExecutableTransaction,
3735 effects: &TransactionEffects,
3736 expected_effects_digest: Option<TransactionEffectsDigest>,
3737 epoch_store: &AuthorityPerEpochStore,
3738 ) {
3739 if !matches!(
3740 transaction.transaction().kind(),
3741 TransactionKind::TransactionDenyRulesUpdate(_)
3742 ) || effects.status().is_success()
3743 {
3744 return;
3745 }
3746 epoch_store
3747 .metrics
3748 .deny_rule_update_execution_failures
3749 .inc();
3750 if expected_effects_digest.is_some() {
3751 error!(
3752 digest = ?transaction.digest(),
3753 status = ?effects.status(),
3754 "TransactionDenyRulesUpdate failed execution; the object misses its delta until \
3755 the epoch boundary re-seeds the mirror"
3756 );
3757 return;
3758 }
3759 debug_fatal!(
3760 "TransactionDenyRulesUpdate failed execution; the object misses its delta until the \
3761 epoch boundary re-seeds the mirror (digest: {:?}, status: {:?})",
3762 transaction.digest(),
3763 effects.status(),
3764 );
3765 }
3766
3767 #[instrument(level = "error", skip_all)]
3768 pub async fn reconfigure(
3769 &self,
3770 cur_epoch_store: &AuthorityPerEpochStore,
3771 supported_protocol_versions: SupportedProtocolVersions,
3772 new_committee: Committee,
3773 epoch_start_configuration: EpochStartConfiguration,
3774 state_hasher: Arc<GlobalStateHasher>,
3775 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3776 epoch_supply_change: i64,
3777 epoch_last_checkpoint: CheckpointSequenceNumber,
3778 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
3779 Self::check_protocol_version(
3780 supported_protocol_versions,
3781 epoch_start_configuration
3782 .epoch_start_state()
3783 .protocol_version(),
3784 );
3785 self.metrics.reset_on_reconfigure();
3786 self.committee_store.insert_new_committee(&new_committee)?;
3787
3788 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3790
3791 cur_epoch_store.epoch_terminated().await;
3793
3794 let highest_locally_built_checkpoint_seq = self
3795 .checkpoint_store
3796 .get_latest_locally_computed_checkpoint()?
3797 .map(|c| c.sequence_number())
3798 .unwrap_or(0);
3799
3800 assert!(
3801 epoch_last_checkpoint >= highest_locally_built_checkpoint_seq,
3802 "expected {epoch_last_checkpoint} >= {highest_locally_built_checkpoint_seq}"
3803 );
3804
3805 self.revert_uncommitted_epoch_transactions(cur_epoch_store)
3811 .await?;
3812 self.get_reconfig_api()
3813 .clear_state_end_of_epoch(&execution_lock);
3814 self.check_system_consistency(
3815 cur_epoch_store,
3816 state_hasher,
3817 expensive_safety_check_config,
3818 epoch_supply_change,
3819 )?;
3820 self.check_transaction_deny_rules_consistency(cur_epoch_store, &epoch_start_configuration);
3821
3822 self.get_reconfig_api()
3823 .try_set_epoch_start_configuration(&epoch_start_configuration)?;
3824 self.hand_over_epoch_end_db_snapshot(cur_epoch_store.epoch())
3825 .await;
3826
3827 let new_epoch = new_committee.epoch;
3828 let new_epoch_store = self
3829 .reopen_epoch_db(
3830 cur_epoch_store,
3831 new_committee,
3832 epoch_start_configuration,
3833 expensive_safety_check_config,
3834 epoch_last_checkpoint,
3835 )
3836 .await?;
3837 assert_eq!(new_epoch_store.epoch(), new_epoch);
3838 match self.execution_scheduler.as_ref() {
3839 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3840 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3841 tm.reconfigure(new_epoch);
3842 }
3843 }
3844 *execution_lock = new_epoch;
3845 Ok(new_epoch_store)
3849 }
3850
3851 pub async fn reconfigure_for_testing(&self) {
3856 self.reconfigure_for_testing_impl(None).await;
3857 }
3858
3859 pub async fn reconfigure_for_testing_with_protocol_config(
3862 &self,
3863 protocol_config: ProtocolConfig,
3864 ) {
3865 self.reconfigure_for_testing_impl(Some(protocol_config))
3866 .await;
3867 }
3868
3869 async fn reconfigure_for_testing_impl(&self, protocol_config: Option<ProtocolConfig>) {
3870 let mut execution_lock = self.execution_lock_for_reconfiguration().await;
3871 let epoch_store = self.epoch_store_for_testing().clone();
3872 let protocol_config =
3876 protocol_config.unwrap_or_else(|| epoch_store.protocol_config().clone());
3877 let _guard =
3878 ProtocolConfig::apply_overrides_for_testing(move |_, _| protocol_config.clone());
3879 let new_epoch_store = epoch_store.new_at_next_epoch_for_testing(
3880 self.get_backing_package_store().clone(),
3881 &self.config.expensive_safety_check_config,
3882 self.checkpoint_store
3883 .get_epoch_last_checkpoint(epoch_store.epoch())
3884 .unwrap()
3885 .map(|c| c.sequence_number())
3886 .unwrap_or_default(),
3887 );
3888 let new_epoch = new_epoch_store.epoch();
3889 match self.execution_scheduler.as_ref() {
3890 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
3891 ExecutionSchedulerWrapper::TransactionManager(tm) => {
3892 tm.reconfigure(new_epoch);
3893 }
3894 }
3895 self.epoch_store.store(new_epoch_store);
3896 epoch_store.epoch_terminated().await;
3897 *execution_lock = new_epoch;
3898 }
3899
3900 #[instrument(level = "error", skip_all)]
3901 fn check_system_consistency(
3902 &self,
3903 cur_epoch_store: &AuthorityPerEpochStore,
3904 state_hasher: Arc<GlobalStateHasher>,
3905 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
3906 epoch_supply_change: i64,
3907 ) -> IotaResult<()> {
3908 info!(
3909 "Performing iota conservation consistency check for epoch {}",
3910 cur_epoch_store.epoch()
3911 );
3912
3913 if cfg!(debug_assertions) {
3914 cur_epoch_store.check_all_executed_transactions_in_checkpoint();
3915 }
3916
3917 self.get_reconfig_api()
3918 .try_expensive_check_iota_conservation(cur_epoch_store, Some(epoch_supply_change))?;
3919
3920 if expensive_safety_check_config.enable_state_consistency_check() {
3922 info!(
3923 "Performing state consistency check for epoch {}",
3924 cur_epoch_store.epoch()
3925 );
3926 self.expensive_check_is_consistent_state(state_hasher, cur_epoch_store);
3927 }
3928
3929 if expensive_safety_check_config.enable_secondary_index_checks() {
3930 if let Some(indexes) = self.indexes.clone() {
3931 verify_indexes(self.get_global_state_hash_store().as_ref(), indexes)
3932 .expect("secondary indexes are inconsistent");
3933 }
3934 }
3935
3936 Ok(())
3937 }
3938
3939 fn expensive_check_is_consistent_state(
3940 &self,
3941 state_hasher: Arc<GlobalStateHasher>,
3942 cur_epoch_store: &AuthorityPerEpochStore,
3943 ) {
3944 let live_object_set_hash = state_hasher.digest_live_object_set();
3945
3946 let root_state_hash: ECMHLiveObjectSetDigest = self
3947 .get_global_state_hash_store()
3948 .get_root_state_hash_for_epoch(cur_epoch_store.epoch())
3949 .expect("Retrieving root state hash cannot fail")
3950 .expect("Root state hash for epoch must exist")
3951 .1
3952 .digest()
3953 .into();
3954
3955 let is_inconsistent = root_state_hash != live_object_set_hash;
3956 if is_inconsistent {
3957 debug_fatal!(
3958 "Inconsistent state detected: root state hash: {:?}, live object set hash: {:?}",
3959 root_state_hash,
3960 live_object_set_hash
3961 );
3962 } else {
3963 info!("State consistency check passed");
3964 }
3965
3966 state_hasher.set_inconsistent_state(is_inconsistent);
3967 }
3968
3969 pub fn current_epoch_for_testing(&self) -> EpochId {
3970 self.epoch_store_for_testing().epoch()
3971 }
3972
3973 #[instrument(level = "error", skip_all)]
3977 async fn hand_over_epoch_end_db_snapshot(&self, epoch: EpochId) {
3978 let Some(handle) = &self.epoch_end_db_snapshots else {
3979 return;
3980 };
3981 let _metrics_guard = self
3982 .metrics
3983 .epoch_end_db_snapshot_handover_latency
3984 .start_timer();
3985 if handle.hand_over(epoch).await == HandOver::Skipped {
3986 self.metrics.epoch_end_db_snapshots_skipped.inc();
3987 }
3988 }
3989
3990 pub fn load_epoch_store_one_call_per_task(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
3997 self.epoch_store.load()
3998 }
3999
4000 pub fn epoch_store_for_testing(&self) -> Guard<Arc<AuthorityPerEpochStore>> {
4002 self.load_epoch_store_one_call_per_task()
4003 }
4004
4005 pub fn clone_committee_for_testing(&self) -> Committee {
4006 Committee::clone(self.epoch_store_for_testing().committee())
4007 }
4008
4009 #[instrument(level = "trace", skip_all)]
4010 pub fn try_get_object(&self, object_id: &ObjectId) -> IotaResult<Option<Object>> {
4011 self.get_object_store()
4012 .try_get_object(object_id)
4013 .map_err(Into::into)
4014 }
4015
4016 pub fn get_object(&self, object_id: &ObjectId) -> Option<Object> {
4018 self.try_get_object(object_id)
4019 .expect("storage access failed")
4020 }
4021
4022 pub fn get_iota_system_package_object_ref(&self) -> IotaResult<ObjectReference> {
4023 Ok(self
4024 .try_get_object(&ObjectId::SYSTEM)?
4025 .expect("system package should always exist")
4026 .object_ref())
4027 }
4028
4029 pub fn get_iota_system_state_object_for_testing(&self) -> IotaResult<IotaSystemState> {
4031 self.get_object_cache_reader()
4032 .try_get_iota_system_state_object_unsafe()
4033 }
4034
4035 #[instrument(level = "trace", skip_all)]
4036 pub fn get_checkpoint_by_sequence_number(
4037 &self,
4038 sequence_number: CheckpointSequenceNumber,
4039 ) -> IotaResult<Option<VerifiedCheckpoint>> {
4040 Ok(self
4041 .checkpoint_store
4042 .get_checkpoint_by_sequence_number(sequence_number)?)
4043 }
4044
4045 pub async fn wait_for_checkpoint_inclusion(
4056 &self,
4057 digests: &[TransactionDigest],
4058 timeout: Duration,
4059 ) -> IotaResult<BTreeMap<TransactionDigest, (CheckpointSequenceNumber, u64)>> {
4060 let deadline = tokio::time::Instant::now() + timeout;
4061 let mut checkpoint_timestamp_cache = HashMap::<CheckpointSequenceNumber, u64>::new();
4062 let mut results = BTreeMap::new();
4063 let mut remaining = digests.to_vec();
4064 let mut epoch_store = self.load_epoch_store_one_call_per_task().clone();
4065
4066 loop {
4067 let wait = epoch_store.wait_for_transactions_in_checkpoint_with_timeout(
4068 &remaining,
4069 deadline.saturating_duration_since(tokio::time::Instant::now()),
4070 |seq| self.checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache),
4071 );
4072 tokio::select! {
4073 wait_results = wait => {
4074 for (digest, seq_and_ts) in remaining.iter().zip(wait_results?) {
4075 if let Some(seq_and_ts) = seq_and_ts {
4076 results.insert(*digest, seq_and_ts);
4077 }
4078 }
4079 return Ok(results);
4080 }
4081 _ = epoch_store.wait_epoch_terminated() => {}
4082 }
4083
4084 let found = match epoch_store.multi_get_transaction_checkpoint(&remaining) {
4091 Ok(found) => found,
4092 Err(IotaError::EpochEnded(_)) => vec![None; remaining.len()],
4097 Err(err) => return Err(err),
4098 };
4099 let mut still_uncheckpointed = Vec::new();
4100 for (digest, found_seq) in remaining.iter().zip(found) {
4101 match found_seq {
4102 Some(seq) => {
4103 let ts = self
4104 .checkpoint_timestamp_ms_cached(seq, &mut checkpoint_timestamp_cache);
4105 results.insert(*digest, (seq, ts));
4106 }
4107 None => still_uncheckpointed.push(*digest),
4108 }
4109 }
4110 remaining = still_uncheckpointed;
4111 if remaining.is_empty() {
4112 return Ok(results);
4113 }
4114
4115 match self
4116 .wait_for_next_epoch_store(epoch_store.epoch(), deadline)
4117 .await
4118 {
4119 Some(next) => epoch_store = next,
4120 None => return Ok(results),
4121 }
4122 }
4123 }
4124
4125 async fn wait_for_next_epoch_store(
4128 &self,
4129 prev_epoch: EpochId,
4130 deadline: tokio::time::Instant,
4131 ) -> Option<Arc<AuthorityPerEpochStore>> {
4132 const EPOCH_STORE_SWAP_POLL_INTERVAL: Duration = Duration::from_millis(100);
4137
4138 loop {
4139 let current = self.load_epoch_store_one_call_per_task().clone();
4142 if current.epoch() > prev_epoch {
4143 return Some(current);
4144 }
4145 if tokio::time::Instant::now() >= deadline {
4146 return None;
4147 }
4148 tokio::time::sleep(EPOCH_STORE_SWAP_POLL_INTERVAL).await;
4149 }
4150 }
4151
4152 fn checkpoint_timestamp_ms_cached(
4156 &self,
4157 seq: CheckpointSequenceNumber,
4158 cache: &mut HashMap<CheckpointSequenceNumber, u64>,
4159 ) -> u64 {
4160 *cache.entry(seq).or_insert_with(|| {
4161 self.get_checkpoint_by_sequence_number(seq)
4162 .ok()
4163 .flatten()
4164 .map(|c| c.timestamp_ms)
4165 .unwrap_or(0)
4166 })
4167 }
4168
4169 #[instrument(level = "trace", skip_all)]
4170 pub fn get_transaction_checkpoint_for_tests(
4171 &self,
4172 digest: &TransactionDigest,
4173 epoch_store: &AuthorityPerEpochStore,
4174 ) -> IotaResult<Option<VerifiedCheckpoint>> {
4175 let checkpoint = epoch_store.get_transaction_checkpoint(digest)?;
4176 let Some(checkpoint) = checkpoint else {
4177 return Ok(None);
4178 };
4179 let checkpoint = self
4180 .checkpoint_store
4181 .get_checkpoint_by_sequence_number(checkpoint)?;
4182 Ok(checkpoint)
4183 }
4184
4185 #[instrument(level = "trace", skip_all)]
4186 pub fn get_object_read(&self, object_id: &ObjectId) -> IotaResult<ObjectRead> {
4187 Ok(
4188 match self
4189 .get_object_cache_reader()
4190 .try_get_latest_object_or_tombstone(*object_id)?
4191 {
4192 Some((_, ObjectOrTombstone::Object(object))) => {
4193 let layout = self.get_object_layout(&object)?;
4194 ObjectRead::Exists(object.object_ref(), object, layout)
4195 }
4196 Some((_, ObjectOrTombstone::Tombstone(objref))) => ObjectRead::Deleted(objref),
4197 None => ObjectRead::NotExists(*object_id),
4198 },
4199 )
4200 }
4201
4202 pub fn get_chain_identifier(&self) -> ChainIdentifier {
4204 self.chain_identifier
4205 }
4206
4207 #[instrument(level = "trace", skip_all)]
4208 pub fn get_move_object<T>(&self, object_id: &ObjectId) -> IotaResult<T>
4209 where
4210 T: DeserializeOwned,
4211 {
4212 let o = self.get_object_read(object_id)?.into_object()?;
4213 if let Some(move_object) = o.data.as_opt_struct() {
4214 Ok(bcs::from_bytes(move_object.contents()).map_err(|e| {
4215 IotaError::ObjectDeserialization {
4216 error: format!("{e}"),
4217 }
4218 })?)
4219 } else {
4220 Err(IotaError::ObjectDeserialization {
4221 error: format!("Provided object : [{object_id}] is not a Move object."),
4222 })
4223 }
4224 }
4225
4226 #[instrument(level = "trace", skip_all)]
4232 pub fn get_past_object_read(
4233 &self,
4234 object_id: &ObjectId,
4235 version: Version,
4236 ) -> IotaResult<PastObjectRead> {
4237 let Some(obj_ref) = self
4239 .get_object_cache_reader()
4240 .try_get_latest_object_ref_or_tombstone(*object_id)?
4241 else {
4242 return Ok(PastObjectRead::ObjectNotExists(*object_id));
4243 };
4244
4245 if version > obj_ref.version {
4246 return Ok(PastObjectRead::VersionTooHigh {
4247 object_id: *object_id,
4248 asked_version: version,
4249 latest_version: obj_ref.version,
4250 });
4251 }
4252
4253 if version < obj_ref.version {
4254 return Ok(match self.read_object_at_version(object_id, version)? {
4256 Some((object, layout)) => {
4257 let obj_ref = object.object_ref();
4258 PastObjectRead::VersionFound(obj_ref, object, layout)
4259 }
4260
4261 None => PastObjectRead::VersionNotFound(*object_id, version),
4262 });
4263 }
4264
4265 if !obj_ref.digest.is_alive() {
4266 return Ok(PastObjectRead::ObjectDeleted(obj_ref));
4267 }
4268
4269 match self.read_object_at_version(object_id, obj_ref.version)? {
4270 Some((object, layout)) => Ok(PastObjectRead::VersionFound(obj_ref, object, layout)),
4271 None => {
4272 debug_fatal!(
4273 "Object with in parent_entry is missing from object store, datastore is \
4274 inconsistent",
4275 );
4276 Err(UserInputError::ObjectNotFound {
4277 object_id: *object_id,
4278 version: Some(obj_ref.version),
4279 }
4280 .into())
4281 }
4282 }
4283 }
4284
4285 #[instrument(level = "trace", skip_all)]
4286 fn read_object_at_version(
4287 &self,
4288 object_id: &ObjectId,
4289 version: Version,
4290 ) -> IotaResult<Option<(Object, Option<MoveStructLayout>)>> {
4291 let Some(object) = self
4292 .get_object_cache_reader()
4293 .try_get_object_by_key(object_id, version)?
4294 else {
4295 return Ok(None);
4296 };
4297
4298 let layout = self.get_object_layout(&object)?;
4299 Ok(Some((object, layout)))
4300 }
4301
4302 fn get_object_layout(&self, object: &Object) -> IotaResult<Option<MoveStructLayout>> {
4303 let layout = object
4304 .data
4305 .as_opt_struct()
4306 .map(|object| {
4307 into_struct_layout(
4308 self.load_epoch_store_one_call_per_task()
4309 .executor()
4310 .type_layout_resolver(Box::new(self.get_backing_package_store().as_ref()))
4312 .get_annotated_layout(object.struct_tag())?,
4313 )
4314 })
4315 .transpose()?;
4316 Ok(layout)
4317 }
4318
4319 fn get_owner_at_version(&self, object_id: &ObjectId, version: Version) -> IotaResult<Owner> {
4320 self.get_object_store()
4321 .try_get_object_by_key(object_id, version)?
4322 .ok_or_else(|| {
4323 IotaError::from(UserInputError::ObjectNotFound {
4324 object_id: *object_id,
4325 version: Some(version),
4326 })
4327 })
4328 .map(|o| o.owner)
4329 }
4330
4331 #[instrument(level = "trace", skip_all)]
4332 pub fn get_owner_objects(
4333 &self,
4334 owner: Address,
4335 cursor: Option<ObjectId>,
4337 limit: usize,
4338 filter: Option<IotaObjectDataFilter>,
4339 ) -> IotaResult<Vec<ObjectInfo>> {
4340 if let Some(indexes) = &self.indexes {
4341 indexes.get_owner_objects(owner, cursor, limit, filter)
4342 } else {
4343 Err(IotaError::IndexStoreNotAvailable)
4344 }
4345 }
4346
4347 #[instrument(level = "trace", skip_all)]
4348 pub fn get_owned_coins_iterator_with_cursor(
4349 &self,
4350 owner: Address,
4351 cursor: (String, ObjectId),
4353 limit: usize,
4354 one_coin_type_only: bool,
4355 ) -> IotaResult<impl Iterator<Item = (String, ObjectId, CoinInfo)> + '_> {
4356 if let Some(indexes) = &self.indexes {
4357 indexes.get_owned_coins_iterator_with_cursor(owner, cursor, limit, one_coin_type_only)
4358 } else {
4359 Err(IotaError::IndexStoreNotAvailable)
4360 }
4361 }
4362
4363 #[instrument(level = "trace", skip_all)]
4364 pub fn get_owner_objects_iterator(
4365 &self,
4366 owner: Address,
4367 cursor: Option<ObjectId>,
4369 filter: Option<IotaObjectDataFilter>,
4370 ) -> IotaResult<impl Iterator<Item = ObjectInfo> + '_> {
4371 if let Some(indexes) = &self.indexes {
4372 indexes.get_owner_objects_iterator(owner, cursor, filter)
4373 } else {
4374 Err(IotaError::IndexStoreNotAvailable)
4375 }
4376 }
4377
4378 #[instrument(level = "trace", skip_all)]
4379 pub fn get_move_objects<T>(&self, owner: Address, tag: StructTag) -> IotaResult<Vec<T>>
4380 where
4381 T: DeserializeOwned,
4382 {
4383 let object_ids = self
4384 .get_owner_objects_iterator(owner, None, None)?
4385 .filter(|o| match &o.object_type {
4386 ObjectType::Struct(s) => *s == tag,
4387 ObjectType::Package => false,
4388 })
4389 .map(|info| ObjectKey(info.object_id, info.version))
4390 .collect::<Vec<_>>();
4391 let mut move_objects = vec![];
4392
4393 let objects = self
4394 .get_object_store()
4395 .try_multi_get_objects_by_key(&object_ids)?;
4396
4397 for (o, id) in objects.into_iter().zip(object_ids) {
4398 let object = o.ok_or_else(|| {
4399 IotaError::from(UserInputError::ObjectNotFound {
4400 object_id: id.0,
4401 version: Some(id.1),
4402 })
4403 })?;
4404 let move_object = object.data.as_opt_struct().ok_or_else(|| {
4405 IotaError::from(UserInputError::MovePackageAsObject { object_id: id.0 })
4406 })?;
4407 move_objects.push(bcs::from_bytes(move_object.contents()).map_err(|e| {
4408 IotaError::ObjectDeserialization {
4409 error: format!("{e}"),
4410 }
4411 })?);
4412 }
4413 Ok(move_objects)
4414 }
4415
4416 #[instrument(level = "trace", skip_all)]
4417 pub fn get_dynamic_fields(
4418 &self,
4419 owner: ObjectId,
4420 cursor: Option<ObjectId>,
4422 limit: usize,
4423 ) -> IotaResult<Vec<(ObjectId, DynamicFieldInfo)>> {
4424 Ok(self
4425 .get_dynamic_fields_iterator(owner, cursor)?
4426 .take(limit)
4427 .collect::<Result<Vec<_>, _>>()?)
4428 }
4429
4430 fn get_dynamic_fields_iterator(
4431 &self,
4432 owner: ObjectId,
4433 cursor: Option<ObjectId>,
4435 ) -> IotaResult<impl Iterator<Item = Result<(ObjectId, DynamicFieldInfo), TypedStoreError>> + '_>
4436 {
4437 if let Some(indexes) = &self.indexes {
4438 indexes.get_dynamic_fields_iterator(owner, cursor)
4439 } else {
4440 Err(IotaError::IndexStoreNotAvailable)
4441 }
4442 }
4443
4444 #[instrument(level = "trace", skip_all)]
4445 pub fn get_dynamic_field_object_id(
4446 &self,
4447 owner: ObjectId,
4448 name_type: TypeTag,
4449 name_bcs_bytes: &[u8],
4450 ) -> IotaResult<Option<ObjectId>> {
4451 if let Some(indexes) = &self.indexes {
4452 indexes.get_dynamic_field_object_id(owner, name_type, name_bcs_bytes)
4453 } else {
4454 Err(IotaError::IndexStoreNotAvailable)
4455 }
4456 }
4457
4458 #[instrument(level = "trace", skip_all)]
4459 pub fn get_total_transaction_blocks(&self) -> IotaResult<u64> {
4460 Ok(self.get_indexes()?.next_sequence_number())
4461 }
4462
4463 #[instrument(level = "trace", skip_all)]
4464 pub async fn get_executed_transaction_and_effects(
4465 &self,
4466 digest: TransactionDigest,
4467 kv_store: Arc<TransactionKeyValueStore>,
4468 ) -> IotaResult<(TransactionEnvelope, TransactionEffects)> {
4469 let transaction = kv_store.get_tx(digest).await?;
4470 let effects = kv_store.get_fx_by_tx_digest(digest).await?;
4471 Ok((transaction, effects))
4472 }
4473
4474 #[instrument(level = "trace", skip_all)]
4475 pub fn multi_get_checkpoint_by_sequence_number(
4476 &self,
4477 sequence_numbers: &[CheckpointSequenceNumber],
4478 ) -> IotaResult<Vec<Option<VerifiedCheckpoint>>> {
4479 Ok(self
4480 .checkpoint_store
4481 .multi_get_checkpoint_by_sequence_number(sequence_numbers)?)
4482 }
4483
4484 #[instrument(level = "trace", skip_all)]
4485 pub fn get_transaction_events(
4486 &self,
4487 digest: &TransactionDigest,
4488 ) -> IotaResult<TransactionEvents> {
4489 self.get_transaction_cache_reader()
4490 .try_get_events(digest)?
4491 .ok_or(IotaError::TransactionEventsNotFound { digest: *digest })
4492 }
4493
4494 pub fn get_transaction_input_objects(
4495 &self,
4496 effects: &TransactionEffects,
4497 ) -> anyhow::Result<Vec<Object>> {
4498 iota_types::storage::get_transaction_input_objects(self.get_object_store(), effects)
4499 .map_err(Into::into)
4500 }
4501
4502 pub fn get_transaction_output_objects(
4503 &self,
4504 effects: &TransactionEffects,
4505 ) -> anyhow::Result<Vec<Object>> {
4506 iota_types::storage::get_transaction_output_objects(self.get_object_store(), effects)
4507 .map_err(Into::into)
4508 }
4509
4510 fn get_indexes(&self) -> IotaResult<Arc<IndexStore>> {
4511 match &self.indexes {
4512 Some(i) => Ok(i.clone()),
4513 None => Err(IotaError::UnsupportedFeature {
4514 error: "extended object indexing is not enabled on this server".into(),
4515 }),
4516 }
4517 }
4518
4519 pub async fn get_transactions_for_tests(
4520 self: &Arc<Self>,
4521 filter: Option<TransactionFilter>,
4522 cursor: Option<TransactionDigest>,
4523 limit: Option<usize>,
4524 reverse: bool,
4525 ) -> IotaResult<Vec<TransactionDigest>> {
4526 let metrics = KeyValueStoreMetrics::new_for_tests();
4527 let kv_store = Arc::new(TransactionKeyValueStore::new(
4528 "rocksdb",
4529 metrics,
4530 self.clone(),
4531 ));
4532 self.get_transactions(&kv_store, filter, cursor, limit, reverse)
4533 .await
4534 }
4535
4536 #[instrument(level = "trace", skip_all)]
4537 pub async fn get_transactions(
4538 &self,
4539 kv_store: &Arc<TransactionKeyValueStore>,
4540 filter: Option<TransactionFilter>,
4541 cursor: Option<TransactionDigest>,
4543 limit: Option<usize>,
4544 reverse: bool,
4545 ) -> IotaResult<Vec<TransactionDigest>> {
4546 if let Some(TransactionFilter::Checkpoint(sequence_number)) = filter {
4547 let checkpoint_contents = kv_store.get_checkpoint_contents(sequence_number).await?;
4548 let iter = checkpoint_contents.iter().map(|c| c.transaction);
4549 if reverse {
4550 let iter = iter
4551 .rev()
4552 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4553 .skip(usize::from(cursor.is_some()));
4554 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4555 } else {
4556 let iter = iter
4557 .skip_while(|d| cursor.is_some() && Some(*d) != cursor)
4558 .skip(usize::from(cursor.is_some()));
4559 return Ok(iter.take(limit.unwrap_or(usize::MAX)).collect());
4560 }
4561 }
4562 self.get_indexes()?
4563 .get_transactions(filter, cursor, limit, reverse)
4564 }
4565
4566 pub fn get_checkpoint_store(&self) -> &Arc<CheckpointStore> {
4567 &self.checkpoint_store
4568 }
4569
4570 pub fn pruner(&self) -> &AuthorityStorePruner {
4573 &self.pruner
4574 }
4575
4576 pub fn retain_objects(&self) -> ObjectRetentionGuard {
4582 self.pruner.retain_objects()
4583 }
4584
4585 pub fn get_latest_checkpoint_sequence_number(&self) -> IotaResult<CheckpointSequenceNumber> {
4586 self.get_checkpoint_store()
4587 .get_highest_executed_checkpoint_seq_number()?
4588 .ok_or(IotaError::UserInput {
4589 error: UserInputError::LatestCheckpointSequenceNumberNotFound,
4590 })
4591 }
4592
4593 #[cfg(msim)]
4594 pub fn get_highest_pruned_checkpoint_for_testing(
4595 &self,
4596 ) -> IotaResult<CheckpointSequenceNumber> {
4597 self.database_for_testing()
4598 .perpetual_tables
4599 .get_highest_pruned_checkpoint()
4600 .map(|c| c.unwrap_or(0))
4601 .map_err(Into::into)
4602 }
4603
4604 #[instrument(level = "trace", skip_all)]
4605 pub fn get_checkpoint_summary_by_sequence_number(
4606 &self,
4607 sequence_number: CheckpointSequenceNumber,
4608 ) -> IotaResult<CheckpointSummary> {
4609 let verified_checkpoint = self
4610 .get_checkpoint_store()
4611 .get_checkpoint_by_sequence_number(sequence_number)?;
4612 match verified_checkpoint {
4613 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4614 None => Err(IotaError::UserInput {
4615 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4616 }),
4617 }
4618 }
4619
4620 #[instrument(level = "trace", skip_all)]
4621 pub fn get_checkpoint_summary_by_digest(
4622 &self,
4623 digest: CheckpointDigest,
4624 ) -> IotaResult<CheckpointSummary> {
4625 let verified_checkpoint = self
4626 .get_checkpoint_store()
4627 .get_checkpoint_by_digest(&digest)?;
4628 match verified_checkpoint {
4629 Some(verified_checkpoint) => Ok(verified_checkpoint.into_inner().into_data()),
4630 None => Err(IotaError::UserInput {
4631 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4632 }),
4633 }
4634 }
4635
4636 #[instrument(level = "trace", skip_all)]
4637 pub fn find_publish_txn_digest(&self, package_id: ObjectId) -> IotaResult<TransactionDigest> {
4638 if package_id.is_system_package() {
4639 return self.find_genesis_txn_digest();
4640 }
4641 Ok(self
4642 .get_object_read(&package_id)?
4643 .into_object()?
4644 .previous_transaction)
4645 }
4646
4647 #[instrument(level = "trace", skip_all)]
4648 pub fn find_genesis_txn_digest(&self) -> IotaResult<TransactionDigest> {
4649 let summary = self
4650 .get_verified_checkpoint_by_sequence_number(0)?
4651 .into_message();
4652 let content = self.get_checkpoint_contents(summary.contents_digest)?;
4653 let genesis_transaction = content.enumerate_transactions(&summary).next();
4654 Ok(genesis_transaction
4655 .ok_or(IotaError::UserInput {
4656 error: UserInputError::GenesisTransactionNotFound,
4657 })?
4658 .1
4659 .transaction)
4660 }
4661
4662 #[instrument(level = "trace", skip_all)]
4663 pub fn get_verified_checkpoint_by_sequence_number(
4664 &self,
4665 sequence_number: CheckpointSequenceNumber,
4666 ) -> IotaResult<VerifiedCheckpoint> {
4667 let verified_checkpoint = self
4668 .get_checkpoint_store()
4669 .get_checkpoint_by_sequence_number(sequence_number)?;
4670 match verified_checkpoint {
4671 Some(verified_checkpoint) => Ok(verified_checkpoint),
4672 None => Err(IotaError::UserInput {
4673 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4674 }),
4675 }
4676 }
4677
4678 #[instrument(level = "trace", skip_all)]
4679 pub fn get_verified_checkpoint_summary_by_digest(
4680 &self,
4681 digest: CheckpointDigest,
4682 ) -> IotaResult<VerifiedCheckpoint> {
4683 let verified_checkpoint = self
4684 .get_checkpoint_store()
4685 .get_checkpoint_by_digest(&digest)?;
4686 match verified_checkpoint {
4687 Some(verified_checkpoint) => Ok(verified_checkpoint),
4688 None => Err(IotaError::UserInput {
4689 error: UserInputError::VerifiedCheckpointDigestNotFound(Base58::encode(digest)),
4690 }),
4691 }
4692 }
4693
4694 #[instrument(level = "trace", skip_all)]
4695 pub fn get_checkpoint_contents(
4696 &self,
4697 digest: CheckpointContentsDigest,
4698 ) -> IotaResult<CheckpointContents> {
4699 self.get_checkpoint_store()
4700 .get_checkpoint_contents(&digest)?
4701 .ok_or(IotaError::UserInput {
4702 error: UserInputError::CheckpointContentsNotFound(digest),
4703 })
4704 }
4705
4706 #[instrument(level = "trace", skip_all)]
4707 pub fn get_checkpoint_contents_by_sequence_number(
4708 &self,
4709 sequence_number: CheckpointSequenceNumber,
4710 ) -> IotaResult<CheckpointContents> {
4711 let verified_checkpoint = self
4712 .get_checkpoint_store()
4713 .get_checkpoint_by_sequence_number(sequence_number)?;
4714 match verified_checkpoint {
4715 Some(verified_checkpoint) => {
4716 let contents_digest = verified_checkpoint.into_inner().contents_digest;
4717 self.get_checkpoint_contents(contents_digest)
4718 }
4719 None => Err(IotaError::UserInput {
4720 error: UserInputError::VerifiedCheckpointNotFound(sequence_number),
4721 }),
4722 }
4723 }
4724
4725 #[instrument(level = "trace", skip_all)]
4726 pub async fn query_events(
4727 &self,
4728 kv_store: &Arc<TransactionKeyValueStore>,
4729 query: EventFilter,
4730 cursor: Option<EventID>,
4732 limit: usize,
4733 descending: bool,
4734 ) -> IotaResult<Vec<IotaEvent>> {
4735 let index_store = self.get_indexes()?;
4736
4737 let (tx_num, event_num) = if let Some(cursor) = cursor.as_ref() {
4739 let tx_seq = index_store.get_transaction_seq(&cursor.tx_digest)?.ok_or(
4740 IotaError::TransactionNotFound {
4741 digest: cursor.tx_digest,
4742 },
4743 )?;
4744 (tx_seq, cursor.event_seq as usize)
4745 } else if descending {
4746 (u64::MAX, usize::MAX)
4747 } else {
4748 (0, 0)
4749 };
4750
4751 let limit = limit + 1;
4752 let mut event_keys = match query {
4753 EventFilter::All(filters) => {
4754 if filters.is_empty() {
4755 index_store.all_events(tx_num, event_num, limit, descending)?
4756 } else {
4757 return Err(IotaError::UserInput {
4758 error: UserInputError::Unsupported(
4759 "This query type does not currently support filter combinations"
4760 .to_string(),
4761 ),
4762 });
4763 }
4764 }
4765 EventFilter::Transaction(digest) => {
4766 index_store.events_by_transaction(&digest, tx_num, event_num, limit, descending)?
4767 }
4768 EventFilter::MoveModule { package, module } => {
4769 let module_id = ModuleId::new(
4770 AccountAddress::new(package.into_bytes()),
4771 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4772 );
4773 index_store.events_by_module_id(&module_id, tx_num, event_num, limit, descending)?
4774 }
4775 EventFilter::MoveEventType(struct_name) => index_store
4776 .events_by_move_event_struct_name(
4777 &struct_name,
4778 tx_num,
4779 event_num,
4780 limit,
4781 descending,
4782 )?,
4783 EventFilter::Sender(sender) => {
4784 index_store.events_by_sender(&sender, tx_num, event_num, limit, descending)?
4785 }
4786 EventFilter::TimeRange {
4787 start_time,
4788 end_time,
4789 } => index_store
4790 .event_iterator(start_time, end_time, tx_num, event_num, limit, descending)?,
4791 EventFilter::MoveEventModule { package, module } => index_store
4792 .events_by_move_event_module(
4793 &ModuleId::new(
4794 AccountAddress::new(package.into_bytes()),
4795 move_core_types::identifier::Identifier::new(module.as_str()).unwrap(),
4796 ),
4797 tx_num,
4798 event_num,
4799 limit,
4800 descending,
4801 )?,
4802 EventFilter::Package(_)
4804 | EventFilter::MoveEventField { .. }
4805 | EventFilter::Any(_)
4806 | EventFilter::And(_, _)
4807 | EventFilter::Or(_, _) => {
4808 return Err(IotaError::UserInput {
4809 error: UserInputError::Unsupported(
4810 "This query type is not supported by the full node.".to_string(),
4811 ),
4812 });
4813 }
4814 };
4815
4816 if cursor.is_some() {
4819 if !event_keys.is_empty() {
4820 event_keys.remove(0);
4821 }
4822 } else {
4823 event_keys.truncate(limit - 1);
4824 }
4825
4826 let transaction_digests = event_keys
4828 .iter()
4829 .map(|(_, digest, _, _)| *digest)
4830 .collect::<HashSet<_>>()
4831 .into_iter()
4832 .collect::<Vec<_>>();
4833
4834 let events = kv_store
4835 .multi_get_events_by_tx_digests(&transaction_digests)
4836 .await?;
4837
4838 let events_map: HashMap<_, _> =
4839 transaction_digests.iter().zip(events.into_iter()).collect();
4840
4841 let stored_events = event_keys
4842 .into_iter()
4843 .map(|k| {
4844 (
4845 k,
4846 events_map
4847 .get(&k.1)
4848 .expect("fetched digest is missing")
4849 .clone()
4850 .and_then(|e| e.get(k.2).cloned()),
4851 )
4852 })
4853 .map(
4854 |((_event_digest, tx_digest, event_seq, timestamp), event)| {
4855 event
4856 .map(|e| (e, tx_digest, event_seq, timestamp))
4857 .ok_or(IotaError::TransactionEventsNotFound { digest: tx_digest })
4858 },
4859 )
4860 .collect::<Result<Vec<_>, _>>()?;
4861
4862 let epoch_store = self.load_epoch_store_one_call_per_task();
4863 let backing_store = self.get_backing_package_store().as_ref();
4864 let mut layout_resolver = epoch_store
4865 .executor()
4866 .type_layout_resolver(Box::new(backing_store));
4867 let mut events = vec![];
4868 for (e, tx_digest, event_seq, timestamp) in stored_events.into_iter() {
4869 events.push(IotaEvent::try_from(
4870 e.clone(),
4871 tx_digest,
4872 event_seq as u64,
4873 Some(timestamp),
4874 layout_resolver.get_annotated_layout(&e.struct_tag)?,
4875 )?)
4876 }
4877 Ok(events)
4878 }
4879
4880 pub fn insert_genesis_object(&self, object: Object) {
4881 self.get_reconfig_api()
4882 .try_insert_genesis_object(object)
4883 .expect("Cannot insert genesis object")
4884 }
4885
4886 pub fn insert_genesis_objects(&self, objects: &[Object]) {
4887 for o in objects {
4888 self.insert_genesis_object(o.clone());
4889 }
4890 }
4891
4892 #[instrument(level = "trace", skip_all)]
4894 pub fn get_transaction_status(
4895 &self,
4896 transaction_digest: &TransactionDigest,
4897 epoch_store: &Arc<AuthorityPerEpochStore>,
4898 ) -> IotaResult<Option<(SenderSignedTransaction, TransactionStatus)>> {
4899 if let Some(effects) =
4901 self.get_signed_effects_and_maybe_resign(transaction_digest, epoch_store)?
4902 {
4903 if let Some(transaction) = self
4904 .get_transaction_cache_reader()
4905 .try_get_transaction_block(transaction_digest)?
4906 {
4907 let cert_sig = epoch_store.get_transaction_cert_sig(transaction_digest)?;
4908 let events = if effects.events_digest().is_some() {
4909 self.get_transaction_events(effects.transaction_digest())?
4910 } else {
4911 TransactionEvents::default()
4912 };
4913 return Ok(Some((
4914 (*transaction).clone().into_message(),
4915 TransactionStatus::Executed(cert_sig, effects.into_inner(), events),
4916 )));
4917 } else {
4918 debug!(tx_digest=?transaction_digest, "Signed effects exist but no transaction found");
4923 }
4924 }
4925 if let Some(signed) = epoch_store.get_signed_transaction(transaction_digest)? {
4926 self.metrics.tx_already_processed.inc();
4927 let (transaction, sig) = signed.into_inner().into_data_and_sig();
4928 Ok(Some((transaction, TransactionStatus::Signed(sig))))
4929 } else {
4930 Ok(None)
4931 }
4932 }
4933
4934 #[instrument(level = "trace", skip_all)]
4938 pub fn get_signed_effects_and_maybe_resign(
4939 &self,
4940 transaction_digest: &TransactionDigest,
4941 epoch_store: &Arc<AuthorityPerEpochStore>,
4942 ) -> IotaResult<Option<VerifiedSignedTransactionEffects>> {
4943 let effects = self
4944 .get_transaction_cache_reader()
4945 .try_get_executed_effects(transaction_digest)?;
4946 match effects {
4947 Some(effects) => {
4948 if effects.epoch() != epoch_store.epoch() {
4969 debug!(
4970 tx_digest=?transaction_digest,
4971 effects_epoch=?effects.epoch(),
4972 epoch=?epoch_store.epoch(),
4973 "Re-signing the effects with the current epoch"
4974 );
4975 }
4976 Ok(Some(self.sign_effects(effects, epoch_store)?))
4977 }
4978 None => Ok(None),
4979 }
4980 }
4981
4982 pub fn check_effects_against_previously_signed(
4992 &self,
4993 epoch_store: &AuthorityPerEpochStore,
4994 tx_digest: &TransactionDigest,
4995 effects_digest: &TransactionEffectsDigest,
4996 surface: &'static str,
4997 ) -> IotaResult<()> {
4998 if let Some(previously_signed_digest) = epoch_store.get_signed_effects_digest(tx_digest)? {
4999 if previously_signed_digest != *effects_digest {
5000 self.metrics
5001 .signed_effects_equivocation_prevented
5002 .with_label_values(&[surface])
5003 .inc();
5004 error!(
5005 ?tx_digest,
5006 ?previously_signed_digest,
5007 executed_digest = ?effects_digest,
5008 surface,
5009 "refusing to report effects that differ from previously signed effects"
5010 );
5011 return Err(IotaError::GenericAuthority {
5012 error: format!(
5013 "Refusing to report effects for transaction {tx_digest}: effects digest \
5014 {effects_digest} differs from previously signed effects digest \
5015 {previously_signed_digest}"
5016 ),
5017 });
5018 }
5019 }
5020 Ok(())
5021 }
5022
5023 #[instrument(level = "trace", skip_all)]
5024 pub(crate) fn sign_effects(
5025 &self,
5026 effects: TransactionEffects,
5027 epoch_store: &Arc<AuthorityPerEpochStore>,
5028 ) -> IotaResult<VerifiedSignedTransactionEffects> {
5029 let tx_digest = *effects.transaction_digest();
5030
5031 self.check_effects_against_previously_signed(
5032 epoch_store,
5033 &tx_digest,
5034 &effects.digest(),
5035 "sign_effects",
5036 )?;
5037
5038 let signed_effects = match epoch_store.get_effects_signature(&tx_digest)? {
5039 Some(sig) => {
5040 debug_assert!(sig.epoch == epoch_store.epoch());
5041 SignedTransactionEffects::new_from_data_and_sig(effects, sig)
5042 }
5043 _ => {
5044 let sig = AuthoritySignInfo::new(
5045 epoch_store.epoch(),
5046 &effects,
5047 Intent::iota_app(IntentScope::TransactionEffects),
5048 self.name,
5049 &*self.secret,
5050 );
5051
5052 let effects = SignedTransactionEffects::new_from_data_and_sig(effects, sig.clone());
5053
5054 epoch_store.insert_effects_digest_and_signature(
5055 &tx_digest,
5056 effects.digest(),
5057 &sig,
5058 )?;
5059
5060 effects
5061 }
5062 };
5063
5064 Ok(VerifiedSignedTransactionEffects::new_unchecked(
5065 signed_effects,
5066 ))
5067 }
5068
5069 #[instrument(level = "trace", skip_all)]
5071 fn fullnode_only_get_tx_coins_for_indexing(
5072 &self,
5073 effects: &TransactionEffects,
5074 inner_temporary_store: &InnerTemporaryStore,
5075 epoch_store: &Arc<AuthorityPerEpochStore>,
5076 ) -> Option<TxCoins> {
5077 if self.indexes.is_none() || self.is_committee_validator(epoch_store) {
5078 return None;
5079 }
5080 let written_coin_objects = inner_temporary_store
5081 .written
5082 .iter()
5083 .filter_map(|(k, v)| {
5084 if v.is_coin() {
5085 Some((*k, v.clone()))
5086 } else {
5087 None
5088 }
5089 })
5090 .collect();
5091 let mut input_coin_objects = inner_temporary_store
5092 .input_objects
5093 .iter()
5094 .filter_map(|(k, v)| {
5095 if v.is_coin() {
5096 Some((*k, v.clone()))
5097 } else {
5098 None
5099 }
5100 })
5101 .collect::<ObjectMap>();
5102
5103 for modified in effects.modified_at_versions() {
5108 let (object_id, version) = (*modified.object_id(), modified.version());
5109 if inner_temporary_store
5110 .loaded_runtime_objects
5111 .contains_key(&object_id)
5112 {
5113 if let Some(object) = self
5114 .get_object_store()
5115 .get_object_by_key(&object_id, version)
5116 {
5117 if object.is_coin() {
5118 input_coin_objects.insert(object_id, object);
5119 }
5120 }
5121 }
5122 }
5123
5124 Some((input_coin_objects, written_coin_objects))
5125 }
5126
5127 #[instrument(level = "trace", skip_all)]
5139 pub fn get_transaction_lock(
5140 &self,
5141 object_ref: &ObjectReference,
5142 epoch_store: &AuthorityPerEpochStore,
5143 ) -> IotaResult<Option<VerifiedSignedTransaction>> {
5144 let lock_info = self
5145 .get_object_cache_reader()
5146 .try_get_lock(*object_ref, epoch_store)?;
5147 let lock_info = match lock_info {
5148 ObjectLockStatus::LockedAtDifferentVersion { locked_ref } => {
5149 return Err(UserInputError::ObjectVersionUnavailableForConsumption {
5150 provided_obj_ref: *object_ref,
5151 current_version: locked_ref.version,
5152 }
5153 .into());
5154 }
5155 ObjectLockStatus::Initialized => {
5156 return Ok(None);
5157 }
5158 ObjectLockStatus::LockedToTx { locked_by_tx } => locked_by_tx,
5159 };
5160
5161 epoch_store.get_signed_transaction(&lock_info)
5162 }
5163
5164 pub fn try_get_objects(&self, objects: &[ObjectId]) -> IotaResult<Vec<Option<Object>>> {
5165 self.get_object_cache_reader().try_get_objects(objects)
5166 }
5167
5168 pub fn get_objects(&self, objects: &[ObjectId]) -> Vec<Option<Object>> {
5170 self.try_get_objects(objects)
5171 .expect("storage access failed")
5172 }
5173
5174 pub fn try_get_object_or_tombstone(
5175 &self,
5176 object_id: ObjectId,
5177 ) -> IotaResult<Option<ObjectReference>> {
5178 self.get_object_cache_reader()
5179 .try_get_latest_object_ref_or_tombstone(object_id)
5180 }
5181
5182 pub fn get_object_or_tombstone(&self, object_id: ObjectId) -> Option<ObjectReference> {
5184 self.try_get_object_or_tombstone(object_id)
5185 .expect("storage access failed")
5186 }
5187
5188 pub fn set_override_protocol_upgrade_buffer_stake(
5198 &self,
5199 expected_epoch: EpochId,
5200 buffer_stake_bps: u64,
5201 ) -> IotaResult {
5202 let epoch_store = self.load_epoch_store_one_call_per_task();
5203 let actual_epoch = epoch_store.epoch();
5204 if actual_epoch != expected_epoch {
5205 return Err(IotaError::WrongEpoch {
5206 expected_epoch,
5207 actual_epoch,
5208 });
5209 }
5210
5211 epoch_store.set_override_protocol_upgrade_buffer_stake(buffer_stake_bps)
5212 }
5213
5214 pub fn clear_override_protocol_upgrade_buffer_stake(
5215 &self,
5216 expected_epoch: EpochId,
5217 ) -> IotaResult {
5218 let epoch_store = self.load_epoch_store_one_call_per_task();
5219 let actual_epoch = epoch_store.epoch();
5220 if actual_epoch != expected_epoch {
5221 return Err(IotaError::WrongEpoch {
5222 expected_epoch,
5223 actual_epoch,
5224 });
5225 }
5226
5227 epoch_store.clear_override_protocol_upgrade_buffer_stake()
5228 }
5229
5230 pub async fn get_available_system_packages(
5234 &self,
5235 protocol_config: &ProtocolConfig,
5236 ) -> Vec<ObjectReference> {
5237 let mut results = vec![];
5238
5239 let system_packages = BuiltInFramework::iter_system_packages();
5240
5241 #[cfg(msim)]
5243 let extra_packages = framework_injection::get_extra_packages(self.name);
5244 #[cfg(msim)]
5245 let system_packages = {
5246 let mut packages: Vec<_> = system_packages.collect();
5247 packages.extend(extra_packages.iter());
5248 packages
5249 };
5250
5251 for system_package in system_packages {
5252 let modules = system_package.modules().to_vec();
5253 #[cfg(msim)]
5255 let modules = framework_injection::get_override_modules(&system_package.id, self.name)
5256 .unwrap_or(modules);
5257
5258 let Some(obj_ref) = iota_framework::compare_system_package(
5259 &self.get_object_store(),
5260 &system_package.id,
5261 &modules,
5262 system_package.dependencies.to_vec(),
5263 protocol_config,
5264 )
5265 .await
5266 else {
5267 return vec![];
5268 };
5269 results.push(obj_ref);
5270 }
5271
5272 results
5273 }
5274
5275 async fn get_system_package_bytes(
5298 &self,
5299 system_packages: Vec<ObjectReference>,
5300 binary_config: &BinaryConfig,
5301 ) -> Option<Vec<SystemPackage>> {
5302 let object_store = self.get_object_cache_reader();
5303
5304 let mut res = Vec::with_capacity(system_packages.len());
5305 for system_package_ref in system_packages {
5306 if object_store
5307 .get_object_by_key(&system_package_ref.object_id, system_package_ref.version)
5308 .is_some_and(|object| object.object_ref() == system_package_ref)
5309 {
5310 info!(
5312 "Framework {} does not need updating",
5313 system_package_ref.object_id
5314 );
5315 continue;
5316 }
5317
5318 let prev_transaction = if system_package_ref.version == Version::OBJECT_START {
5323 TransactionDigest::GENESIS_MARKER
5324 } else {
5325 let prev_version = system_package_ref
5326 .version
5327 .previous()
5328 .expect("version is greater than Version::OBJECT_START");
5329 let Some(prev_object) =
5330 object_store.get_object_by_key(&system_package_ref.object_id, prev_version)
5331 else {
5332 error!(
5333 "Framework {} not available locally at version {prev_version:?}, cannot \
5334 derive upgrade to {system_package_ref:?}",
5335 system_package_ref.object_id
5336 );
5337 return None;
5338 };
5339 prev_object.previous_transaction
5340 };
5341
5342 #[cfg(msim)]
5343 let FrameworkSystemPackage {
5344 id: _,
5345 bytes,
5346 dependencies,
5347 } = framework_injection::get_override_system_package(
5348 &system_package_ref.object_id,
5349 self.name,
5350 )
5351 .unwrap_or_else(|| {
5352 BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone()
5353 });
5354
5355 #[cfg(not(msim))]
5356 let FrameworkSystemPackage {
5357 id: _,
5358 bytes,
5359 dependencies,
5360 } = BuiltInFramework::get_package_by_id(&system_package_ref.object_id).clone();
5361
5362 let modules: Vec<_> = bytes
5363 .iter()
5364 .map(|m| CompiledModule::deserialize_with_config(m, binary_config).unwrap())
5365 .collect();
5366
5367 let new_object = Object::new_system_package(
5368 &modules,
5369 system_package_ref.version,
5370 dependencies.clone(),
5371 prev_transaction,
5372 );
5373
5374 let new_ref = new_object.object_ref();
5375 if new_ref != system_package_ref {
5376 debug_fatal!(
5377 "Framework mismatch -- binary: {new_ref:?}\n upgrade: {system_package_ref:?}"
5378 );
5379 return None;
5380 }
5381
5382 res.push(SystemPackage {
5383 version: system_package_ref.version,
5384 modules: bytes,
5385 dependencies,
5386 });
5387 }
5388
5389 Some(res)
5390 }
5391
5392 fn is_protocol_version_supported_v1(
5396 proposed_protocol_version: ProtocolVersion,
5397 committee: &Committee,
5398 capabilities: Vec<AuthorityCapabilitiesV1>,
5399 mut buffer_stake_bps: u64,
5400 ) -> Option<(ProtocolVersion, Digest, Vec<ObjectReference>)> {
5401 if buffer_stake_bps > 10000 {
5402 warn!("clamping buffer_stake_bps to 10000");
5403 buffer_stake_bps = 10000;
5404 }
5405
5406 let mut desired_upgrades: Vec<_> = capabilities
5409 .into_iter()
5410 .filter_map(|mut cap| {
5411 if cap.available_system_packages.is_empty() {
5413 return None;
5414 }
5415
5416 cap.available_system_packages.sort();
5417
5418 info!(
5419 "validator {:?} supports {:?} with system packages: {:?}",
5420 cap.authority.concise(),
5421 cap.supported_protocol_versions,
5422 cap.available_system_packages,
5423 );
5424
5425 cap.supported_protocol_versions
5429 .get_version_digest(proposed_protocol_version)
5430 .map(|digest| (digest, cap.available_system_packages, cap.authority))
5431 })
5432 .collect();
5433
5434 desired_upgrades.sort();
5437 desired_upgrades
5438 .into_iter()
5439 .chunk_by(|(digest, packages, _authority)| (*digest, packages.clone()))
5440 .into_iter()
5441 .find_map(|((digest, packages), group)| {
5442 assert!(!packages.is_empty());
5444
5445 let mut stake_aggregator: StakeAggregator<(), true> =
5446 StakeAggregator::new(Arc::new(committee.clone()));
5447
5448 for (_, _, authority) in group {
5449 stake_aggregator.insert_generic(authority, ());
5450 }
5451
5452 let total_votes = stake_aggregator.total_votes();
5453 let quorum_threshold = committee.quorum_threshold();
5454 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5455
5456 info!(
5457 protocol_config_digest = ?digest,
5458 ?total_votes,
5459 ?quorum_threshold,
5460 ?buffer_stake_bps,
5461 ?effective_threshold,
5462 ?proposed_protocol_version,
5463 ?packages,
5464 "support for upgrade"
5465 );
5466
5467 let has_support = total_votes >= effective_threshold;
5468 has_support.then_some((proposed_protocol_version, digest, packages))
5469 })
5470 }
5471
5472 fn choose_protocol_version_and_system_packages_v1(
5476 current_protocol_version: ProtocolVersion,
5477 current_protocol_digest: Digest,
5478 committee: &Committee,
5479 capabilities: Vec<AuthorityCapabilitiesV1>,
5480 buffer_stake_bps: u64,
5481 ) -> (ProtocolVersion, Digest, Vec<ObjectReference>) {
5482 let mut next_protocol_version = current_protocol_version;
5483 let mut system_packages = vec![];
5484 let mut protocol_version_digest = current_protocol_digest;
5485
5486 while let Some((version, digest, packages)) = Self::is_protocol_version_supported_v1(
5490 next_protocol_version + 1,
5491 committee,
5492 capabilities.clone(),
5493 buffer_stake_bps,
5494 ) {
5495 next_protocol_version = version;
5496 protocol_version_digest = digest;
5497 system_packages = packages;
5498 }
5499
5500 (
5501 next_protocol_version,
5502 protocol_version_digest,
5503 system_packages,
5504 )
5505 }
5506
5507 fn get_validators_supporting_protocol_version(
5512 target_protocol_version: ProtocolVersion,
5513 target_digest: Digest,
5514 active_validators: &[AggregateAuthorityPublicKey],
5515 capabilities: &[AuthorityCapabilitiesV1],
5516 ) -> Vec<u64> {
5517 let mut eligible_validators = Vec::new();
5518
5519 for capability in capabilities {
5520 if let Some(digest) = capability
5522 .supported_protocol_versions
5523 .get_version_digest(target_protocol_version)
5524 {
5525 if digest == target_digest {
5526 if let Some(index) = active_validators
5528 .iter()
5529 .position(|name| AuthorityName::from(name) == capability.authority)
5530 {
5531 eligible_validators.push(index as u64);
5532 }
5533 }
5534 }
5535 }
5536
5537 eligible_validators.sort();
5539 eligible_validators
5540 }
5541
5542 fn calculate_eligible_validators_weight(
5547 eligible_validator_indices: &[u64],
5548 active_validators: &[AggregateAuthorityPublicKey],
5549 committee: &Committee,
5550 ) -> u64 {
5551 let mut total_weight = 0u64;
5552
5553 for &index in eligible_validator_indices {
5554 let authority_pubkey = &active_validators[index as usize];
5555 if let Some((_, weight)) = committee
5557 .members()
5558 .find(|(name, _)| *name == AuthorityName::from(authority_pubkey))
5559 {
5560 total_weight += weight;
5561 }
5562 }
5563
5564 total_weight
5565 }
5566
5567 #[instrument(level = "error", skip_all)]
5580 pub async fn create_and_execute_advance_epoch_tx(
5581 &self,
5582 epoch_store: &Arc<AuthorityPerEpochStore>,
5583 gas_cost_summary: &GasCostSummary,
5584 checkpoint: CheckpointSequenceNumber,
5585 epoch_start_timestamp_ms: CheckpointTimestamp,
5586 scores: Vec<u64>,
5587 ) -> CheckpointBuilderResult<(
5588 IotaSystemState,
5589 Option<SystemEpochInfoEvent>,
5590 TransactionEffects,
5591 )> {
5592 let mut txns = Vec::new();
5593
5594 if epoch_store.protocol_config().enable_pcool_flow()
5600 && epoch_store
5601 .epoch_start_config()
5602 .transaction_deny_rules_obj_initial_shared_version()
5603 .is_none()
5604 {
5605 txns.push(EndOfEpochTransactionKind::TransactionDenyRulesCreate);
5606 }
5607
5608 let next_epoch = epoch_store.epoch() + 1;
5609
5610 let buffer_stake_bps = epoch_store.get_effective_buffer_stake_bps();
5611 let authority_capabilities = epoch_store
5612 .get_capabilities_v1()
5613 .expect("read capabilities from db cannot fail");
5614 let (next_epoch_protocol_version, next_epoch_protocol_digest, next_epoch_system_packages) =
5615 Self::choose_protocol_version_and_system_packages_v1(
5616 epoch_store.protocol_version(),
5617 SupportedProtocolVersionsWithHashes::protocol_config_digest(
5618 epoch_store.protocol_config(),
5619 ),
5620 epoch_store.committee(),
5621 authority_capabilities.clone(),
5622 buffer_stake_bps,
5623 );
5624
5625 let config = epoch_store.protocol_config();
5629 let binary_config = to_binary_config(config, None);
5630 let Some(next_epoch_system_package_bytes) = self
5631 .get_system_package_bytes(next_epoch_system_packages.clone(), &binary_config)
5632 .await
5633 else {
5634 debug_fatal!(
5635 "upgraded system packages {:?} are not locally available, cannot create \
5636 ChangeEpochTx. validator binary must be upgraded to the correct version!",
5637 next_epoch_system_packages
5638 );
5639 return Err(CheckpointBuilderError::SystemPackagesMissing);
5648 };
5649
5650 if config.select_committee_from_eligible_validators() {
5653 let active_validators = epoch_store.epoch_start_state().get_active_validators();
5655
5656 let mut eligible_active_validators = (0..active_validators.len() as u64).collect();
5657
5658 if config.select_committee_supporting_next_epoch_version() {
5662 eligible_active_validators = Self::get_validators_supporting_protocol_version(
5663 next_epoch_protocol_version,
5664 next_epoch_protocol_digest,
5665 &active_validators,
5666 &authority_capabilities,
5667 );
5668
5669 let eligible_validators_weight = Self::calculate_eligible_validators_weight(
5671 &eligible_active_validators,
5672 &active_validators,
5673 epoch_store.committee(),
5674 );
5675
5676 let committee = epoch_store.committee();
5680 let effective_threshold = committee.effective_threshold(buffer_stake_bps);
5681
5682 if eligible_validators_weight < effective_threshold {
5683 error!(
5684 "Eligible validators weight {eligible_validators_weight} is less than effective threshold {effective_threshold}. \
5685 This could indicate a bug in validator selection logic or inconsistency with protocol version decision.",
5686 );
5687 eligible_active_validators = (0..active_validators.len() as u64).collect();
5690 }
5691 }
5692
5693 if config.pass_validator_scores_to_advance_epoch() {
5696 txns.push(EndOfEpochTransactionKind::new_change_epoch_v4(
5697 next_epoch,
5698 next_epoch_protocol_version.as_u64(),
5699 gas_cost_summary.storage_cost,
5700 gas_cost_summary.computation_cost,
5701 gas_cost_summary.computation_cost_burned,
5702 gas_cost_summary.storage_rebate,
5703 gas_cost_summary.non_refundable_storage_fee,
5704 epoch_start_timestamp_ms,
5705 next_epoch_system_package_bytes,
5706 eligible_active_validators,
5707 scores,
5708 config.adjust_rewards_by_score(),
5709 ));
5710 } else {
5711 txns.push(EndOfEpochTransactionKind::new_change_epoch_v3(
5712 next_epoch,
5713 next_epoch_protocol_version.as_u64(),
5714 gas_cost_summary.storage_cost,
5715 gas_cost_summary.computation_cost,
5716 gas_cost_summary.computation_cost_burned,
5717 gas_cost_summary.storage_rebate,
5718 gas_cost_summary.non_refundable_storage_fee,
5719 epoch_start_timestamp_ms,
5720 next_epoch_system_package_bytes,
5721 eligible_active_validators,
5722 ));
5723 }
5724 } else if config.protocol_defined_base_fee()
5725 && config.max_committee_members_count_as_option().is_some()
5726 {
5727 txns.push(EndOfEpochTransactionKind::new_change_epoch_v2(
5728 next_epoch,
5729 next_epoch_protocol_version.as_u64(),
5730 gas_cost_summary.storage_cost,
5731 gas_cost_summary.computation_cost,
5732 gas_cost_summary.computation_cost_burned,
5733 gas_cost_summary.storage_rebate,
5734 gas_cost_summary.non_refundable_storage_fee,
5735 epoch_start_timestamp_ms,
5736 next_epoch_system_package_bytes,
5737 ));
5738 } else {
5739 txns.push(EndOfEpochTransactionKind::new_change_epoch(
5740 next_epoch,
5741 next_epoch_protocol_version.as_u64(),
5742 gas_cost_summary.storage_cost,
5743 gas_cost_summary.computation_cost,
5744 gas_cost_summary.storage_rebate,
5745 gas_cost_summary.non_refundable_storage_fee,
5746 epoch_start_timestamp_ms,
5747 next_epoch_system_package_bytes,
5748 ));
5749 }
5750
5751 let tx = VerifiedTransaction::new_end_of_epoch_transaction(txns);
5752
5753 let executable_tx = VerifiedExecutableTransaction::new_from_checkpoint(
5754 tx.clone(),
5755 epoch_store.epoch(),
5756 checkpoint,
5757 );
5758
5759 let tx_digest = executable_tx.digest();
5760
5761 info!(
5762 ?next_epoch,
5763 ?next_epoch_protocol_version,
5764 ?next_epoch_system_packages,
5765 computation_cost=?gas_cost_summary.computation_cost,
5766 computation_cost_burned=?gas_cost_summary.computation_cost_burned,
5767 storage_cost=?gas_cost_summary.storage_cost,
5768 storage_rebate=?gas_cost_summary.storage_rebate,
5769 non_refundable_storage_fee=?gas_cost_summary.non_refundable_storage_fee,
5770 ?tx_digest,
5771 "Creating advance epoch transaction"
5772 );
5773
5774 fail_point_async!("change_epoch_tx_delay");
5775 let tx_lock = epoch_store.acquire_tx_lock(tx_digest);
5776
5777 if self
5781 .get_transaction_cache_reader()
5782 .try_is_tx_already_executed(tx_digest)?
5783 {
5784 warn!("change epoch tx has already been executed via state sync");
5785 return Err(CheckpointBuilderError::ChangeEpochTxAlreadyExecuted);
5786 }
5787
5788 let execution_guard = self.execution_lock_for_executable_transaction(&executable_tx)?;
5789
5790 let assigned_versions = epoch_store.assign_shared_object_versions_idempotent(
5794 self.get_object_cache_reader().as_ref(),
5795 std::iter::once(&Schedulable::Transaction(&executable_tx)),
5796 )?;
5797
5798 assert_eq!(assigned_versions.0.len(), 1);
5799 let assigned_versions = assigned_versions.0.into_iter().next().unwrap().1;
5800
5801 let (input_objects, _) = self.read_objects_for_execution(
5802 &tx_lock,
5803 &executable_tx,
5804 assigned_versions,
5805 epoch_store,
5806 )?;
5807
5808 let (temporary_store, effects, _execution_error_opt) = self.execute_transaction(
5809 &execution_guard,
5810 &executable_tx,
5811 input_objects,
5812 vec![],
5813 epoch_store,
5814 )?;
5815 let system_obj = get_iota_system_state(&temporary_store.written)
5816 .expect("change epoch tx must write to system object");
5817 let system_epoch_info_event = temporary_store
5819 .events
5820 .0
5821 .into_iter()
5822 .find(|event| event.is_system_epoch_info_event())
5823 .map(SystemEpochInfoEvent::from);
5824 assert!(system_epoch_info_event.is_some() || system_obj.safe_mode());
5827
5828 self.get_state_sync_store()
5832 .try_insert_transaction_and_effects(&tx, &effects)?;
5833
5834 info!(
5835 "Effects summary of the change epoch transaction: {:?}",
5836 effects.summary_for_debug()
5837 );
5838 epoch_store.record_checkpoint_builder_is_safe_mode_metric(system_obj.safe_mode());
5839 assert!(effects.status().is_success());
5841 Ok((system_obj, system_epoch_info_event, effects))
5842 }
5843
5844 #[instrument(level = "error", skip_all)]
5848 async fn revert_uncommitted_epoch_transactions(
5849 &self,
5850 epoch_store: &AuthorityPerEpochStore,
5851 ) -> IotaResult {
5852 {
5853 let state = epoch_store.get_reconfig_state_write_lock_guard();
5854 if state.should_accept_user_certs() {
5855 epoch_store.close_user_certs(state);
5864 }
5865 }
5867
5868 if !epoch_store.protocol_config().enable_pcool_flow() {
5871 let pending_certificates = epoch_store.pending_consensus_certificates();
5872 info!(
5873 "Reverting {} locally executed transactions that was not included in the epoch: \
5874 {:?}",
5875 pending_certificates.len(),
5876 pending_certificates,
5877 );
5878 for digest in pending_certificates {
5879 if epoch_store.is_transaction_executed_in_checkpoint(&digest)? {
5880 info!(
5881 "Not reverting pending consensus transaction {:?} - it was included in \
5882 checkpoint",
5883 digest
5884 );
5885 continue;
5886 }
5887 info!("Reverting {:?} at the end of epoch", digest);
5888 epoch_store.revert_executed_transaction(&digest)?;
5889 self.get_reconfig_api().try_revert_state_update(&digest)?;
5890 }
5891 info!("All uncommitted local transactions reverted");
5892 } else {
5893 info!("P-COOL mode: skipping revert of uncommitted epoch transactions");
5894 }
5895
5896 Ok(())
5897 }
5898
5899 #[instrument(level = "error", skip_all)]
5900 async fn reopen_epoch_db(
5901 &self,
5902 cur_epoch_store: &AuthorityPerEpochStore,
5903 new_committee: Committee,
5904 epoch_start_configuration: EpochStartConfiguration,
5905 expensive_safety_check_config: &ExpensiveSafetyCheckConfig,
5906 epoch_last_checkpoint: CheckpointSequenceNumber,
5907 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
5908 let new_epoch = new_committee.epoch;
5909 info!(new_epoch = ?new_epoch, "re-opening AuthorityEpochTables for new epoch");
5910 assert_eq!(
5911 epoch_start_configuration.epoch_start_state().epoch(),
5912 new_committee.epoch
5913 );
5914 fail_point!("before-open-new-epoch-store");
5915 let new_epoch_store = cur_epoch_store.new_at_next_epoch(
5916 self.name,
5917 new_committee,
5918 epoch_start_configuration,
5919 self.get_backing_package_store().clone(),
5920 expensive_safety_check_config,
5921 epoch_last_checkpoint,
5922 )?;
5923 self.epoch_store.store(new_epoch_store.clone());
5924 Ok(new_epoch_store)
5925 }
5926
5927 fn check_move_account_for_execution(
5949 &self,
5950 auth_account_object_id: ObjectId,
5951 auth_account_object_seq_number: Option<Version>,
5952 auth_account_object_digest: Option<ObjectDigest>,
5953 account_object: ObjectReadResult,
5954 signer: &Address,
5955 protocol_config: &ProtocolConfig,
5956 ) -> Result<AuthenticatorFunctionRefForExecution, ExecutionError> {
5957 match self.check_move_account(
5958 auth_account_object_id,
5959 auth_account_object_seq_number,
5960 auth_account_object_digest,
5961 account_object,
5962 signer,
5963 true,
5964 protocol_config,
5965 ) {
5966 Ok(function_ref) => Ok(function_ref),
5967 Err(MoveAccountCheckError::Input(input_error)) => {
5968 let status = match &input_error {
5969 UserInputError::MoveAuthenticatorNotFound {
5970 account_object_id, ..
5971 }
5972 | UserInputError::InvalidAuthenticatorFunctionRefField { account_object_id } => {
5973 ExecutionErrorKind::AuthenticatorFunctionNotFound {
5974 object_id: *account_object_id,
5975 }
5976 }
5977 UserInputError::AccountObjectNotSupported { object_id }
5982 | UserInputError::ImmutableAccountObjectNotSupported { object_id }
5983 | UserInputError::InvalidAccountObjectDigest { object_id, .. } => {
5984 ExecutionErrorKind::AccountNotSharedObject {
5985 object_id: *object_id,
5986 }
5987 }
5988 _ => ExecutionErrorKind::FunctionNotFound,
5991 };
5992 Err(ExecutionError::new_with_source(status, input_error))
5993 }
5994 Err(MoveAccountCheckError::Storage(storage_error)) => {
5995 panic!("failed to read the store while checking a Move account: {storage_error}")
5996 }
5997 }
5998 }
5999
6000 fn check_move_account_for_validation(
6004 &self,
6005 auth_account_object_id: ObjectId,
6006 auth_account_object_seq_number: Option<Version>,
6007 auth_account_object_digest: Option<ObjectDigest>,
6008 account_object: ObjectReadResult,
6009 signer: &Address,
6010 protocol_config: &ProtocolConfig,
6011 ) -> IotaResult<AuthenticatorFunctionRefForExecution> {
6012 self.check_move_account(
6013 auth_account_object_id,
6014 auth_account_object_seq_number,
6015 auth_account_object_digest,
6016 account_object,
6017 signer,
6018 false,
6019 protocol_config,
6020 )
6021 .map_err(IotaError::from)
6022 }
6023
6024 fn check_move_account(
6041 &self,
6042 auth_account_object_id: ObjectId,
6043 auth_account_object_seq_number: Option<Version>,
6044 auth_account_object_digest: Option<ObjectDigest>,
6045 account_object: ObjectReadResult,
6046 signer: &Address,
6047 is_execution: bool,
6048 protocol_config: &ProtocolConfig,
6049 ) -> Result<AuthenticatorFunctionRefForExecution, MoveAccountCheckError> {
6050 let auth_account_object_seq_number = match (&account_object.object, is_execution) {
6051 (ObjectReadResultKind::Object(object), _) => {
6055 let account_object_addr = Address::from(auth_account_object_id);
6056 fp_ensure!(
6057 signer == &account_object_addr,
6058 UserInputError::IncorrectUserSignature {
6059 error: format!("Move authenticator is trying to unlock {account_object_addr:?}, but given signer address is {signer:?}")
6060 }
6061 .into()
6062 );
6063
6064 if protocol_config.reject_immutable_account_objects() {
6065 fp_ensure!(
6066 !object.is_immutable(),
6067 UserInputError::ImmutableAccountObjectNotSupported {
6068 object_id: auth_account_object_id
6069 }
6070 .into()
6071 );
6072 }
6073
6074 fp_ensure!(
6075 object.is_shared() || object.is_immutable(),
6076 UserInputError::AccountObjectNotSupported {
6077 object_id: auth_account_object_id
6078 }
6079 .into()
6080 );
6081
6082 let auth_account_object_seq_number =
6083 if let Some(expected_version) = auth_account_object_seq_number {
6084 let account_object_version = object.version();
6085
6086 fp_ensure!(
6087 account_object_version == expected_version,
6088 UserInputError::AccountObjectVersionMismatch {
6089 object_id: auth_account_object_id,
6090 expected_version,
6091 actual_version: account_object_version,
6092 }
6093 .into()
6094 );
6095
6096 expected_version
6097 } else {
6098 object.version()
6099 };
6100
6101 if let Some(expected_digest) = auth_account_object_digest {
6102 let account_object_digest = object.digest();
6103 fp_ensure!(
6104 account_object_digest == expected_digest,
6105 UserInputError::InvalidAccountObjectDigest {
6106 object_id: auth_account_object_id,
6107 expected_digest,
6108 actual_digest: account_object_digest,
6109 }
6110 .into()
6111 );
6112 }
6113
6114 Ok(auth_account_object_seq_number)
6115 }
6116 (ObjectReadResultKind::DeletedSharedObject(version, digest), false) => {
6119 Err(UserInputError::AccountObjectDeleted {
6120 account_id: account_object.id(),
6121 account_version: *version,
6122 transaction_digest: *digest,
6123 })
6124 }
6125 (ObjectReadResultKind::CancelledTransactionObject(version), false) => {
6129 Err(UserInputError::AccountObjectInCanceledTransaction {
6130 account_id: account_object.id(),
6131 account_version: *version,
6132 })
6133 }
6134 (ObjectReadResultKind::DeletedSharedObject(version, _), true) => Ok(*version),
6139 (ObjectReadResultKind::CancelledTransactionObject(version), true) => Ok(*version),
6145 (ObjectReadResultKind::UnreadSharedObject, _) => unreachable!(
6148 "only post-consensus validation at a commit lists an unread shared object, and \
6149 it leaves the account to execution"
6150 ),
6151 }?;
6152
6153 let authenticator_function_ref_field_id =
6154 derive_authenticator_function_ref_v1_dynamic_field_id(auth_account_object_id)?;
6155
6156 let authenticator_function_ref_field = self
6157 .get_object_cache_reader()
6158 .try_find_object_lt_or_eq_version(
6159 authenticator_function_ref_field_id,
6160 auth_account_object_seq_number,
6161 )
6162 .map_err(MoveAccountCheckError::Storage)?;
6163
6164 if let Some(authenticator_function_ref_field_obj) = authenticator_function_ref_field {
6165 Ok(authenticator_function_ref_v1_from_dynamic_field_object(
6166 auth_account_object_id,
6167 &authenticator_function_ref_field_obj,
6168 )?)
6169 } else {
6170 Err(UserInputError::MoveAuthenticatorNotFound {
6171 authenticator_function_ref_id: authenticator_function_ref_field_id,
6172 account_object_id: auth_account_object_id,
6173 account_object_version: auth_account_object_seq_number,
6174 }
6175 .into())
6176 }
6177 }
6178
6179 #[allow(clippy::type_complexity)]
6180 fn read_objects_for_validation(
6181 &self,
6182 transaction: &VerifiedTransaction,
6183 epoch: u64,
6184 ) -> IotaResult<(
6185 InputObjects,
6186 ReceivingObjects,
6187 Vec<(InputObjects, ObjectReadResult)>,
6188 )> {
6189 let (input_objects, tx_receiving_objects) = self.input_loader.read_objects_for_signing(
6190 Some(transaction.digest()),
6191 &transaction.collect_all_input_object_kind_for_reading()?,
6192 &transaction.data().transaction().receiving_objects(),
6193 epoch,
6194 )?;
6195
6196 transaction
6197 .split_input_objects_into_groups_for_reading(input_objects)
6198 .map(|(tx_input_objects, per_authenticator_inputs)| {
6199 (
6200 tx_input_objects,
6201 tx_receiving_objects,
6202 per_authenticator_inputs,
6203 )
6204 })
6205 }
6206
6207 fn read_objects_for_validation_at_commit(
6212 &self,
6213 reader: &CommitIndexedReader,
6214 transaction: &VerifiedTransaction,
6215 ) -> IotaResult<ValidationInputsAtCommit> {
6216 let input_objects = match self.input_loader.read_objects_at_commit(
6217 reader,
6218 &transaction.collect_all_input_object_kind_for_reading()?,
6219 )? {
6220 InputResolution::Loaded(input_objects) => input_objects,
6221 InputResolution::Drop(kind, reason) => {
6222 return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6223 }
6224 InputResolution::Missing(kind, reason) => {
6225 return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6226 }
6227 };
6228 let tx_receiving_objects = match self.input_loader.read_receiving_objects_at_commit(
6229 reader,
6230 &transaction.data().transaction().receiving_objects(),
6231 )? {
6232 ReceivingObjectsResolution::Loaded(receiving_objects) => receiving_objects,
6233 ReceivingObjectsResolution::Drop(kind, reason) => {
6234 return Ok(ValidationInputsAtCommit::Drop(kind, reason));
6235 }
6236 ReceivingObjectsResolution::Missing(kind, reason) => {
6237 return Ok(ValidationInputsAtCommit::Missing(kind, reason));
6238 }
6239 };
6240
6241 let (tx_input_objects, per_authenticator_inputs) =
6242 transaction.split_input_objects_into_groups_for_reading(input_objects)?;
6243 Ok(ValidationInputsAtCommit::Loaded {
6244 tx_input_objects,
6245 tx_receiving_objects,
6246 per_authenticator_inputs,
6247 })
6248 }
6249
6250 #[allow(clippy::type_complexity)]
6251 fn check_transaction_inputs_for_validation(
6252 &self,
6253 protocol_config: &ProtocolConfig,
6254 reference_gas_price: u64,
6255 tx: &Transaction,
6256 tx_input_objects: InputObjects,
6257 tx_receiving_objects: &ReceivingObjects,
6258 move_authenticators: &Vec<&MoveAuthenticator>,
6259 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6260 verifier_limits_source: VerifierLimitsSource<'_>,
6261 ) -> IotaResult<(
6262 IotaGasStatus,
6263 CheckedInputObjects,
6264 Vec<(CheckedInputObjects, AuthenticatorFunctionRef)>,
6265 )> {
6266 let authenticator_gas_budget = if move_authenticators.is_empty() {
6267 0
6268 } else {
6269 protocol_config.max_auth_gas()
6272 };
6273
6274 debug_assert_eq!(
6275 move_authenticators.len(),
6276 per_authenticator_inputs.len(),
6277 "Move authenticators amount must match the number of authenticator inputs"
6278 );
6279
6280 let per_authenticator_checked_inputs = move_authenticators
6281 .iter()
6282 .zip(per_authenticator_inputs)
6283 .map(
6284 |(move_authenticator, (authenticator_input_objects, account_object))| {
6285 let (
6287 auth_account_object_id,
6288 auth_account_object_seq_number,
6289 auth_account_object_digest,
6290 ) = move_authenticator.object_to_authenticate_components()?;
6291
6292 let signer = move_authenticator.address();
6293
6294 let AuthenticatorFunctionRefForExecution {
6296 authenticator_function_ref,
6297 ..
6298 } = self.check_move_account_for_validation(
6299 auth_account_object_id,
6300 auth_account_object_seq_number,
6301 auth_account_object_digest,
6302 account_object,
6303 &signer,
6304 protocol_config,
6305 )?;
6306
6307 let authenticator_checked_input_objects =
6309 iota_transaction_checks::check_move_authenticator_input_for_validation(
6310 authenticator_input_objects,
6311 )?;
6312
6313 Ok((
6314 authenticator_checked_input_objects,
6315 authenticator_function_ref,
6316 ))
6317 },
6318 )
6319 .collect::<IotaResult<Vec<_>>>()?;
6320
6321 let (gas_status, tx_checked_input_objects) =
6323 iota_transaction_checks::check_transaction_input(
6324 protocol_config,
6325 reference_gas_price,
6326 tx,
6327 tx_input_objects,
6328 tx_receiving_objects,
6329 &self.metrics.bytecode_verifier_metrics,
6330 verifier_limits_source,
6331 authenticator_gas_budget,
6332 )?;
6333
6334 Ok((
6335 gas_status,
6336 tx_checked_input_objects,
6337 per_authenticator_checked_inputs,
6338 ))
6339 }
6340
6341 fn check_transaction_inputs_at_commit(
6348 &self,
6349 protocol_config: &ProtocolConfig,
6350 reference_gas_price: u64,
6351 tx: &Transaction,
6352 tx_input_objects: InputObjects,
6353 tx_receiving_objects: &ReceivingObjects,
6354 move_authenticators: &[&MoveAuthenticator],
6355 per_authenticator_inputs: Vec<(InputObjects, ObjectReadResult)>,
6356 verifier_limits_source: VerifierLimitsSource<'_>,
6357 ) -> IotaResult<CheckedValidationInputs> {
6358 let authenticator_gas_budget = if move_authenticators.is_empty() {
6359 0
6360 } else {
6361 protocol_config.max_auth_gas()
6362 };
6363
6364 debug_assert_eq!(
6365 move_authenticators.len(),
6366 per_authenticator_inputs.len(),
6367 "Move authenticators amount must match the number of authenticator inputs"
6368 );
6369
6370 let per_authenticator_checked_inputs = per_authenticator_inputs
6379 .into_iter()
6380 .map(|(authenticator_input_objects, _account_object)| {
6381 iota_transaction_checks::check_move_authenticator_input_for_validation(
6382 authenticator_input_objects,
6383 )
6384 })
6385 .collect::<IotaResult<Vec<_>>>()?;
6386
6387 let (_gas_status, tx_checked_input_objects) =
6389 iota_transaction_checks::check_transaction_input(
6390 protocol_config,
6391 reference_gas_price,
6392 tx,
6393 tx_input_objects,
6394 tx_receiving_objects,
6395 &self.metrics.bytecode_verifier_metrics,
6396 verifier_limits_source,
6397 authenticator_gas_budget,
6398 )?;
6399
6400 Ok((tx_checked_input_objects, per_authenticator_checked_inputs))
6401 }
6402
6403 #[cfg(test)]
6404 pub(crate) fn iter_live_object_set_for_testing(
6405 &self,
6406 ) -> impl Iterator<Item = authority_store_tables::LiveObject> + '_ {
6407 self.get_global_state_hash_store()
6408 .iter_cached_live_object_set_for_testing()
6409 }
6410
6411 #[cfg(test)]
6412 pub(crate) fn shutdown_execution_for_test(&self) {
6413 self.tx_execution_shutdown
6414 .lock()
6415 .take()
6416 .unwrap()
6417 .send(())
6418 .unwrap();
6419 }
6420
6421 pub async fn insert_objects_unsafe_for_testing_only(&self, objects: &[Object]) {
6424 self.get_reconfig_api().bulk_insert_genesis_objects(objects);
6425 self.get_object_cache_reader()
6426 .force_reload_system_packages(&BuiltInFramework::all_package_ids());
6427 self.get_reconfig_api()
6428 .clear_state_end_of_epoch(&self.execution_lock_for_reconfiguration().await);
6429 }
6430}
6431
6432pub struct RandomnessRoundReceiver {
6433 authority_state: Arc<AuthorityState>,
6434 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6435}
6436
6437impl RandomnessRoundReceiver {
6438 pub fn spawn(
6439 authority_state: Arc<AuthorityState>,
6440 randomness_rx: mpsc::Receiver<(EpochId, RandomnessRound, Vec<u8>)>,
6441 ) -> JoinHandle<()> {
6442 let rrr = RandomnessRoundReceiver {
6443 authority_state,
6444 randomness_rx,
6445 };
6446 spawn_monitored_task!(rrr.run())
6447 }
6448
6449 async fn run(mut self) {
6450 info!("RandomnessRoundReceiver event loop started");
6451
6452 loop {
6453 tokio::select! {
6454 maybe_recv = self.randomness_rx.recv() => {
6455 if let Some((epoch, round, bytes)) = maybe_recv {
6456 self.handle_new_randomness(epoch, round, bytes).await;
6457 } else {
6458 break;
6459 }
6460 },
6461 }
6462 }
6463
6464 info!("RandomnessRoundReceiver event loop ended");
6465 }
6466
6467 #[instrument(level = "debug", skip_all, fields(?epoch, ?round))]
6468 async fn handle_new_randomness(&self, epoch: EpochId, round: RandomnessRound, bytes: Vec<u8>) {
6469 fail_point_async!("randomness-delay");
6470
6471 let epoch_store = self.authority_state.load_epoch_store_one_call_per_task();
6472 if epoch_store.epoch() != epoch {
6473 warn!(
6474 "dropping randomness for epoch {epoch}, round {round}, because we are in epoch {}",
6475 epoch_store.epoch()
6476 );
6477 return;
6478 }
6479 let key = TransactionKey::RandomnessRound(epoch, round);
6480 let transaction = VerifiedTransaction::new_randomness_state_update(
6481 epoch,
6482 round,
6483 bytes,
6484 epoch_store
6485 .epoch_start_config()
6486 .randomness_obj_initial_shared_version(),
6487 );
6488 debug!(
6489 "created randomness state update transaction with digest: {:?}",
6490 transaction.digest()
6491 );
6492 let transaction = VerifiedExecutableTransaction::new_system(transaction, epoch);
6493 let digest = *transaction.digest();
6494
6495 self.authority_state
6500 .get_cache_commit()
6501 .persist_transaction(&transaction);
6502
6503 if epoch_store.insert_tx_key(key, digest).is_err() {
6505 warn!("epoch ended while handling new randomness");
6506 }
6507
6508 match self.authority_state.execution_scheduler().as_ref() {
6510 ExecutionSchedulerWrapper::ExecutionScheduler(_) => {}
6511 ExecutionSchedulerWrapper::TransactionManager(manager) => {
6512 manager.notify_transaction_key(&epoch_store, key, digest);
6516 }
6517 }
6518
6519 let authority_state = self.authority_state.clone();
6520 spawn_monitored_task!(async move {
6521 const RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT: Duration = Duration::from_secs(300);
6530 let result = tokio::time::timeout(
6531 RANDOMNESS_STATE_UPDATE_EXECUTION_TIMEOUT,
6532 authority_state
6533 .get_transaction_cache_reader()
6534 .try_notify_read_executed_effects(
6535 "RandomnessRoundReceiver::notify_read_executed_effects_first",
6536 &[digest],
6537 ),
6538 )
6539 .await;
6540 let result = match result {
6541 Ok(result) => result,
6542 Err(_) => {
6543 if cfg!(debug_assertions) {
6544 panic!(
6546 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6547 );
6548 }
6549 warn!(
6550 "randomness state update transaction execution timed out at epoch {epoch}, round {round}"
6551 );
6552 authority_state
6554 .get_transaction_cache_reader()
6555 .try_notify_read_executed_effects(
6556 "RandomnessRoundReceiver::notify_read_executed_effects_second",
6557 &[digest],
6558 )
6559 .await
6560 }
6561 };
6562
6563 let mut effects = result.unwrap_or_else(|_| panic!("failed to get effects for randomness state update transaction at epoch {epoch}, round {round}"));
6564 let effects = effects.pop().expect("should return effects");
6565 if *effects.status() != ExecutionStatus::Success {
6566 fatal!(
6567 "failed to execute randomness state update transaction at epoch {epoch}, round {round}: {effects:?}"
6568 );
6569 }
6570 debug!(
6571 "successfully executed randomness state update transaction at epoch {epoch}, round {round}"
6572 );
6573 });
6574 }
6575}
6576
6577#[async_trait]
6578impl TransactionKeyValueStoreTrait for AuthorityState {
6579 async fn multi_get(
6580 &self,
6581 transaction_keys: &[TransactionDigest],
6582 effects_keys: &[TransactionDigest],
6583 ) -> IotaResult<KVStoreTransactionData> {
6584 let txns = if !transaction_keys.is_empty() {
6585 self.get_transaction_cache_reader()
6586 .try_multi_get_transaction_blocks(transaction_keys)?
6587 .into_iter()
6588 .map(|t| t.map(|t| (*t).clone().into_inner()))
6589 .collect()
6590 } else {
6591 vec![]
6592 };
6593
6594 let fx = if !effects_keys.is_empty() {
6595 self.get_transaction_cache_reader()
6596 .try_multi_get_executed_effects(effects_keys)?
6597 } else {
6598 vec![]
6599 };
6600
6601 Ok((txns, fx))
6602 }
6603
6604 async fn multi_get_checkpoints(
6605 &self,
6606 checkpoint_summaries: &[CheckpointSequenceNumber],
6607 checkpoint_contents: &[CheckpointSequenceNumber],
6608 checkpoint_summaries_by_digest: &[CheckpointDigest],
6609 ) -> IotaResult<(
6610 Vec<Option<CertifiedCheckpointSummary>>,
6611 Vec<Option<CheckpointContents>>,
6612 Vec<Option<CertifiedCheckpointSummary>>,
6613 )> {
6614 let mut summaries = Vec::with_capacity(checkpoint_summaries.len());
6616 let store = self.get_checkpoint_store();
6617 for seq in checkpoint_summaries {
6618 let checkpoint = store
6619 .get_checkpoint_by_sequence_number(*seq)?
6620 .map(|c| c.into_inner());
6621
6622 summaries.push(checkpoint);
6623 }
6624
6625 let mut contents = Vec::with_capacity(checkpoint_contents.len());
6626 for seq in checkpoint_contents {
6627 let checkpoint = store
6628 .get_checkpoint_by_sequence_number(*seq)?
6629 .and_then(|summary| {
6630 store
6631 .get_checkpoint_contents(&summary.contents_digest)
6632 .expect("db read cannot fail")
6633 });
6634 contents.push(checkpoint);
6635 }
6636
6637 let mut summaries_by_digest = Vec::with_capacity(checkpoint_summaries_by_digest.len());
6638 for digest in checkpoint_summaries_by_digest {
6639 let checkpoint = store
6640 .get_checkpoint_by_digest(digest)?
6641 .map(|c| c.into_inner());
6642 summaries_by_digest.push(checkpoint);
6643 }
6644
6645 Ok((summaries, contents, summaries_by_digest))
6646 }
6647
6648 async fn get_transaction_perpetual_checkpoint(
6649 &self,
6650 digest: TransactionDigest,
6651 ) -> IotaResult<Option<CheckpointSequenceNumber>> {
6652 self.get_checkpoint_cache()
6653 .try_get_transaction_perpetual_checkpoint(&digest)
6654 .map(|res| res.map(|(_epoch, checkpoint)| checkpoint))
6655 }
6656
6657 async fn get_object(
6658 &self,
6659 object_id: ObjectId,
6660 version: VersionNumber,
6661 ) -> IotaResult<Option<Object>> {
6662 self.get_object_cache_reader()
6663 .try_get_object_by_key(&object_id, version)
6664 }
6665
6666 #[instrument(skip_all)]
6667 async fn multi_get_objects(
6668 &self,
6669 object_keys: &[ObjectKey],
6670 ) -> IotaResult<Vec<Option<Object>>> {
6671 Ok(self
6672 .get_object_cache_reader()
6673 .multi_get_objects_by_key(object_keys))
6674 }
6675
6676 async fn multi_get_transactions_perpetual_checkpoints(
6677 &self,
6678 digests: &[TransactionDigest],
6679 ) -> IotaResult<Vec<Option<CheckpointSequenceNumber>>> {
6680 let res = self
6681 .get_checkpoint_cache()
6682 .try_multi_get_transactions_perpetual_checkpoints(digests)?;
6683
6684 Ok(res
6685 .into_iter()
6686 .map(|maybe| maybe.map(|(_epoch, checkpoint)| checkpoint))
6687 .collect())
6688 }
6689
6690 #[instrument(skip(self, digests), fields(digests = digests.iter().map(|d| d.to_string()).collect::<Vec<String>>().join(", ")))]
6691 async fn multi_get_events_by_tx_digests(
6692 &self,
6693 digests: &[TransactionDigest],
6694 ) -> IotaResult<Vec<Option<TransactionEvents>>> {
6695 if digests.is_empty() {
6696 return Ok(vec![]);
6697 }
6698
6699 Ok(self
6700 .get_transaction_cache_reader()
6701 .multi_get_events(digests))
6702 }
6703}
6704
6705#[cfg(msim)]
6706pub mod framework_injection {
6707 use std::{
6708 cell::RefCell,
6709 collections::{BTreeMap, BTreeSet},
6710 };
6711
6712 use iota_framework::{BuiltInFramework, SystemPackage};
6713 use iota_sdk_types::ObjectId;
6714 use iota_types::base_types::AuthorityName;
6715 use move_binary_format::CompiledModule;
6716
6717 type FrameworkOverrideConfig = BTreeMap<ObjectId, PackageOverrideConfig>;
6718
6719 thread_local! {
6721 static OVERRIDE: RefCell<FrameworkOverrideConfig> = RefCell::new(FrameworkOverrideConfig::default());
6722 }
6723
6724 type Framework = Vec<CompiledModule>;
6725
6726 pub type PackageUpgradeCallback =
6727 Box<dyn Fn(AuthorityName) -> Option<Framework> + Send + Sync + 'static>;
6728
6729 enum PackageOverrideConfig {
6730 Global(Framework),
6731 PerValidator(PackageUpgradeCallback),
6732 }
6733
6734 fn compiled_modules_to_bytes(modules: &[CompiledModule]) -> Vec<Vec<u8>> {
6735 modules
6736 .iter()
6737 .map(|m| {
6738 let mut buf = Vec::new();
6739 m.serialize_with_version(m.version, &mut buf).unwrap();
6740 buf
6741 })
6742 .collect()
6743 }
6744
6745 pub fn set_override(package_id: ObjectId, modules: Vec<CompiledModule>) {
6746 OVERRIDE.with(|bs| {
6747 bs.borrow_mut()
6748 .insert(package_id, PackageOverrideConfig::Global(modules))
6749 });
6750 }
6751
6752 pub fn set_override_cb(package_id: ObjectId, func: PackageUpgradeCallback) {
6753 OVERRIDE.with(|bs| {
6754 bs.borrow_mut()
6755 .insert(package_id, PackageOverrideConfig::PerValidator(func))
6756 });
6757 }
6758
6759 pub fn get_override_bytes(package_id: &ObjectId, name: AuthorityName) -> Option<Vec<Vec<u8>>> {
6760 OVERRIDE.with(|cfg| {
6761 cfg.borrow().get(package_id).and_then(|entry| match entry {
6762 PackageOverrideConfig::Global(framework) => {
6763 Some(compiled_modules_to_bytes(framework))
6764 }
6765 PackageOverrideConfig::PerValidator(func) => {
6766 func(name).map(|fw| compiled_modules_to_bytes(&fw))
6767 }
6768 })
6769 })
6770 }
6771
6772 pub fn get_override_modules(
6773 package_id: &ObjectId,
6774 name: AuthorityName,
6775 ) -> Option<Vec<CompiledModule>> {
6776 OVERRIDE.with(|cfg| {
6777 cfg.borrow().get(package_id).and_then(|entry| match entry {
6778 PackageOverrideConfig::Global(framework) => Some(framework.clone()),
6779 PackageOverrideConfig::PerValidator(func) => func(name),
6780 })
6781 })
6782 }
6783
6784 pub fn get_override_system_package(
6785 package_id: &ObjectId,
6786 name: AuthorityName,
6787 ) -> Option<SystemPackage> {
6788 let bytes = get_override_bytes(package_id, name)?;
6789 let dependencies = BuiltInFramework::try_get_package_by_id(package_id)
6793 .map_or_else(BuiltInFramework::all_package_ids, |package| {
6794 package.dependencies.to_vec()
6795 });
6796 Some(SystemPackage {
6797 id: *package_id,
6798 bytes,
6799 dependencies,
6800 })
6801 }
6802
6803 pub fn get_extra_packages(name: AuthorityName) -> Vec<SystemPackage> {
6804 let built_in = BTreeSet::from_iter(BuiltInFramework::all_package_ids());
6805 let extra: Vec<ObjectId> = OVERRIDE.with(|cfg| {
6806 cfg.borrow()
6807 .keys()
6808 .filter_map(|package| (!built_in.contains(package)).then_some(*package))
6809 .collect()
6810 });
6811
6812 extra
6813 .into_iter()
6814 .map(|package| SystemPackage {
6815 id: package,
6816 bytes: get_override_bytes(&package, name).unwrap(),
6817 dependencies: BuiltInFramework::all_package_ids(),
6818 })
6819 .collect()
6820 }
6821}
6822
6823#[derive(Debug, Serialize, Deserialize, Clone)]
6824pub struct ObjDumpFormat {
6825 pub id: ObjectId,
6826 pub version: VersionNumber,
6827 pub digest: ObjectDigest,
6828 pub object: Object,
6829}
6830
6831impl ObjDumpFormat {
6832 fn new(object: Object) -> Self {
6833 let oref = object.object_ref();
6834 Self {
6835 id: oref.object_id,
6836 version: oref.version,
6837 digest: oref.digest,
6838 object,
6839 }
6840 }
6841}
6842
6843#[derive(Debug, Serialize, Deserialize, Clone)]
6844pub struct NodeStateDump {
6845 pub tx_digest: TransactionDigest,
6846 pub sender_signed_data: SenderSignedTransaction,
6847 pub executed_epoch: u64,
6848 pub reference_gas_price: u64,
6849 pub protocol_version: u64,
6850 pub epoch_start_timestamp_ms: u64,
6851 pub computed_effects: TransactionEffects,
6852 pub expected_effects_digest: TransactionEffectsDigest,
6853 pub relevant_system_packages: Vec<ObjDumpFormat>,
6854 pub shared_objects: Vec<ObjDumpFormat>,
6855 pub loaded_child_objects: Vec<ObjDumpFormat>,
6856 pub modified_at_versions: Vec<ObjDumpFormat>,
6857 pub runtime_reads: Vec<ObjDumpFormat>,
6858 pub input_objects: Vec<ObjDumpFormat>,
6859}
6860
6861impl NodeStateDump {
6862 pub fn new(
6863 tx_digest: &TransactionDigest,
6864 effects: &TransactionEffects,
6865 expected_effects_digest: TransactionEffectsDigest,
6866 object_store: &dyn ObjectStore,
6867 epoch_store: &Arc<AuthorityPerEpochStore>,
6868 inner_temporary_store: &InnerTemporaryStore,
6869 transaction: &VerifiedExecutableTransaction,
6870 ) -> IotaResult<Self> {
6871 let executed_epoch = epoch_store.epoch();
6873 let reference_gas_price = epoch_store.reference_gas_price();
6874 let epoch_start_config = epoch_store.epoch_start_config();
6875 let protocol_version = epoch_store.protocol_version().as_u64();
6876 let epoch_start_timestamp_ms = epoch_start_config.epoch_data().epoch_start_timestamp();
6877
6878 let mut relevant_system_packages = Vec::new();
6880 for sys_package_id in BuiltInFramework::all_package_ids() {
6881 if let Some(w) = object_store.try_get_object(&sys_package_id)? {
6882 relevant_system_packages.push(ObjDumpFormat::new(w))
6883 }
6884 }
6885
6886 let mut shared_objects = Vec::new();
6888 for kind in effects.input_shared_objects() {
6889 match kind {
6890 InputSharedObject::Mutate(obj_ref) | InputSharedObject::ReadOnly(obj_ref) => {
6891 if let Some(w) =
6892 object_store.try_get_object_by_key(&obj_ref.object_id, obj_ref.version)?
6893 {
6894 shared_objects.push(ObjDumpFormat::new(w))
6895 }
6896 }
6897 InputSharedObject::ReadDeleted(..)
6898 | InputSharedObject::MutateDeleted(..)
6899 | InputSharedObject::Canceled(..) => (),
6901 _ => unimplemented!(
6902 "a new InputSharedObject enum variant was added and needs to be handled"
6903 ),
6904 }
6905 }
6906
6907 let mut loaded_child_objects = Vec::new();
6910 for (id, meta) in &inner_temporary_store.loaded_runtime_objects {
6911 if let Some(w) = object_store.try_get_object_by_key(id, meta.version)? {
6912 loaded_child_objects.push(ObjDumpFormat::new(w))
6913 }
6914 }
6915
6916 let mut modified_at_versions = Vec::new();
6918 for modified in effects.modified_at_versions() {
6919 let (id, ver) = (modified.object_id(), modified.version());
6920 if let Some(w) = object_store.try_get_object_by_key(id, ver)? {
6921 modified_at_versions.push(ObjDumpFormat::new(w))
6922 }
6923 }
6924
6925 let mut runtime_reads = Vec::new();
6929 for obj in inner_temporary_store
6930 .runtime_packages_loaded_from_db
6931 .values()
6932 {
6933 runtime_reads.push(ObjDumpFormat::new(obj.object().clone()));
6934 }
6935
6936 Ok(Self {
6939 tx_digest: *tx_digest,
6940 executed_epoch,
6941 reference_gas_price,
6942 epoch_start_timestamp_ms,
6943 protocol_version,
6944 relevant_system_packages,
6945 shared_objects,
6946 loaded_child_objects,
6947 modified_at_versions,
6948 runtime_reads,
6949 sender_signed_data: transaction.clone().into_message(),
6950 input_objects: inner_temporary_store
6951 .input_objects
6952 .values()
6953 .map(|o| ObjDumpFormat::new(o.clone()))
6954 .collect(),
6955 computed_effects: effects.clone(),
6956 expected_effects_digest,
6957 })
6958 }
6959
6960 pub fn all_objects(&self) -> Vec<ObjDumpFormat> {
6961 let mut objects = Vec::new();
6962 objects.extend(self.relevant_system_packages.clone());
6963 objects.extend(self.shared_objects.clone());
6964 objects.extend(self.loaded_child_objects.clone());
6965 objects.extend(self.modified_at_versions.clone());
6966 objects.extend(self.runtime_reads.clone());
6967 objects.extend(self.input_objects.clone());
6968 objects
6969 }
6970
6971 pub fn write_to_file(&self, path: &Path) -> Result<PathBuf, anyhow::Error> {
6972 let file_name = format!(
6973 "{}_{}_NODE_DUMP.json",
6974 self.tx_digest,
6975 AuthorityState::unixtime_now_ms()
6976 );
6977 let mut path = path.to_path_buf();
6978 path.push(&file_name);
6979 let mut file = File::create(path.clone())?;
6980 file.write_all(serde_json::to_string_pretty(self)?.as_bytes())?;
6981 Ok(path)
6982 }
6983
6984 pub fn read_from_file(path: &PathBuf) -> Result<Self, anyhow::Error> {
6985 let file = File::open(path)?;
6986 serde_json::from_reader(file).map_err(|e| anyhow::anyhow!(e))
6987 }
6988}
6989
6990enum MoveAccountCheckError {
6994 Input(UserInputError),
6996
6997 Storage(IotaError),
6999}
7000
7001impl From<UserInputError> for MoveAccountCheckError {
7002 fn from(error: UserInputError) -> Self {
7003 Self::Input(error)
7004 }
7005}
7006
7007impl From<MoveAccountCheckError> for IotaError {
7008 fn from(error: MoveAccountCheckError) -> Self {
7009 match error {
7010 MoveAccountCheckError::Input(error) => IotaError::UserInput { error },
7011 MoveAccountCheckError::Storage(error) => error,
7012 }
7013 }
7014}
7015
7016fn pre_consensus_move_authenticators<'a>(
7028 tx: &'a VerifiedTransaction,
7029 protocol_config: &ProtocolConfig,
7030) -> Vec<&'a MoveAuthenticator> {
7031 if protocol_config.pre_consensus_sponsor_only_move_authentication() {
7032 if tx.transaction().is_sponsored_tx() {
7033 if let Some(sponsor_move_authenticator) = tx.sponsor_move_authenticator() {
7034 vec![sponsor_move_authenticator]
7035 } else {
7036 vec![]
7037 }
7038 } else {
7039 tx.move_authenticators()
7040 }
7041 } else {
7042 tx.move_authenticators()
7043 }
7044}