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
pub fn hash(&self) -> Hash {
Hash::from(self)

View File

@ -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

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