mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-11 17:55:46 +00:00
add docs
This commit is contained in:
parent
ce2416623f
commit
7879b63321
11
src/entry.rs
11
src/entry.rs
@ -2,8 +2,10 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
|||||||
|
|
||||||
use crate::{EntryKind, NodeData, Error, EntryLink, MAX_NODE_DATA_SIZE};
|
use crate::{EntryKind, NodeData, Error, EntryLink, MAX_NODE_DATA_SIZE};
|
||||||
|
|
||||||
|
/// Max serialized length of entry data.
|
||||||
pub const MAX_ENTRY_SIZE: usize = MAX_NODE_DATA_SIZE + 9;
|
pub const MAX_ENTRY_SIZE: usize = MAX_NODE_DATA_SIZE + 9;
|
||||||
|
|
||||||
|
/// MMR Entry.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Entry {
|
pub struct Entry {
|
||||||
pub(crate) kind: EntryKind,
|
pub(crate) kind: EntryKind,
|
||||||
@ -11,23 +13,28 @@ pub struct Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Entry {
|
impl Entry {
|
||||||
|
/// Update siblings of the entry (to promote it from leaf to node)
|
||||||
pub fn update_siblings(&mut self, left: EntryLink, right: EntryLink) {
|
pub fn update_siblings(&mut self, left: EntryLink, right: EntryLink) {
|
||||||
self.kind = EntryKind::Node(left, right);
|
self.kind = EntryKind::Node(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns if is this node complete (has total of 2^N leaves)
|
||||||
pub fn complete(&self) -> bool {
|
pub fn complete(&self) -> bool {
|
||||||
let leaves = self.leaf_count();
|
let leaves = self.leaf_count();
|
||||||
leaves & (leaves - 1) == 0
|
leaves & (leaves - 1) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Number of leaves under this node.
|
||||||
pub fn leaf_count(&self) -> u64 {
|
pub fn leaf_count(&self) -> u64 {
|
||||||
self.data.end_height - self.data.start_height + 1
|
self.data.end_height - self.data.start_height + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is this node a leaf.
|
||||||
pub fn is_leaf(&self) -> bool {
|
pub fn is_leaf(&self) -> bool {
|
||||||
if let EntryKind::Leaf = self.kind { true } else { false }
|
if let EntryKind::Leaf = self.kind { true } else { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Left child
|
||||||
pub fn left(&self) -> Result<EntryLink, Error> {
|
pub fn left(&self) -> Result<EntryLink, Error> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
EntryKind::Leaf => { Err(Error::ExpectedNode) }
|
EntryKind::Leaf => { Err(Error::ExpectedNode) }
|
||||||
@ -35,6 +42,7 @@ impl Entry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Right child.
|
||||||
pub fn right(&self) -> Result<EntryLink, Error> {
|
pub fn right(&self) -> Result<EntryLink, Error> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
EntryKind::Leaf => { Err(Error::ExpectedNode) }
|
EntryKind::Leaf => { Err(Error::ExpectedNode) }
|
||||||
@ -42,6 +50,7 @@ impl Entry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read from byte representation.
|
||||||
pub fn read<R: std::io::Read>(consensus_branch_id: u32, r: &mut R) -> std::io::Result<Self> {
|
pub fn read<R: std::io::Read>(consensus_branch_id: u32, r: &mut R) -> std::io::Result<Self> {
|
||||||
let kind = {
|
let kind = {
|
||||||
match r.read_u8()? {
|
match r.read_u8()? {
|
||||||
@ -67,6 +76,7 @@ impl Entry {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write to byte representation.
|
||||||
pub fn write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
|
pub fn write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
EntryKind::Node(EntryLink::Stored(left), EntryLink::Stored(right)) => {
|
EntryKind::Node(EntryLink::Stored(left), EntryLink::Stored(right)) => {
|
||||||
@ -85,6 +95,7 @@ impl Entry {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert from byte representation.
|
||||||
pub fn from_bytes<T: AsRef<[u8]>>(consensus_branch_id: u32, buf: T) -> std::io::Result<Self> {
|
pub fn from_bytes<T: AsRef<[u8]>>(consensus_branch_id: u32, buf: T) -> std::io::Result<Self> {
|
||||||
let mut cursor = std::io::Cursor::new(buf);
|
let mut cursor = std::io::Cursor::new(buf);
|
||||||
Self::read(consensus_branch_id, &mut cursor)
|
Self::read(consensus_branch_id, &mut cursor)
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
//! MMR library for Zcash
|
//! MMR library for Zcash
|
||||||
//!
|
//!
|
||||||
//! To be used in zebra and via FFI bindings in zcashd
|
//! To be used in zebra and via FFI bindings in zcashd
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
mod tree;
|
mod tree;
|
||||||
mod node_data;
|
mod node_data;
|
||||||
mod entry;
|
mod entry;
|
||||||
|
|
||||||
|
|
||||||
pub use tree::Tree;
|
pub use tree::Tree;
|
||||||
pub use node_data::{NodeData, MAX_NODE_DATA_SIZE};
|
pub use node_data::{NodeData, MAX_NODE_DATA_SIZE};
|
||||||
pub use entry::{Entry, MAX_ENTRY_SIZE};
|
pub use entry::{Entry, MAX_ENTRY_SIZE};
|
||||||
|
|
||||||
|
/// Crate-level error type
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// Entry expected to be presented in the tree view while it was not.
|
||||||
ExpectedInMemory(EntryLink),
|
ExpectedInMemory(EntryLink),
|
||||||
|
/// Entry expected to be a node.
|
||||||
ExpectedNode,
|
ExpectedNode,
|
||||||
|
/// Entry expected to be a node (specifying for which link this is not true).
|
||||||
ExpectedNodeForLink(EntryLink),
|
ExpectedNodeForLink(EntryLink),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +56,9 @@ impl std::fmt::Display for EntryLink {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EntryKind {
|
pub enum EntryKind {
|
||||||
|
/// Leaf entry.
|
||||||
Leaf,
|
Leaf,
|
||||||
|
/// Node entry with children links.
|
||||||
Node(EntryLink, EntryLink),
|
Node(EntryLink, EntryLink),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,23 +2,36 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt, ByteOrder};
|
|||||||
use bigint::U256;
|
use bigint::U256;
|
||||||
use blake2::Params as Blake2Params;
|
use blake2::Params as Blake2Params;
|
||||||
|
|
||||||
|
/// Maximum serialized size of the node metadata.
|
||||||
pub const MAX_NODE_DATA_SIZE: usize = 32 + 4 + 4 + 4 + 4 + 32 + 32 + 32 + 9 + 9 + 9; // 171
|
pub const MAX_NODE_DATA_SIZE: usize = 32 + 4 + 4 + 4 + 4 + 32 + 32 + 32 + 9 + 9 + 9; // 171
|
||||||
|
|
||||||
/// Node metadata.
|
/// Node metadata.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct NodeData {
|
pub struct NodeData {
|
||||||
|
/// Consensus branch id, should be provided by deserializing node.
|
||||||
pub consensus_branch_id: u32,
|
pub consensus_branch_id: u32,
|
||||||
|
/// Subtree commitment - either block hash for leaves or hashsum of children for nodes.
|
||||||
pub subtree_commitment: [u8; 32],
|
pub subtree_commitment: [u8; 32],
|
||||||
|
/// Start time.
|
||||||
pub start_time: u32,
|
pub start_time: u32,
|
||||||
|
/// End time.
|
||||||
pub end_time: u32,
|
pub end_time: u32,
|
||||||
|
/// Start target.
|
||||||
pub start_target: u32,
|
pub start_target: u32,
|
||||||
|
/// End target.
|
||||||
pub end_target: u32,
|
pub end_target: u32,
|
||||||
|
/// Start sapling tree root.
|
||||||
pub start_sapling_root: [u8; 32],
|
pub start_sapling_root: [u8; 32],
|
||||||
|
/// End sapling tree root.
|
||||||
pub end_sapling_root: [u8; 32],
|
pub end_sapling_root: [u8; 32],
|
||||||
|
/// Part of tree total work.
|
||||||
pub subtree_total_work: U256,
|
pub subtree_total_work: U256,
|
||||||
|
/// Start height.
|
||||||
pub start_height: u64,
|
pub start_height: u64,
|
||||||
|
/// End height
|
||||||
pub end_height: u64,
|
pub end_height: u64,
|
||||||
|
/// Number of shielded transactions.
|
||||||
pub shielded_tx: u64,
|
pub shielded_tx: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +55,7 @@ fn personalization(branch_id: u32) -> [u8; 16] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NodeData {
|
impl NodeData {
|
||||||
|
/// Combine two nodes metadata.
|
||||||
pub fn combine(left: &NodeData, right: &NodeData) -> NodeData {
|
pub fn combine(left: &NodeData, right: &NodeData) -> NodeData {
|
||||||
assert_eq!(left.consensus_branch_id, right.consensus_branch_id);
|
assert_eq!(left.consensus_branch_id, right.consensus_branch_id);
|
||||||
|
|
||||||
@ -106,6 +120,7 @@ impl NodeData {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write to the byte representation.
|
||||||
pub fn write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
|
pub fn write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
|
||||||
w.write_all(&self.subtree_commitment)?;
|
w.write_all(&self.subtree_commitment)?;
|
||||||
w.write_u32::<LittleEndian>(self.start_time)?;
|
w.write_u32::<LittleEndian>(self.start_time)?;
|
||||||
@ -125,6 +140,7 @@ impl NodeData {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read from the byte representation.
|
||||||
pub fn read<R: std::io::Read>(consensus_branch_id: u32, r: &mut R) -> std::io::Result<Self> {
|
pub fn read<R: std::io::Read>(consensus_branch_id: u32, r: &mut R) -> std::io::Result<Self> {
|
||||||
let mut data = Self::default();
|
let mut data = Self::default();
|
||||||
data.consensus_branch_id = consensus_branch_id;
|
data.consensus_branch_id = consensus_branch_id;
|
||||||
@ -147,6 +163,7 @@ impl NodeData {
|
|||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert to byte representation.
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
let mut buf = [0u8; MAX_NODE_DATA_SIZE];
|
let mut buf = [0u8; MAX_NODE_DATA_SIZE];
|
||||||
let pos = {
|
let pos = {
|
||||||
@ -158,6 +175,7 @@ impl NodeData {
|
|||||||
buf[0..pos].to_vec()
|
buf[0..pos].to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert from byte representation.
|
||||||
pub fn from_bytes<T: AsRef<[u8]>>(consensus_branch_id: u32, buf: T) -> std::io::Result<Self> {
|
pub fn from_bytes<T: AsRef<[u8]>>(consensus_branch_id: u32, buf: T) -> std::io::Result<Self> {
|
||||||
let mut cursor = std::io::Cursor::new(buf);
|
let mut cursor = std::io::Cursor::new(buf);
|
||||||
Self::read(consensus_branch_id, &mut cursor)
|
Self::read(consensus_branch_id, &mut cursor)
|
||||||
|
11
src/tree.rs
11
src/tree.rs
@ -24,6 +24,7 @@ pub struct Tree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Tree {
|
impl Tree {
|
||||||
|
/// Resolve link originated from this tree
|
||||||
pub fn resolve_link(&self, link: EntryLink) -> Result<IndexedNode, Error> {
|
pub fn resolve_link(&self, link: EntryLink) -> Result<IndexedNode, Error> {
|
||||||
match link {
|
match link {
|
||||||
EntryLink::Generated(index) => {
|
EntryLink::Generated(index) => {
|
||||||
@ -80,6 +81,12 @@ impl Tree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// New view into the the tree array representation
|
||||||
|
///
|
||||||
|
/// `length` is total length of the array representation
|
||||||
|
/// `peaks` is peaks of the mmr tree
|
||||||
|
/// `extra` is some extra nodes that calculated to be required during next one or more
|
||||||
|
/// operations on the tree.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
length: u32,
|
length: u32,
|
||||||
peaks: Vec<(u32, Entry)>,
|
peaks: Vec<(u32, Entry)>,
|
||||||
@ -267,6 +274,7 @@ impl Tree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reference to the node with link attached.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct IndexedNode<'a> {
|
pub struct IndexedNode<'a> {
|
||||||
node: &'a Entry,
|
node: &'a Entry,
|
||||||
@ -283,14 +291,17 @@ impl<'a> IndexedNode<'a> {
|
|||||||
self.node.right().map_err(|e| e.augment(self.link))
|
self.node.right().map_err(|e| e.augment(self.link))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reference to the entry struct.
|
||||||
pub fn node(&self) -> &Entry {
|
pub fn node(&self) -> &Entry {
|
||||||
self.node
|
self.node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reference to the entry metadata.
|
||||||
pub fn data(&self) -> &NodeData {
|
pub fn data(&self) -> &NodeData {
|
||||||
&self.node.data
|
&self.node.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Actual link by what this node was resolved.
|
||||||
pub fn link(&self) -> EntryLink {
|
pub fn link(&self) -> EntryLink {
|
||||||
self.link
|
self.link
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user