mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-19 03:04:27 -05:00
chore: make engine tree crate items public (#21487)
This commit is contained in:
@@ -76,7 +76,8 @@ impl CacheConfig for EpochCacheConfig {
|
||||
type FixedCache<K, V, H = DefaultHashBuilder> = fixed_cache::Cache<K, V, H, EpochCacheConfig>;
|
||||
|
||||
/// A wrapper of a state provider and a shared cache.
|
||||
pub(crate) struct CachedStateProvider<S> {
|
||||
#[derive(Debug)]
|
||||
pub struct CachedStateProvider<S> {
|
||||
/// The state provider
|
||||
state_provider: S,
|
||||
|
||||
@@ -96,7 +97,7 @@ where
|
||||
{
|
||||
/// Creates a new [`CachedStateProvider`] from an [`ExecutionCache`], state provider, and
|
||||
/// [`CachedStateMetrics`].
|
||||
pub(crate) const fn new(
|
||||
pub const fn new(
|
||||
state_provider: S,
|
||||
caches: ExecutionCache,
|
||||
metrics: CachedStateMetrics,
|
||||
@@ -114,7 +115,7 @@ impl<S> CachedStateProvider<S> {
|
||||
/// [`State`](revm::database::State) also caches internally during block execution and the cache
|
||||
/// is then updated after the block with the entire [`BundleState`] output of that block which
|
||||
/// contains all accessed accounts,code,storage. See also [`ExecutionCache::insert_state`].
|
||||
pub(crate) const fn prewarm(mut self) -> Self {
|
||||
pub const fn prewarm(mut self) -> Self {
|
||||
self.prewarm = true;
|
||||
self
|
||||
}
|
||||
@@ -131,7 +132,7 @@ impl<S> CachedStateProvider<S> {
|
||||
/// and the fixed-cache internal stats (collisions, size, capacity).
|
||||
#[derive(Metrics, Clone)]
|
||||
#[metrics(scope = "sync.caching")]
|
||||
pub(crate) struct CachedStateMetrics {
|
||||
pub struct CachedStateMetrics {
|
||||
/// Number of times a new execution cache was created
|
||||
execution_cache_created_total: Counter,
|
||||
|
||||
@@ -186,7 +187,7 @@ pub(crate) struct CachedStateMetrics {
|
||||
|
||||
impl CachedStateMetrics {
|
||||
/// Sets all values to zero, indicating that a new block is being executed.
|
||||
pub(crate) fn reset(&self) {
|
||||
pub fn reset(&self) {
|
||||
// code cache
|
||||
self.code_cache_hits.set(0);
|
||||
self.code_cache_misses.set(0);
|
||||
@@ -204,7 +205,7 @@ impl CachedStateMetrics {
|
||||
}
|
||||
|
||||
/// Returns a new zeroed-out instance of [`CachedStateMetrics`].
|
||||
pub(crate) fn zeroed() -> Self {
|
||||
pub fn zeroed() -> Self {
|
||||
let zeroed = Self::default();
|
||||
zeroed.reset();
|
||||
zeroed
|
||||
@@ -326,7 +327,7 @@ impl<S: AccountReader> AccountReader for CachedStateProvider<S> {
|
||||
|
||||
/// Represents the status of a key in the cache.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) enum CachedStatus<T> {
|
||||
pub enum CachedStatus<T> {
|
||||
/// The key is not in the cache (or was invalidated). The value was recalculated.
|
||||
NotCached(T),
|
||||
/// The key exists in cache and has a specific value.
|
||||
@@ -487,7 +488,7 @@ impl<S: HashedPostStateProvider> HashedPostStateProvider for CachedStateProvider
|
||||
/// Since EIP-6780, SELFDESTRUCT only works within the same transaction where the
|
||||
/// contract was created, so we don't need to handle clearing the storage.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ExecutionCache {
|
||||
pub struct ExecutionCache {
|
||||
/// Cache for contract bytecode, keyed by code hash.
|
||||
code_cache: Arc<FixedCache<B256, Option<Bytecode>, FbBuildHasher<32>>>,
|
||||
|
||||
@@ -519,7 +520,7 @@ impl ExecutionCache {
|
||||
///
|
||||
/// Fixed-cache requires power-of-two sizes for efficient indexing.
|
||||
/// With epochs enabled, the minimum size is 4096 entries.
|
||||
pub(crate) const fn bytes_to_entries(size_bytes: usize, entry_size: usize) -> usize {
|
||||
pub const fn bytes_to_entries(size_bytes: usize, entry_size: usize) -> usize {
|
||||
let entries = size_bytes / entry_size;
|
||||
// Round down to nearest power of two
|
||||
let rounded = if entries == 0 { 1 } else { (entries + 1).next_power_of_two() >> 1 };
|
||||
@@ -532,7 +533,7 @@ impl ExecutionCache {
|
||||
}
|
||||
|
||||
/// Build an [`ExecutionCache`] struct, so that execution caches can be easily cloned.
|
||||
pub(crate) fn new(total_cache_size: usize) -> Self {
|
||||
pub fn new(total_cache_size: usize) -> Self {
|
||||
let storage_cache_size = (total_cache_size * 8888) / 10000; // 88.88% of total
|
||||
let account_cache_size = (total_cache_size * 556) / 10000; // 5.56% of total
|
||||
let code_cache_size = (total_cache_size * 556) / 10000; // 5.56% of total
|
||||
@@ -566,7 +567,7 @@ impl ExecutionCache {
|
||||
}
|
||||
|
||||
/// Gets code from cache, or inserts using the provided function.
|
||||
pub(crate) fn get_or_try_insert_code_with<E>(
|
||||
pub fn get_or_try_insert_code_with<E>(
|
||||
&self,
|
||||
hash: B256,
|
||||
f: impl FnOnce() -> Result<Option<Bytecode>, E>,
|
||||
@@ -585,7 +586,7 @@ impl ExecutionCache {
|
||||
}
|
||||
|
||||
/// Gets storage from cache, or inserts using the provided function.
|
||||
pub(crate) fn get_or_try_insert_storage_with<E>(
|
||||
pub fn get_or_try_insert_storage_with<E>(
|
||||
&self,
|
||||
address: Address,
|
||||
key: StorageKey,
|
||||
@@ -605,7 +606,7 @@ impl ExecutionCache {
|
||||
}
|
||||
|
||||
/// Gets account from cache, or inserts using the provided function.
|
||||
pub(crate) fn get_or_try_insert_account_with<E>(
|
||||
pub fn get_or_try_insert_account_with<E>(
|
||||
&self,
|
||||
address: Address,
|
||||
f: impl FnOnce() -> Result<Option<Account>, E>,
|
||||
@@ -624,12 +625,7 @@ impl ExecutionCache {
|
||||
}
|
||||
|
||||
/// Insert storage value into cache.
|
||||
pub(crate) fn insert_storage(
|
||||
&self,
|
||||
address: Address,
|
||||
key: StorageKey,
|
||||
value: Option<StorageValue>,
|
||||
) {
|
||||
pub fn insert_storage(&self, address: Address, key: StorageKey, value: Option<StorageValue>) {
|
||||
self.storage_cache.insert((address, key), value.unwrap_or_default());
|
||||
}
|
||||
|
||||
@@ -662,7 +658,8 @@ impl ExecutionCache {
|
||||
///
|
||||
/// Returns an error if the state updates are inconsistent and should be discarded.
|
||||
#[instrument(level = "debug", target = "engine::caching", skip_all)]
|
||||
pub(crate) fn insert_state(&self, state_updates: &BundleState) -> Result<(), ()> {
|
||||
#[expect(clippy::result_unit_err)]
|
||||
pub fn insert_state(&self, state_updates: &BundleState) -> Result<(), ()> {
|
||||
let _enter =
|
||||
debug_span!(target: "engine::tree", "contracts", len = state_updates.contracts.len())
|
||||
.entered();
|
||||
@@ -771,7 +768,7 @@ impl ExecutionCache {
|
||||
/// A saved cache that has been used for executing a specific block, which has been updated for its
|
||||
/// execution.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct SavedCache {
|
||||
pub struct SavedCache {
|
||||
/// The hash of the block these caches were used to execute.
|
||||
hash: B256,
|
||||
|
||||
@@ -791,43 +788,43 @@ pub(crate) struct SavedCache {
|
||||
|
||||
impl SavedCache {
|
||||
/// Creates a new instance with the internals
|
||||
pub(super) fn new(hash: B256, caches: ExecutionCache, metrics: CachedStateMetrics) -> Self {
|
||||
pub fn new(hash: B256, caches: ExecutionCache, metrics: CachedStateMetrics) -> Self {
|
||||
Self { hash, caches, metrics, usage_guard: Arc::new(()), disable_cache_metrics: false }
|
||||
}
|
||||
|
||||
/// Sets whether to disable cache metrics recording.
|
||||
pub(super) const fn with_disable_cache_metrics(mut self, disable: bool) -> Self {
|
||||
pub const fn with_disable_cache_metrics(mut self, disable: bool) -> Self {
|
||||
self.disable_cache_metrics = disable;
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns the hash for this cache
|
||||
pub(crate) const fn executed_block_hash(&self) -> B256 {
|
||||
pub const fn executed_block_hash(&self) -> B256 {
|
||||
self.hash
|
||||
}
|
||||
|
||||
/// Splits the cache into its caches, metrics, and `disable_cache_metrics` flag, consuming it.
|
||||
pub(crate) fn split(self) -> (ExecutionCache, CachedStateMetrics, bool) {
|
||||
pub fn split(self) -> (ExecutionCache, CachedStateMetrics, bool) {
|
||||
(self.caches, self.metrics, self.disable_cache_metrics)
|
||||
}
|
||||
|
||||
/// Returns true if the cache is available for use (no other tasks are currently using it).
|
||||
pub(crate) fn is_available(&self) -> bool {
|
||||
pub fn is_available(&self) -> bool {
|
||||
Arc::strong_count(&self.usage_guard) == 1
|
||||
}
|
||||
|
||||
/// Returns the current strong count of the usage guard.
|
||||
pub(crate) fn usage_count(&self) -> usize {
|
||||
pub fn usage_count(&self) -> usize {
|
||||
Arc::strong_count(&self.usage_guard)
|
||||
}
|
||||
|
||||
/// Returns the [`ExecutionCache`] belonging to the tracked hash.
|
||||
pub(crate) const fn cache(&self) -> &ExecutionCache {
|
||||
pub const fn cache(&self) -> &ExecutionCache {
|
||||
&self.caches
|
||||
}
|
||||
|
||||
/// Returns the metrics associated with this cache.
|
||||
pub(crate) const fn metrics(&self) -> &CachedStateMetrics {
|
||||
pub const fn metrics(&self) -> &CachedStateMetrics {
|
||||
&self.metrics
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@ use std::time::{Duration, Instant};
|
||||
|
||||
/// Metrics for the `EngineApi`.
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct EngineApiMetrics {
|
||||
pub struct EngineApiMetrics {
|
||||
/// Engine API-specific metrics.
|
||||
pub(crate) engine: EngineMetrics,
|
||||
pub engine: EngineMetrics,
|
||||
/// Block executor metrics.
|
||||
pub(crate) executor: ExecutorMetrics,
|
||||
pub executor: ExecutorMetrics,
|
||||
/// Metrics for block validation
|
||||
pub(crate) block_validation: BlockValidationMetrics,
|
||||
pub block_validation: BlockValidationMetrics,
|
||||
/// Canonical chain and reorg related metrics
|
||||
pub tree: TreeMetrics,
|
||||
/// Metrics for EIP-7928 Block-Level Access Lists (BAL).
|
||||
@@ -32,7 +32,7 @@ impl EngineApiMetrics {
|
||||
///
|
||||
/// This method updates metrics for execution time, gas usage, and the number
|
||||
/// of accounts, storage slots and bytecodes updated.
|
||||
pub(crate) fn record_block_execution<R>(
|
||||
pub fn record_block_execution<R>(
|
||||
&self,
|
||||
output: &BlockExecutionOutput<R>,
|
||||
execution_duration: Duration,
|
||||
@@ -59,27 +59,27 @@ impl EngineApiMetrics {
|
||||
}
|
||||
|
||||
/// Returns a reference to the executor metrics for use in state hooks.
|
||||
pub(crate) const fn executor_metrics(&self) -> &ExecutorMetrics {
|
||||
pub const fn executor_metrics(&self) -> &ExecutorMetrics {
|
||||
&self.executor
|
||||
}
|
||||
|
||||
/// Records the duration of block pre-execution changes (e.g., beacon root update).
|
||||
pub(crate) fn record_pre_execution(&self, elapsed: Duration) {
|
||||
pub fn record_pre_execution(&self, elapsed: Duration) {
|
||||
self.executor.pre_execution_histogram.record(elapsed);
|
||||
}
|
||||
|
||||
/// Records the duration of block post-execution changes (e.g., finalization).
|
||||
pub(crate) fn record_post_execution(&self, elapsed: Duration) {
|
||||
pub fn record_post_execution(&self, elapsed: Duration) {
|
||||
self.executor.post_execution_histogram.record(elapsed);
|
||||
}
|
||||
|
||||
/// Records the time spent waiting for the next transaction from the iterator.
|
||||
pub(crate) fn record_transaction_wait(&self, elapsed: Duration) {
|
||||
pub fn record_transaction_wait(&self, elapsed: Duration) {
|
||||
self.executor.transaction_wait_histogram.record(elapsed);
|
||||
}
|
||||
|
||||
/// Records the duration of a single transaction execution.
|
||||
pub(crate) fn record_transaction_execution(&self, elapsed: Duration) {
|
||||
pub fn record_transaction_execution(&self, elapsed: Duration) {
|
||||
self.executor.transaction_execution_histogram.record(elapsed);
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ impl EngineApiMetrics {
|
||||
/// Metrics for the entire blockchain tree
|
||||
#[derive(Metrics)]
|
||||
#[metrics(scope = "blockchain_tree")]
|
||||
pub(crate) struct TreeMetrics {
|
||||
pub struct TreeMetrics {
|
||||
/// The highest block number in the canonical chain
|
||||
pub canonical_chain_height: Gauge,
|
||||
/// The number of reorgs
|
||||
@@ -103,7 +103,7 @@ pub(crate) struct TreeMetrics {
|
||||
/// Metrics for the `EngineApi`.
|
||||
#[derive(Metrics)]
|
||||
#[metrics(scope = "consensus.engine.beacon")]
|
||||
pub(crate) struct EngineMetrics {
|
||||
pub struct EngineMetrics {
|
||||
/// Engine API forkchoiceUpdated response type metrics
|
||||
#[metric(skip)]
|
||||
pub(crate) forkchoice_updated: ForkchoiceUpdatedMetrics,
|
||||
@@ -336,42 +336,42 @@ pub(crate) struct BalMetrics {
|
||||
/// Metrics for non-execution related block validation.
|
||||
#[derive(Metrics, Clone)]
|
||||
#[metrics(scope = "sync.block_validation")]
|
||||
pub(crate) struct BlockValidationMetrics {
|
||||
pub struct BlockValidationMetrics {
|
||||
/// Total number of storage tries updated in the state root calculation
|
||||
pub(crate) state_root_storage_tries_updated_total: Counter,
|
||||
pub state_root_storage_tries_updated_total: Counter,
|
||||
/// Total number of times the parallel state root computation fell back to regular.
|
||||
pub(crate) state_root_parallel_fallback_total: Counter,
|
||||
pub state_root_parallel_fallback_total: Counter,
|
||||
/// Total number of times the state root task failed but the fallback succeeded.
|
||||
pub(crate) state_root_task_fallback_success_total: Counter,
|
||||
pub state_root_task_fallback_success_total: Counter,
|
||||
/// Latest state root duration, ie the time spent blocked waiting for the state root.
|
||||
pub(crate) state_root_duration: Gauge,
|
||||
pub state_root_duration: Gauge,
|
||||
/// Histogram for state root duration ie the time spent blocked waiting for the state root
|
||||
pub(crate) state_root_histogram: Histogram,
|
||||
pub state_root_histogram: Histogram,
|
||||
/// Histogram of deferred trie computation duration.
|
||||
pub(crate) deferred_trie_compute_duration: Histogram,
|
||||
pub deferred_trie_compute_duration: Histogram,
|
||||
/// Payload conversion and validation latency
|
||||
pub(crate) payload_validation_duration: Gauge,
|
||||
pub payload_validation_duration: Gauge,
|
||||
/// Histogram of payload validation latency
|
||||
pub(crate) payload_validation_histogram: Histogram,
|
||||
pub payload_validation_histogram: Histogram,
|
||||
/// Payload processor spawning duration
|
||||
pub(crate) spawn_payload_processor: Histogram,
|
||||
pub spawn_payload_processor: Histogram,
|
||||
/// Post-execution validation duration
|
||||
pub(crate) post_execution_validation_duration: Histogram,
|
||||
pub post_execution_validation_duration: Histogram,
|
||||
/// Total duration of the new payload call
|
||||
pub(crate) total_duration: Histogram,
|
||||
pub total_duration: Histogram,
|
||||
/// Size of `HashedPostStateSorted` (`total_len`)
|
||||
pub(crate) hashed_post_state_size: Histogram,
|
||||
pub hashed_post_state_size: Histogram,
|
||||
/// Size of `TrieUpdatesSorted` (`total_len`)
|
||||
pub(crate) trie_updates_sorted_size: Histogram,
|
||||
pub trie_updates_sorted_size: Histogram,
|
||||
/// Size of `AnchoredTrieInput` overlay `TrieUpdatesSorted` (`total_len`)
|
||||
pub(crate) anchored_overlay_trie_updates_size: Histogram,
|
||||
pub anchored_overlay_trie_updates_size: Histogram,
|
||||
/// Size of `AnchoredTrieInput` overlay `HashedPostStateSorted` (`total_len`)
|
||||
pub(crate) anchored_overlay_hashed_state_size: Histogram,
|
||||
pub anchored_overlay_hashed_state_size: Histogram,
|
||||
}
|
||||
|
||||
impl BlockValidationMetrics {
|
||||
/// Records a new state root time, updating both the histogram and state root gauge
|
||||
pub(crate) fn record_state_root(&self, trie_output: &TrieUpdates, elapsed_as_secs: f64) {
|
||||
pub fn record_state_root(&self, trie_output: &TrieUpdates, elapsed_as_secs: f64) {
|
||||
self.state_root_storage_tries_updated_total
|
||||
.increment(trie_output.storage_tries_ref().len() as u64);
|
||||
self.state_root_duration.set(elapsed_as_secs);
|
||||
@@ -380,7 +380,7 @@ impl BlockValidationMetrics {
|
||||
|
||||
/// Records a new payload validation time, updating both the histogram and the payload
|
||||
/// validation gauge
|
||||
pub(crate) fn record_payload_validation(&self, elapsed_as_secs: f64) {
|
||||
pub fn record_payload_validation(&self, elapsed_as_secs: f64) {
|
||||
self.payload_validation_duration.set(elapsed_as_secs);
|
||||
self.payload_validation_histogram.record(elapsed_as_secs);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
chain::FromOrchestrator,
|
||||
engine::{DownloadRequest, EngineApiEvent, EngineApiKind, EngineApiRequest, FromEngine},
|
||||
persistence::PersistenceHandle,
|
||||
tree::{error::InsertPayloadError, metrics::EngineApiMetrics, payload_validator::TreeCtx},
|
||||
tree::{error::InsertPayloadError, payload_validator::TreeCtx},
|
||||
};
|
||||
use alloy_consensus::BlockHeader;
|
||||
use alloy_eips::{eip1898::BlockWithParent, merge::EPOCH_SLOTS, BlockNumHash, NumHash};
|
||||
@@ -55,7 +55,7 @@ pub mod error;
|
||||
pub mod instrumented_state;
|
||||
mod invalid_headers;
|
||||
mod metrics;
|
||||
mod payload_processor;
|
||||
pub mod payload_processor;
|
||||
pub mod payload_validator;
|
||||
mod persistence_state;
|
||||
pub mod precompile_cache;
|
||||
@@ -66,7 +66,9 @@ mod trie_updates;
|
||||
|
||||
use crate::tree::error::AdvancePersistenceError;
|
||||
pub use block_buffer::BlockBuffer;
|
||||
pub use cached_state::{CachedStateMetrics, CachedStateProvider, ExecutionCache, SavedCache};
|
||||
pub use invalid_headers::InvalidHeaderCache;
|
||||
pub use metrics::EngineApiMetrics;
|
||||
pub use payload_processor::*;
|
||||
pub use payload_validator::{BasicEngineValidator, EngineValidator};
|
||||
pub use persistence_state::PersistenceState;
|
||||
@@ -158,6 +160,16 @@ impl<N: NodePrimitives> EngineApiTreeState<N> {
|
||||
forkchoice_state_tracker: ForkchoiceStateTracker::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the tree state.
|
||||
pub const fn tree_state(&self) -> &TreeState<N> {
|
||||
&self.tree_state
|
||||
}
|
||||
|
||||
/// Returns true if the block has been marked as invalid.
|
||||
pub fn has_invalid_header(&mut self, hash: &B256) -> bool {
|
||||
self.invalid_headers.get(hash).is_some()
|
||||
}
|
||||
}
|
||||
|
||||
/// The outcome of a tree operation.
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn total_slots(bal: &BlockAccessList) -> usize {
|
||||
/// first, followed by read-only slots. The iterator intelligently skips accounts and slots
|
||||
/// outside the specified range for efficient traversal.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct BALSlotIter<'a> {
|
||||
pub struct BALSlotIter<'a> {
|
||||
bal: &'a BlockAccessList,
|
||||
range: Range<usize>,
|
||||
current_index: usize,
|
||||
@@ -34,7 +34,7 @@ pub(crate) struct BALSlotIter<'a> {
|
||||
|
||||
impl<'a> BALSlotIter<'a> {
|
||||
/// Creates a new iterator over storage slots within the specified range.
|
||||
pub(crate) fn new(bal: &'a BlockAccessList, range: Range<usize>) -> Self {
|
||||
pub fn new(bal: &'a BlockAccessList, range: Range<usize>) -> Self {
|
||||
let mut iter = Self { bal, range, current_index: 0, account_idx: 0, slot_idx: 0 };
|
||||
iter.skip_to_range_start();
|
||||
iter
|
||||
|
||||
@@ -145,7 +145,7 @@ where
|
||||
Evm: ConfigureEvm<Primitives = N>,
|
||||
{
|
||||
/// Returns a reference to the workload executor driving payload tasks.
|
||||
pub(super) const fn executor(&self) -> &WorkloadExecutor {
|
||||
pub const fn executor(&self) -> &WorkloadExecutor {
|
||||
&self.executor
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ where
|
||||
///
|
||||
/// Returns a [`PayloadHandle`] to communicate with the task.
|
||||
#[instrument(level = "debug", target = "engine::tree::payload_processor", skip_all)]
|
||||
pub(super) fn spawn_cache_exclusive<P, I: ExecutableTxIterator<Evm>>(
|
||||
pub fn spawn_cache_exclusive<P, I: ExecutableTxIterator<Evm>>(
|
||||
&self,
|
||||
env: ExecutionEnv<Evm>,
|
||||
transactions: I,
|
||||
@@ -634,7 +634,7 @@ where
|
||||
///
|
||||
/// The cache enables subsequent blocks to reuse account, storage, and bytecode data without
|
||||
/// hitting the database, maintaining performance consistency.
|
||||
pub(crate) fn on_inserted_executed_block(
|
||||
pub fn on_inserted_executed_block(
|
||||
&self,
|
||||
block_with_parent: BlockWithParent,
|
||||
bundle_state: &BundleState,
|
||||
@@ -731,19 +731,19 @@ impl<Tx, Err, R: Send + Sync + 'static> PayloadHandle<Tx, Err, R> {
|
||||
}
|
||||
|
||||
/// Returns a clone of the caches used by prewarming
|
||||
pub(super) fn caches(&self) -> Option<ExecutionCache> {
|
||||
pub fn caches(&self) -> Option<ExecutionCache> {
|
||||
self.prewarm_handle.saved_cache.as_ref().map(|cache| cache.cache().clone())
|
||||
}
|
||||
|
||||
/// Returns a clone of the cache metrics used by prewarming
|
||||
pub(super) fn cache_metrics(&self) -> Option<CachedStateMetrics> {
|
||||
pub fn cache_metrics(&self) -> Option<CachedStateMetrics> {
|
||||
self.prewarm_handle.saved_cache.as_ref().map(|cache| cache.metrics().clone())
|
||||
}
|
||||
|
||||
/// Terminates the pre-warming transaction processing.
|
||||
///
|
||||
/// Note: This does not terminate the task yet.
|
||||
pub(super) fn stop_prewarming_execution(&self) {
|
||||
pub fn stop_prewarming_execution(&self) {
|
||||
self.prewarm_handle.stop_prewarming_execution()
|
||||
}
|
||||
|
||||
@@ -754,7 +754,7 @@ impl<Tx, Err, R: Send + Sync + 'static> PayloadHandle<Tx, Err, R> {
|
||||
/// path without cloning the expensive `BundleState`.
|
||||
///
|
||||
/// Returns a sender for the channel that should be notified on block validation success.
|
||||
pub(super) fn terminate_caching(
|
||||
pub fn terminate_caching(
|
||||
&mut self,
|
||||
execution_outcome: Option<Arc<BlockExecutionOutput<R>>>,
|
||||
) -> Option<mpsc::Sender<()>> {
|
||||
@@ -774,7 +774,7 @@ impl<Tx, Err, R: Send + Sync + 'static> PayloadHandle<Tx, Err, R> {
|
||||
/// Generic over `R` (receipt type) to allow sharing `Arc<ExecutionOutcome<R>>` with the
|
||||
/// prewarm task without cloning the expensive `BundleState`.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct CacheTaskHandle<R> {
|
||||
pub struct CacheTaskHandle<R> {
|
||||
/// The shared cache the task operates with.
|
||||
saved_cache: Option<SavedCache>,
|
||||
/// Channel to the spawned prewarm task if any
|
||||
@@ -785,7 +785,7 @@ impl<R: Send + Sync + 'static> CacheTaskHandle<R> {
|
||||
/// Terminates the pre-warming transaction processing.
|
||||
///
|
||||
/// Note: This does not terminate the task yet.
|
||||
pub(super) fn stop_prewarming_execution(&self) {
|
||||
pub fn stop_prewarming_execution(&self) {
|
||||
self.to_prewarm_task
|
||||
.as_ref()
|
||||
.map(|tx| tx.send(PrewarmTaskEvent::TerminateTransactionExecution).ok());
|
||||
@@ -796,7 +796,7 @@ impl<R: Send + Sync + 'static> CacheTaskHandle<R> {
|
||||
/// If the [`BlockExecutionOutput`] is provided it will update the shared cache using its
|
||||
/// bundle state. Using `Arc<ExecutionOutcome>` avoids cloning the expensive `BundleState`.
|
||||
#[must_use = "sender must be used and notified on block validation success"]
|
||||
pub(super) fn terminate_caching(
|
||||
pub fn terminate_caching(
|
||||
&mut self,
|
||||
execution_outcome: Option<Arc<BlockExecutionOutput<R>>>,
|
||||
) -> Option<mpsc::Sender<()>> {
|
||||
@@ -850,7 +850,7 @@ impl<R> Drop for CacheTaskHandle<R> {
|
||||
/// - Prepares data for state root proof computation
|
||||
/// - Runs concurrently but must not interfere with cache saves
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct PayloadExecutionCache {
|
||||
pub struct PayloadExecutionCache {
|
||||
/// Guarded cloneable cache identified by a block hash.
|
||||
inner: Arc<RwLock<Option<SavedCache>>>,
|
||||
/// Metrics for cache operations.
|
||||
@@ -930,7 +930,7 @@ impl PayloadExecutionCache {
|
||||
///
|
||||
/// Violating this requirement can result in cache corruption, incorrect state data,
|
||||
/// and potential consensus failures.
|
||||
pub(crate) fn update_with_guard<F>(&self, update_fn: F)
|
||||
pub fn update_with_guard<F>(&self, update_fn: F)
|
||||
where
|
||||
F: FnOnce(&mut Option<SavedCache>),
|
||||
{
|
||||
|
||||
@@ -100,7 +100,7 @@ impl SparseTrieUpdate {
|
||||
|
||||
/// Messages used internally by the multi proof task.
|
||||
#[derive(Debug)]
|
||||
pub(super) enum MultiProofMessage {
|
||||
pub enum MultiProofMessage {
|
||||
/// Prefetch proof targets
|
||||
PrefetchProofs(VersionedMultiProofTargets),
|
||||
/// New state update from transaction execution with its source
|
||||
@@ -257,7 +257,7 @@ fn extend_multiproof_targets(dest: &mut MultiProofTargets, src: &VersionedMultiP
|
||||
|
||||
/// A set of multiproof targets which can be either in the legacy or V2 representations.
|
||||
#[derive(Debug)]
|
||||
pub(super) enum VersionedMultiProofTargets {
|
||||
pub enum VersionedMultiProofTargets {
|
||||
/// Legacy targets
|
||||
Legacy(MultiProofTargets),
|
||||
/// V2 targets
|
||||
|
||||
@@ -49,7 +49,8 @@ use std::{
|
||||
use tracing::{debug, debug_span, instrument, trace, warn, Span};
|
||||
|
||||
/// Determines the prewarming mode: transaction-based or BAL-based.
|
||||
pub(super) enum PrewarmMode<Tx> {
|
||||
#[derive(Debug)]
|
||||
pub enum PrewarmMode<Tx> {
|
||||
/// Prewarm by executing transactions from a stream.
|
||||
Transactions(Receiver<Tx>),
|
||||
/// Prewarm by prefetching slots from a Block Access List.
|
||||
@@ -69,7 +70,8 @@ struct IndexedTransaction<Tx> {
|
||||
/// individually in parallel.
|
||||
///
|
||||
/// Note: This task runs until cancelled externally.
|
||||
pub(super) struct PrewarmCacheTask<N, P, Evm>
|
||||
#[derive(Debug)]
|
||||
pub struct PrewarmCacheTask<N, P, Evm>
|
||||
where
|
||||
N: NodePrimitives,
|
||||
Evm: ConfigureEvm<Primitives = N>,
|
||||
@@ -99,7 +101,7 @@ where
|
||||
Evm: ConfigureEvm<Primitives = N> + 'static,
|
||||
{
|
||||
/// Initializes the task with the given transactions pending execution
|
||||
pub(super) fn new(
|
||||
pub fn new(
|
||||
executor: WorkloadExecutor,
|
||||
execution_cache: PayloadExecutionCache,
|
||||
ctx: PrewarmContext<N, P, Evm>,
|
||||
@@ -370,11 +372,8 @@ where
|
||||
name = "prewarm and caching",
|
||||
skip_all
|
||||
)]
|
||||
pub(super) fn run<Tx>(
|
||||
self,
|
||||
mode: PrewarmMode<Tx>,
|
||||
actions_tx: Sender<PrewarmTaskEvent<N::Receipt>>,
|
||||
) where
|
||||
pub fn run<Tx>(self, mode: PrewarmMode<Tx>, actions_tx: Sender<PrewarmTaskEvent<N::Receipt>>)
|
||||
where
|
||||
Tx: ExecutableTxFor<Evm> + Clone + Send + 'static,
|
||||
{
|
||||
// Spawn execution tasks based on mode
|
||||
@@ -436,23 +435,29 @@ where
|
||||
|
||||
/// Context required by tx execution tasks.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct PrewarmContext<N, P, Evm>
|
||||
pub struct PrewarmContext<N, P, Evm>
|
||||
where
|
||||
N: NodePrimitives,
|
||||
Evm: ConfigureEvm<Primitives = N>,
|
||||
{
|
||||
pub(super) env: ExecutionEnv<Evm>,
|
||||
pub(super) evm_config: Evm,
|
||||
pub(super) saved_cache: Option<SavedCache>,
|
||||
/// The execution environment.
|
||||
pub env: ExecutionEnv<Evm>,
|
||||
/// The EVM configuration.
|
||||
pub evm_config: Evm,
|
||||
/// The saved cache.
|
||||
pub saved_cache: Option<SavedCache>,
|
||||
/// Provider to obtain the state
|
||||
pub(super) provider: StateProviderBuilder<N, P>,
|
||||
pub(super) metrics: PrewarmMetrics,
|
||||
pub provider: StateProviderBuilder<N, P>,
|
||||
/// The metrics for the prewarm task.
|
||||
pub metrics: PrewarmMetrics,
|
||||
/// An atomic bool that tells prewarm tasks to not start any more execution.
|
||||
pub(super) terminate_execution: Arc<AtomicBool>,
|
||||
pub(super) precompile_cache_disabled: bool,
|
||||
pub(super) precompile_cache_map: PrecompileCacheMap<SpecFor<Evm>>,
|
||||
pub terminate_execution: Arc<AtomicBool>,
|
||||
/// Whether the precompile cache is disabled.
|
||||
pub precompile_cache_disabled: bool,
|
||||
/// The precompile cache map.
|
||||
pub precompile_cache_map: PrecompileCacheMap<SpecFor<Evm>>,
|
||||
/// Whether V2 proof calculation is enabled.
|
||||
pub(super) v2_proofs_enabled: bool,
|
||||
pub v2_proofs_enabled: bool,
|
||||
}
|
||||
|
||||
impl<N, P, Evm> PrewarmContext<N, P, Evm>
|
||||
@@ -852,7 +857,8 @@ fn multiproof_targets_v2_from_state(state: EvmState) -> (VersionedMultiProofTarg
|
||||
///
|
||||
/// Generic over `R` (receipt type) to allow sharing `Arc<ExecutionOutcome<R>>` with the main
|
||||
/// execution path without cloning the expensive `BundleState`.
|
||||
pub(super) enum PrewarmTaskEvent<R> {
|
||||
#[derive(Debug)]
|
||||
pub enum PrewarmTaskEvent<R> {
|
||||
/// Forcefully terminate all remaining transaction execution.
|
||||
TerminateTransactionExecution,
|
||||
/// Forcefully terminate the task on demand and update the shared cache with the given output
|
||||
@@ -882,7 +888,7 @@ pub(super) enum PrewarmTaskEvent<R> {
|
||||
/// Metrics for transactions prewarming.
|
||||
#[derive(Metrics, Clone)]
|
||||
#[metrics(scope = "sync.prewarm")]
|
||||
pub(crate) struct PrewarmMetrics {
|
||||
pub struct PrewarmMetrics {
|
||||
/// The number of transactions to prewarm
|
||||
pub(crate) transactions: Gauge,
|
||||
/// A histogram of the number of transactions to prewarm
|
||||
|
||||
@@ -21,7 +21,8 @@ impl<S> PrecompileCacheMap<S>
|
||||
where
|
||||
S: Eq + Hash + std::fmt::Debug + Send + Sync + Clone + 'static,
|
||||
{
|
||||
pub(crate) fn cache_for_address(&self, address: Address) -> PrecompileCache<S> {
|
||||
/// Get the precompile cache for the given address.
|
||||
pub fn cache_for_address(&self, address: Address) -> PrecompileCache<S> {
|
||||
// Try just using `.get` first to avoid acquiring a write lock.
|
||||
if let Some(cache) = self.0.get(&address) {
|
||||
return cache.clone();
|
||||
@@ -90,7 +91,7 @@ impl<S> CacheEntry<S> {
|
||||
|
||||
/// A cache for precompile inputs / outputs.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct CachedPrecompile<S>
|
||||
pub struct CachedPrecompile<S>
|
||||
where
|
||||
S: Eq + Hash + std::fmt::Debug + Send + Sync + Clone + 'static,
|
||||
{
|
||||
@@ -109,7 +110,7 @@ where
|
||||
S: Eq + Hash + std::fmt::Debug + Send + Sync + Clone + 'static,
|
||||
{
|
||||
/// `CachedPrecompile` constructor.
|
||||
pub(crate) const fn new(
|
||||
pub const fn new(
|
||||
precompile: DynPrecompile,
|
||||
cache: PrecompileCache<S>,
|
||||
spec_id: S,
|
||||
@@ -118,7 +119,8 @@ where
|
||||
Self { precompile, cache, spec_id, metrics }
|
||||
}
|
||||
|
||||
pub(crate) fn wrap(
|
||||
/// Wrap the given precompile in a cached precompile.
|
||||
pub fn wrap(
|
||||
precompile: DynPrecompile,
|
||||
cache: PrecompileCache<S>,
|
||||
spec_id: S,
|
||||
@@ -196,18 +198,18 @@ where
|
||||
/// Metrics for the cached precompile.
|
||||
#[derive(reth_metrics::Metrics, Clone)]
|
||||
#[metrics(scope = "sync.caching")]
|
||||
pub(crate) struct CachedPrecompileMetrics {
|
||||
pub struct CachedPrecompileMetrics {
|
||||
/// Precompile cache hits
|
||||
precompile_cache_hits: metrics::Counter,
|
||||
pub precompile_cache_hits: metrics::Counter,
|
||||
|
||||
/// Precompile cache misses
|
||||
precompile_cache_misses: metrics::Counter,
|
||||
pub precompile_cache_misses: metrics::Counter,
|
||||
|
||||
/// Precompile cache size. Uses the LRU cache length as the size metric.
|
||||
precompile_cache_size: metrics::Gauge,
|
||||
pub precompile_cache_size: metrics::Gauge,
|
||||
|
||||
/// Precompile execution errors.
|
||||
precompile_errors: metrics::Counter,
|
||||
pub precompile_errors: metrics::Counter,
|
||||
}
|
||||
|
||||
impl CachedPrecompileMetrics {
|
||||
@@ -215,7 +217,7 @@ impl CachedPrecompileMetrics {
|
||||
///
|
||||
/// Adds address as an `address` label padded with zeros to at least two hex symbols, prefixed
|
||||
/// by `0x`.
|
||||
pub(crate) fn new_with_address(address: Address) -> Self {
|
||||
pub fn new_with_address(address: Address) -> Self {
|
||||
Self::new_with_labels(&[("address", format!("0x{address:02x}"))])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ pub struct TreeState<N: NodePrimitives = EthPrimitives> {
|
||||
|
||||
impl<N: NodePrimitives> TreeState<N> {
|
||||
/// Returns a new, empty tree state that points to the given canonical head.
|
||||
pub(crate) fn new(current_canonical_head: BlockNumHash, engine_kind: EngineApiKind) -> Self {
|
||||
pub fn new(current_canonical_head: BlockNumHash, engine_kind: EngineApiKind) -> Self {
|
||||
Self {
|
||||
blocks_by_hash: HashMap::default(),
|
||||
blocks_by_number: BTreeMap::new(),
|
||||
@@ -60,25 +60,22 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
}
|
||||
|
||||
/// Resets the state and points to the given canonical head.
|
||||
pub(crate) fn reset(&mut self, current_canonical_head: BlockNumHash) {
|
||||
pub fn reset(&mut self, current_canonical_head: BlockNumHash) {
|
||||
*self = Self::new(current_canonical_head, self.engine_kind);
|
||||
}
|
||||
|
||||
/// Returns the number of executed blocks stored.
|
||||
pub(crate) fn block_count(&self) -> usize {
|
||||
pub fn block_count(&self) -> usize {
|
||||
self.blocks_by_hash.len()
|
||||
}
|
||||
|
||||
/// Returns the [`ExecutedBlock`] by hash.
|
||||
pub(crate) fn executed_block_by_hash(&self, hash: B256) -> Option<&ExecutedBlock<N>> {
|
||||
pub fn executed_block_by_hash(&self, hash: B256) -> Option<&ExecutedBlock<N>> {
|
||||
self.blocks_by_hash.get(&hash)
|
||||
}
|
||||
|
||||
/// Returns the sealed block header by hash.
|
||||
pub(crate) fn sealed_header_by_hash(
|
||||
&self,
|
||||
hash: &B256,
|
||||
) -> Option<SealedHeader<N::BlockHeader>> {
|
||||
pub fn sealed_header_by_hash(&self, hash: &B256) -> Option<SealedHeader<N::BlockHeader>> {
|
||||
self.blocks_by_hash.get(hash).map(|b| b.sealed_block().sealed_header().clone())
|
||||
}
|
||||
|
||||
@@ -87,7 +84,7 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
/// highest persisted block connected to this chain.
|
||||
///
|
||||
/// Returns `None` if the block for the given hash is not found.
|
||||
pub(crate) fn blocks_by_hash(&self, hash: B256) -> Option<(B256, Vec<ExecutedBlock<N>>)> {
|
||||
pub fn blocks_by_hash(&self, hash: B256) -> Option<(B256, Vec<ExecutedBlock<N>>)> {
|
||||
let block = self.blocks_by_hash.get(&hash).cloned()?;
|
||||
let mut parent_hash = block.recovered_block().parent_hash();
|
||||
let mut blocks = vec![block];
|
||||
@@ -160,7 +157,7 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
}
|
||||
|
||||
/// Insert executed block into the state.
|
||||
pub(crate) fn insert_executed(&mut self, executed: ExecutedBlock<N>) {
|
||||
pub fn insert_executed(&mut self, executed: ExecutedBlock<N>) {
|
||||
let hash = executed.recovered_block().hash();
|
||||
let parent_hash = executed.recovered_block().parent_hash();
|
||||
let block_number = executed.recovered_block().number();
|
||||
@@ -216,7 +213,7 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
}
|
||||
|
||||
/// Returns whether or not the hash is part of the canonical chain.
|
||||
pub(crate) fn is_canonical(&self, hash: B256) -> bool {
|
||||
pub fn is_canonical(&self, hash: B256) -> bool {
|
||||
let mut current_block = self.current_canonical_head.hash;
|
||||
if current_block == hash {
|
||||
return true
|
||||
@@ -234,11 +231,7 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
|
||||
/// Removes canonical blocks below the upper bound, only if the last persisted hash is
|
||||
/// part of the canonical chain.
|
||||
pub(crate) fn remove_canonical_until(
|
||||
&mut self,
|
||||
upper_bound: BlockNumber,
|
||||
last_persisted_hash: B256,
|
||||
) {
|
||||
pub fn remove_canonical_until(&mut self, upper_bound: BlockNumber, last_persisted_hash: B256) {
|
||||
debug!(target: "engine::tree", ?upper_bound, ?last_persisted_hash, "Removing canonical blocks from the tree");
|
||||
|
||||
// If the last persisted hash is not canonical, then we don't want to remove any canonical
|
||||
@@ -263,7 +256,7 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
|
||||
/// Removes all blocks that are below the finalized block, as well as removing non-canonical
|
||||
/// sidechains that fork from below the finalized block.
|
||||
pub(crate) fn prune_finalized_sidechains(&mut self, finalized_num_hash: BlockNumHash) {
|
||||
pub fn prune_finalized_sidechains(&mut self, finalized_num_hash: BlockNumHash) {
|
||||
let BlockNumHash { number: finalized_num, hash: finalized_hash } = finalized_num_hash;
|
||||
|
||||
// We remove disconnected sidechains in three steps:
|
||||
@@ -323,7 +316,7 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
/// NOTE: if the finalized block is greater than the upper bound, the only blocks that will be
|
||||
/// removed are canonical blocks and sidechains that fork below the `upper_bound`. This is the
|
||||
/// same behavior as if the `finalized_num` were `Some(upper_bound)`.
|
||||
pub(crate) fn remove_until(
|
||||
pub fn remove_until(
|
||||
&mut self,
|
||||
upper_bound: BlockNumHash,
|
||||
last_persisted_hash: B256,
|
||||
@@ -361,22 +354,22 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
}
|
||||
|
||||
/// Updates the canonical head to the given block.
|
||||
pub(crate) const fn set_canonical_head(&mut self, new_head: BlockNumHash) {
|
||||
pub const fn set_canonical_head(&mut self, new_head: BlockNumHash) {
|
||||
self.current_canonical_head = new_head;
|
||||
}
|
||||
|
||||
/// Returns the tracked canonical head.
|
||||
pub(crate) const fn canonical_head(&self) -> &BlockNumHash {
|
||||
pub const fn canonical_head(&self) -> &BlockNumHash {
|
||||
&self.current_canonical_head
|
||||
}
|
||||
|
||||
/// Returns the block hash of the canonical head.
|
||||
pub(crate) const fn canonical_block_hash(&self) -> B256 {
|
||||
pub const fn canonical_block_hash(&self) -> B256 {
|
||||
self.canonical_head().hash
|
||||
}
|
||||
|
||||
/// Returns the block number of the canonical head.
|
||||
pub(crate) const fn canonical_block_number(&self) -> BlockNumber {
|
||||
pub const fn canonical_block_number(&self) -> BlockNumber {
|
||||
self.canonical_head().number
|
||||
}
|
||||
}
|
||||
@@ -386,7 +379,7 @@ impl<N: NodePrimitives> TreeState<N> {
|
||||
/// Determines if the second block is a descendant of the first block.
|
||||
///
|
||||
/// If the two blocks are the same, this returns `false`.
|
||||
pub(crate) fn is_descendant(
|
||||
pub fn is_descendant(
|
||||
&self,
|
||||
first: BlockNumHash,
|
||||
second: alloy_eips::eip1898::BlockWithParent,
|
||||
|
||||
Reference in New Issue
Block a user