diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 22b5d4009f1..a4480189422 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -185,4 +185,27 @@ impl Transaction { ) -> blake2b_simd::Hash { sighash::SigHasher::new(self, hash_type, network_upgrade, input).sighash() } + + /// Access the joinsplits of this transaction, regardless of version. + // Todo: signature haves to be like: + // pub fn joinsplits(&self) -> Option> { + // but i was not able to make that work yet + pub fn joinsplits(&self) -> bool { + match self { + Transaction::V1 { .. } => false, + Transaction::V2 { joinsplit_data, .. } => joinsplit_data.is_some(), + Transaction::V3 { joinsplit_data, .. } => joinsplit_data.is_some(), + Transaction::V4 { joinsplit_data, .. } => joinsplit_data.is_some(), + } + } + /// Access the shielded data of this transaction. + /// Only V4 transactions will return Some() if any shielded data is present. + pub fn shields(&self) -> Option { + match self { + Transaction::V1 { .. } => None, + Transaction::V2 { .. } => None, + Transaction::V3 { .. } => None, + Transaction::V4 { shielded_data, .. } => shielded_data.clone(), + } + } } diff --git a/zebra-consensus/src/block/check.rs b/zebra-consensus/src/block/check.rs index eb1ef1bb33e..7a54adbd34c 100644 --- a/zebra-consensus/src/block/check.rs +++ b/zebra-consensus/src/block/check.rs @@ -99,6 +99,12 @@ pub fn subsidy_is_valid(block: &Block, network: Network) -> Result<(), BlockErro .activation_height(network) .expect("Canopy activation height is known"); + // Validate shielded coinbase + let shielded_validation = subsidy::general::shielded_coinbase(height, network, coinbase); + if !shielded_validation { + panic!("Failed validating shielded coinbase"); + } + // TODO: the sum of the coinbase transaction outputs must be less than or equal to the block subsidy plus transaction fees // Check founders reward and funding streams diff --git a/zebra-consensus/src/block/subsidy/general.rs b/zebra-consensus/src/block/subsidy/general.rs index f8970db38b7..0b1140caf56 100644 --- a/zebra-consensus/src/block/subsidy/general.rs +++ b/zebra-consensus/src/block/subsidy/general.rs @@ -102,6 +102,26 @@ pub fn find_output_with_amount( .collect() } +/// Validate shielded consensus rules as described in [ZIP-213][ZIP-213] +/// +/// [ZIP-213]: https://zips.z.cash/zip-0213#specification +pub fn shielded_coinbase(height: Height, network: Network, transaction: &Transaction) -> bool { + let heartwood_height = Heartwood + .activation_height(network) + .expect("heartwood activation height should be available"); + + if height < heartwood_height { + if !transaction.joinsplits() && transaction.shields().is_none() { + return true; + } + } else { + if !transaction.joinsplits() { + return true; + } + } + return false; +} + #[cfg(test)] mod test { use super::*;