@@ -6,11 +6,12 @@ use alloy_signer::Signer;
6
6
use alloy_signer_local:: PrivateKeySigner ;
7
7
use futures:: StreamExt ;
8
8
use reth_chainspec:: EthChainSpec ;
9
- use reth_network:: { NetworkConfigBuilder , PeersInfo } ;
9
+ use reth_network:: { NetworkConfigBuilder , Peers , PeersInfo } ;
10
10
use reth_network_api:: block:: EthWireProvider ;
11
11
use reth_rpc_api:: EthApiServer ;
12
12
use reth_scroll_chainspec:: SCROLL_DEV ;
13
13
use reth_scroll_node:: ScrollNetworkPrimitives ;
14
+ use reth_scroll_primitives:: ScrollBlock ;
14
15
use reth_tokio_util:: EventStream ;
15
16
use rollup_node:: {
16
17
constants:: SCROLL_GAS_LIMIT ,
@@ -22,16 +23,19 @@ use rollup_node::{
22
23
GasPriceOracleArgs , L1ProviderArgs , NetworkArgs as ScrollNetworkArgs , RollupNodeContext ,
23
24
ScrollRollupNodeConfig , SequencerArgs ,
24
25
} ;
25
- use rollup_node_manager:: { RollupManagerCommand , RollupManagerEvent , RollupManagerHandle } ;
26
+ use rollup_node_manager:: { RollupManagerCommand , RollupManagerEvent } ;
26
27
use rollup_node_primitives:: { sig_encode_hash, BatchCommitData , ConsensusUpdate } ;
27
28
use rollup_node_providers:: BlobSource ;
28
29
use rollup_node_sequencer:: L1MessageInclusionMode ;
29
30
use rollup_node_watcher:: L1Notification ;
30
31
use scroll_alloy_consensus:: TxL1Message ;
31
32
use scroll_network:: { NewBlockWithPeer , SCROLL_MAINNET } ;
32
33
use scroll_wire:: { ScrollWireConfig , ScrollWireProtocolHandler } ;
33
- use std:: { path:: PathBuf , sync:: Arc } ;
34
- use tokio:: sync:: { oneshot, Mutex } ;
34
+ use std:: { path:: PathBuf , sync:: Arc , time:: Duration } ;
35
+ use tokio:: {
36
+ sync:: { oneshot, Mutex } ,
37
+ time,
38
+ } ;
35
39
use tracing:: trace;
36
40
37
41
#[ tokio:: test]
@@ -63,7 +67,7 @@ async fn can_bridge_l1_messages() -> eyre::Result<()> {
63
67
let ( mut nodes, _tasks, _wallet) = setup_engine ( node_args, 1 , chain_spec, false , false ) . await ?;
64
68
let node = nodes. pop ( ) . unwrap ( ) ;
65
69
66
- let rnm_handle: RollupManagerHandle = node. inner . add_ons_handle . rollup_manager_handle . clone ( ) ;
70
+ let rnm_handle = node. inner . add_ons_handle . rollup_manager_handle . clone ( ) ;
67
71
let mut rnm_events = rnm_handle. get_event_listener ( ) . await ?;
68
72
let l1_watcher_tx = node. inner . add_ons_handle . l1_watcher_tx . clone ( ) . unwrap ( ) ;
69
73
@@ -167,6 +171,93 @@ async fn can_sequence_and_gossip_blocks() {
167
171
. await ;
168
172
}
169
173
174
+ #[ tokio:: test]
175
+ async fn can_penalize_peer_for_invalid_block ( ) {
176
+ reth_tracing:: init_test_tracing ( ) ;
177
+
178
+ // create 2 nodes
179
+ let chain_spec = ( * SCROLL_DEV ) . clone ( ) ;
180
+ let rollup_manager_args = ScrollRollupNodeConfig {
181
+ test : true ,
182
+ network_args : ScrollNetworkArgs {
183
+ enable_eth_scroll_wire_bridge : true ,
184
+ enable_scroll_wire : true ,
185
+ sequencer_url : None ,
186
+ } ,
187
+ database_args : DatabaseArgs { path : Some ( PathBuf :: from ( "sqlite::memory:" ) ) } ,
188
+ l1_provider_args : L1ProviderArgs :: default ( ) ,
189
+ engine_driver_args : EngineDriverArgs :: default ( ) ,
190
+ sequencer_args : SequencerArgs {
191
+ sequencer_enabled : true ,
192
+ block_time : 0 ,
193
+ l1_message_inclusion_mode : L1MessageInclusionMode :: BlockDepth ( 0 ) ,
194
+ payload_building_duration : 1000 ,
195
+ ..SequencerArgs :: default ( )
196
+ } ,
197
+ beacon_provider_args : BeaconProviderArgs {
198
+ blob_source : BlobSource :: Mock ,
199
+ ..Default :: default ( )
200
+ } ,
201
+ signer_args : Default :: default ( ) ,
202
+ gas_price_oracle_args : GasPriceOracleArgs :: default ( ) ,
203
+ consensus_args : ConsensusArgs :: noop ( ) ,
204
+ } ;
205
+
206
+ let ( nodes, _tasks, _) =
207
+ setup_engine ( rollup_manager_args, 2 , chain_spec, false , false ) . await . unwrap ( ) ;
208
+
209
+ let node0_rmn_handle = nodes[ 0 ] . inner . add_ons_handle . rollup_manager_handle . clone ( ) ;
210
+ let node0_network_handle = node0_rmn_handle. get_network_handle ( ) . await . unwrap ( ) ;
211
+ let node0_id = node0_network_handle. inner ( ) . peer_id ( ) ;
212
+
213
+ let node1_rnm_handle = nodes[ 1 ] . inner . add_ons_handle . rollup_manager_handle . clone ( ) ;
214
+ let node1_network_handle = node1_rnm_handle. get_network_handle ( ) . await . unwrap ( ) ;
215
+
216
+ // get initial reputation of node0 from pov of node1
217
+ let initial_reputation =
218
+ node1_network_handle. inner ( ) . reputation_by_id ( * node0_id) . await . unwrap ( ) . unwrap ( ) ;
219
+ assert_eq ! ( initial_reputation, 0 ) ;
220
+
221
+ // create invalid block
222
+ let block = ScrollBlock :: default ( ) ;
223
+
224
+ // send invalid block from node0 to node1. We don't care about the signature here since we use a
225
+ // NoopConsensus in the test.
226
+ node0_network_handle. announce_block ( block, Signature :: new ( U256 :: from ( 1 ) , U256 :: from ( 1 ) , false ) ) ;
227
+
228
+ eventually (
229
+ Duration :: from_secs ( 5 ) ,
230
+ Duration :: from_millis ( 10 ) ,
231
+ "Peer0 reputation should be lower after sending invalid block" ,
232
+ || async {
233
+ // check that the node0 is penalized on node1
234
+ let slashed_reputation =
235
+ node1_network_handle. inner ( ) . reputation_by_id ( * node0_id) . await . unwrap ( ) . unwrap ( ) ;
236
+ slashed_reputation < initial_reputation
237
+ } ,
238
+ )
239
+ . await ;
240
+ }
241
+
242
+ /// Helper function to wait until a predicate is true or a timeout occurs.
243
+ pub async fn eventually < F , Fut > ( timeout : Duration , tick : Duration , message : & str , mut predicate : F )
244
+ where
245
+ F : FnMut ( ) -> Fut ,
246
+ Fut : std:: future:: Future < Output = bool > ,
247
+ {
248
+ let mut interval = time:: interval ( tick) ;
249
+ let start = time:: Instant :: now ( ) ;
250
+ loop {
251
+ if predicate ( ) . await {
252
+ return ;
253
+ }
254
+
255
+ assert ! ( start. elapsed( ) <= timeout, "Timeout while waiting for condition: {message}" ) ;
256
+
257
+ interval. tick ( ) . await ;
258
+ }
259
+ }
260
+
170
261
#[ allow( clippy:: large_stack_frames) ]
171
262
#[ tokio:: test]
172
263
async fn can_sequence_and_gossip_transactions ( ) {
0 commit comments