2
2
3
3
use crate :: {
4
4
budget:: DEFAULT_BUDGET_TRY_DRAIN_DOWNLOADERS , metered_poll_nested_stream_with_budget,
5
- metrics:: EthRequestHandlerMetrics , transform:: header:: HeaderTransform ,
5
+ metrics:: EthRequestHandlerMetrics , transform:: header:: HeaderResponseTransform ,
6
6
} ;
7
7
use alloy_consensus:: { BlockHeader , ReceiptWithBloom } ;
8
8
use alloy_eips:: BlockHashOrNumber ;
9
9
use alloy_rlp:: Encodable ;
10
- use futures:: StreamExt ;
10
+ use futures:: { future :: join_all , StreamExt } ;
11
11
use reth_eth_wire:: {
12
12
BlockBodies , BlockHeaders , EthNetworkPrimitives , GetBlockBodies , GetBlockHeaders , GetNodeData ,
13
13
GetReceipts , HeadersDirection , NetworkPrimitives , NodeData , Receipts , Receipts69 ,
@@ -20,6 +20,7 @@ use reth_storage_api::{BlockReader, HeaderProvider};
20
20
use std:: {
21
21
future:: Future ,
22
22
pin:: Pin ,
23
+ sync:: Arc ,
23
24
task:: { Context , Poll } ,
24
25
time:: Duration ,
25
26
} ;
@@ -54,15 +55,15 @@ pub const SOFT_RESPONSE_LIMIT: usize = 2 * 1024 * 1024;
54
55
#[ must_use = "Manager does nothing unless polled." ]
55
56
pub struct EthRequestHandler < C , N : NetworkPrimitives = EthNetworkPrimitives > {
56
57
/// The client type that can interact with the chain.
57
- client : C ,
58
+ client : Arc < C > ,
58
59
/// Used for reporting peers.
59
60
// TODO use to report spammers
60
61
#[ expect( dead_code) ]
61
62
peers : PeersHandle ,
62
63
/// Incoming request from the [`NetworkManager`](crate::NetworkManager).
63
64
incoming_requests : ReceiverStream < IncomingEthRequest < N > > ,
64
65
/// The header transform to apply to the headers before sending to peers.
65
- header_transform : Option < Box < dyn HeaderTransform < N :: BlockHeader > > > ,
66
+ header_transform : Option < Arc < dyn HeaderResponseTransform < N :: BlockHeader > > > ,
66
67
/// Metrics for the eth request handler.
67
68
metrics : EthRequestHandlerMetrics ,
68
69
}
@@ -74,10 +75,10 @@ impl<C, N: NetworkPrimitives> EthRequestHandler<C, N> {
74
75
client : C ,
75
76
peers : PeersHandle ,
76
77
incoming : Receiver < IncomingEthRequest < N > > ,
77
- header_transform : Option < Box < dyn HeaderTransform < N :: BlockHeader > > > ,
78
+ header_transform : Option < Arc < dyn HeaderResponseTransform < N :: BlockHeader > > > ,
78
79
) -> Self {
79
80
Self {
80
- client,
81
+ client : Arc :: new ( client ) ,
81
82
peers,
82
83
incoming_requests : ReceiverStream :: new ( incoming) ,
83
84
header_transform,
@@ -89,20 +90,22 @@ impl<C, N: NetworkPrimitives> EthRequestHandler<C, N> {
89
90
impl < C , N > EthRequestHandler < C , N >
90
91
where
91
92
N : NetworkPrimitives ,
92
- C : BlockReader < Header = N :: BlockHeader > ,
93
+ C : BlockReader < Header = N :: BlockHeader > + ' static ,
93
94
{
94
95
/// Returns the list of requested headers
95
- fn get_headers_response ( & self , request : GetBlockHeaders ) -> Vec < C :: Header > {
96
+ async fn get_headers_response (
97
+ client : Arc < C > ,
98
+ header_transform : Option < Arc < dyn HeaderResponseTransform < N :: BlockHeader > > > ,
99
+ request : GetBlockHeaders ,
100
+ ) -> Vec < C :: Header > {
96
101
let GetBlockHeaders { start_block, limit, skip, direction } = request;
97
102
98
103
let mut headers = Vec :: new ( ) ;
99
104
100
105
let mut block: BlockHashOrNumber = match start_block {
101
106
BlockHashOrNumber :: Hash ( start) => start. into ( ) ,
102
107
BlockHashOrNumber :: Number ( num) => {
103
- let Some ( hash) = self . client . block_hash ( num) . unwrap_or_default ( ) else {
104
- return headers
105
- } ;
108
+ let Some ( hash) = client. block_hash ( num) . unwrap_or_default ( ) else { return headers } ;
106
109
hash. into ( )
107
110
}
108
111
} ;
@@ -111,7 +114,7 @@ where
111
114
let mut total_bytes = 0 ;
112
115
113
116
for _ in 0 ..limit {
114
- if let Some ( header) = self . client . header_by_hash_or_number ( block) . unwrap_or_default ( ) {
117
+ if let Some ( header) = client. header_by_hash_or_number ( block) . unwrap_or_default ( ) {
115
118
let number = header. number ( ) ;
116
119
let parent_hash = header. parent_hash ( ) ;
117
120
@@ -153,8 +156,8 @@ where
153
156
}
154
157
155
158
// TODO: remove this once we deprecated l2geth
156
- if let Some ( ref header_transform) = self . header_transform {
157
- headers = headers. into_iter ( ) . map ( |h| header_transform. map ( h) ) . collect ( )
159
+ if let Some ( ref header_transform) = header_transform {
160
+ return join_all ( headers. into_iter ( ) . map ( |h| header_transform. map ( h) ) ) . await ;
158
161
}
159
162
160
163
headers
@@ -165,10 +168,14 @@ where
165
168
_peer_id : PeerId ,
166
169
request : GetBlockHeaders ,
167
170
response : oneshot:: Sender < RequestResult < BlockHeaders < C :: Header > > > ,
168
- ) {
171
+ ) -> impl Future < Output = ( ) > + ' static {
169
172
self . metrics . eth_headers_requests_received_total . increment ( 1 ) ;
170
- let headers = self . get_headers_response ( request) ;
171
- let _ = response. send ( Ok ( BlockHeaders ( headers) ) ) ;
173
+ let client = self . client . clone ( ) ;
174
+ let header_transform = self . header_transform . clone ( ) ;
175
+ async move {
176
+ let headers = Self :: get_headers_response ( client, header_transform, request) . await ;
177
+ let _ = response. send ( Ok ( BlockHeaders ( headers) ) ) ;
178
+ }
172
179
}
173
180
174
181
fn on_bodies_request (
@@ -267,7 +274,8 @@ where
267
274
N : NetworkPrimitives ,
268
275
C : BlockReader < Block = N :: Block , Receipt = N :: Receipt >
269
276
+ HeaderProvider < Header = N :: BlockHeader >
270
- + Unpin ,
277
+ + Unpin
278
+ + ' static ,
271
279
{
272
280
type Output = ( ) ;
273
281
@@ -284,7 +292,8 @@ where
284
292
|incoming| {
285
293
match incoming {
286
294
IncomingEthRequest :: GetBlockHeaders { peer_id, request, response } => {
287
- this. on_headers_request( peer_id, request, response)
295
+ let future = this. on_headers_request( peer_id, request, response) ;
296
+ tokio:: spawn( future) ;
288
297
}
289
298
IncomingEthRequest :: GetBlockBodies { peer_id, request, response } => {
290
299
this. on_bodies_request( peer_id, request, response)
0 commit comments