Skip to content

Commit

Permalink
zcash_history: Implement V2 tree format
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Jun 11, 2021
1 parent 63f554b commit e84bb87
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 4 deletions.
1 change: 1 addition & 0 deletions zcash_history/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion zcash_history/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
54 changes: 52 additions & 2 deletions zcash_history/src/node_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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 {
Expand Down
39 changes: 38 additions & 1 deletion zcash_history/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
}
}

0 comments on commit e84bb87

Please sign in to comment.