@@ -2453,3 +2453,75 @@ pub fn simple_nakamoto_coordinator_10_extended_tenures_10_sortitions() -> TestPe
2453
2453
fn test_nakamoto_coordinator_10_tenures_and_extensions_10_blocks ( ) {
2454
2454
simple_nakamoto_coordinator_10_extended_tenures_10_sortitions ( ) ;
2455
2455
}
2456
+
2457
+ #[ test]
2458
+ fn process_next_nakamoto_block_deadlock ( ) {
2459
+ let private_key = StacksPrivateKey :: from_seed ( & [ 2 ] ) ;
2460
+ let addr = StacksAddress :: p2pkh ( false , & StacksPublicKey :: from_private ( & private_key) ) ;
2461
+
2462
+ let num_stackers: u32 = 4 ;
2463
+ let mut signing_key_seed = num_stackers. to_be_bytes ( ) . to_vec ( ) ;
2464
+ signing_key_seed. extend_from_slice ( & [ 1 , 1 , 1 , 1 ] ) ;
2465
+ let signing_key = StacksPrivateKey :: from_seed ( signing_key_seed. as_slice ( ) ) ;
2466
+ let test_stackers = ( 0 ..num_stackers)
2467
+ . map ( |index| TestStacker {
2468
+ signer_private_key : signing_key. clone ( ) ,
2469
+ stacker_private_key : StacksPrivateKey :: from_seed ( & index. to_be_bytes ( ) ) ,
2470
+ amount : u64:: MAX as u128 - 10000 ,
2471
+ pox_addr : Some ( PoxAddress :: Standard (
2472
+ StacksAddress :: new (
2473
+ C32_ADDRESS_VERSION_TESTNET_SINGLESIG ,
2474
+ Hash160 :: from_data ( & index. to_be_bytes ( ) ) ,
2475
+ ) ,
2476
+ Some ( AddressHashMode :: SerializeP2PKH ) ,
2477
+ ) ) ,
2478
+ max_amount : None ,
2479
+ } )
2480
+ . collect :: < Vec < _ > > ( ) ;
2481
+ let test_signers = TestSigners :: new ( vec ! [ signing_key] ) ;
2482
+ let mut pox_constants = TestPeerConfig :: default ( ) . burnchain . pox_constants ;
2483
+ pox_constants. reward_cycle_length = 10 ;
2484
+ pox_constants. v2_unlock_height = 21 ;
2485
+ pox_constants. pox_3_activation_height = 26 ;
2486
+ pox_constants. v3_unlock_height = 27 ;
2487
+ pox_constants. pox_4_activation_height = 28 ;
2488
+
2489
+ let mut boot_plan = NakamotoBootPlan :: new ( function_name ! ( ) )
2490
+ . with_test_stackers ( test_stackers. clone ( ) )
2491
+ . with_test_signers ( test_signers. clone ( ) )
2492
+ . with_private_key ( private_key) ;
2493
+ boot_plan. pox_constants = pox_constants;
2494
+
2495
+ info ! ( "Creating peer" ) ;
2496
+
2497
+ let mut peer = boot_plan. boot_into_nakamoto_peer ( vec ! [ ] , None ) ;
2498
+
2499
+ // Lock the sortdb
2500
+ info ! ( " ------------------------------- TRYING TO LOCK THE SORTDB" ) ;
2501
+ let mut sortition_db = peer. sortdb ( ) . reopen ( ) . unwrap ( ) ;
2502
+ let sort_tx = sortition_db. tx_begin ( ) . unwrap ( ) ;
2503
+
2504
+ // Start another thread that opens the sortdb, waits 10s, then tries to
2505
+ // lock the chainstate db. This should cause a deadlock if the block
2506
+ // processing is not acquiring the locks in the correct order.
2507
+ info ! ( " ------------------------------- SPAWNING BLOCKER THREAD" ) ;
2508
+ let blocker_thread = std:: thread:: spawn ( move || {
2509
+ // Wait a bit, to ensure the tenure will have grabbed any locks it needs
2510
+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 10 ) ) ;
2511
+
2512
+ // Lock the chainstate db
2513
+ info ! ( " ------------------------------- TRYING TO LOCK THE CHAINSTATE" ) ;
2514
+ let chainstate = & mut peer. stacks_node . as_mut ( ) . unwrap ( ) . chainstate ;
2515
+ let ( chainstate_tx, _) = chainstate. chainstate_tx_begin ( ) . unwrap ( ) ;
2516
+
2517
+ info ! ( " ------------------------------- SORTDB AND CHAINSTATE LOCKED" ) ;
2518
+ info ! ( " ------------------------------- BLOCKER THREAD FINISHED" ) ;
2519
+ } ) ;
2520
+
2521
+ info ! ( " ------------------------------- MINING TENURE" ) ;
2522
+ let ( block, burn_height, ..) = peer. single_block_tenure ( & private_key, |_| { } , |_| { } , |_| true ) ;
2523
+ info ! ( " ------------------------------- TENURE MINED" ) ;
2524
+
2525
+ // Wait for the blocker thread to finish
2526
+ blocker_thread. join ( ) . unwrap ( ) ;
2527
+ }
0 commit comments