From 71c1f6390860e8ccc1287615f1a49b35e8038ff6 Mon Sep 17 00:00:00 2001 From: Arya Date: Thu, 12 Dec 2024 21:34:21 -0500 Subject: [PATCH] Updates `coinbase_spend_restriction()` method to always return `OnlyShieldedOutputs` on Regtest. --- zebra-chain/src/block/arbitrary.rs | 2 +- zebra-chain/src/transaction.rs | 6 ++++-- zebra-consensus/src/transaction.rs | 4 +++- zebra-consensus/src/transaction/check.rs | 3 ++- zebra-consensus/src/transaction/tests.rs | 2 +- zebra-state/src/service/check/utxo.rs | 6 ++++-- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/zebra-chain/src/block/arbitrary.rs b/zebra-chain/src/block/arbitrary.rs index 5a39afa2ee4..5a8a91d1700 100644 --- a/zebra-chain/src/block/arbitrary.rs +++ b/zebra-chain/src/block/arbitrary.rs @@ -568,7 +568,7 @@ where + Copy + 'static, { - let mut spend_restriction = transaction.coinbase_spend_restriction(height); + let mut spend_restriction = transaction.coinbase_spend_restriction(&Network::Mainnet, height); let mut new_inputs = Vec::new(); let mut spent_outputs = HashMap::new(); diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 1c121130fcc..881fb4c5227 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -41,7 +41,7 @@ pub use unmined::{ use crate::{ amount::{Amount, Error as AmountError, NegativeAllowed, NonNegative}, block, orchard, - parameters::{ConsensusBranchId, NetworkUpgrade}, + parameters::{ConsensusBranchId, Network, NetworkUpgrade}, primitives::{ed25519, Bctv14Proof, Groth16Proof}, sapling, serialization::ZcashSerialize, @@ -303,9 +303,11 @@ impl Transaction { /// assuming it is mined at `spend_height`. pub fn coinbase_spend_restriction( &self, + network: &Network, spend_height: block::Height, ) -> CoinbaseSpendRestriction { - if self.outputs().is_empty() { + // TODO: Replace `is_regtest()` with a check for a field. + if self.outputs().is_empty() || network.is_regtest() { // we know this transaction must have shielded outputs, // because of other consensus rules OnlyShieldedOutputs { spend_height } diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index ef20881bbbf..864c668b144 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -451,7 +451,7 @@ where // WONTFIX: Return an error for Request::Block as well to replace this check in // the state once #2336 has been implemented? if req.is_mempool() { - Self::check_maturity_height(&req, &spent_utxos)?; + Self::check_maturity_height(&network, &req, &spent_utxos)?; } let cached_ffi_transaction = @@ -728,10 +728,12 @@ where /// mature and valid for the request height, or a [`TransactionError`] if the transaction /// spends transparent coinbase outputs that are immature and invalid for the request height. pub fn check_maturity_height( + network: &Network, request: &Request, spent_utxos: &HashMap, ) -> Result<(), TransactionError> { check::tx_transparent_coinbase_spends_maturity( + network, request.transaction(), request.height(), request.known_utxos(), diff --git a/zebra-consensus/src/transaction/check.rs b/zebra-consensus/src/transaction/check.rs index d3ddc460264..b7338bbdadd 100644 --- a/zebra-consensus/src/transaction/check.rs +++ b/zebra-consensus/src/transaction/check.rs @@ -476,6 +476,7 @@ fn validate_expiry_height_mined( /// Returns `Ok(())` if spent transparent coinbase outputs are /// valid for the block height, or a [`Err(TransactionError)`](TransactionError) pub fn tx_transparent_coinbase_spends_maturity( + network: &Network, tx: Arc, height: Height, block_new_outputs: Arc>, @@ -488,7 +489,7 @@ pub fn tx_transparent_coinbase_spends_maturity( .or_else(|| spent_utxos.get(&spend).cloned()) .expect("load_spent_utxos_fut.await should return an error if a utxo is missing"); - let spend_restriction = tx.coinbase_spend_restriction(height); + let spend_restriction = tx.coinbase_spend_restriction(network, height); zebra_state::check::transparent_coinbase_spend(spend, spend_restriction, &utxo)?; } diff --git a/zebra-consensus/src/transaction/tests.rs b/zebra-consensus/src/transaction/tests.rs index 8627a578c62..cca451d275e 100644 --- a/zebra-consensus/src/transaction/tests.rs +++ b/zebra-consensus/src/transaction/tests.rs @@ -739,7 +739,7 @@ async fn mempool_request_with_immature_spend_is_rejected() { transparent::Input::Coinbase { .. } => panic!("requires a non-coinbase transaction"), }; - let spend_restriction = tx.coinbase_spend_restriction(height); + let spend_restriction = tx.coinbase_spend_restriction(&Network::Mainnet, height); let coinbase_spend_height = Height(5); diff --git a/zebra-state/src/service/check/utxo.rs b/zebra-state/src/service/check/utxo.rs index 324efa3c035..ef6c2533c8c 100644 --- a/zebra-state/src/service/check/utxo.rs +++ b/zebra-state/src/service/check/utxo.rs @@ -72,8 +72,10 @@ pub fn transparent_spend( // We don't want to use UTXOs from invalid pending blocks, // so we check transparent coinbase maturity and shielding // using known valid UTXOs during non-finalized chain validation. - let spend_restriction = - transaction.coinbase_spend_restriction(semantically_verified.height); + let spend_restriction = transaction.coinbase_spend_restriction( + &finalized_state.network(), + semantically_verified.height, + ); transparent_coinbase_spend(spend, spend_restriction, utxo.as_ref())?; // We don't delete the UTXOs until the block is committed,