Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(engine): invalid block hooks crate #10629

Merged
merged 27 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
beae63b
feat: add invalid block hook field to tree
Rjected Aug 21, 2024
8969c27
turn type alias into a trait
shekhirin Aug 30, 2024
257b46f
Merge remote-tracking branch 'origin/main' into dan/invalid-block-hook
shekhirin Aug 30, 2024
a61e345
return debug derive
shekhirin Aug 30, 2024
ec3c090
bad block hook -> invalid block hook
shekhirin Aug 30, 2024
15ca0e9
feat(engine): invalid block hooks crate
shekhirin Aug 30, 2024
6014fac
return manual Debug impl
shekhirin Aug 30, 2024
e40baed
accept hook as a box
shekhirin Aug 30, 2024
4d89b4e
Merge remote-tracking branch 'origin/dan/invalid-block-hook' into ale…
shekhirin Aug 30, 2024
88d8bfe
fix some lints
shekhirin Aug 30, 2024
569668a
remove unused Debug import
shekhirin Aug 30, 2024
b3e1a2b
Merge remote-tracking branch 'origin/dan/invalid-block-hook' into ale…
shekhirin Aug 30, 2024
3646acd
report a hook that's not implemented
shekhirin Aug 30, 2024
2cbac99
ChainInvalidBlockHook -> InvalidBlockHookChain
shekhirin Aug 30, 2024
773eb4b
reorganize again
shekhirin Sep 2, 2024
daae4f4
Merge remote-tracking branch 'origin/main' into dan/invalid-block-hook
shekhirin Sep 2, 2024
b290203
Merge remote-tracking branch 'origin/dan/invalid-block-hook' into ale…
shekhirin Sep 2, 2024
9d4f9a1
disable wasm compilation
shekhirin Sep 2, 2024
57b4b76
non exhaustive
shekhirin Sep 3, 2024
e2ece39
fixes after review
shekhirin Sep 3, 2024
94cbe07
Merge remote-tracking branch 'origin/main' into dan/invalid-block-hook
shekhirin Sep 3, 2024
14c97b1
Merge remote-tracking branch 'origin/dan/invalid-block-hook' into ale…
shekhirin Sep 3, 2024
247787e
use default impl for noop hook
shekhirin Sep 3, 2024
34a8099
Merge remote-tracking branch 'origin/main' into alexey/invalid-block-…
shekhirin Sep 3, 2024
f83f17c
remove unused var, refactor invalid block hook method
shekhirin Sep 3, 2024
e75d773
couple const fns
shekhirin Sep 3, 2024
8705fc4
add Clone back
shekhirin Sep 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/assets/check_wasm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,18 @@ exclude_crates=(
reth-stages
reth-storage-errors
# The following are not supposed to be working
reth # all of the crates below
reth # all of the crates below
reth-db # mdbx
reth-invalid-block-hooks # reth-provider
reth-libmdbx # mdbx
reth-mdbx-sys # mdbx
reth-nippy-jar # sucds
reth-provider # reth-db, reth-nippy-jar
reth-prune # reth-db
reth-stages-api # reth-provider, reth-prune
reth-static-file # reth-nippy-jar
reth-static-file # reth-nippy-jar
reth-transaction-pool # c-kzg
reth-trie-db # reth-db
reth-trie-db # reth-db
reth-trie-parallel # reth-db
)

