Skip to content

Commit 2ee4e67

Browse files
committed
feat: improve peer_state
1 parent eac3400 commit 2ee4e67

7 files changed

Lines changed: 217 additions & 276 deletions

File tree

crates/network/src/manager.rs

Lines changed: 59 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use super::{
44
BlockImportOutcome, BlockValidation, NetworkHandleMessage, NewBlockWithPeer,
55
ScrollNetworkHandle, ScrollNetworkManagerEvent,
66
};
7-
use alloy_primitives::{Address, FixedBytes, Signature, B256, U128};
8-
use futures::{Future, FutureExt, StreamExt};
7+
use alloy_primitives::{Address, Signature, B256, U128};
8+
use futures::StreamExt;
99
use reth_chainspec::EthChainSpec;
1010
use reth_eth_wire_types::NewBlock as EthWireNewBlock;
1111
use reth_network::{
@@ -20,14 +20,10 @@ use reth_tokio_util::{EventSender, EventStream};
2020
use rollup_node_primitives::{sig_encode_hash, BlockInfo};
2121
use scroll_alloy_hardforks::ScrollHardforks;
2222
use scroll_wire::{
23-
NewBlock, PeerState, ScrollWireConfig, ScrollWireEvent, ScrollWireManager,
23+
NewBlock, PeerState, ScrollMessage, ScrollWireConfig, ScrollWireEvent, ScrollWireManager,
2424
ScrollWireProtocolHandler, LRU_CACHE_SIZE,
2525
};
26-
use std::{
27-
pin::Pin,
28-
sync::Arc,
29-
task::{Context, Poll},
30-
};
26+
use std::sync::Arc;
3127
use tokio::sync::mpsc::{self, UnboundedReceiver};
3228
use tokio_stream::wrappers::UnboundedReceiverStream;
3329
use tracing::trace;
@@ -174,12 +170,7 @@ impl<
174170
)
175171
}
176172

