@@ -504,13 +504,11 @@ impl RelayerThread {
504
504
}
505
505
}
506
506
507
- /// Choose a miner directive based on the outcome of a sortition .
507
+ /// Choose a miner directive for a sortition with a winner .
508
508
///
509
509
/// The decision process is a little tricky, because the right decision depends on:
510
510
/// * whether or not we won the _given_ sortition (`sn`)
511
511
/// * whether or not we won the sortition that started the ongoing Stacks tenure
512
- /// * whether or not we won the last sortition with a winner
513
- /// * whether or not the last sortition winner has produced a Stacks block
514
512
/// * whether or not the ongoing Stacks tenure is at or descended from the last-winning
515
513
/// sortition
516
514
///
@@ -520,31 +518,30 @@ impl RelayerThread {
520
518
/// tenure-change. Otherwise, if we won the tenure which started the ongoing Stacks tenure
521
519
/// (i.e. we're the active miner), then we _may_ start mining after a timeout _if_ the winning
522
520
/// miner (not us) fails to submit a `BlockFound` tenure-change block for `sn`.
523
- ///
524
- /// Otherwise, if the given sortition `sn` has no winner, the find out who won the last sortition
525
- /// with a winner. If it was us, and if we haven't yet submitted a `BlockFound` tenure-change
526
- /// for it (which can happen if this given sortition is from a flash block), then start mining
527
- /// immediately with a "late" `BlockFound` tenure, _and_ prepare to start mining right afterwards
528
- /// with an `Extended` tenure-change so as to represent the given sortition `sn`'s burn view in
529
- /// the Stacks chain.
530
- ///
531
- /// Otherwise, if this sortition has no winner, and we did not win the last-winning sortition,
532
- /// then check to see if we're the ongoing Stack's tenure's miner. If so, then we _may_ start
533
- /// mining after a timeout _if_ the winner of the last-good sortition (not us) fails to submit
534
- /// a `BlockFound` tenure-change block. This can happen if `sn` was a flash block, and the
535
- /// remote miner has yet to process it.
536
- ///
537
- /// We won't always be able to mine -- for example, this could be an empty sortition, but the
538
- /// parent block could be an epoch 2 block. In this case, the right thing to do is to wait for
539
- /// the next block-commit.
540
- pub ( crate ) fn choose_miner_directive (
521
+ fn choose_directive_sortition_with_winner (
541
522
& mut self ,
542
523
sn : BlockSnapshot ,
543
- won_sortition : bool ,
524
+ mining_pk : Hash160 ,
544
525
committed_index_hash : StacksBlockId ,
545
526
) -> Option < MinerDirective > {
546
- // Reset the tenure extend time as we need to process this new sortition to deterine if we should extend
547
- self . tenure_extend_time = None ;
527
+ let won_sortition = sn. miner_pk_hash == Some ( mining_pk) ;
528
+ if won_sortition || self . config . get_node_config ( false ) . mock_mining {
529
+ // a sortition happenend, and we won
530
+ info ! ( "Won sortition; begin tenure." ;
531
+ "winning_sortition" => %sn. consensus_hash) ;
532
+ return Some ( MinerDirective :: BeginTenure {
533
+ parent_tenure_start : committed_index_hash,
534
+ burnchain_tip : sn. clone ( ) ,
535
+ election_block : sn,
536
+ late : false ,
537
+ } ) ;
538
+ }
539
+
540
+ // a sortition happened, but we didn't win. Check if we won the ongoing tenure.
541
+ debug ! (
542
+ "Relayer: did not win sortition {}, so stopping tenure" ,
543
+ & sn. sortition
544
+ ) ;
548
545
let ( canonical_stacks_tip_ch, _) =
549
546
SortitionDB :: get_canonical_stacks_chain_tip_hash ( self . sortdb . conn ( ) )
550
547
. expect ( "FATAL: failed to query sortition DB for stacks tip" ) ;
@@ -553,56 +550,68 @@ impl RelayerThread {
553
550
. expect ( "FATAL: failed to query sortiiton DB for epoch" )
554
551
. expect ( "FATAL: no sortition for canonical stacks tip" ) ;
555
552
556
- let mining_pkh_opt = self . get_mining_key_pkh ( ) ;
557
-
558
553
let won_ongoing_tenure_sortition =
559
- mining_pkh_opt. is_some ( ) && canonical_stacks_snapshot. miner_pk_hash == mining_pkh_opt;
560
-
561
- if sn. sortition {
562
- // a sortition happened
563
- if won_sortition || self . config . get_node_config ( false ) . mock_mining {
564
- // a sortition happenend, and we won
565
- info ! ( "Relayer: Won sortition; begin tenure." ;
566
- "winning_sortition" => %sn. consensus_hash) ;
567
- return Some ( MinerDirective :: BeginTenure {
568
- parent_tenure_start : committed_index_hash,
569
- burnchain_tip : sn. clone ( ) ,
570
- election_block : sn,
571
- late : false ,
572
- } ) ;
573
- }
574
-
575
- // a sortition happened, but we didn't win.
576
- debug ! (
577
- "Relayer: did not win sortition {}, so stopping tenure" ,
578
- & sn. sortition
579
- ) ;
580
-
581
- if won_ongoing_tenure_sortition {
582
- // we won the current ongoing tenure, but not the most recent sortition. Should we attempt to extend immediately or wait for the incoming miner?
583
- if let Ok ( result) = Self :: find_highest_valid_sortition (
584
- & self . sortdb ,
585
- & mut self . chainstate ,
586
- & sn,
587
- & canonical_stacks_snapshot. consensus_hash ,
588
- ) {
589
- if result. is_some ( ) {
590
- debug ! ( "Relayer: Did not win current sortition but won the prior valid sortition. Will attempt to extend tenure after allowing the new miner some time to come online." ;
591
- "tenure_extend_wait_timeout_ms" => self . config. miner. tenure_extend_wait_timeout. as_millis( ) ,
592
- ) ;
593
- self . tenure_extend_time = Some ( TenureExtendTime :: delayed (
594
- self . config . miner . tenure_extend_wait_timeout ,
595
- ) ) ;
596
- } else {
597
- info ! ( "Relayer: no valid sortition since our last winning sortition. Will extend tenure." ) ;
598
- self . tenure_extend_time = Some ( TenureExtendTime :: immediate ( ) ) ;
599
- }
554
+ canonical_stacks_snapshot. miner_pk_hash == Some ( mining_pk) ;
555
+ if won_ongoing_tenure_sortition {
556
+ // we won the current ongoing tenure, but not the most recent sortition. Should we attempt to extend immediately or wait for the incoming miner?
557
+ if let Ok ( result) = Self :: find_highest_valid_sortition (
558
+ & self . sortdb ,
559
+ & mut self . chainstate ,
560
+ & sn,
561
+ & canonical_stacks_snapshot. consensus_hash ,
562
+ ) {
563
+ if result. is_some ( ) {
564
+ debug ! ( "Relayer: Did not win current sortition but won the prior valid sortition. Will attempt to extend tenure after allowing the new miner some time to come online." ;
565
+ "tenure_extend_wait_timeout_ms" => self . config. miner. tenure_extend_wait_timeout. as_millis( ) ,
566
+ ) ;
567
+ self . tenure_extend_time = Some ( TenureExtendTime :: delayed (
568
+ self . config . miner . tenure_extend_wait_timeout ,
569
+ ) ) ;
570
+ } else {
571
+ info ! ( "Relayer: no valid sortition since our last winning sortition. Will extend tenure." ) ;
572
+ self . tenure_extend_time = Some ( TenureExtendTime :: immediate ( ) ) ;
600
573
}
601
574
}
602
- return Some ( MinerDirective :: StopTenure ) ;
603
575
}
576
+ return Some ( MinerDirective :: StopTenure ) ;
577
+ }
578
+
579
+ /// Choose a miner directive for a sortition with no winner.
580
+ ///
581
+ /// The decision process is a little tricky, because the right decision depends on:
582
+ /// * whether or not we won the sortition that started the ongoing Stacks tenure
583
+ /// * whether or not we won the last sortition with a winner
584
+ /// * whether or not the last sortition winner has produced a Stacks block
585
+ /// * whether or not the ongoing Stacks tenure is at or descended from the last-winning
586
+ /// sortition
587
+ ///
588
+ /// Find out who won the last sortition with a winner. If it was us, and if we haven't yet
589
+ /// submitted a `BlockFound` tenure-change for it (which can happen if this given sortition is
590
+ /// from a flash block), then start mining immediately with a "late" `BlockFound` tenure, _and_
591
+ /// prepare to start mining right afterwards with an `Extended` tenure-change so as to represent
592
+ /// the given sortition `sn`'s burn view in the Stacks chain.
593
+ ///
594
+ /// Otherwise, if did not win the last-winning sortition, then check to see if we're the ongoing
595
+ /// Stack's tenure's miner. If so, then we _may_ start mining after a timeout _if_ the winner of
596
+ /// the last-good sortition (not us) fails to submit a `BlockFound` tenure-change block.
597
+ /// This can happen if `sn` was a flash block, and the remote miner has yet to process it.
598
+ ///
599
+ /// We won't always be able to mine -- for example, this could be an empty sortition, but the
600
+ /// parent block could be an epoch 2 block. In this case, the right thing to do is to wait for
601
+ /// the next block-commit.
602
+ fn choose_directive_sortition_without_winner (
603
+ & mut self ,
604
+ sn : BlockSnapshot ,
605
+ mining_pk : Hash160 ,
606
+ ) -> Option < MinerDirective > {
607
+ let ( canonical_stacks_tip_ch, _) =
608
+ SortitionDB :: get_canonical_stacks_chain_tip_hash ( self . sortdb . conn ( ) )
609
+ . expect ( "FATAL: failed to query sortition DB for stacks tip" ) ;
610
+ let canonical_stacks_snapshot =
611
+ SortitionDB :: get_block_snapshot_consensus ( self . sortdb . conn ( ) , & canonical_stacks_tip_ch)
612
+ . expect ( "FATAL: failed to query sortiiton DB for epoch" )
613
+ . expect ( "FATAL: no sortition for canonical stacks tip" ) ;
604
614
605
- // no sortition happened.
606
615
// find out what epoch the Stacks tip is in.
607
616
// If it's in epoch 2.x, then we must always begin a new tenure, but we can't do so
608
617
// right now since this sortition has no winner.
@@ -632,9 +641,7 @@ impl RelayerThread {
632
641
return None ;
633
642
} ;
634
643
635
- let won_last_winning_snapshot =
636
- mining_pkh_opt. is_some ( ) && last_winning_snapshot. miner_pk_hash == mining_pkh_opt;
637
-
644
+ let won_last_winning_snapshot = last_winning_snapshot. miner_pk_hash == Some ( mining_pk) ;
638
645
if won_last_winning_snapshot {
639
646
debug ! (
640
647
"Relayer: we won the last winning sortition {}" ,
@@ -657,8 +664,8 @@ impl RelayerThread {
657
664
late : true ,
658
665
} ) ;
659
666
}
660
- let tip_is_last_winning_snapshot = mining_pkh_opt . is_some ( )
661
- && canonical_stacks_snapshot . block_height == last_winning_snapshot. block_height
667
+ let tip_is_last_winning_snapshot = canonical_stacks_snapshot . block_height
668
+ == last_winning_snapshot. block_height
662
669
&& canonical_stacks_snapshot. consensus_hash == last_winning_snapshot. consensus_hash ;
663
670
664
671
if tip_is_last_winning_snapshot {
@@ -671,6 +678,8 @@ impl RelayerThread {
671
678
}
672
679
}
673
680
681
+ let won_ongoing_tenure_sortition =
682
+ canonical_stacks_snapshot. miner_pk_hash == Some ( mining_pk) ;
674
683
if won_ongoing_tenure_sortition {
675
684
info ! ( "Relayer: No sortition, but we produced the canonical Stacks tip. Will extend tenure." ) ;
676
685
if !won_last_winning_snapshot {
@@ -818,8 +827,17 @@ impl RelayerThread {
818
827
. raise_initiative ( "process_sortition" . to_string ( ) ) ;
819
828
return Ok ( None ) ;
820
829
}
821
-
822
- let directive_opt = self . choose_miner_directive ( sn, won_sortition, committed_index_hash) ;
830
+ // Reset the tenure extend time
831
+ self . tenure_extend_time = None ;
832
+ let Some ( mining_pk) = self . get_mining_key_pkh ( ) else {
833
+ debug ! ( "No mining key, will not mine" ) ;
834
+ return Ok ( None ) ;
835
+ } ;
836
+ let directive_opt = if sn. sortition {
837
+ self . choose_directive_sortition_with_winner ( sn, mining_pk, committed_index_hash)
838
+ } else {
839
+ self . choose_directive_sortition_without_winner ( sn, mining_pk)
840
+ } ;
823
841
debug ! (
824
842
"Relayer: Processed sortition {}: Miner directive is {:?}" ,
825
843
& consensus_hash, & directive_opt
0 commit comments