Expand Down
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ members = [
"crates/consensus/consensus/",
"crates/consensus/debug-client/",
"crates/e2e-test-utils/",
"crates/engine/invalid-block-hooks/",
"crates/engine/primitives/",
"crates/engine/service",
"crates/engine/tree/",
Expand Down Expand Up @@ -330,6 +331,7 @@ reth-exex = { path = "crates/exex/exex" }
reth-exex-test-utils = { path = "crates/exex/test-utils" }
reth-exex-types = { path = "crates/exex/types" }
reth-fs-util = { path = "crates/fs-util" }
reth-invalid-block-hooks = { path = "crates/engine/invalid-block-hooks" }
reth-ipc = { path = "crates/rpc/ipc" }
reth-libmdbx = { path = "crates/storage/libmdbx-rs" }
reth-mdbx-sys = { path = "crates/storage/libmdbx-rs/mdbx-sys" }
Expand Down
17 changes: 17 additions & 0 deletions crates/engine/invalid-block-hooks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "reth-invalid-block-hooks"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true

[lints]
workspace = true

[dependencies]
# reth
reth-primitives.workspace = true
reth-provider.workspace = true
reth-trie.workspace = true
5 changes: 5 additions & 0 deletions crates/engine/invalid-block-hooks/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//! Invalid block hook implementations.

mod witness;

pub use witness::witness;
13 changes: 13 additions & 0 deletions crates/engine/invalid-block-hooks/src/witness.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use reth_primitives::{Receipt, SealedBlockWithSenders, SealedHeader, B256};
use reth_provider::BlockExecutionOutput;
use reth_trie::updates::TrieUpdates;

/// Generates a witness for the given block and saves it to a file.
pub fn witness(
_block: &SealedBlockWithSenders,
_header: &SealedHeader,
_output: &BlockExecutionOutput<Receipt>,
_trie_updates: Option<(&TrieUpdates, B256)>,
) {
unimplemented!("witness generation is not supported")
}
55 changes: 39 additions & 16 deletions crates/engine/tree/src/tree/invalid_block_hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,29 @@ pub trait InvalidBlockHook: Send + Sync {
/// Invoked when a bad block is encountered.
fn on_invalid_block(
&self,
block: SealedBlockWithSenders,
header: SealedHeader,
output: BlockExecutionOutput<Receipt>,
trie_updates: Option<(TrieUpdates, B256)>,
block: &SealedBlockWithSenders,
header: &SealedHeader,
output: &BlockExecutionOutput<Receipt>,
trie_updates: Option<(&TrieUpdates, B256)>,
);
}

impl<F> InvalidBlockHook for F
where
F: Fn(
SealedBlockWithSenders,
SealedHeader,
BlockExecutionOutput<Receipt>,
Option<(TrieUpdates, B256)>,
&SealedBlockWithSenders,
&SealedHeader,
&BlockExecutionOutput<Receipt>,
Option<(&TrieUpdates, B256)>,
) + Send
+ Sync,
{
fn on_invalid_block(
&self,
block: SealedBlockWithSenders,
header: SealedHeader,
output: BlockExecutionOutput<Receipt>,
trie_updates: Option<(TrieUpdates, B256)>,
block: &SealedBlockWithSenders,
header: &SealedHeader,
output: &BlockExecutionOutput<Receipt>,
trie_updates: Option<(&TrieUpdates, B256)>,
) {
self(block, header, output, trie_updates)
}
Expand All @@ -43,10 +43,33 @@ pub struct NoopInvalidBlockHook;
impl InvalidBlockHook for NoopInvalidBlockHook {
fn on_invalid_block(
&self,
_block: SealedBlockWithSenders,
_header: SealedHeader,
_output: BlockExecutionOutput<Receipt>,
_trie_updates: Option<(TrieUpdates, B256)>,
_block: &SealedBlockWithSenders,
_header: &SealedHeader,
_output: &BlockExecutionOutput<Receipt>,
_trie_updates: Option<(&TrieUpdates, B256)>,
) {
}
}

/// Multiple [`InvalidBlockHook`]s that are executed in order.
pub struct InvalidBlockHooks(pub Vec<Box<dyn InvalidBlockHook>>);

impl std::fmt::Debug for InvalidBlockHooks {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("InvalidBlockHooks").field("len", &self.0.len()).finish()
}
}

impl InvalidBlockHook for InvalidBlockHooks {
fn on_invalid_block(
&self,
block: &SealedBlockWithSenders,
header: &SealedHeader,
output: &BlockExecutionOutput<Receipt>,
trie_updates: Option<(&TrieUpdates, B256)>,
) {
for hook in &self.0 {
hook.on_invalid_block(block, header, output, trie_updates);
}
}
}
17 changes: 11 additions & 6 deletions crates/engine/tree/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ mod invalid_block_hook;
mod metrics;
use crate::{engine::EngineApiRequest, tree::metrics::EngineApiMetrics};
pub use config::TreeConfig;
pub use invalid_block_hook::{InvalidBlockHook, NoopInvalidBlockHook};
pub use invalid_block_hook::{InvalidBlockHook, InvalidBlockHooks, NoopInvalidBlockHook};

/// Keeps track of the state of the tree.
///
Expand Down Expand Up @@ -1909,7 +1909,12 @@ where
PostExecutionInput::new(&output.receipts, &output.requests),
) {
// call post-block hook
self.invalid_block_hook.on_invalid_block(block.seal_slow(), parent_block, output, None);
self.invalid_block_hook.on_invalid_block(
&block.seal_slow(),
&parent_block,
&output,
None,
);
return Err(err.into())
}

