From 4dac4d4df7c4720f13dff5e0b5b413f975fce1b9 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 18 Aug 2020 10:33:40 -0300 Subject: [PATCH] move `is_coinbase_first` from chain to consensus --- zebra-chain/src/block.rs | 23 ----------------------- zebra-consensus/src/block.rs | 5 ++++- zebra-consensus/src/block/checks.rs | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 24 deletions(-) create mode 100644 zebra-consensus/src/block/checks.rs diff --git a/zebra-chain/src/block.rs b/zebra-chain/src/block.rs index 6f144ad1..6ce2fb24 100644 --- a/zebra-chain/src/block.rs +++ b/zebra-chain/src/block.rs @@ -50,29 +50,6 @@ impl Block { }) } - /// Check that there is exactly one coinbase transaction in `Block`, and that - /// the coinbase transaction is the first transaction in the block. - /// - /// "The first (and only the first) transaction in a block is a coinbase - /// transaction, which collects and spends any miner subsidy and transaction - /// fees paid by transactions included in this block." [§3.10][3.10] - /// - /// [3.10]: https://zips.z.cash/protocol/protocol.pdf#coinbasetransactions - pub fn is_coinbase_first(&self) -> Result<(), Error> { - let first = self - .transactions - .get(0) - .ok_or_else(|| "block has no transactions")?; - let mut rest = self.transactions.iter().skip(1); - if !first.is_coinbase() { - return Err("first transaction must be coinbase".into()); - } - if rest.any(|tx| tx.contains_coinbase_input()) { - return Err("coinbase input found in non-coinbase transaction".into()); - } - Ok(()) - } - /// Get the hash for the current block pub fn hash(&self) -> Hash { Hash::from(self) diff --git a/zebra-consensus/src/block.rs b/zebra-consensus/src/block.rs index f22fc793..7f88b8a0 100644 --- a/zebra-consensus/src/block.rs +++ b/zebra-consensus/src/block.rs @@ -8,9 +8,12 @@ //! Verification is provided via a `tower::Service`, to support backpressure and batch //! verification. +mod checks; + #[cfg(test)] mod tests; +use checks::*; use chrono::Utc; use color_eyre::eyre::{eyre, Report}; use futures_util::FutureExt; @@ -106,7 +109,7 @@ where // Field validity and structure checks let now = Utc::now(); block.header.is_time_valid_at(now)?; - block.is_coinbase_first()?; + is_coinbase_first(&block)?; // TODO: // - context-free header verification: merkle root diff --git a/zebra-consensus/src/block/checks.rs b/zebra-consensus/src/block/checks.rs new file mode 100644 index 00000000..aa4cfdb7 --- /dev/null +++ b/zebra-consensus/src/block/checks.rs @@ -0,0 +1,27 @@ +//! Consensus check functions + +use super::*; +use zebra_chain::block::Block; + +/// Check that there is exactly one coinbase transaction in `Block`, and that +/// the coinbase transaction is the first transaction in the block. +/// +/// "The first (and only the first) transaction in a block is a coinbase +/// transaction, which collects and spends any miner subsidy and transaction +/// fees paid by transactions included in this block." [§3.10][3.10] +/// +/// [3.10]: https://zips.z.cash/protocol/protocol.pdf#coinbasetransactions +pub fn is_coinbase_first(block: &Block) -> Result<(), Error> { + let first = block + .transactions + .get(0) + .ok_or_else(|| "block has no transactions")?; + let mut rest = block.transactions.iter().skip(1); + if !first.is_coinbase() { + return Err("first transaction must be coinbase".into()); + } + if rest.any(|tx| tx.contains_coinbase_input()) { + return Err("coinbase input found in non-coinbase transaction".into()); + } + Ok(()) +}