@@ -26,6 +26,7 @@ use blockstack_lib::chainstate::stacks::{
26
26
TransactionSpendingCondition , TransactionVersion ,
27
27
} ;
28
28
use blockstack_lib:: net:: api:: get_tenures_fork_info:: TenureForkingInfo ;
29
+ use blockstack_lib:: net:: api:: getsortition:: SortitionInfo ;
29
30
use clarity:: types:: chainstate:: { BurnchainHeaderHash , SortitionId } ;
30
31
use clarity:: util:: vrf:: VRFProof ;
31
32
use libsigner:: BlockProposal ;
@@ -128,13 +129,13 @@ fn check_proposal_units() {
128
129
setup_test_environment ( "check_proposal_units" ) ;
129
130
130
131
assert ! ( !view
131
- . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 )
132
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
132
133
. unwrap( ) ) ;
133
134
134
135
view. last_sortition = None ;
135
136
136
137
assert ! ( !view
137
- . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 )
138
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
138
139
. unwrap( ) ) ;
139
140
}
140
141
@@ -150,7 +151,8 @@ fn check_proposal_miner_pkh_mismatch() {
150
151
& mut signer_db,
151
152
& block,
152
153
& different_block_pk,
153
- 1
154
+ 1 ,
155
+ false ,
154
156
)
155
157
. unwrap( ) ) ;
156
158
@@ -161,7 +163,8 @@ fn check_proposal_miner_pkh_mismatch() {
161
163
& mut signer_db,
162
164
& block,
163
165
& different_block_pk,
164
- 1
166
+ 1 ,
167
+ false ,
165
168
)
166
169
. unwrap( ) ) ;
167
170
}
@@ -257,7 +260,7 @@ fn reorg_timing_testing(
257
260
config,
258
261
} = MockServerClient :: new ( ) ;
259
262
let h = std:: thread:: spawn ( move || {
260
- view. check_proposal ( & client, & mut signer_db, & block, & block_pk, 1 )
263
+ view. check_proposal ( & client, & mut signer_db, & block, & block_pk, 1 , false )
261
264
} ) ;
262
265
header_clone. chain_length -= 1 ;
263
266
let response = crate :: client:: tests:: build_get_tenure_tip_response (
@@ -294,16 +297,16 @@ fn check_proposal_invalid_status() {
294
297
setup_test_environment ( "invalid_status" ) ;
295
298
block. header . consensus_hash = view. cur_sortition . consensus_hash ;
296
299
assert ! ( view
297
- . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 )
300
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
298
301
. unwrap( ) ) ;
299
302
view. cur_sortition . miner_status = SortitionMinerStatus :: InvalidatedAfterFirstBlock ;
300
303
assert ! ( !view
301
- . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 )
304
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
302
305
. unwrap( ) ) ;
303
306
304
307
block. header . consensus_hash = view. last_sortition . as_ref ( ) . unwrap ( ) . consensus_hash ;
305
308
assert ! ( !view
306
- . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 )
309
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
307
310
. unwrap( ) ) ;
308
311
309
312
view. cur_sortition . miner_status = SortitionMinerStatus :: InvalidatedBeforeFirstBlock ;
@@ -314,7 +317,7 @@ fn check_proposal_invalid_status() {
314
317
// parent blocks have been seen before, while the signer state checks are only reasoning about
315
318
// stacks blocks seen by the signer, which may be a subset)
316
319
assert ! ( view
317
- . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 )
320
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
318
321
. unwrap( ) ) ;
319
322
}
320
323
@@ -363,7 +366,7 @@ fn check_proposal_tenure_extend_invalid_conditions() {
363
366
let tx = make_tenure_change_tx ( extend_payload) ;
364
367
block. txs = vec ! [ tx] ;
365
368
assert ! ( !view
366
- . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 )
369
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
367
370
. unwrap( ) ) ;
368
371
369
372
let mut extend_payload = make_tenure_change_payload ( ) ;
@@ -373,7 +376,7 @@ fn check_proposal_tenure_extend_invalid_conditions() {
373
376
let tx = make_tenure_change_tx ( extend_payload) ;
374
377
block. txs = vec ! [ tx] ;
375
378
assert ! ( view
376
- . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 )
379
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
377
380
. unwrap( ) ) ;
378
381
}
379
382
@@ -400,7 +403,8 @@ fn check_block_proposal_timeout() {
400
403
& mut signer_db,
401
404
& curr_sortition_block,
402
405
& block_pk,
403
- 1
406
+ 1 ,
407
+ false ,
404
408
)
405
409
. unwrap( ) ) ;
406
410
@@ -410,7 +414,8 @@ fn check_block_proposal_timeout() {
410
414
& mut signer_db,
411
415
& last_sortition_block,
412
416
& block_pk,
413
- 1
417
+ 1 ,
418
+ false ,
414
419
)
415
420
. unwrap( ) ) ;
416
421
@@ -422,7 +427,8 @@ fn check_block_proposal_timeout() {
422
427
& mut signer_db,
423
428
& curr_sortition_block,
424
429
& block_pk,
425
- 1
430
+ 1 ,
431
+ false ,
426
432
)
427
433
. unwrap( ) ) ;
428
434
@@ -432,7 +438,8 @@ fn check_block_proposal_timeout() {
432
438
& mut signer_db,
433
439
& last_sortition_block,
434
440
& block_pk,
435
- 1
441
+ 1 ,
442
+ false ,
436
443
)
437
444
. unwrap( ) ) ;
438
445
}
@@ -513,3 +520,64 @@ fn check_sortition_timeout() {
513
520
. is_timed_out( Duration :: from_secs( 1 ) , & signer_db)
514
521
. unwrap( ) ) ;
515
522
}
523
+
524
+ /// Test that the sortition info is refreshed once
525
+ /// when `check_proposal` is called with a sortition view
526
+ /// that doesn't match the block proposal
527
+ #[ test]
528
+ fn check_proposal_refresh ( ) {
529
+ let ( stacks_client, mut signer_db, block_pk, mut view, mut block) =
530
+ setup_test_environment ( "check_proposal_refresh" ) ;
531
+ block. header . consensus_hash = view. cur_sortition . consensus_hash ;
532
+ assert ! ( view
533
+ . check_proposal( & stacks_client, & mut signer_db, & block, & block_pk, 1 , false )
534
+ . unwrap( ) ) ;
535
+
536
+ let MockServerClient {
537
+ server,
538
+ client,
539
+ config : _,
540
+ } = MockServerClient :: new ( ) ;
541
+
542
+ let last_sortition = view. last_sortition . as_ref ( ) . unwrap ( ) ;
543
+
544
+ let expected_result = vec ! [
545
+ SortitionInfo {
546
+ burn_block_hash: last_sortition. burn_block_hash,
547
+ burn_block_height: 2 ,
548
+ sortition_id: SortitionId ( [ 2 ; 32 ] ) ,
549
+ parent_sortition_id: SortitionId ( [ 1 ; 32 ] ) ,
550
+ consensus_hash: block. header. consensus_hash,
551
+ was_sortition: true ,
552
+ burn_header_timestamp: 2 ,
553
+ miner_pk_hash160: Some ( view. cur_sortition. miner_pkh) ,
554
+ stacks_parent_ch: Some ( view. cur_sortition. parent_tenure_id) ,
555
+ last_sortition_ch: Some ( view. cur_sortition. parent_tenure_id) ,
556
+ committed_block_hash: None ,
557
+ } ,
558
+ SortitionInfo {
559
+ burn_block_hash: BurnchainHeaderHash ( [ 128 ; 32 ] ) ,
560
+ burn_block_height: 1 ,
561
+ sortition_id: SortitionId ( [ 1 ; 32 ] ) ,
562
+ parent_sortition_id: SortitionId ( [ 0 ; 32 ] ) ,
563
+ consensus_hash: view. cur_sortition. parent_tenure_id,
564
+ was_sortition: true ,
565
+ burn_header_timestamp: 1 ,
566
+ miner_pk_hash160: Some ( view. cur_sortition. miner_pkh) ,
567
+ stacks_parent_ch: Some ( view. cur_sortition. parent_tenure_id) ,
568
+ last_sortition_ch: Some ( view. cur_sortition. parent_tenure_id) ,
569
+ committed_block_hash: None ,
570
+ } ,
571
+ ] ;
572
+
573
+ view. cur_sortition . consensus_hash = ConsensusHash ( [ 128 ; 20 ] ) ;
574
+ let h = std:: thread:: spawn ( move || {
575
+ view. check_proposal ( & client, & mut signer_db, & block, & block_pk, 1 , true )
576
+ } ) ;
577
+ crate :: client:: tests:: write_response (
578
+ server,
579
+ format ! ( "HTTP/1.1 200 Ok\n \n {}" , serde_json:: json!( expected_result) ) . as_bytes ( ) ,
580
+ ) ;
581
+ let result = h. join ( ) . unwrap ( ) ;
582
+ assert ! ( result. unwrap( ) ) ;
583
+ }
0 commit comments