docs(exex): include code for ExEx book from real files (#11545)

This commit is contained in:
Alexey Shekhirin
2024-10-08 11:46:53 +01:00
committed by GitHub
parent a2cfa9e050
commit 3765dbe470
10 changed files with 114 additions and 85 deletions

View File

@ -30,7 +30,12 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- run: cargo clippy --bin "${{ matrix.binary }}" --workspace --features "${{ matrix.network }} asm-keccak jemalloc jemalloc-prof min-error-logs min-warn-logs min-info-logs min-debug-logs min-trace-logs"
- name: Run clippy on binaries
run: cargo clippy --bin "${{ matrix.binary }}" --workspace --features "${{ matrix.network }} asm-keccak jemalloc jemalloc-prof min-error-logs min-warn-logs min-info-logs min-debug-logs min-trace-logs"
env:
RUSTFLAGS: -D warnings
- name: Run clippy on book binary sources
run: cargo clippy --manifest-path book/sources/Cargo.toml --workspace --bins
env:
RUSTFLAGS: -D warnings
@ -128,7 +133,10 @@ jobs:
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- run: cargo fmt --all --check
- name: Run fmt
run: cargo fmt --all --check
- name: Run fmt on book sources
run: cargo fmt --manifest-path book/sources/Cargo.toml --all --check
udeps:
name: udeps

View File

@ -42,6 +42,11 @@ jobs:
--workspace --exclude ef-tests \
--partition hash:${{ matrix.partition }}/2 \
-E "!kind(test)"
- name: Run tests on book sources
run: |
cargo nextest run \
--manifest-path book/sources/Cargo.toml --workspace \
-E "!kind(test)"
state:
name: Ethereum state tests

3
.gitignore vendored
View File

@ -50,3 +50,6 @@ crates/storage/libmdbx-rs/mdbx-sys/libmdbx/cmake-build-debug
# Rust bug report
rustc-ice-*
# Book sources should be able to build with the latest version
book/sources/Cargo.lock

View File

@ -148,6 +148,7 @@ members = [
"testing/testing-utils",
]
default-members = ["bin/reth"]
exclude = ["book/sources"]
# Explicitly set the resolver to version 2, which is the default for packages with edition >= 2021
# https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html

View File

@ -14,19 +14,7 @@ cd my-exex
And add Reth as a dependency in `Cargo.toml`
```toml
[package]
name = "my-exex"
version = "0.1.0"
edition = "2021"
[dependencies]
reth = { git = "https://github.com/paradigmxyz/reth.git" } # Reth
reth-exex = { git = "https://github.com/paradigmxyz/reth.git" } # Execution Extensions
reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth.git" } # Ethereum Node implementation
reth-tracing = { git = "https://github.com/paradigmxyz/reth.git" } # Logging
eyre = "0.6" # Easy error handling
futures-util = "0.3" # Stream utilities for consuming notifications
{{#include ../../sources/exex/hello-world/Cargo.toml}}
```
### Default Reth node
@ -34,15 +22,7 @@ futures-util = "0.3" # Stream utilities for consuming notifications
Now, let's jump to our `main.rs` and start by initializing and launching a default Reth node
```rust,norun,noplayground,ignore
use reth_node_ethereum::EthereumNode;
fn main() -> eyre::Result<()> {
reth::cli::Cli::parse_args().run(|builder, _| async move {
let handle = builder.node(EthereumNode::default()).launch().await?;
handle.wait_for_node_exit().await
})
}
{{#include ../../sources/exex/hello-world/src/bin/1.rs}}
```
You can already test that it works by running the binary and initializing the Holesky node in a custom datadir
@ -63,26 +43,7 @@ $ cargo run -- init --chain holesky --datadir data
The simplest ExEx is just an async function that never returns. We need to install it into our node
```rust,norun,noplayground,ignore
use reth::api::FullNodeComponents;
use reth_exex::{ExExContext, ExExEvent, ExExNotification};
use reth_node_ethereum::EthereumNode;
use reth_tracing::tracing::info;
async fn my_exex<Node: FullNodeComponents>(mut _ctx: ExExContext<Node>) -> eyre::Result<()> {
loop {}
}
fn main() -> eyre::Result<()> {
reth::cli::Cli::parse_args().run(|builder, _| async move {
let handle = builder
.node(EthereumNode::default())
.install_exex("my-exex", |ctx| async move { Ok(my_exex(ctx)) })
.launch()
.await?;
handle.wait_for_node_exit().await
})
}
{{#include ../../sources/exex/hello-world/src/bin/2.rs}}
```
See that unused `_ctx`? That's the context that we'll use to listen to new notifications coming from the main node,
@ -103,46 +64,7 @@ If you try running a node with an ExEx that exits, the node will exit as well.
Now, let's extend our simplest ExEx and start actually listening to new notifications, log them, and send events back to the main node
```rust,norun,noplayground,ignore
use futures_util::StreamExt;
use reth::api::FullNodeComponents;
use reth_exex::{ExExContext, ExExEvent, ExExNotification};
use reth_node_ethereum::EthereumNode;
use reth_tracing::tracing::info;
async fn my_exex<Node: FullNodeComponents>(mut ctx: ExExContext<Node>) -> eyre::Result<()> {
while let Some(notification) = ctx.notifications.next().await {
match &notification {
ExExNotification::ChainCommitted { new } => {
info!(committed_chain = ?new.range(), "Received commit");
}
ExExNotification::ChainReorged { old, new } => {
info!(from_chain = ?old.range(), to_chain = ?new.range(), "Received reorg");
}
ExExNotification::ChainReverted { old } => {
info!(reverted_chain = ?old.range(), "Received revert");
}
};
if let Some(committed_chain) = notification.committed_chain() {
ctx.events
.send(ExExEvent::FinishedHeight(committed_chain.tip().num_hash()))?;
}
}
Ok(())
}
fn main() -> eyre::Result<()> {
reth::cli::Cli::parse_args().run(|builder, _| async move {
let handle = builder
.node(EthereumNode::default())
.install_exex("my-exex", |ctx| async move { Ok(my_exex(ctx)) })
.launch()
.await?;
handle.wait_for_node_exit().await
})
}
{{#include ../../sources/exex/hello-world/src/bin/3.rs}}
```
Woah, there's a lot of new stuff here! Let's go through it step by step:

9
book/sources/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[workspace]
members = [
"exex/hello-world",
]
# Explicitly set the resolver to version 2, which is the default for packages with edition >= 2021
# https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html
resolver = "2"

View File

@ -0,0 +1,13 @@
[package]
name = "my-exex"
version = "0.1.0"
edition = "2021"
[dependencies]
reth = { git = "https://github.com/paradigmxyz/reth.git" } # Reth
reth-exex = { git = "https://github.com/paradigmxyz/reth.git" } # Execution Extensions
reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth.git" } # Ethereum Node implementation
reth-tracing = { git = "https://github.com/paradigmxyz/reth.git" } # Logging
eyre = "0.6" # Easy error handling
futures-util = "0.3" # Stream utilities for consuming notifications

View File

@ -0,0 +1,9 @@
use reth_node_ethereum::EthereumNode;
fn main() -> eyre::Result<()> {
reth::cli::Cli::parse_args().run(|builder, _| async move {
let handle = builder.node(EthereumNode::default()).launch().await?;
handle.wait_for_node_exit().await
})
}

View File

@ -0,0 +1,20 @@
use reth::api::FullNodeComponents;
use reth_exex::ExExContext;
use reth_node_ethereum::EthereumNode;
async fn my_exex<Node: FullNodeComponents>(mut _ctx: ExExContext<Node>) -> eyre::Result<()> {
#[allow(clippy::empty_loop)]
loop {}
}
fn main() -> eyre::Result<()> {
reth::cli::Cli::parse_args().run(|builder, _| async move {
let handle = builder
.node(EthereumNode::default())
.install_exex("my-exex", |ctx| async move { Ok(my_exex(ctx)) })
.launch()
.await?;
handle.wait_for_node_exit().await
})
}

View File

@ -0,0 +1,39 @@
use futures_util::TryStreamExt;
use reth::api::FullNodeComponents;
use reth_exex::{ExExContext, ExExEvent, ExExNotification};
use reth_node_ethereum::EthereumNode;
use reth_tracing::tracing::info;
async fn my_exex<Node: FullNodeComponents>(mut ctx: ExExContext<Node>) -> eyre::Result<()> {
while let Some(notification) = ctx.notifications.try_next().await? {
match &notification {
ExExNotification::ChainCommitted { new } => {
info!(committed_chain = ?new.range(), "Received commit");
}
ExExNotification::ChainReorged { old, new } => {
info!(from_chain = ?old.range(), to_chain = ?new.range(), "Received reorg");
}
ExExNotification::ChainReverted { old } => {
info!(reverted_chain = ?old.range(), "Received revert");
}
};
if let Some(committed_chain) = notification.committed_chain() {
ctx.events.send(ExExEvent::FinishedHeight(committed_chain.tip().num_hash()))?;
}
}
Ok(())
}
fn main() -> eyre::Result<()> {
reth::cli::Cli::parse_args().run(|builder, _| async move {
let handle = builder
.node(EthereumNode::default())
.install_exex("my-exex", |ctx| async move { Ok(my_exex(ctx)) })
.launch()
.await?;
handle.wait_for_node_exit().await
})
}