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

Commit 8d27cec

Browse files
authored
Merge pull request #133 from anton-rs/rf/use-l2-rpc-for-block-ref
chore: use l2 block rpc
2 parents 2de14d9 + b8e476c commit 8d27cec

File tree

6 files changed

+66
-24
lines changed

6 files changed

+66
-24
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/driver/src/driver.rs

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ where
8080
let pipeline = self.init_pipeline(cursor.clone()).await?;
8181
let exec = EngineController::new(
8282
self.cfg.l2_engine_url.clone(),
83+
self.cfg.l2_rpc_url.clone(),
8384
self.cfg.jwt_secret,
8485
cursor.origin(),
8586
cursor.l2_safe_head().block_info.into(),

crates/engine/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ repository.workspace = true
1313
rust-version.workspace = true
1414

1515
[dependencies]
16+
# Hilo
17+
hilo-providers-alloy.workspace = true
18+
1619
# Kona
1720
kona-driver.workspace = true
1821

crates/engine/src/client.rs

+32-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use alloy_eips::eip1898::BlockNumberOrTag;
44
use alloy_network::AnyNetwork;
55
use alloy_primitives::{Bytes, B256};
6-
use alloy_provider::RootProvider;
6+
use alloy_provider::{ReqwestProvider, RootProvider};
77
use alloy_rpc_client::RpcClient;
88
use alloy_rpc_types_engine::{
99
ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, JwtSecret, PayloadId, PayloadStatus,
@@ -17,12 +17,16 @@ use alloy_transport_http::{
1717
};
1818
use async_trait::async_trait;
1919
use http_body_util::Full;
20-
use op_alloy_protocol::L2BlockInfo;
20+
use op_alloy_genesis::RollupConfig;
21+
use op_alloy_protocol::{BatchValidationProvider, L2BlockInfo};
2122
use op_alloy_provider::ext::engine::OpEngineApi;
2223
use op_alloy_rpc_types_engine::{OpExecutionPayloadEnvelopeV3, OpPayloadAttributes};
24+
use std::sync::Arc;
2325
use tower::ServiceBuilder;
2426
use url::Url;
2527

28+
use hilo_providers_alloy::AlloyL2ChainProvider;
29+
2630
use crate::{Engine, EngineApiError};
2731

2832
/// A Hyper HTTP client with a JWT authentication layer.
@@ -31,24 +35,28 @@ type HyperAuthClient<B = Full<Bytes>> = HyperClient<B, AuthService<Client<HttpCo
3135
/// An external engine api client
3236
#[derive(Debug, Clone)]
3337
pub struct EngineClient {
34-
/// The inner provider
35-
provider: RootProvider<Http<HyperAuthClient>, AnyNetwork>,
38+
/// The L2 engine provider.
39+
engine: RootProvider<Http<HyperAuthClient>, AnyNetwork>,
40+
/// The L2 chain provider.
41+
rpc: AlloyL2ChainProvider,
3642
}
3743

3844
impl EngineClient {
3945
/// Creates a new [`EngineClient`] from the provided [Url] and [JwtSecret].
40-
pub fn new_http(url: Url, jwt: JwtSecret) -> Self {
46+
pub fn new_http(engine: Url, rpc: Url, cfg: Arc<RollupConfig>, jwt: JwtSecret) -> Self {
4147
let hyper_client = Client::builder(TokioExecutor::new()).build_http::<Full<Bytes>>();
4248

4349
let auth_layer = AuthLayer::new(jwt);
4450
let service = ServiceBuilder::new().layer(auth_layer).service(hyper_client);
4551

4652
let layer_transport = HyperClient::with_service(service);
47-
let http_hyper = Http::with_client(layer_transport, url);
53+
let http_hyper = Http::with_client(layer_transport, engine);
4854
let rpc_client = RpcClient::new(http_hyper, true);
49-
let provider = RootProvider::<_, AnyNetwork>::new(rpc_client);
55+
let engine = RootProvider::<_, AnyNetwork>::new(rpc_client);
5056

51-
Self { provider }
57+
let rpc = ReqwestProvider::new_http(rpc);
58+
let rpc = AlloyL2ChainProvider::new(rpc, cfg);
59+
Self { engine, rpc }
5260
}
5361
}
5462

@@ -60,15 +68,15 @@ impl Engine for EngineClient {
6068
&self,
6169
payload_id: PayloadId,
6270
) -> Result<OpExecutionPayloadEnvelopeV3, Self::Error> {
63-
self.provider.get_payload_v3(payload_id).await.map_err(|_| EngineApiError::PayloadError)
71+
self.engine.get_payload_v3(payload_id).await.map_err(|_| EngineApiError::PayloadError)
6472
}
6573

6674
async fn forkchoice_update(
6775
&self,
6876
state: ForkchoiceState,
6977
attr: Option<OpPayloadAttributes>,
7078
) -> Result<ForkchoiceUpdated, Self::Error> {
71-
self.provider
79+
self.engine
7280
.fork_choice_updated_v2(state, attr)
7381
.await
7482
.map_err(|_| EngineApiError::PayloadError)
@@ -79,24 +87,31 @@ impl Engine for EngineClient {
7987
payload: ExecutionPayloadV3,
8088
parent_beacon_block_root: B256,
8189
) -> Result<PayloadStatus, Self::Error> {
82-
self.provider
90+
self.engine
8391
.new_payload_v3(payload, parent_beacon_block_root)
8492
.await
8593
.map_err(|_| EngineApiError::PayloadError)
8694
}
8795

88-
async fn l2_block_ref_by_label(&self, _: BlockNumberOrTag) -> Result<L2BlockInfo, Self::Error> {
89-
// Convert the payload into an L2 block info.
90-
// go impl uses an L2 client and fetches block by number, converting block to payload and
91-
// payload to L2 block info.
92-
todo!("implement l2_block_ref_by_label for the engine client")
96+
async fn l2_block_ref_by_label(
97+
&mut self,
98+
numtag: BlockNumberOrTag,
99+
) -> Result<L2BlockInfo, Self::Error> {
100+
let number = match numtag {
101+
BlockNumberOrTag::Number(n) => n,
102+
BlockNumberOrTag::Latest => {
103+
self.rpc.latest_block_number().await.map_err(|_| EngineApiError::PayloadError)?
104+
}
105+
_ => return Err(EngineApiError::PayloadError),
106+
};
107+
self.rpc.l2_block_info_by_number(number).await.map_err(|_| EngineApiError::PayloadError)
93108
}
94109
}
95110

96111
impl std::ops::Deref for EngineClient {
97112
type Target = RootProvider<Http<HyperAuthClient>, AnyNetwork>;
98113

99114
fn deref(&self) -> &Self::Target {
100-
&self.provider
115+
&self.engine
101116
}
102117
}

crates/engine/src/controller.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use kona_driver::Executor;
1010
use op_alloy_genesis::RollupConfig;
1111
use op_alloy_protocol::BlockInfo;
1212
use op_alloy_rpc_types_engine::OpPayloadAttributes;
13-
use std::time::Duration;
13+
use std::{sync::Arc, time::Duration};
1414
use tokio::time::sleep;
1515
use url::Url;
1616

@@ -56,12 +56,18 @@ impl EngineController {
5656
/// Creates a new engine controller.
5757
pub fn new(
5858
l2_engine_url: Url,
59+
l2_rpc_url: Url,
5960
jwt_secret: JwtSecret,
6061
finalized_head: BlockInfo,
6162
finalized_epoch: Epoch,
6263
config: &RollupConfig,
6364
) -> Self {
64-
let client = EngineClient::new_http(l2_engine_url.clone(), jwt_secret);
65+
let client = EngineClient::new_http(
66+
l2_engine_url.clone(),
67+
l2_rpc_url,
68+
Arc::new(config.clone()),
69+
jwt_secret,
70+
);
6571
Self {
6672
blocktime: config.block_time,
6773
unsafe_head: finalized_head,
@@ -93,15 +99,31 @@ impl Executor for EngineController {
9399
/// Waits for the engine to be ready.
94100
async fn wait_until_ready(&mut self) {
95101
let forkchoice = self.create_forkchoice_state();
96-
// Loop until the forkchoice is updated
97-
while !self.client.forkchoice_update(forkchoice, None).await.is_ok_and(|u| u.is_valid()) {
102+
while self.client.forkchoice_update(forkchoice, None).await.is_err() {
98103
sleep(Duration::from_secs(1)).await;
99104
}
100105
}
101106

102107
/// Updates the safe head.
103-
fn update_safe_head(&mut self, _: Sealed<Header>) {
104-
todo!()
108+
fn update_safe_head(&mut self, header: Sealed<Header>) {
109+
if self.safe_head.number < header.number {
110+
self.safe_head = BlockInfo {
111+
number: header.number,
112+
hash: header.hash_slow(),
113+
timestamp: header.timestamp,
114+
parent_hash: header.parent_hash,
115+
};
116+
self.safe_epoch = self.safe_head.into();
117+
}
118+
119+
if header.number > self.unsafe_head.number {
120+
self.unsafe_head = BlockInfo {
121+
number: header.number,
122+
hash: header.hash_slow(),
123+
timestamp: header.timestamp,
124+
parent_hash: header.parent_hash,
125+
};
126+
}
105127
}
106128

107129
/// Execute the given payload attributes.

crates/engine/src/traits.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub trait Engine {
3838

3939
/// Returns the [L2BlockInfo] for the given label.
4040
async fn l2_block_ref_by_label(
41-
&self,
41+
&mut self,
4242
label: BlockNumberOrTag,
4343
) -> Result<L2BlockInfo, Self::Error>;
4444
}

0 commit comments

Comments
 (0)