diff --git a/stackslib/src/chainstate/stacks/block.rs b/stackslib/src/chainstate/stacks/block.rs index 881b59be6..9827d28e9 100644 --- a/stackslib/src/chainstate/stacks/block.rs +++ b/stackslib/src/chainstate/stacks/block.rs @@ -570,44 +570,55 @@ impl StacksBlock { epoch_id: StacksEpochId, ) -> bool { for tx in txs.iter() { - if let TransactionPayload::Coinbase(_, ref recipient_opt, ref proof_opt) = &tx.payload { - if proof_opt.is_some() && epoch_id < StacksEpochId::Epoch30 { - // not supported - error!("Coinbase with VRF proof not supported before Stacks 3.0"; "txid" => %tx.txid()); - return false; - } - if proof_opt.is_none() && epoch_id >= StacksEpochId::Epoch30 { - // not supported - error!("Coinbase with VRF proof is required in Stacks 3.0 and later"; "txid" => %tx.txid()); - return false; - } - if recipient_opt.is_some() && epoch_id < StacksEpochId::Epoch21 { - // not supported - error!("Coinbase pay-to-alt-recipient not supported before Stacks 2.1"; "txid" => %tx.txid()); - return false; - } - } - if let TransactionPayload::SmartContract(_, ref version_opt) = &tx.payload { - if version_opt.is_some() && epoch_id < StacksEpochId::Epoch21 { - // not supported - error!("Versioned smart contracts not supported before Stacks 2.1"); - return false; - } - } - if let TransactionPayload::TenureChange(..) = &tx.payload { - if epoch_id < StacksEpochId::Epoch30 { - error!("TenureChange transaction not supported before Stacks 3.0"; "txid" => %tx.txid()); - return false; - } - } - if !tx.auth.is_supported_in_epoch(epoch_id) { - error!("Authentication mode not supported in Epoch {epoch_id}"); + if !StacksBlock::validate_transaction_static_epoch(tx, epoch_id) { return false; } } return true; } + /// Verify that one transaction is supported in the given epoch, as indicated by `epoch_id` + pub fn validate_transaction_static_epoch( + tx: &StacksTransaction, + epoch_id: StacksEpochId, + ) -> bool { + if let TransactionPayload::Coinbase(_, ref recipient_opt, ref proof_opt) = &tx.payload { + if proof_opt.is_some() && epoch_id < StacksEpochId::Epoch30 { + // not supported + error!("Coinbase with VRF proof not supported before Stacks 3.0"; "txid" => %tx.txid()); + return false; + } + if proof_opt.is_none() && epoch_id >= StacksEpochId::Epoch30 { + // not supported + error!("Coinbase with VRF proof is required in Stacks 3.0 and later"; "txid" => %tx.txid()); + return false; + } + if recipient_opt.is_some() && epoch_id < StacksEpochId::Epoch21 { + // not supported + error!("Coinbase pay-to-alt-recipient not supported before Stacks 2.1"; "txid" => %tx.txid()); + return false; + } + } + if let TransactionPayload::SmartContract(_, ref version_opt) = &tx.payload { + if version_opt.is_some() && epoch_id < StacksEpochId::Epoch21 { + // not supported + error!("Versioned smart contracts not supported before Stacks 2.1"); + return false; + } + } + if let TransactionPayload::TenureChange(..) = &tx.payload { + if epoch_id < StacksEpochId::Epoch30 { + error!("TenureChange transaction not supported before Stacks 3.0"; "txid" => %tx.txid()); + return false; + } + } + if !tx.auth.is_supported_in_epoch(epoch_id) { + error!("Authentication mode not supported in Epoch {epoch_id}"); + return false; + } + return true; + } + /// static sanity checks on transactions. pub fn validate_transactions_static( &self, diff --git a/stackslib/src/chainstate/stacks/db/blocks.rs b/stackslib/src/chainstate/stacks/db/blocks.rs index 5d05ae0a4..0759ac0d0 100644 --- a/stackslib/src/chainstate/stacks/db/blocks.rs +++ b/stackslib/src/chainstate/stacks/db/blocks.rs @@ -6666,7 +6666,7 @@ impl StacksChainState { } // 4: check if transaction is valid in the current epoch - if !StacksBlock::validate_transactions_static_epoch(&[tx.clone()], epoch) { + if !StacksBlock::validate_transaction_static_epoch(tx, epoch) { return Err(MemPoolRejection::Other( "Transaction is not supported in this epoch".to_string(), ));