@@ -10854,12 +10854,11 @@ fn rejected_blocks_count_towards_miner_validity() {
10854
10854
let sender_addr = tests:: to_addr ( & sender_sk) ;
10855
10855
let send_amt = 100 ;
10856
10856
let send_fee = 180 ;
10857
- let nmb_txs = 2 ;
10858
10857
let recipient = PrincipalData :: from ( StacksAddress :: burn_address ( false ) ) ;
10859
10858
let block_proposal_timeout = Duration :: from_secs ( 20 ) ;
10860
10859
let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new_with_config_modifications (
10861
10860
num_signers,
10862
- vec ! [ ( sender_addr, ( send_amt + send_fee) * nmb_txs ) ] ,
10861
+ vec ! [ ( sender_addr, send_amt + send_fee) ] ,
10863
10862
|config| {
10864
10863
config. block_proposal_timeout = block_proposal_timeout;
10865
10864
} ,
@@ -10955,30 +10954,31 @@ fn rejected_blocks_count_towards_miner_validity() {
10955
10954
info ! ( "------------------------- Wait for Block N' Rejection -------------------------" ) ;
10956
10955
// TODO: need 429 handling enabled for this to pass here
10957
10956
wait_for ( 30 , || {
10958
- let chunks = test_observer:: get_stackerdb_chunks ( ) ;
10959
- for chunk in chunks. into_iter ( ) . flat_map ( |chunk| chunk. modified_slots ) {
10960
- let Ok ( message) = SignerMessage :: consensus_deserialize ( & mut chunk. data . as_slice ( ) )
10961
- else {
10962
- continue ;
10963
- } ;
10964
- if let SignerMessage :: BlockResponse ( BlockResponse :: Rejected ( BlockRejection {
10965
- reason : _reason,
10966
- reason_code,
10967
- signer_signature_hash,
10968
- ..
10969
- } ) ) = message
10970
- {
10971
- if signer_signature_hash
10972
- == block_proposal_n_prime. block . header . signer_signature_hash ( )
10973
- {
10974
- assert_eq ! ( reason_code, RejectCode :: SortitionViewMismatch ) ;
10975
- return Ok ( true ) ;
10957
+ let stackerdb_events = test_observer:: get_stackerdb_chunks ( ) ;
10958
+ let block_rejections = stackerdb_events
10959
+ . into_iter ( )
10960
+ . flat_map ( |chunk| chunk. modified_slots )
10961
+ . filter_map ( |chunk| {
10962
+ let message = SignerMessage :: consensus_deserialize ( & mut chunk. data . as_slice ( ) )
10963
+ . expect ( "Failed to deserialize SignerMessage" ) ;
10964
+ match message {
10965
+ SignerMessage :: BlockResponse ( BlockResponse :: Rejected ( rejection) ) => {
10966
+ if rejection. signer_signature_hash
10967
+ == block_proposal_n_prime. block . header . signer_signature_hash ( )
10968
+ {
10969
+ assert_eq ! ( rejection. reason_code, RejectCode :: SortitionViewMismatch ) ;
10970
+ Some ( rejection)
10971
+ } else {
10972
+ None
10973
+ }
10974
+ }
10975
+ _ => None ,
10976
10976
}
10977
- }
10978
- }
10979
- Ok ( false )
10977
+ } )
10978
+ . collect :: < Vec < _ > > ( ) ;
10979
+ Ok ( block_rejections . len ( ) >= num_signers * 7 / 10 )
10980
10980
} )
10981
- . expect ( "Timed out waiting for N' block rejection " ) ;
10981
+ . expect ( "FAIL: Timed out waiting for block proposal rejections of N' " ) ;
10982
10982
10983
10983
info ! ( "------------------------- Test Mine Block N+1 -------------------------" ) ;
10984
10984
// The signer should automatically attempt to mine a new block once the signers eventually tell it to abandon the previous block
@@ -11002,3 +11002,130 @@ fn rejected_blocks_count_towards_miner_validity() {
11002
11002
) ;
11003
11003
signer_test. shutdown ( ) ;
11004
11004
}
11005
+
11006
+ #[ test]
11007
+ #[ ignore]
11008
+ /// Test that signers mark a miner malicious if it doesn't propose any blocks before the block proposal timeout
11009
+ ///
11010
+ /// Test Setup:
11011
+ /// The test spins up five stacks signers, one miner Nakamoto node, and a corresponding bitcoind.
11012
+ /// The stacks node is then advanced to Epoch 3.0 boundary to allow block signing. The block proposal timeout is set to 20 seconds.
11013
+ ///
11014
+ /// Test Execution:
11015
+ /// Block proposals are paused for the miner.
11016
+ /// Tenure A starts.
11017
+ /// The test waits for the block proposal timeout + 1 second.
11018
+ /// Block proposals are unpaused for the miner.
11019
+ /// Miner propose a block N.
11020
+ /// Signers reject the block and mark the miner as malicious.
11021
+ ///
11022
+ //
11023
+ /// Test Assertion:
11024
+ /// Stacks tip does not advance to block N.
11025
+ fn block_proposal_timeout ( ) {
11026
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
11027
+ return ;
11028
+ }
11029
+
11030
+ tracing_subscriber:: registry ( )
11031
+ . with ( fmt:: layer ( ) )
11032
+ . with ( EnvFilter :: from_default_env ( ) )
11033
+ . init ( ) ;
11034
+
11035
+ info ! ( "------------------------- Test Setup -------------------------" ) ;
11036
+ let num_signers = 5 ;
11037
+ let block_proposal_timeout = Duration :: from_secs ( 20 ) ;
11038
+ let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new_with_config_modifications (
11039
+ num_signers,
11040
+ vec ! [ ] ,
11041
+ |config| {
11042
+ config. block_proposal_timeout = block_proposal_timeout;
11043
+ } ,
11044
+ |_| { } ,
11045
+ None ,
11046
+ None ,
11047
+ ) ;
11048
+
11049
+ signer_test. boot_to_epoch_3 ( ) ;
11050
+
11051
+ // Pause the miner's block proposals
11052
+ TEST_BROADCAST_STALL . set ( true ) ;
11053
+
11054
+ let wait_for_block_proposal = || {
11055
+ let mut block_proposal = None ;
11056
+ let _ = wait_for ( 30 , || {
11057
+ block_proposal = test_observer:: get_stackerdb_chunks ( )
11058
+ . into_iter ( )
11059
+ . flat_map ( |chunk| chunk. modified_slots )
11060
+ . find_map ( |chunk| {
11061
+ let message = SignerMessage :: consensus_deserialize ( & mut chunk. data . as_slice ( ) )
11062
+ . expect ( "Failed to deserialize SignerMessage" ) ;
11063
+ if let SignerMessage :: BlockProposal ( proposal) = message {
11064
+ return Some ( proposal) ;
11065
+ }
11066
+ None
11067
+ } ) ;
11068
+ Ok ( block_proposal. is_some ( ) )
11069
+ } ) ;
11070
+ block_proposal
11071
+ } ;
11072
+
11073
+ info ! ( "------------------------- Start Tenure A -------------------------" ) ;
11074
+ let commits_before = signer_test
11075
+ . running_nodes
11076
+ . commits_submitted
11077
+ . load ( Ordering :: SeqCst ) ;
11078
+
11079
+ next_block_and (
11080
+ & mut signer_test. running_nodes . btc_regtest_controller ,
11081
+ 60 ,
11082
+ || {
11083
+ let commits_count = signer_test
11084
+ . running_nodes
11085
+ . commits_submitted
11086
+ . load ( Ordering :: SeqCst ) ;
11087
+ Ok ( commits_count > commits_before)
11088
+ } ,
11089
+ )
11090
+ . unwrap ( ) ;
11091
+
11092
+ let chain_before = get_chain_info ( & signer_test. running_nodes . conf ) ;
11093
+ std:: thread:: sleep ( block_proposal_timeout. add ( Duration :: from_secs ( 1 ) ) ) ;
11094
+ test_observer:: clear ( ) ;
11095
+
11096
+ info ! ( "------------------------- Attempt Mine Block N -------------------------" ) ;
11097
+ TEST_BROADCAST_STALL . set ( false ) ;
11098
+
11099
+ let block_proposal_n = wait_for_block_proposal ( ) . expect ( "Failed to get block proposal N" ) ;
11100
+
11101
+ wait_for ( 30 , || {
11102
+ let stackerdb_events = test_observer:: get_stackerdb_chunks ( ) ;
11103
+ let block_rejections = stackerdb_events
11104
+ . into_iter ( )
11105
+ . flat_map ( |chunk| chunk. modified_slots )
11106
+ . filter_map ( |chunk| {
11107
+ let message = SignerMessage :: consensus_deserialize ( & mut chunk. data . as_slice ( ) )
11108
+ . expect ( "Failed to deserialize SignerMessage" ) ;
11109
+ match message {
11110
+ SignerMessage :: BlockResponse ( BlockResponse :: Rejected ( rejection) ) => {
11111
+ if rejection. signer_signature_hash
11112
+ == block_proposal_n. block . header . signer_signature_hash ( )
11113
+ {
11114
+ assert_eq ! ( rejection. reason_code, RejectCode :: SortitionViewMismatch ) ;
11115
+ Some ( rejection)
11116
+ } else {
11117
+ None
11118
+ }
11119
+ }
11120
+ _ => None ,
11121
+ }
11122
+ } )
11123
+ . collect :: < Vec < _ > > ( ) ;
11124
+ Ok ( block_rejections. len ( ) >= num_signers * 7 / 10 )
11125
+ } )
11126
+ . expect ( "FAIL: Timed out waiting for block proposal rejections" ) ;
11127
+
11128
+ let chain_after = get_chain_info ( & signer_test. running_nodes . conf ) ;
11129
+ assert_eq ! ( chain_after, chain_before) ;
11130
+ signer_test. shutdown ( ) ;
11131
+ }
0 commit comments