Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
5790a5c
bump up kona
Nov 15, 2025
1b77763
bump optimism
Nov 16, 2025
6bcd7ca
bump optimism-package
Nov 16, 2025
e6705df
change directory
Nov 20, 2025
b9eec29
change directory
Nov 20, 2025
32e1baa
start server
Nov 21, 2025
315ef13
create preimage sequentially
Nov 21, 2025
6260bbd
configure
Nov 22, 2025
53356d5
fix write and load
Nov 22, 2025
fa7566d
collect parallel
Nov 22, 2025
3797455
add test
Nov 22, 2025
edc914d
add test
Nov 23, 2025
1422c66
fix clippy
Nov 23, 2025
826c641
add test
Nov 23, 2025
15aebb6
fix conflict
Dec 3, 2025
7b9ea58
add l1 finality cache
Dec 4, 2025
5561b45
fix
Dec 4, 2025
83c8750
fix logic
Dec 4, 2025
816b680
fix logic
Dec 5, 2025
c1db3dc
fix log
Dec 6, 2025
aa82b66
add test
Dec 6, 2025
44664ae
add inspector
Dec 6, 2025
aaf86cb
add inspection
Dec 6, 2025
806fb88
tweak
Dec 13, 2025
080c36d
fix lint
Dec 13, 2025
7330c2e
check order
Dec 14, 2025
39303a1
change cache type from vec to hash
Dec 14, 2025
171f9f5
sort save order
Dec 14, 2025
3e8ce62
add test
Dec 14, 2025
62c4f5c
Change log
Dec 14, 2025
f7f3c3e
check dir existence
Dec 14, 2025
b2bc1f3
refactor
Dec 14, 2025
14e15b5
add comment and test
Dec 14, 2025
84c44c2
tweak comment
Dec 14, 2025
2a3070b
add test for collector
Dec 14, 2025
9809898
fix format
Dec 14, 2025
c9d920f
add unit test for web
Dec 14, 2025
f027f5a
simplify logic
Dec 14, 2025
5b9d098
add test
Dec 14, 2025
84fa27e
use hashset instead of hashmap
Dec 14, 2025
fe63460
change progress on error
Dec 16, 2025
9948bdd
fix conflict
Dec 21, 2025
61b9913
fix conflict
Dec 25, 2025
d415e4d
tweak
Dec 25, 2025
bd07d09
use modified instead of created
Jan 8, 2026
27a49f5
use write rename pattern for file
Jan 8, 2026
2541074
reuse http client / add timeout
Jan 8, 2026
7816a37
fix clippy
Jan 9, 2026
2396523
fix ci
Jan 9, 2026
4e2afcd
rename retry_count -> attempts_count / add the comment
Jan 12, 2026
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Install components
run: |
rustup component add rustfmt clippy
cargo install cargo-machete --version 0.8.0
cargo install cargo-machete --version 0.8.0 --locked
- name: Check format
run: cargo fmt --all -- --check
- name: Check clippy
Expand Down Expand Up @@ -51,7 +51,7 @@ jobs:
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: 'v1.0.0'
version: 'v1.0.0'
- name: Install kurtosis
run: |
sudo apt-get install jq
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ target/
/.data
*.bin
*.json
chain
chain
.preimage
.finalized_l1
10 changes: 5 additions & 5 deletions Cargo.lock

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

18 changes: 11 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ wait:

.PHONY: server-up
server-up:
mkdir -p .preimage && true
mkdir -p .finalized_l1 && true
@L2_ROLLUP_PORT=$$(jq -r '.l2RollupPort' hostPort.json);\
L2_GETH_PORT=$$(jq -r '.l2GethPort' hostPort.json);\
L1_GETH_PORT=$$(jq -r '.l1GethPort' hostPort.json);\
Expand All @@ -47,19 +49,21 @@ server-up:
--l2=http://localhost:$$L2_GETH_PORT \
--l1=http://localhost:$$L1_GETH_PORT \
--beacon=http://localhost:$$L1_BEACON_PORT \
--l1-chain-config=$$L1_CHAIN_CONFIG
--l1-chain-config=$$L1_CHAIN_CONFIG \
--initial-claimed-l2=103 \
--ttl=1800 \
--max-preimage-distance=100 \
--purger-interval-seconds=100

.PHONY: test
test:
@L2_ROLLUP_PORT=$$(jq -r '.l2RollupPort' hostPort.json);\
L2_GETH_PORT=$$(jq -r '.l2GethPort' hostPort.json);\
L2_ROLLUP_PORT=$$L2_ROLLUP_PORT L2_GETH_PORT=$$L2_GETH_PORT cargo test --manifest-path=./server/Cargo.toml
L2_ROLLUP_ADDR=http://localhost:$$L2_ROLLUP_PORT L2_GETH_ADDR=http://localhost:$$L2_GETH_PORT cargo test --manifest-path=./server/Cargo.toml

