chore: make engine tree crate items public (#21487)

This commit is contained in:
Julian Meyer
2026-01-30 10:40:30 -08:00
committed by GitHub
parent 3ec065295e
commit 435d915422
9 changed files with 140 additions and 130 deletions

View File

@@ -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
}

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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>),
{

View File

@@ -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

View File

@@ -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

View File

@@ -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}"))])
}
}

View File

@@ -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,