Skip to content
This repository was archived by the owner on Feb 6, 2026. It is now read-only.

Commit 306e495

Browse files
authored
Merge pull request #116 from semiotic-ai/suchapalaver/fix-examples
build: port examples from beacon protos and fix
2 parents 0334940 + 7ec3744 commit 306e495

7 files changed

Lines changed: 194 additions & 10 deletions

File tree

Cargo.lock

Lines changed: 32 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ alloy-primitives = "1.4.0"
1919
anyhow = "1.0.100"
2020
arbitrum-ve = { path = "crates/arbitrum-ve" }
2121
base64 = "0.22.1"
22+
beacon-protos = { git = "https://github.com/semiotic-ai/beacon-protos.git", branch = "main" }
2223
bincode = { version = "2.0.1", features = ["serde"] }
2324
clap = { version = "4.5.23", features = ["derive"] }
2425
criterion = { version = "0.7.0", features = ["html_reports"] }
@@ -30,9 +31,11 @@ ethereum_ssz = "0.9.0"
3031
ethereum_ssz_derive = "0.9.0"
3132
firehose-protos = { path = "crates/firehose-protos" }
3233
firehose-rs = "0.3.0"
34+
futures = "0.3.31"
3335
header-accumulator = { path = "crates/header-accumulator" }
3436
hex = "0.4.3"
3537
keccak-hash = "0.11.0"
38+
kzg = { git = "https://github.com/sigp/lighthouse.git", branch = "stable" }
3639
merkle_proof = { git = "https://github.com/sigp/lighthouse.git", branch = "stable" }
3740
parquet = "56.2.0"
3841
primitive-types = "0.14.0"
@@ -58,6 +61,7 @@ tracing-subscriber = "0.3.19"
5861
tree_hash = "0.10.0"
5962
tree_hash_derive = "0.10.0"
6063
validation = { path = "crates/validation" }
64+
vee = { path = "crates/vee" }
6165
types = { git = "https://github.com/sigp/lighthouse.git", branch = "stable" }
6266
zstd = "0.13.3"
6367

crates/firehose-protos-examples/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ edition = "2021"
55

