move `is_coinbase_first` from chain to consensus
This commit is contained in:
parent
e67d3fc5e3
commit
4dac4d4df7
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(())
|
||||
}
|
Loading…
Reference in New Issue