@@ -26,11 +26,12 @@ use stacks_common::address::{
26
26
AddressHashMode , C32_ADDRESS_VERSION_MAINNET_MULTISIG , C32_ADDRESS_VERSION_MAINNET_SINGLESIG ,
27
27
} ;
28
28
use stacks_common:: types:: chainstate:: {
29
- ConsensusHash , StacksAddress , StacksPrivateKey , StacksPublicKey ,
29
+ BlockHeaderHash , ConsensusHash , StacksAddress , StacksPrivateKey , StacksPublicKey ,
30
30
} ;
31
31
use stacks_common:: util:: hash:: { Hash160 , Sha512Trunc256Sum } ;
32
32
use stacks_common:: util:: secp256k1:: { MessageSignature , Secp256k1PrivateKey } ;
33
33
34
+ use crate :: chainstate:: burn:: db:: sortdb:: SortitionDB ;
34
35
use crate :: net:: relay:: Relayer ;
35
36
use crate :: net:: stackerdb:: db:: SlotValidation ;
36
37
use crate :: net:: stackerdb:: { StackerDBConfig , StackerDBs } ;
@@ -280,6 +281,199 @@ fn test_stackerdb_replica_2_neighbors_1_chunk() {
280
281
} )
281
282
}
282
283
284
+ #[ test]
285
+ fn test_stackerdb_replica_2_neighbors_1_chunk_stale_view ( ) {
286
+ with_timeout ( 600 , || {
287
+ std:: env:: set_var ( "STACKS_TEST_DISABLE_EDGE_TRIGGER_TEST" , "1" ) ;
288
+ let mut peer_1_config = TestPeerConfig :: from_port ( BASE_PORT ) ;
289
+ let mut peer_2_config = TestPeerConfig :: from_port ( BASE_PORT + 2 ) ;
290
+
291
+ peer_1_config. allowed = -1 ;
292
+ peer_2_config. allowed = -1 ;
293
+
294
+ // short-lived walks...
295
+ peer_1_config. connection_opts . walk_max_duration = 10 ;
296
+ peer_2_config. connection_opts . walk_max_duration = 10 ;
297
+
298
+ // peer 1 crawls peer 2, and peer 2 crawls peer 1
299
+ peer_1_config. add_neighbor ( & peer_2_config. to_neighbor ( ) ) ;
300
+ peer_2_config. add_neighbor ( & peer_1_config. to_neighbor ( ) ) ;
301
+
302
+ // set up stacker DBs for both peers
303
+ let idx_1 = add_stackerdb ( & mut peer_1_config, Some ( StackerDBConfig :: template ( ) ) ) ;
304
+ let idx_2 = add_stackerdb ( & mut peer_2_config, Some ( StackerDBConfig :: template ( ) ) ) ;
305
+
306
+ let mut peer_1 = TestPeer :: new ( peer_1_config) ;
307
+ let mut peer_2 = TestPeer :: new ( peer_2_config) ;
308
+
309
+ // peer 1 gets the DB
310
+ setup_stackerdb ( & mut peer_1, idx_1, true , 1 ) ;
311
+ setup_stackerdb ( & mut peer_2, idx_2, false , 1 ) ;
312
+
313
+ // verify that peer 1 got the data
314
+ let peer_1_db_chunks = load_stackerdb ( & peer_1, idx_1) ;
315
+ assert_eq ! ( peer_1_db_chunks. len( ) , 1 ) ;
316
+ assert_eq ! ( peer_1_db_chunks[ 0 ] . 0 . slot_id, 0 ) ;
317
+ assert_eq ! ( peer_1_db_chunks[ 0 ] . 0 . slot_version, 1 ) ;
318
+ assert ! ( peer_1_db_chunks[ 0 ] . 1 . len( ) > 0 ) ;
319
+
320
+ // verify that peer 2 did NOT get the data
321
+ let peer_2_db_chunks = load_stackerdb ( & peer_2, idx_2) ;
322
+ assert_eq ! ( peer_2_db_chunks. len( ) , 1 ) ;
323
+ assert_eq ! ( peer_2_db_chunks[ 0 ] . 0 . slot_id, 0 ) ;
324
+ assert_eq ! ( peer_2_db_chunks[ 0 ] . 0 . slot_version, 0 ) ;
325
+ assert ! ( peer_2_db_chunks[ 0 ] . 1 . len( ) == 0 ) ;
326
+
327
+ let peer_1_db_configs = peer_1. config . get_stacker_db_configs ( ) ;
328
+ let peer_2_db_configs = peer_2. config . get_stacker_db_configs ( ) ;
329
+
330
+ // force peer 2 to have a stale view
331
+ let ( old_tip_ch, old_tip_bh) = {
332
+ let sortdb = peer_1. sortdb ( ) ;
333
+ let ( tip_bh, tip_ch) =
334
+ SortitionDB :: get_canonical_stacks_chain_tip_hash ( sortdb. conn ( ) ) . unwrap ( ) ;
335
+ SortitionDB :: set_canonical_stacks_chain_tip (
336
+ sortdb. conn ( ) ,
337
+ & ConsensusHash ( [ 0x22 ; 20 ] ) ,
338
+ & BlockHeaderHash ( [ 0x33 ; 32 ] ) ,
339
+ 45 ,
340
+ )
341
+ . unwrap ( ) ;
342
+ ( tip_bh, tip_ch)
343
+ } ;
344
+
345
+ let mut i = 0 ;
346
+ let mut peer_1_stale = false ;
347
+ let mut peer_2_stale = false ;
348
+ loop {
349
+ // run peer network state-machines
350
+ peer_1. network . stacker_db_configs = peer_1_db_configs. clone ( ) ;
351
+ peer_2. network . stacker_db_configs = peer_2_db_configs. clone ( ) ;
352
+
353
+ let res_1 = peer_1. step_with_ibd ( false ) ;
354
+ let res_2 = peer_2. step_with_ibd ( false ) ;
355
+
356
+ if let Ok ( mut res) = res_1 {
357
+ for sync_res in res. stacker_db_sync_results . iter ( ) {
358
+ assert_eq ! ( sync_res. chunks_to_store. len( ) , 0 ) ;
359
+ if sync_res. stale . len ( ) > 0 {
360
+ peer_1_stale = true ;
361
+ }
362
+ }
363
+ Relayer :: process_stacker_db_chunks (
364
+ & mut peer_1. network . stackerdbs ,
365
+ & peer_1_db_configs,
366
+ res. stacker_db_sync_results ,
367
+ None ,
368
+ )
369
+ . unwrap ( ) ;
370
+ Relayer :: process_pushed_stacker_db_chunks (
371
+ & mut peer_1. network . stackerdbs ,
372
+ & peer_1_db_configs,
373
+ & mut res. unhandled_messages ,
374
+ None ,
375
+ )
376
+ . unwrap ( ) ;
377
+ }
378
+
379
+ if let Ok ( mut res) = res_2 {
380
+ for sync_res in res. stacker_db_sync_results . iter ( ) {
381
+ assert_eq ! ( sync_res. chunks_to_store. len( ) , 0 ) ;
382
+ if sync_res. stale . len ( ) > 0 {
383
+ peer_2_stale = true ;
384
+ }
385
+ }
386
+ Relayer :: process_stacker_db_chunks (
387
+ & mut peer_2. network . stackerdbs ,
388
+ & peer_2_db_configs,
389
+ res. stacker_db_sync_results ,
390
+ None ,
391
+ )
392
+ . unwrap ( ) ;
393
+ Relayer :: process_pushed_stacker_db_chunks (
394
+ & mut peer_2. network . stackerdbs ,
395
+ & peer_2_db_configs,
396
+ & mut res. unhandled_messages ,
397
+ None ,
398
+ )
399
+ . unwrap ( ) ;
400
+ }
401
+
402
+ if peer_1_stale && peer_2_stale {
403
+ break ;
404
+ }
405
+
406
+ i += 1 ;
407
+ }
408
+
409
+ debug ! ( "Completed stacker DB stale detection in {} step(s)" , i) ;
410
+
411
+ // fix and re-run
412
+ {
413
+ let sortdb = peer_1. sortdb ( ) ;
414
+ SortitionDB :: set_canonical_stacks_chain_tip ( sortdb. conn ( ) , & old_tip_ch, & old_tip_bh, 0 )
415
+ . unwrap ( ) ;
416
+
417
+ // force chain view refresh
418
+ peer_1. network . num_state_machine_passes = 0 ;
419
+ }
420
+
421
+ let mut i = 0 ;
422
+ loop {
423
+ // run peer network state-machines
424
+ peer_1. network . stacker_db_configs = peer_1_db_configs. clone ( ) ;
425
+ peer_2. network . stacker_db_configs = peer_2_db_configs. clone ( ) ;
426
+
427
+ let res_1 = peer_1. step_with_ibd ( false ) ;
428
+ let res_2 = peer_2. step_with_ibd ( false ) ;
429
+
430
+ if let Ok ( mut res) = res_1 {
431
+ Relayer :: process_stacker_db_chunks (
432
+ & mut peer_1. network . stackerdbs ,
433
+ & peer_1_db_configs,
434
+ res. stacker_db_sync_results ,
435
+ None ,
436
+ )
437
+ . unwrap ( ) ;
438
+ Relayer :: process_pushed_stacker_db_chunks (
439
+ & mut peer_1. network . stackerdbs ,
440
+ & peer_1_db_configs,
441
+ & mut res. unhandled_messages ,
442
+ None ,
443
+ )
444
+ . unwrap ( ) ;
445
+ }
446
+
447
+ if let Ok ( mut res) = res_2 {
448
+ Relayer :: process_stacker_db_chunks (
449
+ & mut peer_2. network . stackerdbs ,
450
+ & peer_2_db_configs,
451
+ res. stacker_db_sync_results ,
452
+ None ,
453
+ )
454
+ . unwrap ( ) ;
455
+ Relayer :: process_pushed_stacker_db_chunks (
456
+ & mut peer_2. network . stackerdbs ,
457
+ & peer_2_db_configs,
458
+ & mut res. unhandled_messages ,
459
+ None ,
460
+ )
461
+ . unwrap ( ) ;
462
+ }
463
+
464
+ let db1 = load_stackerdb ( & peer_1, idx_1) ;
465
+ let db2 = load_stackerdb ( & peer_2, idx_2) ;
466
+
467
+ if db1 == db2 {
468
+ break ;
469
+ }
470
+ i += 1 ;
471
+ }
472
+
473
+ debug ! ( "Completed stacker DB sync in {} step(s)" , i) ;
474
+ } )
475
+ }
476
+
283
477
#[ test]
284
478
#[ ignore]
285
479
fn test_stackerdb_replica_2_neighbors_10_chunks ( ) {
0 commit comments