.PHONY: test-ignored
test-ignored:
@L2_ROLLUP_PORT=$$(jq -r '.l2RollupPort' hostPort.json);\
L2_GETH_PORT=$$(jq -r '.l2GethPort' hostPort.json);\
REQUEST_PATH=$(CURDIR)/tool/body.json L2_ROLLUP_PORT=$$L2_ROLLUP_PORT L2_GETH_PORT=$$L2_GETH_PORT cargo test --manifest-path=./server/Cargo.toml -- --ignored
.PHONY: inspect
inspect:
cargo test --manifest-path=./server/Cargo.toml -- --ignored

.PHONY: devnet-down
devnet-down:
Expand Down
4 changes: 2 additions & 2 deletions server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "optimism-preimage-maker"
version = "0.1.3"
version = "0.2.0"
edition = "2021"

[dependencies]
Expand All @@ -15,6 +15,7 @@ tracing = { version = "0.1", default-features = false }
tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }
axum = "0.7.9"
tokio = { version="1.41", features=["full"] }
base64 = "0.22.1"

# Kona
kona-client = { workspace = true }
Expand All @@ -29,7 +30,6 @@ alloy-primitives = { workspace = true, features = ["map", "serde"] }

# optimism derivation
optimism-derivation = { git = "https://github.com/datachainlab/optimism-elc", rev = "v0.1.10", default-features = false }
base64 = "0.22.1"

[dev-dependencies]
prost = "0.11.9"
Expand Down
126 changes: 126 additions & 0 deletions server/src/client/beacon_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use alloy_primitives::B256;
use axum::async_trait;
use reqwest::Response;

#[derive(Debug, Clone, serde::Deserialize)]
pub struct LightClientFinalityUpdateResponse {
pub data: LightClientFinalityUpdate,
}

#[derive(Debug, Clone, serde::Deserialize)]
pub struct LightClientFinalityUpdate {
pub finalized_header: LightClientHeader,
}

#[derive(Debug, Clone, serde::Deserialize)]
pub struct LightClientHeader {
pub execution: ExecutionPayloadHeader,
}

#[derive(Debug, Clone, serde::Deserialize)]
pub struct ExecutionPayloadHeader {
pub block_hash: B256,
#[serde(deserialize_with = "deserialize_u64_from_str")]
pub block_number: u64,
}

// serde helper to allow numbers encoded as strings
fn deserialize_u64_from_str<'de, D>(deserializer: D) -> Result<u64, D::Error>
where
D: serde::Deserializer<'de>,
{
struct U64StringOrNumber;

impl<'de> serde::de::Visitor<'de> for U64StringOrNumber {
type Value = u64;

fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "a u64 as number or string")
}

fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
Ok(v)
}

fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if v < 0 {
return Err(E::custom("negative value for u64"));
}
Ok(v as u64)
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
v.parse::<u64>()
.map_err(|e| E::custom(format!("invalid u64 string: {e}")))
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.visit_str(&v)
}
}

deserializer.deserialize_any(U64StringOrNumber)
}

#[async_trait]
pub trait BeaconClient: Send + Sync + 'static {
async fn get_raw_light_client_finality_update(&self) -> anyhow::Result<String>;
}

#[derive(Debug, Clone)]
pub struct HttpBeaconClient {
beacon_addr: String,
client: reqwest::Client,
}

impl HttpBeaconClient {
pub fn new(beacon_addr: String, timeout: std::time::Duration) -> Self {
Self {
beacon_addr,
client: reqwest::Client::builder()
.timeout(timeout)
.build()
.expect("failed to build reqwest client"),
}
}

async fn check_response(&self, response: Response) -> anyhow::Result<Response> {
if response.status().is_success() {
Ok(response)
} else {
Err(anyhow::anyhow!(
"Request failed with status: {} body={:?}",
response.status(),
response.text().await
))
}
}
}

#[async_trait]
impl BeaconClient for HttpBeaconClient {
async fn get_raw_light_client_finality_update(&self) -> anyhow::Result<String> {
let response = self
.client
.get(format!(
"{}/eth/v1/beacon/light_client/finality_update",
self.beacon_addr
))
.send()
.await?;
let response = self.check_response(response).await?;
response
.text()
.await
.map_err(|e| anyhow::anyhow!("Failed to get finality update: {e:?}"))
}
}
Loading