Zebra/zebra-chain/src/block/root_hash.rs

83 lines
3.1 KiB
Rust

//! The LightClientRootHash enum, used for the corresponding block header field.
use crate::parameters::{Network, NetworkUpgrade, NetworkUpgrade::*};
use crate::sapling::tree::Root;
use super::Height;
/// Zcash blocks contain different kinds of root hashes, depending on the network upgrade.
///
/// The `BlockHeader.root_bytes` field is interpreted differently,
/// based on the current block height. The interpretation changes at or after
/// network upgrades.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum RootHash {
/// [Pre-Sapling] Reserved field.
///
/// All zeroes.
PreSaplingReserved([u8; 32]),
/// [Sapling and Blossom] The final Sapling treestate of this block.
///
/// The root LEBS2OSP256(rt) of the Sapling note commitment tree
/// corresponding to the final Sapling treestate of this block.
FinalSaplingRoot(Root),
/// [Heartwood activation block] Reserved field.
///
/// All zeroes. This MUST NOT be interpreted as a root hash.
/// See ZIP-221 for details.
ChainHistoryActivationReserved([u8; 32]),
/// [After Heartwood activation block] The root of a Merkle Mountain
/// Range chain history tree.
///
/// This root hash commits to various features of the chain's history,
/// including the Sapling commitment tree. This commitment supports the
/// FlyClient protocol. See ZIP-221 for details.
///
/// The commitment in each block covers the chain history from the most
/// recent network upgrade, through to the previous block. In particular,
/// an activation block commits to the entire previous network upgrade, and
/// the block after activation commits only to the activation block.
ChainHistoryRoot(ChainHistoryMmrRootHash),
}
impl RootHash {
/// Returns `bytes` as the LightClientRootHash variant for `network` and
/// `height`.
pub(super) fn from_bytes(bytes: [u8; 32], network: Network, height: Height) -> RootHash {
use RootHash::*;
match NetworkUpgrade::current(network, height) {
Genesis | BeforeOverwinter | Overwinter => PreSaplingReserved(bytes),
Sapling | Blossom => FinalSaplingRoot(Root(bytes)),
Heartwood if Some(height) == Heartwood.activation_height(network) => {
ChainHistoryActivationReserved(bytes)
}
Heartwood | Canopy => ChainHistoryRoot(ChainHistoryMmrRootHash(bytes)),
}
}
/// Returns the serialized bytes for this LightClientRootHash.
#[allow(dead_code)]
pub(super) fn to_bytes(self) -> [u8; 32] {
use RootHash::*;
match self {
PreSaplingReserved(b) => b,
FinalSaplingRoot(v) => v.0,
ChainHistoryActivationReserved(b) => b,
ChainHistoryRoot(v) => v.0,
}
}
}
/// The root hash of a Merkle Mountain Range chain history tree.
// TODO:
// - add methods for maintaining the MMR peaks, and calculating the root
// hash from the current set of peaks.
// - move to a separate file.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct ChainHistoryMmrRootHash([u8; 32]);