@@ -528,6 +528,17 @@ impl NakamotoChainState {
528
528
}
529
529
}
530
530
531
+ /// Get the nakamoto tenure by id
532
+ pub fn get_nakamoto_tenure_change_by_tenure_id (
533
+ headers_conn : & Connection ,
534
+ tenure_consensus_hash : & ConsensusHash ,
535
+ ) -> Result < Option < NakamotoTenure > , ChainstateError > {
536
+ let sql = "SELECT * FROM nakamoto_tenures WHERE tenure_id_consensus_hash = ?1 ORDER BY tenure_index DESC LIMIT 1" ;
537
+ let args: & [ & dyn ToSql ] = & [ & tenure_consensus_hash] ;
538
+ let tenure_opt: Option < NakamotoTenure > = query_row ( headers_conn, sql, args) ?;
539
+ Ok ( tenure_opt)
540
+ }
541
+
531
542
/// Get a nakamoto tenure-change by its tenure ID consensus hash.
532
543
/// Get the highest such record. It will be the last-processed BlockFound tenure
533
544
/// for the given sortition consensus hash.
@@ -544,7 +555,7 @@ impl NakamotoChainState {
544
555
Ok ( tenure_opt)
545
556
}
546
557
547
- /// Get the highest processed tenure on the canonical sortition history.
558
+ /// Get the highest non-empty processed tenure on the canonical sortition history.
548
559
pub fn get_highest_nakamoto_tenure (
549
560
headers_conn : & Connection ,
550
561
sortdb_conn : & Connection ,
@@ -555,10 +566,7 @@ impl NakamotoChainState {
555
566
// no chain tip, so no tenure
556
567
return Ok ( None ) ;
557
568
}
558
- let sql = "SELECT * FROM nakamoto_tenures WHERE tenure_id_consensus_hash = ?1 ORDER BY tenure_index DESC LIMIT 1" ;
559
- let args: & [ & dyn ToSql ] = & [ & tip_ch] ;
560
- let tenure_opt: Option < NakamotoTenure > = query_row ( headers_conn, sql, args) ?;
561
- Ok ( tenure_opt)
569
+ Self :: get_nakamoto_tenure_change_by_tenure_id ( headers_conn, & tip_ch)
562
570
}
563
571
564
572
/// Verify that a tenure change tx is a valid first-ever tenure change. It must connect to an
@@ -655,7 +663,7 @@ impl NakamotoChainState {
655
663
/// * previous_tenure_blocks
656
664
/// * cause
657
665
///
658
- /// Returns Ok(Some(highest- processed-tenure)) on success
666
+ /// Returns Ok(Some(processed-tenure)) on success
659
667
/// Returns Ok(None) if the tenure change is invalid
660
668
/// Returns Err(..) on DB error
661
669
pub ( crate ) fn check_nakamoto_tenure < SH : SortitionHandle > (
@@ -742,10 +750,13 @@ impl NakamotoChainState {
742
750
return Ok ( None ) ;
743
751
}
744
752
745
- let Some ( highest_processed_tenure) =
746
- Self :: get_highest_nakamoto_tenure ( headers_conn, sort_handle. sqlite ( ) ) ?
753
+ // Note in the extend case, this will actually return the current tenure, not the parent as prev_tenure_consensus_hash will be the same as tenure_consensus_hash
754
+ let Some ( tenure) = Self :: get_nakamoto_tenure_change_by_tenure_id (
755
+ headers_conn,
756
+ & tenure_payload. prev_tenure_consensus_hash ,
757
+ ) ?
747
758
else {
748
- // no previous tenures . This is the first tenure change. It should point to an epoch
759
+ // not building off of a previous Nakamoto tenure . This is the first tenure change. It should point to an epoch
749
760
// 2.x block.
750
761
return Self :: check_first_nakamoto_tenure_change ( headers_conn, tenure_payload) ;
751
762
} ;
@@ -764,84 +775,34 @@ impl NakamotoChainState {
764
775
) ;
765
776
return Ok ( None ) ;
766
777
}
767
- if tenure_payload. burn_view_consensus_hash
768
- == highest_processed_tenure. burn_view_consensus_hash
769
- {
770
- // if we're extending tenure within the same sortition, then the tenure and
771
- // prev_tenure consensus hashes must match that of the highest.
772
- if highest_processed_tenure. tenure_id_consensus_hash
773
- != tenure_payload. tenure_consensus_hash
774
- || highest_processed_tenure. tenure_id_consensus_hash
775
- != tenure_payload. prev_tenure_consensus_hash
776
- {
777
- warn ! ( "Invalid tenure-change: tenure extension within the same sortition tries to override the highest sortition" ;
778
- "tenure_consensus_hash" => %tenure_payload. tenure_consensus_hash,
779
- "prev_tenure_consensus_hash" => %tenure_payload. prev_tenure_consensus_hash,
780
- "highest_processed_tenure.consensus_hash" => %highest_processed_tenure. tenure_id_consensus_hash,
781
- "highest_processed_tenure.prev_consensus_hash" => %highest_processed_tenure. prev_tenure_id_consensus_hash
782
- ) ;
783
- return Ok ( None ) ;
784
- }
785
- }
786
778
}
787
- }
788
-
789
- let Some ( last_tenure_finish_block_id) = Self :: get_nakamoto_tenure_finish_block_header (
790
- headers_conn,
791
- & highest_processed_tenure. tenure_id_consensus_hash ,
792
- ) ?
793
- . map ( |hdr| hdr. index_block_hash ( ) ) else {
794
- // last tenure doesn't exist (should be unreachable)
795
- warn ! ( "Invalid tenure-change: no blocks found for highest processed tenure" ;
796
- "consensus_hash" => %highest_processed_tenure. tenure_id_consensus_hash,
797
- ) ;
798
- return Ok ( None ) ;
799
779
} ;
800
780
801
- // must build atop the highest-processed tenure.
802
- // NOTE: for tenure-extensions, the second check is always false, since the tenure and
803
- // prev-tenure consensus hashes must be the same per the above check.
804
- if last_tenure_finish_block_id != tenure_payload. previous_tenure_end
805
- || highest_processed_tenure. tenure_id_consensus_hash
806
- != tenure_payload. prev_tenure_consensus_hash
807
- {
808
- // not continuous -- this tenure-change does not point to the end of the
809
- // last-processed tenure, or does not point to the last-processed tenure's sortition
810
- warn ! ( "Invalid tenure-change: discontiguous" ;
811
- "tenure_consensus_hash" => %tenure_payload. tenure_consensus_hash,
812
- "prev_tenure_consensus_hash" => %tenure_payload. prev_tenure_consensus_hash,
813
- "highest_processed_tenure.consensus_hash" => %highest_processed_tenure. tenure_id_consensus_hash,
814
- "last_tenure_finish_block_id" => %last_tenure_finish_block_id,
815
- "tenure_payload.previous_tenure_end" => %tenure_payload. previous_tenure_end
816
- ) ;
817
- return Ok ( None ) ;
818
- }
819
-
820
- // The tenure-change must report the number of blocks _so far_ in the current tenure. If
821
- // there is a succession of tenure-extensions for a given tenure, then the reported tenure
781
+ // The tenure-change must report the number of blocks _so far_ in the previous tenure (note if this is a TenureChangeCause::Extended, then its parent tenure will be its own tenure).
782
+ // If there is a succession of tenure-extensions for a given tenure, then the reported tenure
822
783
// length must report the number of blocks since the last _sortition-induced_ tenure
823
784
// change.
824
785
let tenure_len = Self :: get_nakamoto_tenure_length (
825
786
headers_conn,
826
- & highest_processed_tenure . tenure_id_consensus_hash ,
787
+ & tenure_payload . prev_tenure_consensus_hash ,
827
788
) ?;
828
789
if tenure_len != tenure_payload. previous_tenure_blocks {
829
790
// invalid -- does not report the correct number of blocks in the past tenure
830
791
warn ! ( "Invalid tenure-change: wrong number of blocks" ;
831
792
"tenure_consensus_hash" => %tenure_payload. tenure_consensus_hash,
832
- "highest_processed_tenure.consensus_hash " => %highest_processed_tenure . tenure_id_consensus_hash ,
793
+ "prev_tenure_consensus_hash " => %tenure_payload . prev_tenure_consensus_hash ,
833
794
"tenure_len" => tenure_len,
834
795
"tenure_payload.previous_tenure_blocks" => tenure_payload. previous_tenure_blocks
835
796
) ;
836
797
return Ok ( None ) ;
837
798
}
838
799
839
- Ok ( Some ( highest_processed_tenure ) )
800
+ Ok ( Some ( tenure ) )
840
801
}
841
802
842
803
/// Advance the tenures table with a validated block's tenure data.
843
804
/// This applies to both tenure-changes and tenure-extends.
844
- /// Returns the highest tenure-change height (this is parent_coinbase_height + 1 if there was a
805
+ /// Returns the tenure-change height (this is parent_coinbase_height + 1 if there was a
845
806
/// tenure-change tx, or just parent_coinbase_height if there was a tenure-extend tx or no tenure
846
807
/// txs at all).
847
808
/// TODO: unit test
@@ -869,7 +830,7 @@ impl NakamotoChainState {
869
830
}
870
831
} ;
871
832
872
- let Some ( highest_processed_tenure ) =
833
+ let Some ( processed_tenure ) =
873
834
Self :: check_nakamoto_tenure ( headers_tx, sort_tx, & block. header , tenure_payload) ?
874
835
else {
875
836
return Err ( ChainstateError :: InvalidStacksTransaction (
@@ -882,7 +843,7 @@ impl NakamotoChainState {
882
843
headers_tx,
883
844
& block. header ,
884
845
coinbase_height,
885
- highest_processed_tenure
846
+ processed_tenure
886
847
. tenure_index
887
848
. checked_add ( 1 )
888
849
. expect ( "too many tenure-changes" ) ,
0 commit comments