177-
/// Runs the network manager event loop.
178-
///
179-
/// This is the main event loop that processes:
180-
/// - Messages from the network handle
181-
/// - Events from the scroll-wire protocol
182-
/// - Blocks received from the eth-wire protocol
173+
/// Main execution loop for the [`ScrollNetworkManager`].
183174
pub async fn run(mut self) {
184175
loop {
185176
tokio::select! {
@@ -189,7 +180,7 @@ impl<
189180
message = self.from_handle_rx.next() => {
190181
match message {
191182
Some(message) => {
192-
self.on_handle_message(message);
183+
self.on_handle_message(message).await;
193184
}
194185
// All network handles have been dropped so we can shutdown the network.
195186
None => {
@@ -221,7 +212,7 @@ impl<
221212
}
222213

223214
/// Announces a new block to the network.
224-
fn announce_block(&mut self, block: NewBlock) {
215+
async fn announce_block(&mut self, block: NewBlock) {
225216
#[cfg(feature = "test-utils")]
226217
if !self.gossip {
227218
return;
@@ -230,27 +221,13 @@ impl<
230221
// Compute the block hash.
231222
let hash = block.block.hash_slow();
232223

233-
// Filter the peers that have not seen this block hash via either protocol.
234-
// We iterate over all connected scroll-wire peers.
235-
let peers: Vec<FixedBytes<64>> = self
236-
.scroll_wire
237-
.connected_peers()
238-
.filter_map(|peer_id| {
239-
// Check if peer has seen this block via any protocol
240-
let has_seen = self
241-
.scroll_wire
242-
.peer_state()
243-
.get(peer_id)
244-
.is_some_and(|state| state.has_seen(&hash));
245-
246-
// Only announce if peer hasn't seen this block
247-
if !has_seen {
248-
Some(*peer_id)
249-
} else {
250-
None
251-
}
252-
})
253-
.collect();
224+
let peers = match self.inner_network_handle.get_all_peers().await {
225+
Ok(peers) => peers,
226+
Err(e) => {
227+
tracing::error!(target: "scroll::network::manager", "Failed to get all peers: {}", e);
228+
return;
229+
}
230+
};
254231

255232
// TODO: remove this once we deprecate l2geth.
256233
// Determine if we should announce via eth wire
@@ -272,22 +249,42 @@ impl<
272249
// If no authorized signer is set, always announce
273250
true
274251
};
252+
let eth_wire_new_block = {
253+
let td = compute_td(self.td_constant, block.block.header.number);
254+
let mut eth_wire_block = block.block.clone();
255+
eth_wire_block.header.extra_data = block.signature.clone().into();
256+
EthWireNewBlock { block: eth_wire_block, td }
257+
};
275258

276-
// Announce via eth wire if allowed
277-
if should_announce_eth_wire {
278-
let eth_wire_new_block = {
279-
let td = compute_td(self.td_constant, block.block.header.number);
280-
let mut eth_wire_block = block.block.clone();
281-
eth_wire_block.header.extra_data = block.signature.clone().into();
282-
EthWireNewBlock { block: eth_wire_block, td }
283-
};
284-
self.inner_network_handle.eth_wire_announce_block(eth_wire_new_block, hash);
285-
}
259+
for peer in peers {
260+
// Skip peers that have already seen this block
261+
if self
262+
.scroll_wire
263+
.peer_state()
264+
.get(&peer.remote_id)
265+
.is_some_and(|state| state.has_seen(&hash))
266+
{
267+
continue;
268+
}
286269

287-
// Announce block to the filtered set of peers
288-
for peer_id in peers {
289-
trace!(target: "scroll::network::manager", peer_id = %peer_id, block_number = %block.block.header.number, block_hash = %hash, "Announcing new block to peer");
290-
self.scroll_wire.announce_block(peer_id, &block, hash);
270+
if peer
271+
.capabilities
272+
.capabilities()
273+
.iter()
274+
.any(|cap| cap == &ScrollMessage::capability())
275+
{
276+
trace!(target: "scroll::network::manager", peer_id = %peer.remote_id, block_number = %block.block.header.number, block_hash = %hash, "Announcing new block to peer via scroll-wire");
277+
self.scroll_wire.announce_block(peer.remote_id, &block, hash);
278+
} else {
279+
if should_announce_eth_wire {
280+
trace!(target: "scroll::network::manager", peer_id = %peer.remote_id, block_number = %block.block.header.number, block_hash = %hash, "Announcing new block to peer via eth-wire");
281+
self.inner_network_handle.eth_wire_announce_block_to(
282+
peer.remote_id,
283+
eth_wire_new_block.clone(),
284+
hash,
285+
);
286+
}
287+
};
291288
}
292289
}
293290

@@ -309,16 +306,16 @@ impl<
309306
.entry(peer_id)
310307
.or_insert_with(|| PeerState::new(LRU_CACHE_SIZE));
311308

312-
if state.has_seen_via_scroll_wire(&block_hash) {
309+
if state.has_received(&block_hash) {
313310
tracing::warn!(target: "scroll::network::manager", peer_id = ?peer_id, block = ?block_hash, "Peer sent duplicate block via scroll-wire, penalizing");
314311
self.inner_network_handle.reputation_change(
315312
peer_id,
316313
reth_network_api::ReputationChangeKind::BadBlock,
317314
);
318315
return None;
319316
}
320-
// Update the state: peer has seen this block via scroll-wire
321-
state.insert_scroll_wire(block_hash);
317+
// Update the state that the peer has received this block
318+
state.insert_received(block_hash);
322319

323320
if self.blocks_seen.contains(&(block_hash, signature)) {
324321
None
@@ -341,13 +338,13 @@ impl<
341338
}
342339

343340
/// Handler for received messages from the [`ScrollNetworkHandle`].
344-
fn on_handle_message(&mut self, message: NetworkHandleMessage) {
341+
async fn on_handle_message(&mut self, message: NetworkHandleMessage) {
345342
match message {
346343
NetworkHandleMessage::AnnounceBlock { block, signature } => {
347-
self.announce_block(NewBlock::new(signature, block))
344+
self.announce_block(NewBlock::new(signature, block)).await
348345
}
349346
NetworkHandleMessage::BlockImportOutcome(outcome) => {
350-
self.on_block_import_result(outcome);
347+
self.on_block_import_result(outcome).await;
351348
}
352349
NetworkHandleMessage::Shutdown(tx) => {
353350
tx.send(()).unwrap()
@@ -366,13 +363,13 @@ impl<
366363
}
367364

368365
/// Handler for the result of a block import.
369-
fn on_block_import_result(&mut self, outcome: BlockImportOutcome) {
366+
async fn on_block_import_result(&mut self, outcome: BlockImportOutcome) {
370367
let BlockImportOutcome { peer, result } = outcome;
371368
match result {
372369
Ok(BlockValidation::ValidBlock { new_block: msg }) |
373370
Ok(BlockValidation::ValidHeader { new_block: msg }) => {
374371
trace!(target: "scroll::network::manager", peer_id = ?peer, block = %Into::<BlockInfo>::into(&msg.block), "Block import successful - announcing block to network");
375-
self.announce_block(msg);
372+
self.announce_block(msg).await;
376373
}
377374
Err(BlockImportError::Consensus(err)) => {
378375
trace!(target: "scroll::network::manager", peer_id = ?peer, ?err, "Block import failed - consensus error - penalizing peer");
@@ -427,14 +424,14 @@ impl<
427424
.entry(peer_id)
428425
.or_insert_with(|| PeerState::new(LRU_CACHE_SIZE));
429426

430-
if state.has_seen_via_eth_wire(&block_hash) {
427+
if state.has_received(&block_hash) {
431428
tracing::warn!(target: "scroll::bridge::import", peer_id = ?peer_id, block = ?block_hash, "Peer sent duplicate block via eth-wire, penalizing");
432429
self.inner_network_handle
433430
.reputation_change(peer_id, reth_network_api::ReputationChangeKind::BadBlock);
434431
return None;
435432
}
436-
// Update the state: peer has seen this block via eth-wire
437-
state.insert_eth_wire(block_hash);
433+
// Update the state that the peer has received this block
434+
state.insert_received(block_hash);
438435

439436
if self.blocks_seen.contains(&(block_hash, signature)) {
440437
None
@@ -458,52 +455,6 @@ impl<
458455
}
459456
}
460457

461-
impl<
462-
N: FullNetwork<Primitives = ScrollNetworkPrimitives>,
463-
CS: ScrollHardforks + EthChainSpec + Send + Sync + 'static,
464-
> Future for ScrollNetworkManager<N, CS>
465-
{
466-
type Output = ();
467-
468-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
469-
let this = self.get_mut();
470-
471-
// We handle the messages from the network handle.
472-
loop {
473-
match this.from_handle_rx.poll_next_unpin(cx) {
474-
// A message has been received from the network handle.
475-
Poll::Ready(Some(message)) => {
476-
this.on_handle_message(message);
477-
}
478-
// All network handles have been dropped so we can shutdown the network.
479-
Poll::Ready(None) => {
480-
return Poll::Ready(());
481-
}
482-
// No additional messages exist break.
483-
Poll::Pending => break,
484-
}
485-
}
486-
487-
// Next we handle the scroll-wire events.
488-
while let Poll::Ready(event) = this.scroll_wire.poll_unpin(cx) {
489-
if let Some(event) = this.on_scroll_wire_event(event) {
490-
this.event_sender.notify(event);
491-
}
492-
}
493-
494-
// Handle blocks received from the eth-wire protocol.
495-
while let Some(Poll::Ready(Some(block))) =
496-
this.eth_wire_listener.as_mut().map(|new_block_rx| new_block_rx.poll_next_unpin(cx))
497-
{
498-
if let Some(event) = this.handle_eth_wire_block(block) {
499-
this.event_sender.notify(event);
500-
}
501-
}
502-
503-
Poll::Pending
504-
}
505-
}
506-
507458
/// Compute totally difficulty for a given block number.
508459
fn compute_td(td_constant: U128, block_number: u64) -> U128 {
509460
td_constant.saturating_add(U128::from(block_number))

crates/node/src/args.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ impl ScrollRollupNodeConfig {
357357
td_constant(chain_spec.chain().named()),
358358
authorized_signer,
359359
);
360-
ctx.task_executor.spawn(scroll_network_manager);
360+
ctx.task_executor.spawn(scroll_network_manager.run());
361361

362362
tracing::info!(target: "scroll::node::args", fcs = ?fcs, payload_building_duration = ?self.sequencer_args.payload_building_duration, "Starting engine driver");
363363
let engine = Engine::new(Arc::new(engine_api), fcs);

crates/node/src/node.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ where
6969

7070
*self.scroll_wire_events.try_lock().unwrap() = Some(events);
7171

72+
let mut network_builder = ScrollNetworkBuilder::new(
73+
self.config.database.clone().expect("database is set via hydration"),
74+
)
75+
.with_signer(self.config.network_args.signer_address);
76+
77+
// Only add scroll-wire sub-protocol if enabled
78+
if self.config.network_args.enable_scroll_wire {
79+
network_builder =
80+
network_builder.with_sub_protocol(scroll_wire_handler.into_rlpx_sub_protocol());
81+
}
82+
7283
ScrollNode::components()
7384
.payload(BasicPayloadServiceBuilder::new(ScrollPayloadBuilderBuilder {
7485
payload_building_time_limit: Duration::from_millis(
@@ -77,13 +88,7 @@ where
7788
best_transactions: (),
7889
block_da_size_limit: Some(constants::DEFAULT_PAYLOAD_SIZE_LIMIT),
7990
}))
80-
.network(
81-
ScrollNetworkBuilder::new(
82-
self.config.database.clone().expect("database is set via hydration"),
83-
)
84-
.with_sub_protocol(scroll_wire_handler.into_rlpx_sub_protocol())
85-
.with_signer(self.config.network_args.signer_address),
86-
)
91+
.network(network_builder)
8792
}
8893

8994
fn add_ons(&self) -> Self::AddOns {

0 commit comments

Comments
 (0)