Skip to content

Commit 54f800b

Browse files
committed
Merge branch 'develop' of https://github.com/stacks-network/stacks-core into chore/merge-develop-to-aac-client-breaking
2 parents 9c13b5f + a7d73af commit 54f800b

File tree

6 files changed

+439
-397
lines changed

6 files changed

+439
-397
lines changed

contrib/stacks-inspect/src/lib.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,12 +1105,7 @@ fn replay_block_nakamoto(
11051105
};
11061106

11071107
// find commit and sortition burns if this is a tenure-start block
1108-
let Ok(new_tenure) = block.is_wellformed_tenure_start_block() else {
1109-
return Err(ChainstateError::InvalidStacksBlock(
1110-
"Invalid Nakamoto block: invalid tenure change tx(s)".into(),
1111-
));
1112-
};
1113-
1108+
let new_tenure = block.is_wellformed_tenure_start_block()?;
11141109
let (commit_burn, sortition_burn) = if new_tenure {
11151110
// find block-commit to get commit-burn
11161111
let block_commit = SortitionDB::get_block_commit(

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 51 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)