Skip to content

Commit 51beb48

Browse files
feat: skip empty blocks (#287)
* feat: skip empty blocks * fix: add CLI arg to enable empty blocks * fix: fix docker test --------- Co-authored-by: Jonas Theis <[email protected]>
1 parent 49bd97c commit 51beb48

File tree

7 files changed

+110
-4
lines changed

7 files changed

+110
-4
lines changed

crates/engine/src/driver.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ pub struct EngineDriver<EC, CS, P> {
5353
metrics: EngineDriverMetrics,
5454
/// The waker to notify when the engine driver should be polled.
5555
waker: AtomicWaker,
56+
/// Whether to allow empty blocks.
57+
allow_empty_blocks: bool,
5658
}
5759

5860
impl<EC, CS, P> EngineDriver<EC, CS, P>
@@ -69,6 +71,7 @@ where
6971
fcs: ForkchoiceState,
7072
sync_at_start_up: bool,
7173
block_building_duration: Duration,
74+
allow_empty_blocks: bool,
7275
) -> Self {
7376
Self {
7477
client,
@@ -85,6 +88,7 @@ where
8588
engine_future: None,
8689
metrics: EngineDriverMetrics::default(),
8790
waker: AtomicWaker::new(),
91+
allow_empty_blocks,
8892
}
8993
}
9094

@@ -312,6 +316,12 @@ where
312316

313317
match result {
314318
Ok(block) => {
319+
// Skip block if no transactions are present in block.
320+
if !self.allow_empty_blocks && block.body.transactions.is_empty() {
321+
tracing::trace!(target: "scroll::engine", "no transactions in block");
322+
return None;
323+
}
324+
315325
// Update the unsafe block info and return the block
316326
let block_info = BlockInfo::new(block.number, block.hash_slow());
317327
tracing::trace!(target: "scroll::engine", ?block_info, "updating unsafe block info from new payload");
@@ -531,8 +541,15 @@ mod tests {
531541
ForkchoiceState::from_block_info(BlockInfo { number: 0, hash: Default::default() });
532542
let duration = Duration::from_secs(2);
533543

534-
let mut driver =
535-
EngineDriver::new(client, chain_spec, None::<ScrollRootProvider>, fcs, false, duration);
544+
let mut driver = EngineDriver::new(
545+
client,
546+
chain_spec,
547+
None::<ScrollRootProvider>,
548+
fcs,
549+
false,
550+
duration,
551+
true,
552+
);
536553

537554
// Initially, it should be false
538555
assert!(!driver.is_payload_building_in_progress());
@@ -559,6 +576,7 @@ mod tests {
559576
fcs,
560577
false,
561578
duration,
579+
true,
562580
);
563581

564582
// Initially, it should be false

crates/node/src/args.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ impl ScrollRollupNodeConfig {
261261
fcs,
262262
self.engine_driver_args.sync_at_startup && !self.test && !chain_spec.is_dev_chain(),
263263
Duration::from_millis(self.sequencer_args.payload_building_duration),
264+
self.sequencer_args.allow_empty_blocks,
264265
);
265266

266267
// Create the consensus.
@@ -567,6 +568,14 @@ pub struct SequencerArgs {
567568
help = "L1 message inclusion mode. Use 'finalized' for finalized messages only, or 'depth:{number}' for block depth confirmation (e.g. 'depth:10')"
568569
)]
569570
pub l1_message_inclusion_mode: L1MessageInclusionMode,
571+
/// Enable empty blocks.
572+
#[arg(
573+
long = "sequencer.allow-empty-blocks",
574+
id = "sequencer_allow_empty_blocks",
575+
value_name = "SEQUENCER_ALLOW_EMPTY_BLOCKS",
576+
default_value_t = false
577+
)]
578+
pub allow_empty_blocks: bool,
570579
}
571580

572581
/// The arguments for the signer.

