Skip to content

Commit 724ab64

Browse files
committed
impl gas price controller, rpc & tx filter
1 parent 36f40fb commit 724ab64

25 files changed

Lines changed: 1701 additions & 28 deletions

File tree

Cargo.lock

Lines changed: 34 additions & 0 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
@@ -85,6 +85,8 @@ members = [
8585
"crates/optimism/rpc/",
8686
"crates/optimism/storage",
8787
"crates/optimism/txpool/",
88+
"crates/xlayer/gasprice/",
89+
"crates/xlayer/txpool/",
8890
"crates/payload/basic/",
8991
"crates/payload/builder/",
9092
"crates/payload/builder-primitives/",
@@ -414,6 +416,8 @@ reth-optimism-primitives = { path = "crates/optimism/primitives", default-featur
414416
reth-optimism-rpc = { path = "crates/optimism/rpc" }
415417
reth-optimism-storage = { path = "crates/optimism/storage" }
416418
reth-optimism-txpool = { path = "crates/optimism/txpool" }
419+
reth-xlayer-gasprice = { path = "crates/xlayer/gasprice" }
420+
reth-xlayer-txpool = { path = "crates/xlayer/txpool" }
417421
reth-payload-builder = { path = "crates/payload/builder" }
418422
reth-payload-builder-primitives = { path = "crates/payload/builder-primitives" }
419423
reth-payload-primitives = { path = "crates/payload/primitives" }

crates/optimism/node/Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ reth-transaction-pool.workspace = true
2525
reth-network.workspace = true
2626
reth-evm.workspace = true
2727
reth-rpc-server-types.workspace = true
28-
reth-tasks = { workspace = true, optional = true }
28+
reth-tasks.workspace = true
2929
reth-trie-common.workspace = true
3030
reth-node-core.workspace = true
3131
reth-rpc-engine-api.workspace = true
3232
reth-engine-local = { workspace = true, features = ["op"] }
3333
reth-rpc-api.workspace = true
34+
reth-rpc-eth-api.workspace = true
3435

3536
# op-reth
3637
reth-optimism-payload-builder.workspace = true
@@ -43,6 +44,10 @@ reth-optimism-consensus = { workspace = true, features = ["std"] }
4344
reth-optimism-forks.workspace = true
4445
reth-optimism-primitives = { workspace = true, features = ["serde", "serde-bincode-compat", "reth-codec"] }
4546

47+
# xlayer
48+
reth-xlayer-gasprice.workspace = true
49+
reth-xlayer-txpool.workspace = true
50+
4651
# revm with required optimism features
4752
# Note: this must be kept to ensure all features are properly enabled/forwarded
4853
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg"] }
@@ -95,7 +100,6 @@ asm-keccak = [
95100
]
96101
js-tracer = ["reth-node-builder/js-tracer"]
97102
test-utils = [
98-
"reth-tasks",
99103
"reth-e2e-test-utils",
100104
"alloy-genesis",
101105
"serde_json",

crates/optimism/node/src/args.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use reth_optimism_txpool::supervisor::DEFAULT_SUPERVISOR_URL;
88
use url::Url;
99

1010
/// Parameters for rollup configuration
11-
#[derive(Debug, Clone, PartialEq, Eq, clap::Args)]
11+
#[derive(Debug, Clone, PartialEq, clap::Args)]
1212
#[command(next_help_heading = "Rollup")]
1313
pub struct RollupArgs {
1414
/// Endpoint for the sequencer mempool (can be both HTTP and WS)

crates/optimism/node/src/args_xlayer.rs

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1+
use alloy_primitives::U256;
12
use clap::Args;
23
use reth_optimism_payload_builder::BridgeInterceptConfig;
4+
use std::time::Duration;
35

46
/// X Layer specific configuration flags
5-
#[derive(Debug, Clone, Args, PartialEq, Eq, Default)]
7+
#[derive(Debug, Clone, Args, PartialEq, Default)]
68
#[command(next_help_heading = "X Layer")]
79
pub struct XLayerArgs {
810
/// Bridge transaction interception configuration
911
#[command(flatten)]
1012
pub intercept: XLayerInterceptArgs,
13+
14+
/// XLayer gas price configuration
15+
#[command(flatten)]
16+
pub gas_price: XLayerGasPriceArgs,
1117
// /// Another X Layer feature
1218
// #[command(flatten)]
1319
// pub another_feature: AnotherFeatureArgs,
@@ -16,8 +22,9 @@ pub struct XLayerArgs {
1622
impl XLayerArgs {
1723
/// Validate all X Layer configurations
1824
pub fn validate(&self) -> Result<(), String> {
19-
self.intercept.validate()
25+
self.intercept.validate()?;
2026
// self.another_feature.validate()?;
27+
Ok(())
2128
}
2229
}
2330

@@ -122,6 +129,134 @@ impl XLayerInterceptArgs {
122129
}
123130
}
124131

132+
/// XLayer gas price configuration
133+
#[derive(Debug, Clone, Args, PartialEq)]
134+
#[command(next_help_heading = "XLayer Gas Price")]
135+
pub struct XLayerGasPriceArgs {
136+
/// Gas price calculation type: "default", "follower", or "fixed"
137+
/// If not specified, XLayer gas price scheduler will not be initialized
138+
#[arg(long = "xlayer.gasprice.type")]
139+
pub price_type: Option<String>,
140+
141+
/// Gas price update period
142+
#[arg(long = "xlayer.gasprice.update-period", value_parser = parse_duration)]
143+
pub update_period: Option<Duration>,
144+
145+
/// Gas price calculation factor
146+
#[arg(long = "xlayer.gasprice.factor")]
147+
pub factor: Option<f64>,
148+
149+
/// Kafka URL for gas price updates
150+
#[arg(long = "xlayer.gasprice.kafka-url")]
151+
pub kafka_url: Option<String>,
152+
153+
/// Kafka topic for gas price updates
154+
#[arg(long = "xlayer.gasprice.topic")]
155+
pub topic: Option<String>,
156+
157+
/// Kafka consumer group ID
158+
#[arg(long = "xlayer.gasprice.group-id")]
159+
pub group_id: Option<String>,
160+
161+
/// Kafka username for authentication
162+
#[arg(long = "xlayer.gasprice.username")]
163+
pub username: Option<String>,
164+
165+
/// Kafka password for authentication
166+
#[arg(long = "xlayer.gasprice.password")]
167+
pub password: Option<String>,
168+
169+
/// Path to Kafka root CA certificate
170+
#[arg(long = "xlayer.gasprice.root-ca-path")]
171+
pub root_ca_path: Option<String>,
172+
173+
/// L1 coin ID for price tracking
174+
#[arg(long = "xlayer.gasprice.l1-coin-id")]
175+
pub l1_coin_id: Option<i32>,
176+
177+
/// L2 coin ID for price tracking
178+
#[arg(long = "xlayer.gasprice.l2-coin-id")]
179+
pub l2_coin_id: Option<i32>,
180+
181+
/// Default L1 coin price (fallback value)
182+
#[arg(long = "xlayer.gasprice.default-l1-coin-price")]
183+
pub default_l1_coin_price: Option<f64>,
184+
185+
/// Default L2 coin price (fallback value)
186+
#[arg(long = "xlayer.gasprice.default-l2-coin-price")]
187+
pub default_l2_coin_price: Option<f64>,
188+
189+
/// Fixed gas price in USDT (for "fixed" type)
190+
#[arg(long = "xlayer.gasprice.gas-price-usdt")]
191+
pub gas_price_usdt: Option<f64>,
192+
193+
/// Congestion threshold for dynamic gas price adjustment
194+
#[arg(long = "xlayer.gasprice.congestion-threshold")]
195+
pub congestion_threshold: Option<i32>,
196+
197+
/// Default gas price for XLayer (in wei)
198+
#[arg(long = "xlayer.gasprice.default")]
199+
pub default: Option<U256>,
200+
}
201+
202+
/// Helper function to parse duration from string
203+
fn parse_duration(s: &str) -> Result<Duration, String> {
204+
// Parse duration string like "10s", "5m", "1h"
205+
let s = s.trim();
206+
if s.is_empty() {
207+
return Err("empty duration string".to_string());
208+
}
209+
210+
let (num_str, unit) = if let Some(pos) = s.find(|c: char| !c.is_ascii_digit()) {
211+
(&s[..pos], &s[pos..])
212+
} else {
213+
return Err("duration must have a unit (s, m, h)".to_string());
214+
};
215+
216+
let num: u64 = num_str.parse().map_err(|e| format!("invalid number: {}", e))?;
217+
218+
match unit {
219+
"s" | "sec" | "second" | "seconds" => Ok(Duration::from_secs(num)),
220+
"m" | "min" | "minute" | "minutes" => Ok(Duration::from_secs(num * 60)),
221+
"h" | "hour" | "hours" => Ok(Duration::from_secs(num * 3600)),
222+
"ms" | "millisecond" | "milliseconds" => Ok(Duration::from_millis(num)),
223+
_ => Err(format!("unknown duration unit: {}", unit)),
224+
}
225+
}
226+
227+
impl Default for XLayerGasPriceArgs {
228+
fn default() -> Self {
229+
Self {
230+
price_type: None,
231+
update_period: None,
232+
factor: None,
233+
kafka_url: None,
234+
topic: None,
235+
group_id: None,
236+
username: None,
237+
password: None,
238+
root_ca_path: None,
239+
l1_coin_id: None,
240+
l2_coin_id: None,
241+
default_l1_coin_price: None,
242+
default_l2_coin_price: None,
243+
gas_price_usdt: None,
244+
congestion_threshold: None,
245+
default: None,
246+
}
247+
}
248+
}
249+
250+
impl reth_xlayer_gasprice::suggester::XLayerGasPriceArgsTrait for XLayerGasPriceArgs {
251+
fn price_type(&self) -> Option<&str> {
252+
self.price_type.as_deref()
253+
}
254+
255+
fn default(&self) -> Option<alloy_primitives::U256> {
256+
self.default
257+
}
258+
}
259+
125260
#[cfg(test)]
126261
mod tests {
127262
use super::*;
@@ -141,6 +276,7 @@ mod tests {
141276
assert_eq!(args.intercept.enabled, default_args.intercept.enabled);
142277
assert_eq!(args.intercept.bridge_contract, default_args.intercept.bridge_contract);
143278
assert_eq!(args.intercept.target_token, default_args.intercept.target_token);
279+
assert_eq!(args.gas_price, default_args.gas_price);
144280
assert!(args.validate().is_ok());
145281
}
146282

@@ -321,4 +457,27 @@ mod tests {
321457
assert!(config.enabled);
322458
assert!(!config.wildcard);
323459
}
460+
461+
#[test]
462+
fn test_parse_xlayer_gas_price_args() {
463+
let args = CommandParser::<XLayerGasPriceArgs>::parse_from([
464+
"reth",
465+
"--xlayer.gasprice.type",
466+
"follower",
467+
"--xlayer.gasprice.factor",
468+
"1.5",
469+
])
470+
.args;
471+
assert_eq!(args.price_type, Some("follower".to_string()));
472+
assert_eq!(args.factor, Some(1.5));
473+
}
474+
475+
#[test]
476+
fn test_parse_duration() {
477+
assert_eq!(parse_duration("10s").unwrap(), Duration::from_secs(10));
478+
assert_eq!(parse_duration("5m").unwrap(), Duration::from_secs(300));
479+
assert_eq!(parse_duration("1h").unwrap(), Duration::from_secs(3600));
480+
assert_eq!(parse_duration("500ms").unwrap(), Duration::from_millis(500));
481+
assert!(parse_duration("invalid").is_err());
482+
}
324483
}

crates/optimism/node/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub use reth_optimism_evm::*;
4444
pub use reth_optimism_storage::OpStorage;
4545

4646
mod args_xlayer;
47-
pub use args_xlayer::XLayerArgs;
47+
pub use args_xlayer::{XLayerArgs, XLayerGasPriceArgs};
4848

4949
use op_revm as _;
5050
use revm as _;

0 commit comments

Comments
 (0)