Factor serialization out from merkle tree data structures.
This commit is contained in:
parent
831a6cd396
commit
6f2cbfc7de
|
@ -12,6 +12,7 @@ use zcash_primitives::{
|
||||||
block::BlockHash,
|
block::BlockHash,
|
||||||
consensus::{self, BlockHeight},
|
consensus::{self, BlockHeight},
|
||||||
memo::MemoBytes,
|
memo::MemoBytes,
|
||||||
|
merkle_tree::{write_commitment_tree, write_incremental_witness},
|
||||||
sapling::{self, Diversifier, Nullifier},
|
sapling::{self, Diversifier, Nullifier},
|
||||||
transaction::{components::Amount, TxId},
|
transaction::{components::Amount, TxId},
|
||||||
zip32::{AccountId, DiversifierIndex},
|
zip32::{AccountId, DiversifierIndex},
|
||||||
|
@ -279,7 +280,7 @@ impl<'a, P> DataConnStmtCache<'a, P> {
|
||||||
commitment_tree: &sapling::CommitmentTree,
|
commitment_tree: &sapling::CommitmentTree,
|
||||||
) -> Result<(), SqliteClientError> {
|
) -> Result<(), SqliteClientError> {
|
||||||
let mut encoded_tree = Vec::new();
|
let mut encoded_tree = Vec::new();
|
||||||
commitment_tree.write(&mut encoded_tree).unwrap();
|
write_commitment_tree(commitment_tree, &mut encoded_tree).unwrap();
|
||||||
|
|
||||||
self.stmt_insert_block.execute(params![
|
self.stmt_insert_block.execute(params![
|
||||||
u32::from(block_height),
|
u32::from(block_height),
|
||||||
|
@ -784,7 +785,7 @@ impl<'a, P> DataConnStmtCache<'a, P> {
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let mut encoded = Vec::new();
|
let mut encoded = Vec::new();
|
||||||
witness.write(&mut encoded).unwrap();
|
write_incremental_witness(witness, &mut encoded).unwrap();
|
||||||
|
|
||||||
self.stmt_insert_witness
|
self.stmt_insert_witness
|
||||||
.execute(params![note_id, u32::from(height), encoded])?;
|
.execute(params![note_id, u32::from(height), encoded])?;
|
||||||
|
|
|
@ -73,6 +73,7 @@ use zcash_primitives::{
|
||||||
block::BlockHash,
|
block::BlockHash,
|
||||||
consensus::{self, BlockHeight, BranchId, NetworkUpgrade, Parameters},
|
consensus::{self, BlockHeight, BranchId, NetworkUpgrade, Parameters},
|
||||||
memo::{Memo, MemoBytes},
|
memo::{Memo, MemoBytes},
|
||||||
|
merkle_tree::{read_commitment_tree, read_incremental_witness},
|
||||||
sapling::{self, Note, Nullifier},
|
sapling::{self, Note, Nullifier},
|
||||||
transaction::{components::Amount, Transaction, TxId},
|
transaction::{components::Amount, Transaction, TxId},
|
||||||
zip32::{
|
zip32::{
|
||||||
|
@ -693,7 +694,7 @@ pub(crate) fn get_sapling_commitment_tree<P>(
|
||||||
[u32::from(block_height)],
|
[u32::from(block_height)],
|
||||||
|row| {
|
|row| {
|
||||||
let row_data: Vec<u8> = row.get(0)?;
|
let row_data: Vec<u8> = row.get(0)?;
|
||||||
sapling::CommitmentTree::read(&row_data[..]).map_err(|e| {
|
read_commitment_tree(&row_data[..]).map_err(|e| {
|
||||||
rusqlite::Error::FromSqlConversionFailure(
|
rusqlite::Error::FromSqlConversionFailure(
|
||||||
row_data.len(),
|
row_data.len(),
|
||||||
rusqlite::types::Type::Blob,
|
rusqlite::types::Type::Blob,
|
||||||
|
@ -719,7 +720,7 @@ pub(crate) fn get_sapling_witnesses<P>(
|
||||||
.query_map([u32::from(block_height)], |row| {
|
.query_map([u32::from(block_height)], |row| {
|
||||||
let id_note = NoteId::ReceivedNoteId(row.get(0)?);
|
let id_note = NoteId::ReceivedNoteId(row.get(0)?);
|
||||||
let wdb: Vec<u8> = row.get(1)?;
|
let wdb: Vec<u8> = row.get(1)?;
|
||||||
Ok(sapling::IncrementalWitness::read(&wdb[..]).map(|witness| (id_note, witness)))
|
Ok(read_incremental_witness(&wdb[..]).map(|witness| (id_note, witness)))
|
||||||
})
|
})
|
||||||
.map_err(SqliteClientError::from)?;
|
.map_err(SqliteClientError::from)?;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use group::ff::PrimeField;
|
||||||
|
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
consensus::BlockHeight,
|
consensus::BlockHeight,
|
||||||
merkle_tree::IncrementalWitness,
|
merkle_tree::read_incremental_witness,
|
||||||
sapling::{Diversifier, Rseed},
|
sapling::{Diversifier, Rseed},
|
||||||
transaction::components::Amount,
|
transaction::components::Amount,
|
||||||
zip32::AccountId,
|
zip32::AccountId,
|
||||||
|
@ -50,7 +50,7 @@ fn to_spendable_note(row: &Row) -> Result<SpendableNote<NoteId>, SqliteClientErr
|
||||||
|
|
||||||
let witness = {
|
let witness = {
|
||||||
let d: Vec<_> = row.get(4)?;
|
let d: Vec<_> = row.get(4)?;
|
||||||
IncrementalWitness::read(&d[..])?
|
read_incremental_witness(&d[..])?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(SpendableNote {
|
Ok(SpendableNote {
|
||||||
|
|
|
@ -14,11 +14,17 @@ and this library adheres to Rust's notion of
|
||||||
type has been removed.
|
type has been removed.
|
||||||
- `sapling::SAPLING_COMMITMENT_TREE_DEPTH_U8` and `sapling::SAPLING_COMMITMENT_TREE_DEPTH`
|
- `sapling::SAPLING_COMMITMENT_TREE_DEPTH_U8` and `sapling::SAPLING_COMMITMENT_TREE_DEPTH`
|
||||||
have been removed; use `sapling::NOTE_COMMITMENT_TREE_DEPTH` instead.
|
have been removed; use `sapling::NOTE_COMMITMENT_TREE_DEPTH` instead.
|
||||||
- `merkle_tree::incremental::write_auth_fragment_v1`
|
- `merkle_tree:` removals:
|
||||||
|
- `incremental::write_auth_fragment_v1`
|
||||||
|
- `CommitmentTree::write` and `CommitmentTree::read` have been replaced by
|
||||||
|
`write_commitment_tree` and `read_commitment_tree` respectively.
|
||||||
|
- `IncrementalWitness::write` and `IncrementalWitness::read` have been
|
||||||
|
replaced by `write_incremental_witness` and `read_incremental_witness`
|
||||||
|
respectively.
|
||||||
|
- `MerklePath::from_slice` has been replaced by `merkle_path_from_slice`
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- `merkle_tree::incremental::{read_address, write_address}`
|
- `merkle_tree::incremental::{read_address, write_address, read_bridge_v2}`
|
||||||
- `merkle_tree::incremental::read_bridge_v2`
|
|
||||||
- `sapling::{CommitmentTree, IncrementalWitness, MerklePath, NOTE_COMMITMENT_TREE_DEPTH}`
|
- `sapling::{CommitmentTree, IncrementalWitness, MerklePath, NOTE_COMMITMENT_TREE_DEPTH}`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -150,12 +150,10 @@ impl<Node, const DEPTH: u8> CommitmentTree<Node, DEPTH> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node: Hashable + Clone, const DEPTH: u8> CommitmentTree<Node, DEPTH> {
|
/// Reads a `CommitmentTree` from its serialized form.
|
||||||
/// Reads a `CommitmentTree` from its serialized form.
|
pub fn read_commitment_tree<Node: HashSer, R: Read, const DEPTH: u8>(
|
||||||
pub fn read<R: Read>(mut reader: R) -> io::Result<Self>
|
mut reader: R,
|
||||||
where
|
) -> io::Result<CommitmentTree<Node, DEPTH>> {
|
||||||
Node: HashSer,
|
|
||||||
{
|
|
||||||
let left = Optional::read(&mut reader, Node::read)?;
|
let left = Optional::read(&mut reader, Node::read)?;
|
||||||
let right = Optional::read(&mut reader, Node::read)?;
|
let right = Optional::read(&mut reader, Node::read)?;
|
||||||
let parents = Vector::read(&mut reader, |r| Optional::read(r, Node::read))?;
|
let parents = Vector::read(&mut reader, |r| Optional::read(r, Node::read))?;
|
||||||
|
@ -165,20 +163,21 @@ impl<Node: Hashable + Clone, const DEPTH: u8> CommitmentTree<Node, DEPTH> {
|
||||||
right,
|
right,
|
||||||
parents,
|
parents,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes this tree as an array of bytes.
|
/// Serializes this tree as an array of bytes.
|
||||||
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()>
|
pub fn write_commitment_tree<Node: HashSer, W: Write, const DEPTH: u8>(
|
||||||
where
|
tree: &CommitmentTree<Node, DEPTH>,
|
||||||
Node: HashSer,
|
mut writer: W,
|
||||||
{
|
) -> io::Result<()> {
|
||||||
Optional::write(&mut writer, self.left.as_ref(), |w, n| n.write(w))?;
|
Optional::write(&mut writer, tree.left.as_ref(), |w, n| n.write(w))?;
|
||||||
Optional::write(&mut writer, self.right.as_ref(), |w, n| n.write(w))?;
|
Optional::write(&mut writer, tree.right.as_ref(), |w, n| n.write(w))?;
|
||||||
Vector::write(&mut writer, &self.parents, |w, e| {
|
Vector::write(&mut writer, &tree.parents, |w, e| {
|
||||||
Optional::write(w, e.as_ref(), |w, n| n.write(w))
|
Optional::write(w, e.as_ref(), |w, n| n.write(w))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Node: Hashable + Clone, const DEPTH: u8> CommitmentTree<Node, DEPTH> {
|
||||||
/// Adds a leaf node to the tree.
|
/// Adds a leaf node to the tree.
|
||||||
///
|
///
|
||||||
/// Returns an error if the tree is full.
|
/// Returns an error if the tree is full.
|
||||||
|
@ -307,13 +306,14 @@ impl<Node, const DEPTH: u8> IncrementalWitness<Node, DEPTH> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node: Hashable + HashSer + Clone, const DEPTH: u8> IncrementalWitness<Node, DEPTH> {
|
/// Reads an `IncrementalWitness` from its serialized form.
|
||||||
/// Reads an `IncrementalWitness` from its serialized form.
|
#[allow(clippy::redundant_closure)]
|
||||||
#[allow(clippy::redundant_closure)]
|
pub fn read_incremental_witness<Node: HashSer, R: Read, const DEPTH: u8>(
|
||||||
pub fn read<R: Read>(mut reader: R) -> io::Result<IncrementalWitness<Node, DEPTH>> {
|
mut reader: R,
|
||||||
let tree = CommitmentTree::<Node, DEPTH>::read(&mut reader)?;
|
) -> io::Result<IncrementalWitness<Node, DEPTH>> {
|
||||||
|
let tree = read_commitment_tree(&mut reader)?;
|
||||||
let filled = Vector::read(&mut reader, |r| Node::read(r))?;
|
let filled = Vector::read(&mut reader, |r| Node::read(r))?;
|
||||||
let cursor = Optional::read(&mut reader, CommitmentTree::<Node, DEPTH>::read)?;
|
let cursor = Optional::read(&mut reader, read_commitment_tree)?;
|
||||||
|
|
||||||
let mut witness = IncrementalWitness {
|
let mut witness = IncrementalWitness {
|
||||||
tree,
|
tree,
|
||||||
|
@ -325,20 +325,28 @@ impl<Node: Hashable + HashSer + Clone, const DEPTH: u8> IncrementalWitness<Node,
|
||||||
witness.cursor_depth = witness.next_depth();
|
witness.cursor_depth = witness.next_depth();
|
||||||
|
|
||||||
Ok(witness)
|
Ok(witness)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes this `IncrementalWitness` as an array of bytes.
|
/// Serializes this `IncrementalWitness` as an array of bytes.
|
||||||
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
pub fn write_incremental_witness<Node: HashSer, W: Write, const DEPTH: u8>(
|
||||||
self.tree.write(&mut writer)?;
|
witness: &IncrementalWitness<Node, DEPTH>,
|
||||||
Vector::write(&mut writer, &self.filled, |w, n| n.write(w))?;
|
mut writer: W,
|
||||||
Optional::write(&mut writer, self.cursor.as_ref(), |w, t| t.write(w))
|
) -> io::Result<()> {
|
||||||
}
|
write_commitment_tree(&witness.tree, &mut writer)?;
|
||||||
|
Vector::write(&mut writer, &witness.filled, |w, n| n.write(w))?;
|
||||||
|
Optional::write(&mut writer, witness.cursor.as_ref(), |w, t| {
|
||||||
|
write_commitment_tree(t, w)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Node, const DEPTH: u8> IncrementalWitness<Node, DEPTH> {
|
||||||
/// Returns the position of the witnessed leaf node in the commitment tree.
|
/// Returns the position of the witnessed leaf node in the commitment tree.
|
||||||
pub fn position(&self) -> usize {
|
pub fn position(&self) -> usize {
|
||||||
self.tree.size() - 1
|
self.tree.size() - 1
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Node: Hashable + Clone, const DEPTH: u8> IncrementalWitness<Node, DEPTH> {
|
||||||
fn filler(&self) -> PathFiller<Node> {
|
fn filler(&self) -> PathFiller<Node> {
|
||||||
let cursor_root = self
|
let cursor_root = self
|
||||||
.cursor
|
.cursor
|
||||||
|
@ -349,7 +357,9 @@ impl<Node: Hashable + HashSer + Clone, const DEPTH: u8> IncrementalWitness<Node,
|
||||||
queue: self.filled.iter().cloned().chain(cursor_root).collect(),
|
queue: self.filled.iter().cloned().chain(cursor_root).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Node, const DEPTH: u8> IncrementalWitness<Node, DEPTH> {
|
||||||
/// Finds the next "depth" of an unfilled subtree.
|
/// Finds the next "depth" of an unfilled subtree.
|
||||||
fn next_depth(&self) -> u8 {
|
fn next_depth(&self) -> u8 {
|
||||||
let mut skip: u8 = self
|
let mut skip: u8 = self
|
||||||
|
@ -388,7 +398,9 @@ impl<Node: Hashable + HashSer + Clone, const DEPTH: u8> IncrementalWitness<Node,
|
||||||
|
|
||||||
d + skip
|
d + skip
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Node: Hashable + Clone, const DEPTH: u8> IncrementalWitness<Node, DEPTH> {
|
||||||
/// Tracks a leaf node that has been added to the underlying tree.
|
/// Tracks a leaf node that has been added to the underlying tree.
|
||||||
///
|
///
|
||||||
/// Returns an error if the tree is full.
|
/// Returns an error if the tree is full.
|
||||||
|
@ -499,9 +511,10 @@ impl<Node, const DEPTH: u8> MerklePath<Node, DEPTH> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node: Hashable + HashSer, const DEPTH: u8> MerklePath<Node, DEPTH> {
|
/// Reads a Merkle path from its serialized form.
|
||||||
/// Reads a Merkle path from its serialized form.
|
pub fn merkle_path_from_slice<Node: HashSer, const DEPTH: u8>(
|
||||||
pub fn from_slice(mut witness: &[u8]) -> Result<Self, ()> {
|
mut witness: &[u8],
|
||||||
|
) -> Result<MerklePath<Node, DEPTH>, ()> {
|
||||||
// Skip the first byte, which should be DEPTH to signify the length of
|
// Skip the first byte, which should be DEPTH to signify the length of
|
||||||
// the following vector of Pedersen hashes.
|
// the following vector of Pedersen hashes.
|
||||||
if witness[0] != DEPTH {
|
if witness[0] != DEPTH {
|
||||||
|
@ -559,8 +572,9 @@ impl<Node: Hashable + HashSer, const DEPTH: u8> MerklePath<Node, DEPTH> {
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Node: Hashable + HashSer, const DEPTH: u8> MerklePath<Node, DEPTH> {
|
||||||
/// Returns the root of the tree corresponding to this path applied to `leaf`.
|
/// Returns the root of the tree corresponding to this path applied to `leaf`.
|
||||||
pub fn root(&self, leaf: Node) -> Node {
|
pub fn root(&self, leaf: Node) -> Node {
|
||||||
self.auth_path
|
self.auth_path
|
||||||
|
@ -587,8 +601,10 @@ mod tests {
|
||||||
use crate::sapling::{self, testing::arb_node, Node};
|
use crate::sapling::{self, testing::arb_node, Node};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
merkle_path_from_slice, read_commitment_tree, read_incremental_witness,
|
||||||
testing::{arb_commitment_tree, TestNode},
|
testing::{arb_commitment_tree, TestNode},
|
||||||
CommitmentTree, HashSer, IncrementalWitness, MerklePath, PathFiller,
|
write_commitment_tree, write_incremental_witness, CommitmentTree, HashSer,
|
||||||
|
IncrementalWitness, PathFiller,
|
||||||
};
|
};
|
||||||
|
|
||||||
const HEX_EMPTY_ROOTS: [&str; 33] = [
|
const HEX_EMPTY_ROOTS: [&str; 33] = [
|
||||||
|
@ -1001,14 +1017,14 @@ mod tests {
|
||||||
fn assert_tree_ser_eq(tree: &CommitmentTree<Node, TESTING_DEPTH>, expected: &str) {
|
fn assert_tree_ser_eq(tree: &CommitmentTree<Node, TESTING_DEPTH>, expected: &str) {
|
||||||
// Check that the tree matches its encoding
|
// Check that the tree matches its encoding
|
||||||
let mut tmp = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
tree.write(&mut tmp).unwrap();
|
write_commitment_tree(tree, &mut tmp).unwrap();
|
||||||
assert_eq!(hex::encode(&tmp[..]), expected);
|
assert_eq!(hex::encode(&tmp[..]), expected);
|
||||||
|
|
||||||
// Check round-trip encoding
|
// Check round-trip encoding
|
||||||
let decoded: CommitmentTree<Node, TESTING_DEPTH> =
|
let decoded: CommitmentTree<Node, TESTING_DEPTH> =
|
||||||
CommitmentTree::read(&hex::decode(expected).unwrap()[..]).unwrap();
|
read_commitment_tree(&hex::decode(expected).unwrap()[..]).unwrap();
|
||||||
tmp.clear();
|
tmp.clear();
|
||||||
decoded.write(&mut tmp).unwrap();
|
write_commitment_tree(&decoded, &mut tmp).unwrap();
|
||||||
assert_eq!(hex::encode(tmp), expected);
|
assert_eq!(hex::encode(tmp), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,14 +1034,14 @@ mod tests {
|
||||||
) {
|
) {
|
||||||
// Check that the witness matches its encoding
|
// Check that the witness matches its encoding
|
||||||
let mut tmp = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
witness.write(&mut tmp).unwrap();
|
write_incremental_witness(witness, &mut tmp).unwrap();
|
||||||
assert_eq!(hex::encode(&tmp[..]), expected);
|
assert_eq!(hex::encode(&tmp[..]), expected);
|
||||||
|
|
||||||
// Check round-trip encoding
|
// Check round-trip encoding
|
||||||
let decoded: IncrementalWitness<Node, TESTING_DEPTH> =
|
let decoded: IncrementalWitness<Node, TESTING_DEPTH> =
|
||||||
IncrementalWitness::read(&hex::decode(expected).unwrap()[..]).unwrap();
|
read_incremental_witness(&hex::decode(expected).unwrap()[..]).unwrap();
|
||||||
tmp.clear();
|
tmp.clear();
|
||||||
decoded.write(&mut tmp).unwrap();
|
write_incremental_witness(&decoded, &mut tmp).unwrap();
|
||||||
assert_eq!(hex::encode(tmp), expected);
|
assert_eq!(hex::encode(tmp), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1063,7 +1079,7 @@ mod tests {
|
||||||
if let Some(leaf) = leaf {
|
if let Some(leaf) = leaf {
|
||||||
let path = witness.path().expect("should be able to create a path");
|
let path = witness.path().expect("should be able to create a path");
|
||||||
let expected =
|
let expected =
|
||||||
MerklePath::from_slice(&hex::decode(paths[paths_i]).unwrap()).unwrap();
|
merkle_path_from_slice(&hex::decode(paths[paths_i]).unwrap()).unwrap();
|
||||||
assert_eq!(path, expected);
|
assert_eq!(path, expected);
|
||||||
|
|
||||||
assert_eq!(path.root(*leaf), witness.root());
|
assert_eq!(path.root(*leaf), witness.root());
|
||||||
|
@ -1136,8 +1152,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn prop_commitment_tree_roundtrip_ser(ct in arb_commitment_tree::<_, _, 8>(32, arb_node())) {
|
fn prop_commitment_tree_roundtrip_ser(ct in arb_commitment_tree::<_, _, 8>(32, arb_node())) {
|
||||||
let mut serialized = vec![];
|
let mut serialized = vec![];
|
||||||
assert_matches!(ct.write(&mut serialized), Ok(()));
|
assert_matches!(write_commitment_tree(&ct, &mut serialized), Ok(()));
|
||||||
assert_matches!(CommitmentTree::<_, 8>::read(&serialized[..]), Ok(ct_out) if ct == ct_out);
|
assert_matches!(read_commitment_tree::<_, _, 8>(&serialized[..]), Ok(ct_out) if ct == ct_out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use incrementalmerkletree::{Address, Hashable, Level, Position};
|
||||||
use orchard::tree::MerkleHashOrchard;
|
use orchard::tree::MerkleHashOrchard;
|
||||||
use zcash_encoding::{Optional, Vector};
|
use zcash_encoding::{Optional, Vector};
|
||||||
|
|
||||||
use super::{CommitmentTree, HashSer};
|
use super::{read_commitment_tree, HashSer};
|
||||||
use crate::sapling;
|
use crate::sapling;
|
||||||
|
|
||||||
pub const SER_V1: u8 = 1;
|
pub const SER_V1: u8 = 1;
|
||||||
|
@ -80,8 +80,7 @@ pub fn read_address<R: Read>(mut reader: R) -> io::Result<Address> {
|
||||||
pub fn read_frontier_v0<H: Hashable + HashSer + Clone, R: Read>(
|
pub fn read_frontier_v0<H: Hashable + HashSer + Clone, R: Read>(
|
||||||
mut reader: R,
|
mut reader: R,
|
||||||
) -> io::Result<Frontier<H, { sapling::NOTE_COMMITMENT_TREE_DEPTH }>> {
|
) -> io::Result<Frontier<H, { sapling::NOTE_COMMITMENT_TREE_DEPTH }>> {
|
||||||
let tree = CommitmentTree::<H, { sapling::NOTE_COMMITMENT_TREE_DEPTH }>::read(&mut reader)?;
|
let tree = read_commitment_tree(&mut reader)?;
|
||||||
|
|
||||||
Ok(tree.to_frontier())
|
Ok(tree.to_frontier())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +311,10 @@ mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
merkle_tree::testing::{arb_commitment_tree, TestNode},
|
merkle_tree::{
|
||||||
|
testing::{arb_commitment_tree, TestNode},
|
||||||
|
write_commitment_tree,
|
||||||
|
},
|
||||||
sapling::{testing as sapling, Node},
|
sapling::{testing as sapling, Node},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -321,7 +323,7 @@ mod tests {
|
||||||
fn frontier_serialization_v0(t in arb_commitment_tree::<_, _, 32>(0, sapling::arb_node()))
|
fn frontier_serialization_v0(t in arb_commitment_tree::<_, _, 32>(0, sapling::arb_node()))
|
||||||
{
|
{
|
||||||
let mut buffer = vec![];
|
let mut buffer = vec![];
|
||||||
t.write(&mut buffer).unwrap();
|
write_commitment_tree(&t, &mut buffer).unwrap();
|
||||||
let frontier: Frontier<Node, 32> = read_frontier_v0(&buffer[..]).unwrap();
|
let frontier: Frontier<Node, 32> = read_frontier_v0(&buffer[..]).unwrap();
|
||||||
|
|
||||||
let expected: Frontier<Node, 32> = t.to_frontier();
|
let expected: Frontier<Node, 32> = t.to_frontier();
|
||||||
|
|
Loading…
Reference in New Issue