zcash_history: Implement V2 tree format
This commit is contained in:
parent
63f554b308
commit
e84bb874af
|
@ -10,6 +10,7 @@ and this library adheres to Rust's notion of
|
|||
- Support for multiple history tree versions:
|
||||
- `zcash_history::Version` trait.
|
||||
- `zcash_history::V1`, marking the original history tree version.
|
||||
- `zcash_history::V2`, marking the history tree version from NU5.
|
||||
- `zcash_history::Entry::new_leaf`
|
||||
|
||||
### Changed
|
||||
|
|
|
@ -14,7 +14,7 @@ mod version;
|
|||
pub use entry::{Entry, MAX_ENTRY_SIZE};
|
||||
pub use node_data::{NodeData, MAX_NODE_DATA_SIZE};
|
||||
pub use tree::Tree;
|
||||
pub use version::{Version, V1};
|
||||
pub use version::{Version, V1, V2};
|
||||
|
||||
/// Crate-level error type
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -14,8 +14,11 @@ pub const MAX_NODE_DATA_SIZE: usize = 32 + // subtree commitment
|
|||
32 + // subtree total work
|
||||
9 + // start height (compact uint)
|
||||
9 + // end height (compact uint)
|
||||
9; // Sapling tx count (compact uint)
|
||||
// = total of 171
|
||||
9 + // Sapling tx count (compact uint)
|
||||
32 + // start Orchard tree root
|
||||
32 + // end Orchard tree root
|
||||
9; // Orchard tx count (compact uint)
|
||||
// = total of 244
|
||||
|
||||
/// V1 node metadata.
|
||||
#[repr(C)]
|
||||
|
@ -166,6 +169,53 @@ impl NodeData {
|
|||
}
|
||||
}
|
||||
|
||||
/// V2 node metadata.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub struct V2 {
|
||||
/// The V1 node data retained in V2.
|
||||
pub v1: NodeData,
|
||||
/// Start Orchard tree root.
|
||||
pub start_orchard_root: [u8; 32],
|
||||
/// End Orchard tree root.
|
||||
pub end_orchard_root: [u8; 32],
|
||||
/// Number of Orchard transactions.
|
||||
pub orchard_tx: u64,
|
||||
}
|
||||
|
||||
impl V2 {
|
||||
pub(crate) fn combine_inner(subtree_commitment: [u8; 32], left: &V2, right: &V2) -> V2 {
|
||||
V2 {
|
||||
v1: NodeData::combine_inner(subtree_commitment, &left.v1, &right.v1),
|
||||
start_orchard_root: left.start_orchard_root,
|
||||
end_orchard_root: right.end_orchard_root,
|
||||
orchard_tx: left.orchard_tx + right.orchard_tx,
|
||||
}
|
||||
}
|
||||
|
||||
/// Write to the byte representation.
|
||||
pub fn write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
|
||||
self.v1.write(w)?;
|
||||
w.write_all(&self.start_orchard_root)?;
|
||||
w.write_all(&self.end_orchard_root)?;
|
||||
NodeData::write_compact(w, self.orchard_tx)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Read from the byte representation.
|
||||
pub fn read<R: std::io::Read>(consensus_branch_id: u32, r: &mut R) -> std::io::Result<Self> {
|
||||
let mut data = V2 {
|
||||
v1: NodeData::read(consensus_branch_id, r)?,
|
||||
..Default::default()
|
||||
};
|
||||
r.read_exact(&mut data.start_orchard_root)?;
|
||||
r.read_exact(&mut data.end_orchard_root)?;
|
||||
data.orchard_tx = NodeData::read_compact(r)?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl quickcheck::Arbitrary for NodeData {
|
||||
fn arbitrary<G: quickcheck::Gen>(gen: &mut G) -> Self {
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::io;
|
|||
use blake2::Params as Blake2Params;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
use crate::{NodeData, MAX_NODE_DATA_SIZE};
|
||||
use crate::{node_data, NodeData, MAX_NODE_DATA_SIZE};
|
||||
|
||||
fn blake2b_personal(personalization: &[u8], input: &[u8]) -> [u8; 32] {
|
||||
let hash_result = Blake2Params::new()
|
||||
|
@ -141,3 +141,40 @@ impl Version for V1 {
|
|||
data.write(w)
|
||||
}
|
||||
}
|
||||
|
||||
/// Version 2 of the Zcash chain history tree.
|
||||
///
|
||||
/// This version is used from the NU5 epoch.
|
||||
pub enum V2 {}
|
||||
|
||||
impl Version for V2 {
|
||||
type NodeData = node_data::V2;
|
||||
|
||||
fn consensus_branch_id(data: &Self::NodeData) -> u32 {
|
||||
data.v1.consensus_branch_id
|
||||
}
|
||||
|
||||
fn start_height(data: &Self::NodeData) -> u64 {
|
||||
data.v1.start_height
|
||||
}
|
||||
|
||||
fn end_height(data: &Self::NodeData) -> u64 {
|
||||
data.v1.end_height
|
||||
}
|
||||
|
||||
fn combine_inner(
|
||||
subtree_commitment: [u8; 32],
|
||||
left: &Self::NodeData,
|
||||
right: &Self::NodeData,
|
||||
) -> Self::NodeData {
|
||||
node_data::V2::combine_inner(subtree_commitment, left, right)
|
||||
}
|
||||
|
||||
fn read<R: io::Read>(consensus_branch_id: u32, r: &mut R) -> io::Result<Self::NodeData> {
|
||||
node_data::V2::read(consensus_branch_id, r)
|
||||
}
|
||||
|
||||
fn write<W: io::Write>(data: &Self::NodeData, w: &mut W) -> io::Result<()> {
|
||||
data.write(w)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue