Skip to content

Commit be4d330

Browse files
author
Solar Mithril
committed
Add txpool test
Fix DA config, set it via miner Extend tests
1 parent f9ec955 commit be4d330

File tree

10 files changed

+156
-57
lines changed

10 files changed

+156
-57
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/op-rbuilder/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ tikv-jemallocator = { version = "0.6", optional = true }
108108
vergen = { workspace = true, features = ["build", "cargo", "emit_and_set"] }
109109
vergen-git2.workspace = true
110110

111+
[dev-dependencies]
112+
alloy-provider = {workspace = true, default-features = true, features = ["txpool-api"]}
113+
111114
[features]
112115
default = ["jemalloc"]
113116

crates/op-rbuilder/src/args/op.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,6 @@ pub struct OpRbuilderArgs {
5858
env = "PLAYGROUND_DIR",
5959
)]
6060
pub playground: Option<PathBuf>,
61-
#[arg(long = "builder.max-da-tx-size", default_value = "0")]
62-
pub max_da_tx_size: u64,
63-
#[arg(long = "builder.max-da-block-size", default_value = "0")]
64-
pub max_da_block_size: u64,
6561
}
6662

6763
fn expand_path(s: &str) -> Result<PathBuf, String> {

crates/op-rbuilder/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,15 @@ fn main() {
5151
.run(|builder, builder_args| async move {
5252
let rollup_args = builder_args.rollup_args;
5353

54-
let da_config =
55-
OpDAConfig::new(builder_args.max_da_tx_size, builder_args.max_da_block_size);
54+
let da_config = OpDAConfig::default();
5655
let op_node = OpNode::new(rollup_args.clone());
5756
let handle = builder
5857
.with_types::<OpNode>()
5958
.with_components(op_node.components().payload(CustomOpPayloadBuilder::new(
6059
builder_args.builder_signer,
6160
std::time::Duration::from_secs(builder_args.extra_block_deadline_secs),
6261
builder_args.enable_revert_protection,
63-
da_config,
62+
da_config.clone(),
6463
builder_args.flashblocks_ws_url,
6564
builder_args.chain_block_time,
6665
builder_args.flashblock_block_time,
@@ -69,6 +68,7 @@ fn main() {
6968
OpAddOnsBuilder::default()
7069
.with_sequencer(rollup_args.sequencer.clone())
7170
.with_enable_tx_conditional(rollup_args.enable_tx_conditional)
71+
.with_da_config(da_config)
7272
.build(),
7373
)
7474
.on_node_started(move |ctx| {

crates/op-rbuilder/src/tests/framework/blocks.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,4 +372,12 @@ impl BlockGenerated {
372372
pub fn includes(&self, tx_hash: B256) -> bool {
373373
self.block.transactions.hashes().any(|hash| hash == tx_hash)
374374
}
375+
376+
pub fn includes_vec(&self, tx_hashes: Vec<B256>) -> bool {
377+
tx_hashes.iter().all(|hash| self.includes(*hash))
378+
}
379+
380+
pub fn not_includes_vec(&self, tx_hashes: Vec<B256>) -> bool {
381+
tx_hashes.iter().all(|hash| self.not_includes(*hash))
382+
}
375383
}

crates/op-rbuilder/src/tests/framework/harness.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ pub struct TestHarnessBuilder {
2525
flashblocks_ws_url: Option<String>,
2626
chain_block_time: Option<u64>,
2727
flashbots_block_time: Option<u64>,
28-
max_da_tx_size: Option<u64>,
29-
max_da_block_size: Option<u64>,
28+
namespaces: Option<String>,
29+
extra_params: Option<String>,
3030
}
3131

3232
impl TestHarnessBuilder {
@@ -37,8 +37,8 @@ impl TestHarnessBuilder {
3737
flashblocks_ws_url: None,
3838
chain_block_time: None,
3939
flashbots_block_time: None,
40-
max_da_tx_size: None,
41-
max_da_block_size: None,
40+
namespaces: None,
41+
extra_params: None,
4242
}
4343
}
4444

@@ -62,13 +62,13 @@ impl TestHarnessBuilder {
6262
self
6363
}
6464

65-
pub fn with_max_da_tx_size(mut self, max_da_tx_size: u64) -> Self {
66-
self.max_da_tx_size = Some(max_da_tx_size);
65+
pub fn with_namespaces(mut self, namespaces: &str) -> Self {
66+
self.namespaces = Some(namespaces.to_string());
6767
self
6868
}
6969

70-
pub fn with_max_da_block_size(mut self, max_da_block_size: u64) -> Self {
71-
self.max_da_block_size = Some(max_da_block_size);
70+
pub fn with_extra_params(mut self, extra_params: &str) -> Self {
71+
self.extra_params = Some(extra_params.to_string());
7272
self
7373
}
7474

@@ -83,7 +83,7 @@ impl TestHarnessBuilder {
8383
std::fs::write(&genesis_path, genesis)?;
8484

8585
// create the builder
86-
let builder_data_dir = std::env::temp_dir().join(Uuid::new_v4().to_string());
86+
let builder_data_dir: PathBuf = std::env::temp_dir().join(Uuid::new_v4().to_string());
8787
let builder_auth_rpc_port = get_available_port();
8888
let builder_http_port = get_available_port();
8989
let mut op_rbuilder_config = OpRbuilderConfig::new()
@@ -94,8 +94,8 @@ impl TestHarnessBuilder {
9494
.http_port(builder_http_port)
9595
.with_builder_private_key(BUILDER_PRIVATE_KEY)
9696
.with_revert_protection(self.use_revert_protection)
97-
.with_max_da_block_size(self.max_da_block_size)
98-
.with_max_da_tx_size(self.max_da_tx_size);
97+
.with_namespaces(self.namespaces)
98+
.with_extra_params(self.extra_params);
9999
if let Some(flashblocks_ws_url) = self.flashblocks_ws_url {
100100
op_rbuilder_config = op_rbuilder_config.with_flashblocks_ws_url(&flashblocks_ws_url);
101101
}

crates/op-rbuilder/src/tests/framework/op.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ pub struct OpRbuilderConfig {
2727
chain_block_time: Option<u64>,
2828
flashbots_block_time: Option<u64>,
2929
with_revert_protection: Option<bool>,
30-
max_da_tx_size: Option<u64>,
31-
max_da_block_size: Option<u64>,
30+
namespaces: Option<String>,
31+
extra_params: Option<String>,
3232
}
3333

3434
impl OpRbuilderConfig {
@@ -86,13 +86,13 @@ impl OpRbuilderConfig {
8686
self
8787
}
8888

89-
pub fn with_max_da_tx_size(mut self, size: Option<u64>) -> Self {
90-
self.max_da_tx_size = size;
89+
pub fn with_namespaces(mut self, namespaces: Option<String>) -> Self {
90+
self.namespaces = namespaces;
9191
self
9292
}
9393

94-
pub fn with_max_da_block_size(mut self, size: Option<u64>) -> Self {
95-
self.max_da_block_size = size;
94+
pub fn with_extra_params(mut self, extra_params: Option<String>) -> Self {
95+
self.extra_params = extra_params;
9696
self
9797
}
9898
}
@@ -167,14 +167,12 @@ impl Service for OpRbuilderConfig {
167167
.arg(flashbots_block_time.to_string());
168168
}
169169

170-
if let Some(max_da_tx_size) = self.max_da_tx_size {
171-
cmd.arg("--builder.max-da-tx-size")
172-
.arg(max_da_tx_size.to_string());
170+
if let Some(namespaces) = &self.namespaces {
171+
cmd.arg("--http.api").arg(namespaces);
173172
}
174173

175-
if let Some(max_da_block_size) = self.max_da_block_size {
176-
cmd.arg("--builder.max-da-block-size")
177-
.arg(max_da_block_size.to_string());
174+
if let Some(extra_params) = &self.extra_params {
175+
cmd.args(extra_params.split_ascii_whitespace());
178176
}
179177

180178
cmd
@@ -232,7 +230,7 @@ impl OpRethConfig {
232230

233231
impl Service for OpRethConfig {
234232
fn command(&self) -> Command {
235-
let bin_path = PathBuf::from("op-reth");
233+
let bin_path = PathBuf::from("/home/msozin/neth/op-rbuilder/op-reth");
236234

237235
let mut cmd = Command::new(bin_path);
238236
let jwt_path = get_or_create_jwt_path(self.jwt_secret_path.as_ref());
Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
use crate::tests::framework::TestHarnessBuilder;
2+
use alloy_provider::Provider;
23

34
/// This test ensures that the transaction size limit is respected.
45
/// We will set limit to 1 byte and see that the builder will not include any transactions.
56
#[tokio::test]
67
async fn data_availability_tx_size_limit() -> eyre::Result<()> {
78
let harness = TestHarnessBuilder::new("data_availability_tx_size_limit")
8-
.with_max_da_tx_size(1)
9+
.with_namespaces("admin,eth,miner")
910
.build()
1011
.await?;
1112

1213
let mut generator = harness.block_generator().await?;
1314

14-
// generate regualr tx
15-
let invalid_tx = harness.send_valid_transaction().await?;
15+
// Set (max_tx_da_size, max_block_da_size), with this case block won't fit any transaction
16+
let call = harness
17+
.provider()?
18+
.raw_request::<(i32, i32), bool>("miner_setMaxDASize".into(), (1, 0))
19+
.await?;
20+
assert!(call, "miner_setMaxDASize should be executed successfully");
1621

22+
let unfit_tx = harness
23+
.create_transaction()
24+
.with_max_priority_fee_per_gas(50)
25+
.send()
26+
.await?;
1727
let block = generator.generate_block().await?;
18-
1928
// tx should not be included because we set the tx_size_limit to 1
2029
assert!(
21-
block.not_includes(*invalid_tx.tx_hash()),
30+
block.not_includes(*unfit_tx.tx_hash()),
2231
"transaction should not be included in the block"
2332
);
2433

@@ -30,20 +39,24 @@ async fn data_availability_tx_size_limit() -> eyre::Result<()> {
3039
#[tokio::test]
3140
async fn data_availability_block_size_limit() -> eyre::Result<()> {
3241
let harness = TestHarnessBuilder::new("data_availability_block_size_limit")
33-
.with_max_da_block_size(1)
42+
.with_namespaces("admin,eth,miner")
3443
.build()
3544
.await?;
3645

3746
let mut generator = harness.block_generator().await?;
3847

39-
// generate regualr tx
40-
let invalid_tx = harness.send_valid_transaction().await?;
48+
// Set block da size to be small, so it won't include tx
49+
let call = harness
50+
.provider()?
51+
.raw_request::<(i32, i32), bool>("miner_setMaxDASize".into(), (0, 1))
52+
.await?;
53+
assert!(call, "miner_setMaxDASize should be executed successfully");
4154

55+
let unfit_tx = harness.send_valid_transaction().await?;
4256
let block = generator.generate_block().await?;
43-
4457
// tx should not be included because we set the tx_size_limit to 1
4558
assert!(
46-
block.not_includes(*invalid_tx.tx_hash()),
59+
block.not_includes(*unfit_tx.tx_hash()),
4760
"transaction should not be included in the block"
4861
);
4962

@@ -56,29 +69,38 @@ async fn data_availability_block_size_limit() -> eyre::Result<()> {
5669
/// We should not forget about builder transaction so we will spawn only 2 regular txs.
5770
#[tokio::test]
5871
async fn data_availability_block_fill() -> eyre::Result<()> {
59-
let harness = TestHarnessBuilder::new("data_availability_block_fill")
60-
.with_max_da_block_size(100000000 * 3)
72+
let harness = TestHarnessBuilder::new("data_availability_tx_size_limit")
73+
.with_namespaces("admin,eth,miner")
6174
.build()
6275
.await?;
6376

6477
let mut generator = harness.block_generator().await?;
6578

66-
// generate regualr tx
67-
let valid_tx_1 = harness.send_valid_transaction().await?;
68-
let valid_tx_2 = harness.send_valid_transaction().await?;
69-
let unfit_tx_3 = harness.send_valid_transaction().await?;
79+
// Set block big enough so it could fit 3 transactions without tx size limit
80+
let call = harness
81+
.provider()?
82+
.raw_request::<(i32, i32), bool>("miner_setMaxDASize".into(), (0, 100000000 * 3))
83+
.await?;
84+
assert!(call, "miner_setMaxDASize should be executed successfully");
85+
86+
// We already have 2 so we will spawn one more to check that it won't be included (it won't fit
87+
// because of builder tx)
88+
let fit_tx_1 = harness
89+
.create_transaction()
90+
.with_max_priority_fee_per_gas(50)
91+
.send()
92+
.await?;
93+
let fit_tx_2 = harness
94+
.create_transaction()
95+
.with_max_priority_fee_per_gas(50)
96+
.send()
97+
.await?;
98+
let unfit_tx_3 = harness.create_transaction().send().await?;
7099

71100
let block = generator.generate_block().await?;
72-
73-
// tx should not be included because we set the tx_size_limit to 1
74-
assert!(
75-
block.includes(*valid_tx_1.tx_hash()),
76-
"tx should be in block"
77-
);
78-
assert!(
79-
block.includes(*valid_tx_2.tx_hash()),
80-
"tx should be in block"
81-
);
101+
// Now the first 2 txs will fit into the block
102+
assert!(block.includes(*fit_tx_1.tx_hash()), "tx should be in block");
103+
assert!(block.includes(*fit_tx_2.tx_hash()), "tx should be in block");
82104
assert!(
83105
block.not_includes(*unfit_tx_3.tx_hash()),
84106
"unfit tx should not be in block"
@@ -87,5 +109,6 @@ async fn data_availability_block_fill() -> eyre::Result<()> {
87109
harness.latest_block().await.transactions.len() == 4,
88110
"builder + deposit + 2 valid txs should be in the block"
89111
);
112+
90113
Ok(())
91114
}

crates/op-rbuilder/src/tests/vanilla/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ mod data_availability;
44
mod ordering;
55
mod revert;
66
mod smoke;
7+
mod txpool;
78

89
use super::*;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use crate::tests::{framework::TestHarnessBuilder, ONE_ETH};
2+
use alloy_provider::ext::TxPoolApi;
3+
4+
/// This test ensures that pending pool custom limit is respected and priority tx would be included even when pool if full.
5+
#[tokio::test]
6+
async fn pending_pool_limit() -> eyre::Result<()> {
7+
let harness = TestHarnessBuilder::new("data_availability_tx_size_limit")
8+
.with_namespaces("txpool,eth,debug,admin")
9+
.with_extra_params("--txpool.pending-max-count 50")
10+
.build()
11+
.await?;
12+
13+
let mut generator = harness.block_generator().await?;
14+
15+
// Send 50 txs from different addrs
16+
let accounts = generator.create_funded_accounts(2, ONE_ETH).await?;
17+
let acc_no_priority = accounts.first().unwrap();
18+
let acc_with_priority = accounts.last().unwrap();
19+
20+
for _ in 0..50 {
21+
let _ = harness
22+
.create_transaction()
23+
.with_signer(*acc_no_priority)
24+
.send()
25+
.await?;
26+
}
27+
28+
let pool = harness
29+
.provider()
30+
.expect("provider not available")
31+
.txpool_status()
32+
.await?;
33+
assert_eq!(
34+
pool.pending, 50,
35+
"Pending pool must contain at max 50 txs {:?}",
36+
pool
37+
);
38+
39+
// Send 10 txs that should be included in the block
40+
let mut txs = Vec::new();
41+
for _ in 0..10 {
42+
let tx = harness
43+
.create_transaction()
44+
.with_signer(*acc_with_priority)
45+
.with_max_priority_fee_per_gas(10)
46+
.send()
47+
.await?;
48+
txs.push(*tx.tx_hash());
49+
}
50+
51+
let pool = harness
52+
.provider()
53+
.expect("provider not available")
54+
.txpool_status()
55+
.await?;
56+
assert_eq!(
57+
pool.pending, 50,
58+
"Pending pool must contain at max 50 txs {:?}",
59+
pool
60+
);
61+
62+
// After we try building block our reverting tx would be removed and other tx will move to queue pool
63+
let block = generator.generate_block().await?;
64+
65+
// Ensure that 10 extra txs got included
66+
assert!(block.includes_vec(txs));
67+
68+
Ok(())
69+
}

0 commit comments

Comments
 (0)