@@ -696,6 +696,7 @@ impl TestStacksNode {
696696 mut after_block : G ,
697697 malleablize : bool ,
698698 mined_canonical : bool ,
699+ timestamp : Option < u64 > ,
699700 ) -> Result < Vec < ( NakamotoBlock , u64 , ExecutionCost , Vec < NakamotoBlock > ) > , ChainstateError >
700701 where
701702 S : FnMut ( & mut NakamotoBlockBuilder ) ,
@@ -804,6 +805,10 @@ impl TestStacksNode {
804805 & coinbase. clone ( ) . unwrap ( ) ,
805806 )
806807 } ;
808+ // Optionally overwrite the timestamp to enable predictable blocks.
809+ if let Some ( timestamp) = timestamp {
810+ builder. header . timestamp = timestamp;
811+ }
807812 miner_setup ( & mut builder) ;
808813
809814 tenure_change = None ;
@@ -1060,82 +1065,82 @@ impl TestStacksNode {
10601065 }
10611066}
10621067
1063- impl TestPeer < ' _ > {
1064- /// Get the Nakamoto parent linkage data for building atop the last-produced tenure or
1065- /// Stacks 2.x block.
1066- /// Returns (last-tenure-id, epoch2-parent, nakamoto-parent-tenure, parent-sortition)
1067- fn get_nakamoto_parent (
1068- miner : & TestMiner ,
1069- stacks_node : & TestStacksNode ,
1070- sortdb : & SortitionDB ,
1071- ) -> (
1072- StacksBlockId ,
1073- Option < StacksBlock > ,
1074- Option < Vec < NakamotoBlock > > ,
1075- ) {
1076- let tip = SortitionDB :: get_canonical_burn_chain_tip ( sortdb. conn ( ) ) . unwrap ( ) ;
1077- if let Some ( parent_blocks) = stacks_node. get_last_nakamoto_tenure ( miner) {
1078- debug ! ( "Parent will be a Nakamoto block" ) ;
1079-
1080- // parent is an epoch 3 nakamoto block
1081- let first_parent = parent_blocks. first ( ) . unwrap ( ) ;
1082- debug ! ( "First parent is {:?}" , first_parent) ;
1068+ /// Get the Nakamoto parent linkage data for building atop the last-produced tenure or
1069+ /// Stacks 2.x block.
1070+ /// Returns (last-tenure-id, epoch2-parent, nakamoto-parent-tenure, parent-sortition)
1071+ pub fn get_nakamoto_parent (
1072+ miner : & TestMiner ,
1073+ stacks_node : & TestStacksNode ,
1074+ sortdb : & SortitionDB ,
1075+ ) -> (
1076+ StacksBlockId ,
1077+ Option < StacksBlock > ,
1078+ Option < Vec < NakamotoBlock > > ,
1079+ ) {
1080+ let tip = SortitionDB :: get_canonical_burn_chain_tip ( sortdb. conn ( ) ) . unwrap ( ) ;
1081+ if let Some ( parent_blocks) = stacks_node. get_last_nakamoto_tenure ( miner) {
1082+ debug ! ( "Parent will be a Nakamoto block" ) ;
1083+
1084+ // parent is an epoch 3 nakamoto block
1085+ let first_parent = parent_blocks. first ( ) . unwrap ( ) ;
1086+ debug ! ( "First parent is {:?}" , first_parent) ;
1087+
1088+ // sanity check -- this parent must correspond to a sortition
1089+ assert ! (
1090+ SortitionDB :: get_block_snapshot_consensus(
1091+ sortdb. conn( ) ,
1092+ & first_parent. header. consensus_hash,
1093+ )
1094+ . unwrap( )
1095+ . unwrap( )
1096+ . sortition
1097+ ) ;
10831098
1084- // sanity check -- this parent must correspond to a sortition
1085- assert ! (
1086- SortitionDB :: get_block_snapshot_consensus(
1087- sortdb. conn( ) ,
1088- & first_parent. header. consensus_hash,
1089- )
1090- . unwrap( )
1091- . unwrap( )
1092- . sortition
1099+ let last_tenure_id = StacksBlockId :: new (
1100+ & first_parent. header . consensus_hash ,
1101+ & first_parent. header . block_hash ( ) ,
1102+ ) ;
1103+ ( last_tenure_id, None , Some ( parent_blocks) )
1104+ } else {
1105+ // parent may be an epoch 2.x block
1106+ let ( parent_opt, parent_sortition_opt) = if let Some ( parent_block) =
1107+ stacks_node. get_last_anchored_block ( miner)
1108+ {
1109+ debug ! ( "Parent will be a Stacks 2.x block" ) ;
1110+ let ic = sortdb. index_conn ( ) ;
1111+ let sort_opt = SortitionDB :: get_block_snapshot_for_winning_stacks_block (
1112+ & ic,
1113+ & tip. sortition_id ,
1114+ & parent_block. block_hash ( ) ,
1115+ )
1116+ . unwrap ( ) ;
1117+ if sort_opt. is_none ( ) {
1118+ warn ! ( "No parent sortition in epoch2: tip.sortition_id = {}, parent_block.block_hash() = {}" , & tip. sortition_id, & parent_block. block_hash( ) ) ;
1119+ }
1120+ ( Some ( parent_block) , sort_opt)
1121+ } else {
1122+ warn ! (
1123+ "No parent sortition in epoch2: tip.sortition_id = {}" ,
1124+ & tip. sortition_id
10931125 ) ;
1126+ ( None , None )
1127+ } ;
10941128
1095- let last_tenure_id = StacksBlockId :: new (
1096- & first_parent. header . consensus_hash ,
1097- & first_parent. header . block_hash ( ) ,
1098- ) ;
1099- ( last_tenure_id, None , Some ( parent_blocks) )
1129+ let last_tenure_id = if let Some ( last_epoch2_block) = parent_opt. as_ref ( ) {
1130+ let parent_sort = parent_sortition_opt. as_ref ( ) . unwrap ( ) ;
1131+ StacksBlockId :: new (
1132+ & parent_sort. consensus_hash ,
1133+ & last_epoch2_block. header . block_hash ( ) ,
1134+ )
11001135 } else {
1101- // parent may be an epoch 2.x block
1102- let ( parent_opt, parent_sortition_opt) = if let Some ( parent_block) =
1103- stacks_node. get_last_anchored_block ( miner)
1104- {
1105- debug ! ( "Parent will be a Stacks 2.x block" ) ;
1106- let ic = sortdb. index_conn ( ) ;
1107- let sort_opt = SortitionDB :: get_block_snapshot_for_winning_stacks_block (
1108- & ic,
1109- & tip. sortition_id ,
1110- & parent_block. block_hash ( ) ,
1111- )
1112- . unwrap ( ) ;
1113- if sort_opt. is_none ( ) {
1114- warn ! ( "No parent sortition in epoch2: tip.sortition_id = {}, parent_block.block_hash() = {}" , & tip. sortition_id, & parent_block. block_hash( ) ) ;
1115- }
1116- ( Some ( parent_block) , sort_opt)
1117- } else {
1118- warn ! (
1119- "No parent sortition in epoch2: tip.sortition_id = {}" ,
1120- & tip. sortition_id
1121- ) ;
1122- ( None , None )
1123- } ;
1124-
1125- let last_tenure_id = if let Some ( last_epoch2_block) = parent_opt. as_ref ( ) {
1126- let parent_sort = parent_sortition_opt. as_ref ( ) . unwrap ( ) ;
1127- StacksBlockId :: new (
1128- & parent_sort. consensus_hash ,
1129- & last_epoch2_block. header . block_hash ( ) ,
1130- )
1131- } else {
1132- // must be a genesis block (testing only!)
1133- StacksBlockId ( BOOT_BLOCK_HASH . 0 )
1134- } ;
1135- ( last_tenure_id, parent_opt, None )
1136- }
1136+ // must be a genesis block (testing only!)
1137+ StacksBlockId ( BOOT_BLOCK_HASH . 0 )
1138+ } ;
1139+ ( last_tenure_id, parent_opt, None )
11371140 }
1141+ }
11381142
1143+ impl TestPeer < ' _ > {
11391144 /// Start the next Nakamoto tenure.
11401145 /// This generates the VRF key and block-commit txs, as well as the TenureChange and
11411146 /// leader key this commit references
@@ -1161,7 +1166,7 @@ impl TestPeer<'_> {
11611166 Some ( nakamoto_parent_tenure. clone ( ) ) ,
11621167 )
11631168 } else {
1164- Self :: get_nakamoto_parent ( & self . miner , & stacks_node, & sortdb)
1169+ get_nakamoto_parent ( & self . miner , & stacks_node, & sortdb)
11651170 } ;
11661171
11671172 // find the VRF leader key register tx to use.
@@ -1464,6 +1469,7 @@ impl TestPeer<'_> {
14641469 after_block,
14651470 peer. mine_malleablized_blocks ,
14661471 peer. nakamoto_parent_tenure_opt . is_none ( ) ,
1472+ None ,
14671473 ) ?;
14681474
14691475 let just_blocks = blocks
@@ -1552,6 +1558,7 @@ impl TestPeer<'_> {
15521558 |_| true ,
15531559 self . mine_malleablized_blocks ,
15541560 self . nakamoto_parent_tenure_opt . is_none ( ) ,
1561+ None ,
15551562 )
15561563 . unwrap ( ) ;
15571564
0 commit comments