zebra/zebra-chain/src/block.rs

138 lines
4.3 KiB
Rust
Raw Normal View History

//! Blocks and block-related structures (heights, headers, etc.)
mod commitment;
mod error;
mod hash;
mod header;
2020-08-14 23:51:41 -07:00
mod height;
mod serialize;
pub mod merkle;
#[cfg(any(test, feature = "proptest-impl"))]
mod arbitrary;
#[cfg(any(test, feature = "bench"))]
pub mod tests;
use std::fmt;
pub use commitment::{ChainHistoryMmrRootHash, Commitment, CommitmentError};
pub use hash::Hash;
pub use header::{BlockTimeError, CountedHeader, Header};
pub use height::Height;
Implement Trusted Vector Preallocation (#1920) * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Impl TrustedPreallocate for Joinsplit * Impl ZcashDeserialize for Vec<u8> * Arbitrary, TrustedPreallocate, Serialize, and tests for Spend<SharedAnchor> Co-authored-by: teor <teor@riseup.net>
2021-04-05 16:49:42 -07:00
pub use serialize::MAX_BLOCK_BYTES;
2021-04-22 20:19:33 -07:00
#[cfg(any(test, feature = "proptest-impl"))]
pub use arbitrary::LedgerState;
2020-08-15 22:25:30 -07:00
use serde::{Deserialize, Serialize};
Implement Trusted Vector Preallocation (#1920) * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Impl TrustedPreallocate for Joinsplit * Impl ZcashDeserialize for Vec<u8> * Arbitrary, TrustedPreallocate, Serialize, and tests for Spend<SharedAnchor> Co-authored-by: teor <teor@riseup.net>
2021-04-05 16:49:42 -07:00
use crate::{
fmt::DisplayToDebug,
parameters::{Network, NetworkUpgrade},
Implement Trusted Vector Preallocation (#1920) * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Impl TrustedPreallocate for Joinsplit * Impl ZcashDeserialize for Vec<u8> * Arbitrary, TrustedPreallocate, Serialize, and tests for Spend<SharedAnchor> Co-authored-by: teor <teor@riseup.net>
2021-04-05 16:49:42 -07:00
serialization::{TrustedPreallocate, MAX_PROTOCOL_MESSAGE_LEN},
transaction::Transaction,
transparent,
};
2020-08-15 22:25:30 -07:00
2020-08-16 12:08:24 -07:00
/// A Zcash block, containing a header and a list of transactions.
2020-08-15 22:25:30 -07:00
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Block {
/// The block header, containing block metadata.
pub header: Header,
2020-08-15 22:25:30 -07:00
/// The block transactions.
pub transactions: Vec<std::sync::Arc<Transaction>>,
}
impl fmt::Display for Block {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut fmter = f.debug_struct("Block");
if let Some(height) = self.coinbase_height() {
fmter.field("height", &height);
}
fmter.field("hash", &DisplayToDebug(self.hash())).finish()
}
}
2020-08-15 22:25:30 -07:00
impl Block {
/// Return the block height reported in the coinbase transaction, if any.
pub fn coinbase_height(&self) -> Option<Height> {
2020-08-15 22:25:30 -07:00
self.transactions
.get(0)
.and_then(|tx| tx.inputs().get(0))
.and_then(|input| match input {
transparent::Input::Coinbase { ref height, .. } => Some(*height),
2020-08-15 22:25:30 -07:00
_ => None,
})
}
/// Compute the hash of this block.
pub fn hash(&self) -> Hash {
Hash::from(self)
2020-08-15 22:25:30 -07:00
}
/// Get the parsed block [`Commitment`] for this block.
2020-08-15 22:25:30 -07:00
///
/// The interpretation of the commitment depends on the
2020-08-15 22:25:30 -07:00
/// configured `network`, and this block's height.
///
/// Returns an error if this block does not have a block height,
/// or if the commitment value is structurally invalid.
pub fn commitment(&self, network: Network) -> Result<Commitment, CommitmentError> {
match self.coinbase_height() {
None => Err(CommitmentError::MissingBlockHeight {
block_hash: self.hash(),
}),
Some(height) => Commitment::from_bytes(self.header.commitment_bytes, network, height),
}
2020-08-15 22:25:30 -07:00
}
/// 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(())
}
2020-08-15 22:25:30 -07:00
}
impl<'a> From<&'a Block> for Hash {
fn from(block: &'a Block) -> Hash {
2020-08-15 22:25:30 -07:00
(&block.header).into()
}
}
Implement Trusted Vector Preallocation (#1920) * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Impl TrustedPreallocate for Joinsplit * Impl ZcashDeserialize for Vec<u8> * Arbitrary, TrustedPreallocate, Serialize, and tests for Spend<SharedAnchor> Co-authored-by: teor <teor@riseup.net>
2021-04-05 16:49:42 -07:00
/// A serialized Block hash takes 32 bytes
const BLOCK_HASH_SIZE: u64 = 32;
Implement Trusted Vector Preallocation (#1920) * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Implement SafePreallocate. Resolves #1880 * Add proptests for SafePreallocate * Apply suggestions from code review Comments which did not include replacement code will be addressed in a follow-up commit. Co-authored-by: teor <teor@riseup.net> * Rename [Safe-> Trusted]Allocate. Add doc and tests Add tests to show that the largest allowed vec under TrustedPreallocate is small enough to fit in a Zcash block/message (depending on type). Add doc comments to all TrustedPreallocate test cases. Tighten bounds on max_trusted_alloc for some types. Note - this commit does NOT include TrustedPreallocate impls for JoinSplitData, String, and Script. These impls will be added in a follow up commit * Impl TrustedPreallocate for Joinsplit * Impl ZcashDeserialize for Vec<u8> * Arbitrary, TrustedPreallocate, Serialize, and tests for Spend<SharedAnchor> Co-authored-by: teor <teor@riseup.net>
2021-04-05 16:49:42 -07:00
/// The maximum number of hashes in a valid Zcash protocol message.
impl TrustedPreallocate for Hash {
fn max_allocation() -> u64 {
// Every vector type requires a length field of at least one byte for de/serialization.
// Since a block::Hash takes 32 bytes, we can never receive more than (MAX_PROTOCOL_MESSAGE_LEN - 1) / 32 hashes in a single message
((MAX_PROTOCOL_MESSAGE_LEN - 1) as u64) / BLOCK_HASH_SIZE
}
}