@@ -1005,13 +1005,13 @@ impl NakamotoBlock {
10051005 /// If it's present, then it's the first transaction (i.e. tx 0).
10061006 /// NOTE: this does _not_ return a tenure-extend transaction payload.
10071007 pub fn get_tenure_change_tx_payload ( & self ) -> Option < & TenureChangePayload > {
1008- if self . is_wellformed_tenure_start_block ( ) != Ok ( true ) {
1008+ let Ok ( true ) = self . is_wellformed_tenure_start_block ( ) else {
10091009 // no tenure-change, or invalid
10101010 return None ;
1011- }
1011+ } ;
10121012
10131013 // if it exists, it's the first
1014- self . txs . get ( 0 ) . and_then ( |tx| {
1014+ self . txs . first ( ) . and_then ( |tx| {
10151015 if let TransactionPayload :: TenureChange ( ref tc) = & tx. payload {
10161016 Some ( tc)
10171017 } else {
@@ -1024,13 +1024,13 @@ impl NakamotoBlock {
10241024 /// If it's present, then it's the first transaction (i.e. tx 0)
10251025 /// NOTE: this does _not_ return a tenure-change transaction payload.
10261026 pub fn get_tenure_extend_tx_payload ( & self ) -> Option < & TenureChangePayload > {
1027- if self . is_wellformed_tenure_extend_block ( ) != Ok ( true ) {
1027+ let Ok ( true ) = self . is_wellformed_tenure_extend_block ( ) else {
10281028 // no tenure-extend, or invalid
10291029 return None ;
1030- }
1030+ } ;
10311031
10321032 // if it exists, it's the first
1033- self . txs . get ( 0 ) . and_then ( |tx| {
1033+ self . txs . first ( ) . and_then ( |tx| {
10341034 if let TransactionPayload :: TenureChange ( ref tc) = & tx. payload {
10351035 Some ( tc)
10361036 } else {
@@ -1048,16 +1048,16 @@ impl NakamotoBlock {
10481048 if let Some ( payload) = self . get_tenure_extend_tx_payload ( ) {
10491049 return Some ( payload) ;
10501050 }
1051- return None ;
1051+ None
10521052 }
10531053
10541054 /// Get the coinbase transaction in Nakamoto.
10551055 /// It's the first non-TenureChange transaction (i.e. tx 1)
10561056 pub fn get_coinbase_tx ( & self ) -> Option < & StacksTransaction > {
1057- if self . is_wellformed_tenure_start_block ( ) != Ok ( true ) {
1057+ let Ok ( true ) = self . is_wellformed_tenure_start_block ( ) else {
10581058 // not a tenure-change block, or invalid
10591059 return None ;
1060- }
1060+ } ;
10611061
10621062 // there is one coinbase.
10631063 // go find it.
@@ -1083,7 +1083,7 @@ impl NakamotoBlock {
10831083 /// Return Some(tenure-change-payload) if it's a tenure change
10841084 /// Return None if not
10851085 pub fn try_get_tenure_change_payload ( & self ) -> Option < & TenureChangePayload > {
1086- if let TransactionPayload :: TenureChange ( ref tc) = & self . txs . get ( 0 ) ?. payload {
1086+ if let TransactionPayload :: TenureChange ( ref tc) = & self . txs . first ( ) ?. payload {
10871087 Some ( tc)
10881088 } else {
10891089 None
@@ -1099,14 +1099,14 @@ impl NakamotoBlock {
10991099 ///
11001100 /// Returns Ok(true) if the above are true
11011101 /// Returns Ok(false) if it is not a tenure-extend block
1102- /// Returns Err(()) if this block cannot be a valid block
1103- pub fn is_wellformed_tenure_extend_block ( & self ) -> Result < bool , ( ) > {
1102+ /// Returns Err(ChainstateError::InvalidStacksBlock) if this block cannot be a valid block
1103+ pub fn is_wellformed_tenure_extend_block ( & self ) -> Result < bool , ChainstateError > {
1104+ let err = ChainstateError :: InvalidStacksBlock ( "Malformed tenure-extend block" . into ( ) ) ;
11041105 // find coinbases
11051106 let has_coinbase = self
11061107 . txs
11071108 . iter ( )
1108- . find ( |tx| matches ! ( & tx. payload, TransactionPayload :: Coinbase ( ..) ) )
1109- . is_some ( ) ;
1109+ . any ( |tx| matches ! ( & tx. payload, TransactionPayload :: Coinbase ( ..) ) ) ;
11101110
11111111 if has_coinbase {
11121112 // can't be
@@ -1137,7 +1137,7 @@ impl NakamotoBlock {
11371137 "Invalid block -- {} tenure txs" ,
11381138 tenure_change_positions. len( )
11391139 ) ;
1140- return Err ( ( ) ) ;
1140+ return Err ( err ) ;
11411141 }
11421142
11431143 let Some ( tc_payload) = self . try_get_tenure_change_payload ( ) else {
@@ -1146,7 +1146,7 @@ impl NakamotoBlock {
11461146 "stacks_block_hash" => %self . header. block_hash( ) ,
11471147 "stacks_block_id" => %self . header. block_id( )
11481148 ) ;
1149- return Err ( ( ) ) ;
1149+ return Err ( err ) ;
11501150 } ;
11511151 if tc_payload. cause != TenureChangeCause :: Extended {
11521152 // not a tenure-extend, and can't be valid since all other tenure-change types require
@@ -1156,7 +1156,7 @@ impl NakamotoBlock {
11561156 "stacks_block_hash" => %self . header. block_hash( ) ,
11571157 "stacks_block_id" => %self . header. block_id( )
11581158 ) ;
1159- return Err ( ( ) ) ;
1159+ return Err ( err ) ;
11601160 }
11611161
11621162 if tc_payload. previous_tenure_end != self . header . parent_block_id {
@@ -1169,7 +1169,7 @@ impl NakamotoBlock {
11691169 "stacks_block_hash" => %self . header. block_hash( ) ,
11701170 "stacks_block_id" => %self . header. block_id( )
11711171 ) ;
1172- return Err ( ( ) ) ;
1172+ return Err ( err ) ;
11731173 }
11741174
11751175 if tc_payload. tenure_consensus_hash != self . header . consensus_hash
@@ -1184,7 +1184,7 @@ impl NakamotoBlock {
11841184 "stacks_block_hash" => %self . header. block_hash( ) ,
11851185 "stacks_block_id" => %self . header. block_id( )
11861186 ) ;
1187- return Err ( ( ) ) ;
1187+ return Err ( err ) ;
11881188 }
11891189
11901190 Ok ( true )
@@ -1198,9 +1198,10 @@ impl NakamotoBlock {
11981198 ///
11991199 /// Returns Ok(true) if the above are true
12001200 /// Returns Ok(false) if this is not a tenure-start block
1201- /// Returns Err(() ) if this block cannot be a valid block
1202- pub fn is_wellformed_tenure_start_block ( & self ) -> Result < bool , ( ) > {
1201+ /// Returns Err(ChainstateError::InvalidStacksBlock ) if this block cannot be a valid block
1202+ pub fn is_wellformed_tenure_start_block ( & self ) -> Result < bool , ChainstateError > {
12031203 // sanity check -- this may contain no coinbases or tenure-changes
1204+ let err = ChainstateError :: InvalidStacksBlock ( "Malformed tenure-start block" . into ( ) ) ;
12041205 let coinbase_positions = self
12051206 . txs
12061207 . iter ( )
@@ -1243,7 +1244,7 @@ impl NakamotoBlock {
12431244 "stacks_block_hash" => %self . header. block_hash( ) ,
12441245 "stacks_block_id" => %self . header. block_id( )
12451246 ) ;
1246- return Err ( ( ) ) ;
1247+ return Err ( err ) ;
12471248 }
12481249
12491250 let coinbase_position = coinbase_positions. first ( ) . copied ( ) ;
@@ -1256,7 +1257,7 @@ impl NakamotoBlock {
12561257 "stacks_block_hash" => %self . header. block_hash( ) ,
12571258 "stacks_block_id" => %self . header. block_id( )
12581259 ) ;
1259- return Err ( ( ) ) ;
1260+ return Err ( err ) ;
12601261 }
12611262
12621263 if let ( None , Some ( tenure_change_position) ) = ( coinbase_position, tenure_change_position) {
@@ -1265,13 +1266,12 @@ impl NakamotoBlock {
12651266 if tenure_change_position != 0 {
12661267 // wrong position
12671268 warn ! (
1268- "Invalid block -- tenure change positions = {:?}, expected [0]" ,
1269- & tenure_change_positions;
1269+ "Invalid block -- tenure change positions = {tenure_change_positions:?}, expected [0]" ;
12701270 "consensus_hash" => %self . header. consensus_hash,
12711271 "stacks_block_hash" => %self . header. block_hash( ) ,
12721272 "stacks_block_id" => %self . header. block_id( )
12731273 ) ;
1274- return Err ( ( ) ) ;
1274+ return Err ( err ) ;
12751275 }
12761276
12771277 // must be a non-sortition-triggered tenure change
@@ -1285,7 +1285,7 @@ impl NakamotoBlock {
12851285 "stacks_block_hash" => %self . header. block_hash( ) ,
12861286 "stacks_block_id" => %self . header. block_id( )
12871287 ) ;
1288- return Err ( ( ) ) ;
1288+ return Err ( err ) ;
12891289 } ;
12901290
12911291 if tc_payload. cause . expects_sortition ( ) {
@@ -1295,7 +1295,7 @@ impl NakamotoBlock {
12951295 "stacks_block_hash" => %self . header. block_hash( ) ,
12961296 "stacks_block_id" => %self . header. block_id( )
12971297 ) ;
1298- return Err ( ( ) ) ;
1298+ return Err ( err ) ;
12991299 }
13001300
13011301 // not a tenure-start block, but syntactically valid w.r.t. tenure changes
@@ -1308,20 +1308,20 @@ impl NakamotoBlock {
13081308 if coinbase_position != Some ( coinbase_idx) && tenure_change_position != Some ( tc_idx) {
13091309 // invalid -- expect exactly one sortition-induced tenure change and exactly one coinbase expected,
13101310 // and the tenure change must be the first transaction and the coinbase must be the second transaction
1311- warn ! ( "Invalid block -- coinbase and/or tenure change txs are in the wrong position -- ({:?}, {:?}) != [{}], [{}]" , & coinbase_positions , & tenure_change_positions , coinbase_idx , tc_idx ;
1311+ warn ! ( "Invalid block -- coinbase and/or tenure change txs are in the wrong position -- ({coinbase_positions :?}, {tenure_change_positions :?}) != [{coinbase_idx }], [{tc_idx }]" ;
13121312 "consensus_hash" => %self . header. consensus_hash,
13131313 "stacks_block_hash" => %self . header. block_hash( ) ,
13141314 "stacks_block_id" => %self . header. block_id( )
13151315 ) ;
1316- return Err ( ( ) ) ;
1316+ return Err ( err ) ;
13171317 }
13181318 let Some ( tc_payload) = self . try_get_tenure_change_payload ( ) else {
13191319 warn ! ( "Invalid block -- tx at index 0 is not a tenure tx" ;
13201320 "consensus_hash" => %self . header. consensus_hash,
13211321 "stacks_block_hash" => %self . header. block_hash( ) ,
13221322 "stacks_block_id" => %self . header. block_id( )
13231323 ) ;
1324- return Err ( ( ) ) ;
1324+ return Err ( err ) ;
13251325 } ;
13261326 if !tc_payload. cause . expects_sortition ( ) {
13271327 // the only tenure change allowed in a block with a coinbase is a sortition-triggered
@@ -1331,7 +1331,7 @@ impl NakamotoBlock {
13311331 "stacks_block_hash" => %self . header. block_hash( ) ,
13321332 "stacks_block_id" => %self . header. block_id( )
13331333 ) ;
1334- return Err ( ( ) ) ;
1334+ return Err ( err ) ;
13351335 }
13361336 if tc_payload. previous_tenure_end != self . header . parent_block_id {
13371337 // discontinuous
@@ -1342,7 +1342,7 @@ impl NakamotoBlock {
13421342 "stacks_block_hash" => %self . header. block_hash( ) ,
13431343 "stacks_block_id" => %self . header. block_id( )
13441344 ) ;
1345- return Err ( ( ) ) ;
1345+ return Err ( err ) ;
13461346 }
13471347
13481348 // must be a Nakamoto coinbase
@@ -1351,13 +1351,12 @@ impl NakamotoBlock {
13511351 else {
13521352 // this transaction is not a coinbase (but this should be unreachable)
13531353 warn ! (
1354- "Invalid block -- tx index {} is not a coinbase" ,
1355- coinbase_idx;
1354+ "Invalid block -- tx index {coinbase_idx} is not a coinbase" ;
13561355 "consensus_hash" => %self . header. consensus_hash,
13571356 "stacks_block_hash" => %self . header. block_hash( ) ,
13581357 "stacks_block_id" => %self . header. block_id( )
13591358 ) ;
1360- return Err ( ( ) ) ;
1359+ return Err ( err ) ;
13611360 } ;
13621361 if vrf_proof_opt. is_none ( ) {
13631362 // not a Nakamoto coinbase
@@ -1366,10 +1365,10 @@ impl NakamotoBlock {
13661365 "stacks_block_hash" => %self . header. block_hash( ) ,
13671366 "stacks_block_id" => %self . header. block_id( )
13681367 ) ;
1369- return Err ( ( ) ) ;
1368+ return Err ( err ) ;
13701369 }
13711370
1372- return Ok ( true ) ;
1371+ Ok ( true )
13731372 }
13741373
13751374 /// Verify that the VRF seed of this block's block-commit is the hash of the parent tenure's
@@ -1649,27 +1648,14 @@ impl NakamotoBlock {
16491648 chain_id : u32 ,
16501649 epoch_id : StacksEpochId ,
16511650 ) -> bool {
1652- if self . txs . is_empty ( ) {
1653- return false ;
1654- }
1655- if !StacksBlock :: validate_transactions_unique ( & self . txs ) {
1656- return false ;
1657- }
1658- if !StacksBlock :: validate_transactions_network ( & self . txs , mainnet) {
1659- return false ;
1660- }
1661- if !StacksBlock :: validate_transactions_chain_id ( & self . txs , chain_id) {
1651+ if self . txs . is_empty ( )
1652+ || !StacksBlock :: validate_transactions_unique ( & self . txs )
1653+ || !StacksBlock :: validate_transactions_network ( & self . txs , mainnet)
1654+ || !StacksBlock :: validate_transactions_chain_id ( & self . txs , chain_id)
1655+ {
16621656 return false ;
16631657 }
1664- let valid_tenure_start = self . is_wellformed_tenure_start_block ( ) ;
1665- if valid_tenure_start == Ok ( true ) {
1666- if self . get_coinbase_tx ( ) . is_none ( ) {
1667- return false ;
1668- }
1669- if self . get_tenure_change_tx_payload ( ) . is_none ( ) {
1670- return false ;
1671- }
1672- } else if valid_tenure_start. is_err ( ) {
1658+ if self . is_wellformed_tenure_start_block ( ) . is_err ( ) {
16731659 // bad tenure change
16741660 warn ! ( "Not a well-formed tenure-start block" ;
16751661 "consensus_hash" => %self . header. consensus_hash,
@@ -1678,24 +1664,16 @@ impl NakamotoBlock {
16781664 ) ;
16791665 return false ;
16801666 }
1681- let valid_tenure_extend = self . is_wellformed_tenure_extend_block ( ) ;
1682- if valid_tenure_extend == Ok ( true ) {
1683- if self . get_tenure_extend_tx_payload ( ) . is_none ( ) {
1684- return false ;
1685- }
1686- } else if valid_tenure_extend. is_err ( ) {
1667+ if self . is_wellformed_tenure_extend_block ( ) . is_err ( ) {
16871668 // bad tenure extend
16881669 warn ! ( "Not a well-formed tenure-extend block" ;
16891670 "consensus_hash" => %self . header. consensus_hash,
16901671 "stacks_block_hash" => %self . header. block_hash( ) ,
16911672 "stacks_block_id" => %self . header. block_id( )
16921673 ) ;
16931674 return false ;
1694- }
1695- if !StacksBlock :: validate_transactions_static_epoch ( & self . txs , epoch_id) {
1696- return false ;
1697- }
1698- return true ;
1675+ } ;
1676+ StacksBlock :: validate_transactions_static_epoch ( & self . txs , epoch_id)
16991677 }
17001678}
17011679
@@ -1992,11 +1970,7 @@ impl NakamotoChainState {
19921970 } ;
19931971
19941972 // find commit and sortition burns if this is a tenure-start block
1995- let Ok ( new_tenure) = next_ready_block. is_wellformed_tenure_start_block ( ) else {
1996- return Err ( ChainstateError :: InvalidStacksBlock (
1997- "Invalid Nakamoto block: invalid tenure change tx(s)" . into ( ) ,
1998- ) ) ;
1999- } ;
1973+ let new_tenure = next_ready_block. is_wellformed_tenure_start_block ( ) ?;
20001974
20011975 let ( commit_burn, sortition_burn) = if new_tenure && !next_ready_block. is_shadow_block ( ) {
20021976 // find block-commit to get commit-burn
@@ -2417,15 +2391,13 @@ impl NakamotoChainState {
24172391 }
24182392
24192393 // if this is the first tenure block, then make sure it's well-formed
2420- block. is_wellformed_tenure_start_block ( ) . map_err ( |_| {
2394+ block. is_wellformed_tenure_start_block ( ) . inspect_err ( |_| {
24212395 warn ! ( "Block {block_id} is not a well-formed first tenure block" ) ;
2422- ChainstateError :: InvalidStacksBlock ( "Not a well-formed first-tenure block" . into ( ) )
24232396 } ) ?;
24242397
24252398 // if this is a tenure-extend block, then make sure it's well-formed
2426- block. is_wellformed_tenure_extend_block ( ) . map_err ( |_| {
2399+ block. is_wellformed_tenure_extend_block ( ) . inspect_err ( |_| {
24272400 warn ! ( "Block {block_id} is not a well-formed tenure-extend block" ) ;
2428- ChainstateError :: InvalidStacksBlock ( "Not a well-formed tenure-extend block" . into ( ) )
24292401 } ) ?;
24302402
24312403 // it's okay if this fails because we might not have the parent block yet. It will be
@@ -4537,21 +4509,15 @@ impl NakamotoChainState {
45374509 Self :: check_sortition_exists ( burn_dbconn, & block. header . consensus_hash ) ?;
45384510 let block_hash = block. header . block_hash ( ) ;
45394511
4540- let new_tenure = block. is_wellformed_tenure_start_block ( ) . map_err ( |_| {
4541- ChainstateError :: InvalidStacksBlock ( "Invalid tenure changes in nakamoto block" . into ( ) )
4542- } ) ?;
4543-
4512+ let new_tenure = block. is_wellformed_tenure_start_block ( ) ?;
45444513 // this block is mined in the ongoing tenure.
45454514 if !new_tenure
45464515 && !Self :: check_tenure_continuity ( chainstate_tx. as_tx ( ) , & parent_ch, & block. header ) ?
45474516 {
45484517 // this block is not part of the ongoing tenure; it's invalid
45494518 return Err ( ChainstateError :: ExpectedTenureChange ) ;
45504519 }
4551- let tenure_extend = block. is_wellformed_tenure_extend_block ( ) . map_err ( |_| {
4552- ChainstateError :: InvalidStacksBlock ( "Invalid tenure changes in nakamoto block" . into ( ) )
4553- } ) ?;
4554-
4520+ let tenure_extend = block. is_wellformed_tenure_extend_block ( ) ?;
45554521 if tenure_extend && new_tenure {
45564522 return Err ( ChainstateError :: InvalidStacksBlock (
45574523 "Both started and extended tenure" . into ( ) ,
0 commit comments