crates/node/src/test_utils.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,11 @@ pub fn default_test_scroll_rollup_node_config() -> ScrollRollupNodeConfig {
149149
optimistic_sync_trigger: 100,
150150
chain_buffer_size: 100,
151151
},
152-
sequencer_args: SequencerArgs { payload_building_duration: 1000, ..Default::default() },
152+
sequencer_args: SequencerArgs {
153+
payload_building_duration: 1000,
154+
allow_empty_blocks: true,
155+
..Default::default()
156+
},
153157
beacon_provider_args: BeaconProviderArgs {
154158
blob_source: BlobSource::Mock,
155159
..Default::default()
@@ -185,6 +189,7 @@ pub fn default_sequencer_test_scroll_rollup_node_config() -> ScrollRollupNodeCon
185189
payload_building_duration: 40,
186190
fee_recipient: Default::default(),
187191
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
192+
allow_empty_blocks: true,
188193
},
189194
beacon_provider_args: BeaconProviderArgs {
190195
blob_source: BlobSource::Mock,

crates/node/tests/e2e.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ async fn can_bridge_l1_messages() -> eyre::Result<()> {
6464
sequencer_enabled: true,
6565
block_time: 0,
6666
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
67+
allow_empty_blocks: true,
6768
..SequencerArgs::default()
6869
},
6970
beacon_provider_args: BeaconProviderArgs {
@@ -159,6 +160,7 @@ async fn can_sequence_and_gossip_blocks() {
159160
block_time: 0,
160161
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
161162
payload_building_duration: 1000,
163+
allow_empty_blocks: true,
162164
..SequencerArgs::default()
163165
},
164166
beacon_provider_args: BeaconProviderArgs {
@@ -256,6 +258,7 @@ async fn can_penalize_peer_for_invalid_block() {
256258
block_time: 0,
257259
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
258260
payload_building_duration: 1000,
261+
allow_empty_blocks: true,
259262
..SequencerArgs::default()
260263
},
261264
beacon_provider_args: BeaconProviderArgs {

crates/node/tests/sync.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,11 @@ async fn test_should_consolidate_to_block_15k() -> eyre::Result<()> {
5757
initial_backoff: 100,
5858
},
5959
engine_driver_args: EngineDriverArgs { sync_at_startup: false },
60-
sequencer_args: SequencerArgs { sequencer_enabled: false, ..Default::default() },
60+
sequencer_args: SequencerArgs {
61+
sequencer_enabled: false,
62+
allow_empty_blocks: true,
63+
..Default::default()
64+
},
6165
beacon_provider_args: BeaconProviderArgs {
6266
url: Some(Url::parse("https://eth-beacon-chain.drpc.org/rest/")?),
6367
compute_units_per_second: 100,
@@ -195,6 +199,7 @@ async fn test_should_consolidate_after_optimistic_sync() -> eyre::Result<()> {
195199
sequencer_enabled: true,
196200
block_time: 0,
197201
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
202+
allow_empty_blocks: true,
198203
..SequencerArgs::default()
199204
},
200205
beacon_provider_args: BeaconProviderArgs {
@@ -442,6 +447,7 @@ async fn test_consolidation() -> eyre::Result<()> {
442447
sequencer_enabled: true,
443448
block_time: 0,
444449
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
450+
allow_empty_blocks: true,
445451
..SequencerArgs::default()
446452
},
447453
beacon_provider_args: BeaconProviderArgs {
@@ -614,6 +620,7 @@ async fn test_chain_orchestrator_shallow_reorg_with_gap() -> eyre::Result<()> {
614620
sequencer_enabled: true,
615621
block_time: 0,
616622
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
623+
allow_empty_blocks: true,
617624
..SequencerArgs::default()
618625
},
619626
beacon_provider_args: BeaconProviderArgs {

crates/sequencer/tests/e2e.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,61 @@ use tokio::{
3737
time::{Duration, Instant},
3838
};
3939

40+
#[tokio::test]
41+
async fn skip_block_with_no_transactions() {
42+
reth_tracing::init_test_tracing();
43+
44+
const BLOCK_BUILDING_DURATION: Duration = Duration::from_millis(0);
45+
46+
// setup a test node
47+
let (mut nodes, _tasks, _wallet) = setup(1, false).await.unwrap();
48+
let node = nodes.pop().unwrap();
49+
50+
// create a forkchoice state
51+
let genesis_hash = node.inner.chain_spec().genesis_hash();
52+
let fcs = ForkchoiceState::new(
53+
BlockInfo { hash: genesis_hash, number: 0 },
54+
Default::default(),
55+
Default::default(),
56+
);
57+
58+
// create the engine driver connected to the node
59+
let auth_client = node.inner.engine_http_client();
60+
let engine_client = ScrollAuthApiEngineClient::new(auth_client);
61+
let mut engine_driver = EngineDriver::new(
62+
Arc::new(engine_client),
63+
(*SCROLL_DEV).clone(),
64+
None::<ScrollRootProvider>,
65+
fcs,
66+
false,
67+
BLOCK_BUILDING_DURATION,
68+
false,
69+
);
70+
71+
// create a test database
72+
let database = Arc::new(setup_test_db().await);
73+
let provider = Arc::new(DatabaseL1MessageProvider::new(database.clone(), 0));
74+
75+
// create a sequencer
76+
let mut sequencer = Sequencer::new(
77+
provider,
78+
Default::default(),
79+
SCROLL_GAS_LIMIT,
80+
4,
81+
1,
82+
L1MessageInclusionMode::BlockDepth(0),
83+
);
84+
85+
// send a new payload attributes request.
86+
sequencer.build_payload_attributes();
87+
let payload_attributes = sequencer.next().await.unwrap();
88+
engine_driver.handle_build_new_payload(payload_attributes);
89+
90+
// assert that no new payload event is emitted
91+
let res = tokio::time::timeout(Duration::from_secs(1), engine_driver.next()).await;
92+
assert!(res.is_err(), "expected no new payload, but a block was built: {:?}", res.ok());
93+
}
94+
4095
#[tokio::test]
4196
async fn can_build_blocks() {
4297
reth_tracing::init_test_tracing();
@@ -66,6 +121,7 @@ async fn can_build_blocks() {
66121
fcs,
67122
false,
68123
BLOCK_BUILDING_DURATION,
124+
true,
69125
);
70126

71127
// create a test database
@@ -192,6 +248,7 @@ async fn can_build_blocks_with_delayed_l1_messages() {
192248
fcs,
193249
false,
194250
BLOCK_BUILDING_DURATION,
251+
true,
195252
);
196253

197254
// create a test database
@@ -317,6 +374,7 @@ async fn can_build_blocks_with_finalized_l1_messages() {
317374
fcs,
318375
false,
319376
BLOCK_BUILDING_DURATION,
377+
true,
320378
);
321379

322380
// create a test database
@@ -447,6 +505,7 @@ async fn can_sequence_blocks_with_private_key_file() -> eyre::Result<()> {
447505
block_time: 0,
448506
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
449507
payload_building_duration: 1000,
508+
allow_empty_blocks: true,
450509
..SequencerArgs::default()
451510
},
452511
beacon_provider_args: BeaconProviderArgs {
@@ -538,6 +597,7 @@ async fn can_sequence_blocks_with_hex_key_file_without_prefix() -> eyre::Result<
538597
block_time: 0,
539598
l1_message_inclusion_mode: L1MessageInclusionMode::BlockDepth(0),
540599
payload_building_duration: 1000,
600+
allow_empty_blocks: true,
541601
..SequencerArgs::default()
542602
},
543603
beacon_provider_args: BeaconProviderArgs {
@@ -658,6 +718,7 @@ async fn can_build_blocks_and_exit_at_gas_limit() {
658718
fcs,
659719
false,
660720
BLOCK_BUILDING_DURATION,
721+
true,
661722
);
662723

663724
// issue a new payload to the execution layer.
@@ -743,6 +804,7 @@ async fn can_build_blocks_and_exit_at_time_limit() {
743804
fcs,
744805
false,
745806
BLOCK_BUILDING_DURATION,
807+
true,
746808
);
747809

748810
// start timer.
@@ -809,6 +871,7 @@ async fn should_limit_l1_message_cumulative_gas() {
809871
fcs,
810872
false,
811873
BLOCK_BUILDING_DURATION,
874+
true,
812875
);
813876

814877
// create a test database

tests/launch_rollup_node_sequencer.bash

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ exec rollup-node node --chain dev --datadir=/l2reth --metrics=0.0.0.0:6060 --net
99
--sequencer.enabled \
1010
--sequencer.block-time 250 \
1111
--sequencer.payload-building-duration 230 \
12+
--sequencer.allow-empty-blocks \
1213
--txpool.pending-max-count=1000 \
1314
--builder.gaslimit=20000000 \
1415
--rpc.max-connections=5000 \

0 commit comments

Comments
 (0)