mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: add TreeConfig (#9833)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -7765,6 +7765,7 @@ dependencies = [
|
|||||||
"reth-consensus",
|
"reth-consensus",
|
||||||
"reth-db",
|
"reth-db",
|
||||||
"reth-e2e-test-utils",
|
"reth-e2e-test-utils",
|
||||||
|
"reth-engine-tree",
|
||||||
"reth-ethereum-engine",
|
"reth-ethereum-engine",
|
||||||
"reth-ethereum-engine-primitives",
|
"reth-ethereum-engine-primitives",
|
||||||
"reth-ethereum-payload-builder",
|
"reth-ethereum-payload-builder",
|
||||||
|
|||||||
74
crates/engine/tree/src/tree/config.rs
Normal file
74
crates/engine/tree/src/tree/config.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//! Engine tree configuration.
|
||||||
|
|
||||||
|
const DEFAULT_PERSISTENCE_THRESHOLD: u64 = 256;
|
||||||
|
const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = 256;
|
||||||
|
const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
|
||||||
|
|
||||||
|
/// The configuration of the engine tree.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TreeConfig {
|
||||||
|
/// Maximum number of blocks to be kept only in memory without triggering persistence.
|
||||||
|
persistence_threshold: u64,
|
||||||
|
/// Number of pending blocks that cannot be executed due to missing parent and
|
||||||
|
/// are kept in cache.
|
||||||
|
block_buffer_limit: u32,
|
||||||
|
/// Number of invalid headers to keep in cache.
|
||||||
|
max_invalid_header_cache_length: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TreeConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
persistence_threshold: DEFAULT_PERSISTENCE_THRESHOLD,
|
||||||
|
block_buffer_limit: DEFAULT_BLOCK_BUFFER_LIMIT,
|
||||||
|
max_invalid_header_cache_length: DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TreeConfig {
|
||||||
|
/// Create engine tree configuration.
|
||||||
|
pub const fn new(
|
||||||
|
persistence_threshold: u64,
|
||||||
|
block_buffer_limit: u32,
|
||||||
|
max_invalid_header_cache_length: u32,
|
||||||
|
) -> Self {
|
||||||
|
Self { persistence_threshold, block_buffer_limit, max_invalid_header_cache_length }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the persistence threshold.
|
||||||
|
pub const fn persistence_threshold(&self) -> u64 {
|
||||||
|
self.persistence_threshold
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the block buffer limit.
|
||||||
|
pub const fn block_buffer_limit(&self) -> u32 {
|
||||||
|
self.block_buffer_limit
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the maximum invalid cache header length.
|
||||||
|
pub const fn max_invalid_header_cache_length(&self) -> u32 {
|
||||||
|
self.max_invalid_header_cache_length
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Setter for persistence threshold.
|
||||||
|
pub const fn with_persistence_threshold(mut self, persistence_threshold: u64) -> Self {
|
||||||
|
self.persistence_threshold = persistence_threshold;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Setter for block buffer limit.
|
||||||
|
pub const fn with_block_buffer_limit(mut self, block_buffer_limit: u32) -> Self {
|
||||||
|
self.block_buffer_limit = block_buffer_limit;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Setter for maximum invalid header cache length.
|
||||||
|
pub const fn with_max_invalid_header_cache_length(
|
||||||
|
mut self,
|
||||||
|
max_invalid_header_cache_length: u32,
|
||||||
|
) -> Self {
|
||||||
|
self.max_invalid_header_cache_length = max_invalid_header_cache_length;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -49,13 +49,8 @@ use tokio::sync::{
|
|||||||
};
|
};
|
||||||
use tracing::*;
|
use tracing::*;
|
||||||
|
|
||||||
/// Maximum number of blocks to be kept only in memory without triggering persistence.
|
mod config;
|
||||||
const PERSISTENCE_THRESHOLD: u64 = 256;
|
pub use config::TreeConfig;
|
||||||
/// Number of pending blocks that cannot be executed due to missing parent and
|
|
||||||
/// are kept in cache.
|
|
||||||
const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = 256;
|
|
||||||
/// Number of invalid headers to keep in cache.
|
|
||||||
const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
|
|
||||||
|
|
||||||
/// Keeps track of the state of the tree.
|
/// Keeps track of the state of the tree.
|
||||||
///
|
///
|
||||||
@ -387,6 +382,8 @@ pub struct EngineApiTreeHandlerImpl<P, E, T: EngineTypes> {
|
|||||||
/// Handle to the payload builder that will receive payload attributes for valid forkchoice
|
/// Handle to the payload builder that will receive payload attributes for valid forkchoice
|
||||||
/// updates
|
/// updates
|
||||||
payload_builder: PayloadBuilderHandle<T>,
|
payload_builder: PayloadBuilderHandle<T>,
|
||||||
|
/// Configuration settings.
|
||||||
|
config: TreeConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P, E, T> EngineApiTreeHandlerImpl<P, E, T>
|
impl<P, E, T> EngineApiTreeHandlerImpl<P, E, T>
|
||||||
@ -407,6 +404,7 @@ where
|
|||||||
canonical_in_memory_state: CanonicalInMemoryState,
|
canonical_in_memory_state: CanonicalInMemoryState,
|
||||||
persistence: PersistenceHandle,
|
persistence: PersistenceHandle,
|
||||||
payload_builder: PayloadBuilderHandle<T>,
|
payload_builder: PayloadBuilderHandle<T>,
|
||||||
|
config: TreeConfig,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
provider,
|
provider,
|
||||||
@ -421,6 +419,7 @@ where
|
|||||||
state,
|
state,
|
||||||
canonical_in_memory_state,
|
canonical_in_memory_state,
|
||||||
payload_builder,
|
payload_builder,
|
||||||
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,14 +436,15 @@ where
|
|||||||
persistence: PersistenceHandle,
|
persistence: PersistenceHandle,
|
||||||
payload_builder: PayloadBuilderHandle<T>,
|
payload_builder: PayloadBuilderHandle<T>,
|
||||||
canonical_in_memory_state: CanonicalInMemoryState,
|
canonical_in_memory_state: CanonicalInMemoryState,
|
||||||
|
config: TreeConfig,
|
||||||
) -> UnboundedReceiver<EngineApiEvent> {
|
) -> UnboundedReceiver<EngineApiEvent> {
|
||||||
let best_block_number = provider.best_block_number().unwrap_or(0);
|
let best_block_number = provider.best_block_number().unwrap_or(0);
|
||||||
let header = provider.sealed_header(best_block_number).ok().flatten().unwrap_or_default();
|
let header = provider.sealed_header(best_block_number).ok().flatten().unwrap_or_default();
|
||||||
|
|
||||||
let (tx, outgoing) = tokio::sync::mpsc::unbounded_channel();
|
let (tx, outgoing) = tokio::sync::mpsc::unbounded_channel();
|
||||||
let state = EngineApiTreeState::new(
|
let state = EngineApiTreeState::new(
|
||||||
DEFAULT_BLOCK_BUFFER_LIMIT,
|
config.block_buffer_limit(),
|
||||||
DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH,
|
config.max_invalid_header_cache_length(),
|
||||||
header.num_hash(),
|
header.num_hash(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -459,6 +459,7 @@ where
|
|||||||
canonical_in_memory_state,
|
canonical_in_memory_state,
|
||||||
persistence,
|
persistence,
|
||||||
payload_builder,
|
payload_builder,
|
||||||
|
config,
|
||||||
);
|
);
|
||||||
std::thread::Builder::new().name("Tree Task".to_string()).spawn(|| task.run()).unwrap();
|
std::thread::Builder::new().name("Tree Task".to_string()).spawn(|| task.run()).unwrap();
|
||||||
outgoing
|
outgoing
|
||||||
@ -657,12 +658,12 @@ where
|
|||||||
fn should_persist(&self) -> bool {
|
fn should_persist(&self) -> bool {
|
||||||
self.state.tree_state.max_block_number() -
|
self.state.tree_state.max_block_number() -
|
||||||
self.persistence_state.last_persisted_block_number >=
|
self.persistence_state.last_persisted_block_number >=
|
||||||
PERSISTENCE_THRESHOLD
|
self.config.persistence_threshold()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_blocks_to_persist(&self) -> Vec<ExecutedBlock> {
|
fn get_blocks_to_persist(&self) -> Vec<ExecutedBlock> {
|
||||||
let start = self.persistence_state.last_persisted_block_number;
|
let start = self.persistence_state.last_persisted_block_number;
|
||||||
let end = start + PERSISTENCE_THRESHOLD;
|
let end = start + self.config.persistence_threshold();
|
||||||
|
|
||||||
// NOTE: this is an exclusive range, to try to include exactly PERSISTENCE_THRESHOLD blocks
|
// NOTE: this is an exclusive range, to try to include exactly PERSISTENCE_THRESHOLD blocks
|
||||||
self.state
|
self.state
|
||||||
@ -1607,6 +1608,7 @@ mod tests {
|
|||||||
canonical_in_memory_state,
|
canonical_in_memory_state,
|
||||||
persistence_handle,
|
persistence_handle,
|
||||||
payload_builder,
|
payload_builder,
|
||||||
|
TreeConfig::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Self { tree, to_tree_tx, blocks: vec![], action_rx, payload_command_rx }
|
Self { tree, to_tree_tx, blocks: vec![], action_rx, payload_command_rx }
|
||||||
@ -1675,6 +1677,7 @@ mod tests {
|
|||||||
canonical_in_memory_state,
|
canonical_in_memory_state,
|
||||||
persistence_handle,
|
persistence_handle,
|
||||||
payload_builder,
|
payload_builder,
|
||||||
|
TreeConfig::default(),
|
||||||
);
|
);
|
||||||
let last_executed_block = blocks.last().unwrap().clone();
|
let last_executed_block = blocks.last().unwrap().clone();
|
||||||
let pending = Some(BlockState::new(last_executed_block));
|
let pending = Some(BlockState::new(last_executed_block));
|
||||||
@ -1688,8 +1691,10 @@ mod tests {
|
|||||||
async fn test_tree_persist_blocks() {
|
async fn test_tree_persist_blocks() {
|
||||||
// we need more than PERSISTENCE_THRESHOLD blocks to trigger the
|
// we need more than PERSISTENCE_THRESHOLD blocks to trigger the
|
||||||
// persistence task.
|
// persistence task.
|
||||||
|
let tree_config = TreeConfig::default();
|
||||||
|
|
||||||
let TestHarness { tree, to_tree_tx, action_rx, mut blocks, payload_command_rx } =
|
let TestHarness { tree, to_tree_tx, action_rx, mut blocks, payload_command_rx } =
|
||||||
get_default_test_harness(PERSISTENCE_THRESHOLD + 1);
|
get_default_test_harness(tree_config.persistence_threshold() + 1);
|
||||||
std::thread::Builder::new().name("Tree Task".to_string()).spawn(|| tree.run()).unwrap();
|
std::thread::Builder::new().name("Tree Task".to_string()).spawn(|| tree.run()).unwrap();
|
||||||
|
|
||||||
// send a message to the tree to enter the main loop.
|
// send a message to the tree to enter the main loop.
|
||||||
@ -1699,7 +1704,7 @@ mod tests {
|
|||||||
if let PersistenceAction::SaveBlocks((saved_blocks, _)) = received_action {
|
if let PersistenceAction::SaveBlocks((saved_blocks, _)) = received_action {
|
||||||
// only PERSISTENCE_THRESHOLD will be persisted
|
// only PERSISTENCE_THRESHOLD will be persisted
|
||||||
blocks.pop();
|
blocks.pop();
|
||||||
assert_eq!(saved_blocks.len() as u64, PERSISTENCE_THRESHOLD);
|
assert_eq!(saved_blocks.len() as u64, tree_config.persistence_threshold());
|
||||||
assert_eq!(saved_blocks, blocks);
|
assert_eq!(saved_blocks, blocks);
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected action received {received_action:?}");
|
panic!("unexpected action received {received_action:?}");
|
||||||
@ -1731,8 +1736,10 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_engine_request_during_backfill() {
|
async fn test_engine_request_during_backfill() {
|
||||||
|
let tree_config = TreeConfig::default();
|
||||||
|
|
||||||
let TestHarness { mut tree, to_tree_tx, action_rx, blocks, payload_command_rx } =
|
let TestHarness { mut tree, to_tree_tx, action_rx, blocks, payload_command_rx } =
|
||||||
get_default_test_harness(PERSISTENCE_THRESHOLD);
|
get_default_test_harness(tree_config.persistence_threshold());
|
||||||
|
|
||||||
// set backfill active
|
// set backfill active
|
||||||
tree.backfill_sync_state = BackfillSyncState::Active;
|
tree.backfill_sync_state = BackfillSyncState::Active;
|
||||||
@ -1754,7 +1761,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_holesky_payload() {
|
async fn test_holesky_payload() {
|
||||||
let s = include_str!("../test-data/holesky/1.rlp");
|
let s = include_str!("../../test-data/holesky/1.rlp");
|
||||||
let data = Bytes::from_str(s).unwrap();
|
let data = Bytes::from_str(s).unwrap();
|
||||||
let block = Block::decode(&mut data.as_ref()).unwrap();
|
let block = Block::decode(&mut data.as_ref()).unwrap();
|
||||||
let sealed = block.seal_slow();
|
let sealed = block.seal_slow();
|
||||||
@ -8,7 +8,7 @@ use reth_engine_tree::{
|
|||||||
download::BasicBlockDownloader,
|
download::BasicBlockDownloader,
|
||||||
engine::{EngineApiRequestHandler, EngineHandler},
|
engine::{EngineApiRequestHandler, EngineHandler},
|
||||||
persistence::PersistenceHandle,
|
persistence::PersistenceHandle,
|
||||||
tree::EngineApiTreeHandlerImpl,
|
tree::{EngineApiTreeHandlerImpl, TreeConfig},
|
||||||
};
|
};
|
||||||
pub use reth_engine_tree::{
|
pub use reth_engine_tree::{
|
||||||
chain::{ChainEvent, ChainOrchestrator},
|
chain::{ChainEvent, ChainOrchestrator},
|
||||||
@ -68,6 +68,7 @@ where
|
|||||||
blockchain_db: BlockchainProvider2<DB>,
|
blockchain_db: BlockchainProvider2<DB>,
|
||||||
pruner: Pruner<DB, ProviderFactory<DB>>,
|
pruner: Pruner<DB, ProviderFactory<DB>>,
|
||||||
payload_builder: PayloadBuilderHandle<EthEngineTypes>,
|
payload_builder: PayloadBuilderHandle<EthEngineTypes>,
|
||||||
|
tree_config: TreeConfig,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let consensus = Arc::new(EthBeaconConsensus::new(chain_spec.clone()));
|
let consensus = Arc::new(EthBeaconConsensus::new(chain_spec.clone()));
|
||||||
let downloader = BasicBlockDownloader::new(client, consensus.clone());
|
let downloader = BasicBlockDownloader::new(client, consensus.clone());
|
||||||
@ -89,6 +90,7 @@ where
|
|||||||
persistence_handle,
|
persistence_handle,
|
||||||
payload_builder,
|
payload_builder,
|
||||||
canonical_in_memory_state,
|
canonical_in_memory_state,
|
||||||
|
tree_config,
|
||||||
);
|
);
|
||||||
|
|
||||||
let engine_handler = EngineApiRequestHandler::new(to_tree_tx, from_tree);
|
let engine_handler = EngineApiRequestHandler::new(to_tree_tx, from_tree);
|
||||||
@ -174,6 +176,7 @@ mod tests {
|
|||||||
blockchain_db,
|
blockchain_db,
|
||||||
pruner,
|
pruner,
|
||||||
PayloadBuilderHandle::new(tx),
|
PayloadBuilderHandle::new(tx),
|
||||||
|
TreeConfig::default(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ reth-node-events.workspace = true
|
|||||||
reth-node-core.workspace = true
|
reth-node-core.workspace = true
|
||||||
reth-exex.workspace = true
|
reth-exex.workspace = true
|
||||||
reth-blockchain-tree.workspace = true
|
reth-blockchain-tree.workspace = true
|
||||||
|
reth-engine-tree.workspace = true
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
eyre.workspace = true
|
eyre.workspace = true
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use reth_beacon_consensus::{
|
|||||||
BeaconConsensusEngineHandle,
|
BeaconConsensusEngineHandle,
|
||||||
};
|
};
|
||||||
use reth_blockchain_tree::BlockchainTreeConfig;
|
use reth_blockchain_tree::BlockchainTreeConfig;
|
||||||
|
use reth_engine_tree::tree::TreeConfig;
|
||||||
use reth_ethereum_engine::service::{ChainEvent, EthService};
|
use reth_ethereum_engine::service::{ChainEvent, EthService};
|
||||||
use reth_ethereum_engine_primitives::EthEngineTypes;
|
use reth_ethereum_engine_primitives::EthEngineTypes;
|
||||||
use reth_exex::ExExManagerHandle;
|
use reth_exex::ExExManagerHandle;
|
||||||
@ -171,6 +172,8 @@ where
|
|||||||
let pruner_events = pruner.events();
|
let pruner_events = pruner.events();
|
||||||
info!(target: "reth::cli", prune_config=?ctx.prune_config().unwrap_or_default(), "Pruner initialized");
|
info!(target: "reth::cli", prune_config=?ctx.prune_config().unwrap_or_default(), "Pruner initialized");
|
||||||
|
|
||||||
|
let tree_config = TreeConfig::default().with_persistence_threshold(120);
|
||||||
|
|
||||||
// Configure the consensus engine
|
// Configure the consensus engine
|
||||||
let mut eth_service = EthService::new(
|
let mut eth_service = EthService::new(
|
||||||
ctx.chain_spec(),
|
ctx.chain_spec(),
|
||||||
@ -182,6 +185,7 @@ where
|
|||||||
ctx.blockchain_db().clone(),
|
ctx.blockchain_db().clone(),
|
||||||
pruner,
|
pruner,
|
||||||
ctx.components().payload_builder().clone(),
|
ctx.components().payload_builder().clone(),
|
||||||
|
tree_config,
|
||||||
);
|
);
|
||||||
|
|
||||||
let event_sender = EventSender::default();
|
let event_sender = EventSender::default();
|
||||||
|
|||||||
Reference in New Issue
Block a user