mod metadata;
pub use metadata::*;
mod bytes;
mod genesis;
mod merkle;
mod serialize;
mod string;
mod verify;
use crate::{Ratifications, Transactions};
use console::{
network::prelude::*,
program::{HEADER_DEPTH, HeaderLeaf, HeaderPath, HeaderTree},
types::Field,
};
use snarkvm_synthesizer_program::FinalizeOperation;
use anyhow::Context;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Header<N: Network> {
previous_state_root: N::StateRoot,
transactions_root: Field<N>,
finalize_root: Field<N>,
ratifications_root: Field<N>,
solutions_root: Field<N>,
subdag_root: Field<N>,
metadata: Metadata<N>,
}
impl<N: Network> Header<N> {
pub fn from(
previous_state_root: N::StateRoot,
transactions_root: Field<N>,
finalize_root: Field<N>,
ratifications_root: Field<N>,
solutions_root: Field<N>,
subdag_root: Field<N>,
metadata: Metadata<N>,
) -> Result<Self> {
let header = Self {
previous_state_root,
transactions_root,
finalize_root,
ratifications_root,
solutions_root,
subdag_root,
metadata,
};
header.check_validity().with_context(|| "Invalid block header")?;
Ok(header)
}
pub fn is_valid(&self) -> bool {
self.check_validity().is_ok()
}
pub fn check_validity(&self) -> Result<()> {
if self.height() == 0u32 {
if !self.is_genesis()? {
bail!("Block at height 0 is not a gensis block");
}
return Ok(());
}
self.metadata.check_validity().with_context(|| "Invalid metadata")?;
ensure!(*self.previous_state_root != Field::zero(), "Previous state root cannot be zero");
ensure!(self.transactions_root != Field::zero(), "Transactions root cannot be zero");
ensure!(self.finalize_root != Field::zero(), "Finalize root cannot be zero");
ensure!(self.ratifications_root != Field::zero(), "Ratifications root cannot be zero");
Ok(())
}
pub const fn previous_state_root(&self) -> N::StateRoot {
self.previous_state_root
}
pub const fn transactions_root(&self) -> Field<N> {
self.transactions_root
}
pub const fn finalize_root(&self) -> Field<N> {
self.finalize_root
}
pub const fn ratifications_root(&self) -> Field<N> {
self.ratifications_root
}
pub const fn solutions_root(&self) -> Field<N> {
self.solutions_root
}
pub const fn subdag_root(&self) -> Field<N> {
self.subdag_root
}
pub const fn metadata(&self) -> &Metadata<N> {
&self.metadata
}
pub const fn network(&self) -> u16 {
self.metadata.network()
}
pub const fn round(&self) -> u64 {
self.metadata.round()
}
pub const fn height(&self) -> u32 {
self.metadata.height()
}
pub const fn cumulative_weight(&self) -> u128 {
self.metadata.cumulative_weight()
}
pub const fn cumulative_proof_target(&self) -> u128 {
self.metadata.cumulative_proof_target()
}
pub const fn coinbase_target(&self) -> u64 {
self.metadata.coinbase_target()
}
pub const fn proof_target(&self) -> u64 {
self.metadata.proof_target()
}
pub const fn last_coinbase_target(&self) -> u64 {
self.metadata.last_coinbase_target()
}
pub const fn last_coinbase_timestamp(&self) -> i64 {
self.metadata.last_coinbase_timestamp()
}
pub const fn timestamp(&self) -> i64 {
self.metadata.timestamp()
}
}
#[cfg(test)]
pub mod test_helpers {
use super::*;
type CurrentNetwork = console::network::MainnetV0;
pub(crate) fn sample_block_header(rng: &mut TestRng) -> Header<CurrentNetwork> {
*crate::test_helpers::sample_genesis_block(rng).header()
}
}