Expand All @@ -1921,10 +1926,10 @@ where
if state_root != block.state_root {
// call post-block hook
self.invalid_block_hook.on_invalid_block(
block.clone().seal_slow(),
parent_block,
output,
Some((trie_output, state_root)),
&block.clone().seal_slow(),
&parent_block,
&output,
Some((&trie_output, state_root)),
);
return Err(ConsensusError::BodyStateRootDiff(
GotExpected { got: state_root, expected: block.state_root }.into(),
Expand Down
1 change: 1 addition & 0 deletions crates/node/builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ reth-payload-validator.workspace = true
reth-engine-service.workspace = true
reth-tokio-util.workspace = true
reth-engine-tree.workspace = true
reth-invalid-block-hooks.workspace = true

## ethereum
alloy-network.workspace = true
Expand Down
28 changes: 27 additions & 1 deletion crates/node/builder/src/launch/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use reth_consensus::Consensus;
use reth_db_api::{database::Database, database_metrics::DatabaseMetrics};
use reth_db_common::init::{init_genesis, InitDatabaseError};
use reth_downloaders::{bodies::noop::NoopBodiesDownloader, headers::noop::NoopHeaderDownloader};
use reth_engine_tree::tree::{InvalidBlockHook, InvalidBlockHooks, NoopInvalidBlockHook};
use reth_evm::noop::NoopBlockExecutorProvider;
use reth_network_p2p::headers::client::HeadersClient;
use reth_node_api::FullNodeTypes;
Expand Down Expand Up @@ -813,7 +814,7 @@ where
inconsistent_stage_checkpoint = stage_checkpoint,
"Pipeline sync progress is inconsistent"
);
return self.blockchain_db().block_hash(first_stage_checkpoint)
return self.blockchain_db().block_hash(first_stage_checkpoint);
}
}

Expand All @@ -839,6 +840,31 @@ where
pub const fn components(&self) -> &CB::Components {
&self.node_adapter().components
}

/// Returns the [`InvalidBlockHook`] to use for the node.
pub fn invalid_block_hook(&self) -> eyre::Result<Box<dyn InvalidBlockHook>> {
Ok(if let Some(ref hook) = self.node_config().debug.invalid_block_hook {
let hooks = hook
.iter()
.copied()
.map(|hook| {
Ok(match hook {
reth_node_core::args::InvalidBlockHook::Witness => {
Box::new(reth_invalid_block_hooks::witness) as Box<dyn InvalidBlockHook>
}
reth_node_core::args::InvalidBlockHook::PreState |
reth_node_core::args::InvalidBlockHook::Opcode => {
eyre::bail!("invalid block hook {hook:?} is not implemented yet")
}
})
})
.collect::<Result<_, _>>()?;

Box::new(InvalidBlockHooks(hooks))
} else {
Box::new(NoopInvalidBlockHook::default())
})
}
}

/// Joins two attachments together.
Expand Down
6 changes: 2 additions & 4 deletions crates/node/builder/src/launch/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use reth_chainspec::ChainSpec;
use reth_engine_service::service::{ChainEvent, EngineService};
use reth_engine_tree::{
engine::{EngineApiRequest, EngineRequestHandler},
tree::{NoopInvalidBlockHook, TreeConfig},
tree::TreeConfig,
};
use reth_engine_util::EngineMessageStreamExt;
use reth_exex::ExExManagerHandle;
Expand Down Expand Up @@ -207,8 +207,6 @@ where
warn!(target: "reth::cli", ?hook_type, "Invalid block hooks are not implemented yet! The `debug.invalid-block-hook` flag will do nothing for now.");
}

let invalid_block_hook = Box::new(NoopInvalidBlockHook::default());

// Configure the consensus engine
let mut eth_service = EngineService::new(
ctx.consensus(),
Expand All @@ -223,7 +221,7 @@ where
pruner,
ctx.components().payload_builder().clone(),
TreeConfig::default(),
invalid_block_hook,
ctx.invalid_block_hook()?,
);

let event_sender = EventSender::default();
Expand Down
7 changes: 6 additions & 1 deletion crates/node/core/src/args/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub struct DebugArgs {
/// use reth_node_core::args::{InvalidBlockHook, InvalidBlockSelection};
/// let config: InvalidBlockSelection = vec![InvalidBlockHook::Witness].into();
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, derive_more::Deref)]
pub struct InvalidBlockSelection(HashSet<InvalidBlockHook>);

impl InvalidBlockSelection {
Expand Down Expand Up @@ -135,6 +135,11 @@ impl InvalidBlockSelection {
{
selection.into_iter().map(TryInto::try_into).collect()
}

/// Clones the set of configured [`InvalidBlockHook`].
pub fn to_selection(&self) -> HashSet<InvalidBlockHook> {
self.0.clone()
}
}

impl From<&[InvalidBlockHook]> for InvalidBlockSelection {
Expand Down
Loading