Move network_upgrade check into zebra-chain (#2354)
* move network_upgrade check into zebra-chain * fix the errors * rename function * typo fix * rename the check function * make changes from last code review
This commit is contained in:
parent
76ad543ec5
commit
7638c43a7c
|
@ -1,6 +1,7 @@
|
||||||
//! Blocks and block-related structures (heights, headers, etc.)
|
//! Blocks and block-related structures (heights, headers, etc.)
|
||||||
|
|
||||||
mod commitment;
|
mod commitment;
|
||||||
|
mod error;
|
||||||
mod hash;
|
mod hash;
|
||||||
mod header;
|
mod header;
|
||||||
mod height;
|
mod height;
|
||||||
|
@ -28,7 +29,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fmt::DisplayToDebug,
|
fmt::DisplayToDebug,
|
||||||
parameters::Network,
|
parameters::{Network, NetworkUpgrade},
|
||||||
serialization::{TrustedPreallocate, MAX_PROTOCOL_MESSAGE_LEN},
|
serialization::{TrustedPreallocate, MAX_PROTOCOL_MESSAGE_LEN},
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
transparent,
|
transparent,
|
||||||
|
@ -86,6 +87,35 @@ impl Block {
|
||||||
Some(height) => Commitment::from_bytes(self.header.commitment_bytes, network, height),
|
Some(height) => Commitment::from_bytes(self.header.commitment_bytes, network, height),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the `network_upgrade` fields from each transaction in the block matches
|
||||||
|
/// the network upgrade calculated from the `network` and block height.
|
||||||
|
///
|
||||||
|
/// # Consensus rule:
|
||||||
|
///
|
||||||
|
/// The nConsensusBranchId field MUST match the consensus branch ID used for
|
||||||
|
/// SIGHASH transaction hashes, as specifed in [ZIP-244] ([7.1]).
|
||||||
|
///
|
||||||
|
/// [ZIP-244]: https://zips.z.cash/zip-0244
|
||||||
|
/// [7.1]: https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus
|
||||||
|
pub fn check_transaction_network_upgrade_consistency(
|
||||||
|
&self,
|
||||||
|
network: Network,
|
||||||
|
) -> Result<(), error::BlockError> {
|
||||||
|
let block_nu =
|
||||||
|
NetworkUpgrade::current(network, self.coinbase_height().expect("a valid height"));
|
||||||
|
|
||||||
|
if self
|
||||||
|
.transactions
|
||||||
|
.iter()
|
||||||
|
.filter_map(|trans| trans.as_ref().network_upgrade())
|
||||||
|
.any(|trans_nu| trans_nu != block_nu)
|
||||||
|
{
|
||||||
|
return Err(error::BlockError::WrongTransactionConsensusBranchId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Block> for Hash {
|
impl<'a> From<&'a Block> for Hash {
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
//! Errors that can occur when checking Block consensus rules.
|
||||||
|
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[allow(dead_code, missing_docs)]
|
||||||
|
#[derive(Error, Debug, PartialEq)]
|
||||||
|
pub enum BlockError {
|
||||||
|
#[error("transaction has wrong consensus branch id for block network upgrade")]
|
||||||
|
WrongTransactionConsensusBranchId,
|
||||||
|
}
|
|
@ -192,6 +192,22 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get this transaction's network upgrade field, if any.
|
||||||
|
/// This field is serialized as `nConsensusBranchId` ([7.1]).
|
||||||
|
///
|
||||||
|
/// [7.1]: https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus
|
||||||
|
pub fn network_upgrade(&self) -> Option<NetworkUpgrade> {
|
||||||
|
match self {
|
||||||
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
|
| Transaction::V3 { .. }
|
||||||
|
| Transaction::V4 { .. } => None,
|
||||||
|
Transaction::V5 {
|
||||||
|
network_upgrade, ..
|
||||||
|
} => Some(*network_upgrade),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// transparent
|
// transparent
|
||||||
|
|
||||||
/// Access the transparent inputs of this transaction, regardless of version.
|
/// Access the transparent inputs of this transaction, regardless of version.
|
||||||
|
|
|
@ -97,13 +97,7 @@ fn transaction_valid_network_upgrade_strategy() -> Result<()> {
|
||||||
});
|
});
|
||||||
|
|
||||||
proptest!(|((network, block) in strategy)| {
|
proptest!(|((network, block) in strategy)| {
|
||||||
// TODO: replace with check_transaction_network_upgrade from #2343
|
block.check_transaction_network_upgrade_consistency(network)?;
|
||||||
let block_network_upgrade = NetworkUpgrade::current(network, block.coinbase_height().unwrap());
|
|
||||||
for transaction in block.transactions {
|
|
||||||
if let Transaction::V5 { network_upgrade, .. } = transaction.as_ref() {
|
|
||||||
prop_assert_eq!(network_upgrade, &block_network_upgrade);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -189,23 +189,9 @@ pub fn merkle_root_validity(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
transaction_hashes: &[transaction::Hash],
|
transaction_hashes: &[transaction::Hash],
|
||||||
) -> Result<(), BlockError> {
|
) -> Result<(), BlockError> {
|
||||||
use transaction::Transaction;
|
|
||||||
let block_nu =
|
|
||||||
NetworkUpgrade::current(network, block.coinbase_height().expect("a valid height"));
|
|
||||||
|
|
||||||
if block
|
if block
|
||||||
.transactions
|
.check_transaction_network_upgrade_consistency(network)
|
||||||
.iter()
|
.is_err()
|
||||||
.filter_map(|trans| match *trans.as_ref() {
|
|
||||||
Transaction::V5 {
|
|
||||||
network_upgrade, ..
|
|
||||||
} => Some(network_upgrade),
|
|
||||||
Transaction::V1 { .. }
|
|
||||||
| Transaction::V2 { .. }
|
|
||||||
| Transaction::V3 { .. }
|
|
||||||
| Transaction::V4 { .. } => None,
|
|
||||||
})
|
|
||||||
.any(|trans_nu| trans_nu != block_nu)
|
|
||||||
{
|
{
|
||||||
return Err(BlockError::WrongTransactionConsensusBranchId);
|
return Err(BlockError::WrongTransactionConsensusBranchId);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue