move `is_coinbase_first` from chain to consensus

This commit is contained in:
Alfredo Garcia 2020-08-18 10:33:40 -03:00 committed by Henry de Valence
parent e67d3fc5e3
commit 4dac4d4df7
3 changed files with 31 additions and 24 deletions

View File

@ -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 /// Get the hash for the current block
pub fn hash(&self) -> Hash { pub fn hash(&self) -> Hash {
Hash::from(self) Hash::from(self)

View File

@ -8,9 +8,12 @@
//! Verification is provided via a `tower::Service`, to support backpressure and batch //! Verification is provided via a `tower::Service`, to support backpressure and batch
//! verification. //! verification.
mod checks;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use checks::*;
use chrono::Utc; use chrono::Utc;
use color_eyre::eyre::{eyre, Report}; use color_eyre::eyre::{eyre, Report};
use futures_util::FutureExt; use futures_util::FutureExt;
@ -106,7 +109,7 @@ where
// Field validity and structure checks // Field validity and structure checks
let now = Utc::now(); let now = Utc::now();
block.header.is_time_valid_at(now)?; block.header.is_time_valid_at(now)?;
block.is_coinbase_first()?; is_coinbase_first(&block)?;
// TODO: // TODO:
// - context-free header verification: merkle root // - context-free header verification: merkle root

View File

@ -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(())
}