66
[dev-dependencies]
77
alloy-primitives.workspace = true
8+
beacon-protos.workspace = true
89
firehose-client = { git = "https://github.com/semiotic-ai/firehose-client.git", branch = "main" }
910
firehose-protos.workspace = true
11+
futures.workspace = true
12+
hex.workspace = true
1013
tokio.workspace = true
14+
vee.workspace = true
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2024-, Semiotic AI, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! # Fetch Beacon Block
5+
//!
6+
//! Demonstrates how to fetch a single block from Beacon Firehose, using the `Fetch` API.
7+
8+
use beacon_protos::{Block as BeaconBlock, Body};
9+
use firehose_client::{Chain, FirehoseClient};
10+
use vee::EthBlock;
11+
12+
#[tokio::main]
13+
async fn main() {
14+
// Show matching data from execution layer and beacon chain
15+
let mut execution_layer_client = FirehoseClient::new(Chain::Ethereum);
16+
17+
let response = execution_layer_client
18+
.fetch_block(20672593)
19+
.await
20+
.unwrap()
21+
.unwrap();
22+
23+
let block = EthBlock::try_from(response.into_inner()).unwrap();
24+
25+
assert_eq!(block.number, 20672593);
26+
assert_eq!(
27+
format!("0x{}", hex::encode(block.hash)).as_str(),
28+
"0xea48ba1c8e38ea586239e9c5ec62949ddd79404c6006c099bb02a8b22ddd18e4"
29+
);
30+
31+
let mut beacon_client = FirehoseClient::new(Chain::Beacon);
32+
// This is the slot number for the Beacon block we want to fetch, but right now
33+
// we don't have a way to map the block number of the execution block to the slot number
34+
// of the Beacon block.
35+
let response = beacon_client.fetch_block(9881091).await.unwrap().unwrap();
36+
let block = BeaconBlock::try_from(response.into_inner()).unwrap();
37+
38+
assert_eq!(block.slot, 9881091);
39+
40+
let body = block.body.as_ref().unwrap();
41+
42+
match body {
43+
Body::Deneb(body) => {
44+
let execution_payload = body.execution_payload.as_ref().unwrap();
45+
46+
let block_hash = &execution_payload.block_hash;
47+
48+
assert_eq!(
49+
format!("0x{}", hex::encode(block_hash)).as_str(),
50+
"0xea48ba1c8e38ea586239e9c5ec62949ddd79404c6006c099bb02a8b22ddd18e4"
51+
);
52+
53+
let block_number = execution_payload.block_number;
54+
55+
assert_eq!(block_number, 20672593);
56+
}
57+
_ => unimplemented!(),
58+
};
59+
60+
println!("fetch_beacon ran to completion!");
61+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2024-, Semiotic AI, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! # Fetch Ethereum Block
5+
//!
6+
//! Demonstrates how to fetch a single block from Ethereum firehose.
7+
8+
use firehose_client::{Chain, FirehoseClient};
9+
use vee::EthBlock as Block;
10+
11+
#[tokio::main]
12+
async fn main() {
13+
let mut client = FirehoseClient::new(Chain::Ethereum);
14+
let response = client.fetch_block(20672593).await.unwrap().unwrap();
15+
let block = Block::try_from(response.into_inner()).unwrap();
16+
17+
assert_eq!(block.number, 20672593);
18+
assert_eq!(
19+
format!("0x{}", hex::encode(block.hash)).as_str(),
20+
"0xea48ba1c8e38ea586239e9c5ec62949ddd79404c6006c099bb02a8b22ddd18e4"
21+
);
22+
23+
println!("fetch_beacon completed successfully!");
24+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2024-, Semiotic AI, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! # Example: Stream Beacon Blocks
5+
//!
6+
//! Demonstrates how to stream a range of blocks from Firehose Beacon
7+
8+
use beacon_protos::Block as FirehoseBeaconBlock;
9+
use firehose_client::{Chain, FirehoseClient};
10+
use futures::StreamExt;
11+
12+
#[tokio::main]
13+
async fn main() {
14+
// Testing this so far without proper benchmarking, the time taken to fetch the blocks
15+
// grows linearly with the number of TOTAL_BLOCKS requested, to around 20 minutes for 8192 blocks!
16+
const TOTAL_SLOTS: u64 = 100;
17+
const START_SLOT: u64 = 9968872;
18+
19+
let mut client = FirehoseClient::new(Chain::Beacon);
20+
let mut stream = client
21+
.stream_blocks::<FirehoseBeaconBlock>(START_SLOT, TOTAL_SLOTS)
22+
.await
23+
.unwrap();
24+
25+
let mut blocks: Vec<FirehoseBeaconBlock> = Vec::with_capacity(TOTAL_SLOTS as usize);
26+
27+
while let Some(block) = stream.next().await {
28+
blocks.push(block);
29+
}
30+
31+
// For now, just using this to signal that the test has completed
32+
assert_eq!(blocks.len(), TOTAL_SLOTS as usize);
33+
34+
println!("stream_beacon ran to completion!");
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2024-, Semiotic AI, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! # Example: Stream Ethereum Blocks
5+
//!
6+
//! This example demonstrates how to stream Ethereum blocks using the Firehose client.
7+
use firehose_client::{Chain, FirehoseClient};
8+
use futures::StreamExt;
9+
use vee::EthBlock as Block;
10+
11+
#[tokio::main]
12+
async fn main() {
13+
// Testing this so far without proper benchmarking, the time taken to fetch the blocks
14+
// grows linearly with the number of TOTAL_BLOCKS requested, to around 20 minutes for 8192 blocks!
15+
const TOTAL_BLOCKS: u64 = 100;
16+
const START_BLOCK: u64 = 19581798;
17+
18+
let mut client = FirehoseClient::new(Chain::Ethereum);
19+
let mut stream = client
20+
.stream_blocks::<Block>(START_BLOCK, TOTAL_BLOCKS)
21+
.await
22+
.unwrap();
23+
24+
let mut blocks: Vec<Block> = Vec::with_capacity(TOTAL_BLOCKS as usize);
25+
26+
while let Some(block) = stream.next().await {
27+
blocks.push(block);
28+
}
29+
30+
// For now, just using this to signal that the test has completed
31+
assert_eq!(blocks.len(), TOTAL_BLOCKS as usize);
32+
33+
println!("stream_ethereum ran successfully");
34+
}

0 commit comments

Comments
 (0)