zebra/zebra-chain/src/sapling/tree.rs

805 lines
28 KiB
Rust
Raw Normal View History

//! Note Commitment Trees.
//!
//! A note commitment tree is an incremental Merkle tree of fixed depth
//! used to store note commitments that JoinSplit transfers or Spend
//! transfers produce. Just as the unspent transaction output set (UTXO
//! set) used in Bitcoin, it is used to express the existence of value and
//! the capability to spend it. However, unlike the UTXO set, it is not
//! the job of this tree to protect against double-spending, as it is
//! append-only.
//!
//! A root of a note commitment tree is associated with each treestate.
use std::{
default::Default,
fmt,
hash::{Hash, Hasher},
io,
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
sync::Arc,
};
use bitvec::prelude::*;
use bridgetree::{self, NonEmptyFrontier};
use hex::ToHex;
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
use incrementalmerkletree::{frontier::Frontier, Hashable};
use lazy_static::lazy_static;
use thiserror::Error;
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
use zcash_encoding::{Optional, Vector};
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
use zcash_primitives::merkle_tree::HashSer;
use super::commitment::pedersen_hashes::pedersen_hash;
use crate::{
serialization::{
serde_helpers, ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize,
},
change(state): Add note subtree indexes for new and existing blocks (#7437) * Copy the add_subtrees upgrade from the original branch * Copy the database write changes in shielded.rs from the original branch * Copy the tree API changes from the original branch * Simplify subtree APIs to avoid exposing frontiers * Fix a dead code warning by re-using existing methods * Use mpsc::Receiver<CancelFormatChange> in the subtree upgrade * Run the subtree upgrade on startup * Bump the database format version to 25.2.0 * Fix a confusing 'upgrade complete' log * Clarify some comments and error messages * Simplify prev_tree unwrap to avoid an (impossible?) concurrency bug * Use separate subtree writing functions * Use common note commitment list code * Fix subtree completion condition and add asserts * Simplify subtree API and avoid exposing Address * Fix API compatibility when Arcs are removed * Log when each subtree is added * If a format change is cancelled, don't mark the database as upgraded or do format checks * Log subtree progress about once every two minutes * Adds a state validity check for subtrees upgrade * Orchard is faster, decrease log interval * Clarify subtree index docs * Move a log to the correct location * Refactor subtree upgrade to remove duplicate inverted loop conditions * updates subtree state validity check * Add a subtree format check when there is no upgrade * Fix an off-by-one error with the final subtree check * Use error-level logs for database format checks * Skip format checks in tests that create invalid formats * fix state validity test * Add a concurrency comment to subtree by height methods * Add individual subtree state methods: reverts removing these methods in an earlier PR * fastmod "subtrees_by_index" "subtree_list_by_index_for_rpc" --------- Co-authored-by: arya2 <aryasolhi@gmail.com>
2023-09-05 09:52:06 -07:00
subtree::{NoteCommitmentSubtreeIndex, TRACKED_SUBTREE_HEIGHT},
};
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
pub mod legacy;
use legacy::{LegacyLeaf, LegacyNoteCommitmentTree};
/// The type that is used to update the note commitment tree.
///
/// Unfortunately, this is not the same as `sapling::NoteCommitment`.
pub type NoteCommitmentUpdate = jubjub::Fq;
pub(super) const MERKLE_DEPTH: u8 = 32;
/// MerkleCRH^Sapling Hash Function
///
/// Used to hash incremental Merkle tree hash values for Sapling.
///
/// MerkleCRH^Sapling(layer, left, right) := PedersenHash("Zcash_PH", l || left || right)
/// where l = I2LEBSP_6(MerkleDepth^Sapling 1 layer) and
/// left, right, and the output are all technically 255 bits (l_MerkleSapling), not 256.
///
/// <https://zips.z.cash/protocol/protocol.pdf#merklecrh>
fn merkle_crh_sapling(layer: u8, left: [u8; 32], right: [u8; 32]) -> [u8; 32] {
let mut s = bitvec![u8, Lsb0;];
// Prefix: l = I2LEBSP_6(MerkleDepth^Sapling 1 layer)
let l = MERKLE_DEPTH - 1 - layer;
s.extend_from_bitslice(&BitSlice::<_, Lsb0>::from_element(&l)[0..6]);
s.extend_from_bitslice(&BitArray::<_, Lsb0>::from(left)[0..255]);
s.extend_from_bitslice(&BitArray::<_, Lsb0>::from(right)[0..255]);
pedersen_hash(*b"Zcash_PH", &s).to_bytes()
}
lazy_static! {
/// List of "empty" Sapling note commitment nodes, one for each layer.
///
/// The list is indexed by the layer number (0: root; MERKLE_DEPTH: leaf).
///
/// <https://zips.z.cash/protocol/protocol.pdf#constants>
pub(super) static ref EMPTY_ROOTS: Vec<[u8; 32]> = {
// The empty leaf node. This is layer 32.
let mut v = vec![NoteCommitmentTree::uncommitted()];
// Starting with layer 31 (the first internal layer, after the leaves),
// generate the empty roots up to layer 0, the root.
for layer in (0..MERKLE_DEPTH).rev() {
// The vector is generated from the end, pushing new nodes to its beginning.
// For this reason, the layer below is v[0].
let next = merkle_crh_sapling(layer, v[0], v[0]);
v.insert(0, next);
}
v
};
}
/// Sapling note commitment tree root node hash.
///
/// The root hash in LEBS2OSP256(rt) encoding of the Sapling note
/// commitment tree corresponding to the final Sapling treestate of
/// this block. A root of a note commitment tree is associated with
/// each treestate.
#[derive(Clone, Copy, Default, Eq, Serialize, Deserialize)]
pub struct Root(#[serde(with = "serde_helpers::Fq")] pub(crate) jubjub::Base);
impl fmt::Debug for Root {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("Root")
.field(&hex::encode(self.0.to_bytes()))
.finish()
}
}
impl From<Root> for [u8; 32] {
fn from(root: Root) -> Self {
root.0.to_bytes()
}
}
impl From<&Root> for [u8; 32] {
fn from(root: &Root) -> Self {
(*root).into()
}
}
impl PartialEq for Root {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Hash for Root {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.to_bytes().hash(state)
}
}
impl TryFrom<[u8; 32]> for Root {
type Error = SerializationError;
fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
let possible_point = jubjub::Base::from_bytes(&bytes);
if possible_point.is_some().into() {
Ok(Self(possible_point.unwrap()))
} else {
Err(SerializationError::Parse(
"Invalid jubjub::Base value for Sapling note commitment tree root",
))
}
}
}
impl ZcashSerialize for Root {
fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
writer.write_all(&<[u8; 32]>::from(*self)[..])?;
Ok(())
}
}
impl ZcashDeserialize for Root {
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
Self::try_from(reader.read_32_bytes()?)
}
}
/// A node of the Sapling Incremental Note Commitment Tree.
///
/// Note that it's handled as a byte buffer and not a point coordinate (jubjub::Fq)
/// because that's how the spec handles the MerkleCRH^Sapling function inputs and outputs.
#[derive(Copy, Clone, Eq, PartialEq, Default)]
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
pub struct Node([u8; 32]);
impl AsRef<[u8; 32]> for Node {
fn as_ref(&self) -> &[u8; 32] {
&self.0
}
}
impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.encode_hex::<String>())
}
}
impl fmt::Debug for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("sapling::Node")
.field(&self.encode_hex::<String>())
.finish()
}
}
impl Node {
/// Return the node bytes in little-endian byte order suitable for printing out byte by byte.
///
/// `zcashd`'s `z_getsubtreesbyindex` does not reverse the byte order of subtree roots.
pub fn bytes_in_display_order(&self) -> [u8; 32] {
self.0
}
}
impl ToHex for &Node {
fn encode_hex<T: FromIterator<char>>(&self) -> T {
self.bytes_in_display_order().encode_hex()
}
fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
self.bytes_in_display_order().encode_hex_upper()
}
}
impl ToHex for Node {
fn encode_hex<T: FromIterator<char>>(&self) -> T {
(&self).encode_hex()
}
fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
(&self).encode_hex_upper()
}
}
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// Required to convert [`NoteCommitmentTree`] into [`SerializedTree`].
///
/// Zebra stores Sapling note commitment trees as [`Frontier`]s while the
/// [`z_gettreestate`][1] RPC requires [`CommitmentTree`][2]s. Implementing
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
/// [`incrementalmerkletree::Hashable`] for [`Node`]s allows the conversion.
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
///
/// [1]: https://zcash.github.io/rpc/z_gettreestate.html
/// [2]: incrementalmerkletree::frontier::CommitmentTree
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
impl HashSer for Node {
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
fn read<R: io::Read>(mut reader: R) -> io::Result<Self> {
let mut node = [0u8; 32];
reader.read_exact(&mut node)?;
Ok(Self(node))
}
fn write<W: io::Write>(&self, mut writer: W) -> io::Result<()> {
writer.write_all(self.0.as_ref())
}
}
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
impl Hashable for Node {
fn empty_leaf() -> Self {
Self(NoteCommitmentTree::uncommitted())
}
/// Combine two nodes to generate a new node in the given level.
/// Level 0 is the layer above the leaves (layer 31).
/// Level 31 is the root (layer 0).
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
fn combine(level: incrementalmerkletree::Level, a: &Self, b: &Self) -> Self {
let layer = MERKLE_DEPTH - 1 - u8::from(level);
Self(merkle_crh_sapling(layer, a.0, b.0))
}
/// Return the node for the level below the given level. (A quirk of the API)
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
fn empty_root(level: incrementalmerkletree::Level) -> Self {
let layer_below = usize::from(MERKLE_DEPTH) - usize::from(level);
Self(EMPTY_ROOTS[layer_below])
}
}
impl From<jubjub::Fq> for Node {
fn from(x: jubjub::Fq) -> Self {
Node(x.into())
}
}
impl TryFrom<&[u8]> for Node {
type Error = &'static str;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
Option::<jubjub::Fq>::from(jubjub::Fq::from_bytes(
bytes.try_into().map_err(|_| "wrong byte slice len")?,
))
.map(Node::from)
.ok_or("invalid jubjub field element")
}
}
Track anchors and note commitment trees in zebra-state (#2458) * Tidy chain Cargo.toml * Organize imports * Add method to get note commitments from all Actions in Orchard shielded data * Add method to get note commitments from all JoinSplits in Sprout JoinSplitData * Add Request and Response variants for awaiting anchors * Add anchors and note commitment trees to finalized state db * Add (From|Into)Disk impls for tree::Roots and stubs for NoteCommitmentTrees * Track anchors and note commitment trees in Chain Append note commitments to their trees when doing update_chain_state_with, then use the resulting Sapling and Orchard roots to pass to history_tree, and add new roots to the anchor sets. * Handle errors when appending to note commitment trees * Add comments explaining why note commitment are not removed from the tree in revert_chain_state_with * Implementing note commitments in finalized state * Finish serialization of Orchard tree; remove old tree when updating finalize state * Add serialization and finalized state updates for Sprout and Sapling trees * Partially handle trees in non-finalized state. Use Option for trees in Chain * Rebuild trees when forking; change finalized state tree getters to not require height * Pass empty trees to tests; use empty trees by default in Chain * Also rebuild anchor sets when forking * Use empty tree as default in finalized state tree getters (for now) * Use HashMultiSet for anchors in order to make pop_root() work correctly * Reduce DEFAULT_PARTIAL_CHAIN_PROPTEST_CASES and MAX_PARTIAL_CHAIN_BLOCKS * Reduce DEFAULT_PARTIAL_CHAIN_PROPTEST_CASES and MAX_PARTIAL_CHAIN_BLOCKS even more * Apply suggestions from code review * Add comments about order of note commitments and related methods/fields * Don't use Option for trees * Set DEFAULT_PARTIAL_CHAIN_PROPTEST_CASES=1 and restore MAX_PARTIAL_CHAIN_BLOCKS * Remove unneeded anchor set rebuilding in fork() * Improve proptest formatting * Add missing comparisons to eq_internal_state * Renamed sprout::tree::NoteCommitmentTree::hash() to root() * Improve comments * Add asserts, add issues to TODOs * Remove impl Default for Chain since it was only used by tests * Improve documentation and assertions; add tree serialization tests * Remove Sprout code, which will be moved to another branch * Add todo! in Sprout tree append() * Remove stub request, response *Anchor* handling for now * Add test for validating Sapling note commitment tree using test blocks * Increase database version (new columns added for note commitment trees and anchors) * Update test to make sure the order of sapling_note_commitments() is being tested * Improve comments and structure of the test * Improve variable names again * Rustfmt Co-authored-by: Deirdre Connolly <deirdre@zfnd.org> Co-authored-by: Conrado P. L. Gouvea <conradoplg@gmail.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org> Co-authored-by: teor <teor@riseup.net>
2021-07-29 06:37:18 -07:00
impl serde::Serialize for Node {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de> serde::Deserialize<'de> for Node {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bytes = <[u8; 32]>::deserialize(deserializer)?;
Option::<jubjub::Fq>::from(jubjub::Fq::from_bytes(&bytes))
.map(Node::from)
.ok_or_else(|| serde::de::Error::custom("invalid JubJub field element"))
}
}
#[derive(Error, Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[allow(missing_docs)]
pub enum NoteCommitmentTreeError {
#[error("The note commitment tree is full")]
FullTree,
}
/// Sapling Incremental Note Commitment Tree.
///
/// Note that the default value of the [`Root`] type is `[0, 0, 0, 0]`. However, this value differs
/// from the default value of the root of the default tree which is the hash of the root's child
/// nodes. The default tree is the empty tree which has all leaves empty.
#[derive(Debug, Serialize, Deserialize)]
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
#[serde(into = "LegacyNoteCommitmentTree")]
#[serde(from = "LegacyNoteCommitmentTree")]
pub struct NoteCommitmentTree {
/// The tree represented as a [`Frontier`].
///
/// A Frontier is a subset of the tree that allows to fully specify it.
/// It consists of nodes along the rightmost (newer) branch of the tree that
/// has non-empty nodes. Upper (near root) empty nodes of the branch are not
/// stored.
///
/// # Consensus
///
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// > [Sapling onward] A block MUST NOT add Sapling note commitments that
/// > would result in the Sapling note commitment tree exceeding its capacity
/// > of 2^(MerkleDepth^Sapling) leaf nodes.
///
/// <https://zips.z.cash/protocol/protocol.pdf#merkletree>
///
/// Note: MerkleDepth^Sapling = MERKLE_DEPTH = 32.
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
inner: Frontier<Node, MERKLE_DEPTH>,
/// A cached root of the tree.
///
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// Every time the root is computed by [`Self::root`] it is cached here, and
/// the cached value will be returned by [`Self::root`] until the tree is
/// changed by [`Self::append`]. This greatly increases performance because
/// it avoids recomputing the root when the tree does not change between
/// blocks. In the finalized state, the tree is read from disk for every
/// block processed, which would also require recomputing the root even if
/// it has not changed (note that the cached root is serialized with the
/// tree). This is particularly important since we decided to instantiate
/// the trees from the genesis block, for simplicity.
///
/// We use a [`RwLock`](std::sync::RwLock) for this cache, because it is only written once per
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// tree update. Each tree has its own cached root, a new lock is created
/// for each clone.
cached_root: std::sync::RwLock<Option<Root>>,
}
impl NoteCommitmentTree {
/// Adds a note commitment u-coordinate to the tree.
///
/// The leaves of the tree are actually a base field element, the
/// u-coordinate of the commitment, the data that is actually stored on the
/// chain and input into the proof.
///
/// Returns an error if the tree is full.
#[allow(clippy::unwrap_in_result)]
pub fn append(&mut self, cm_u: NoteCommitmentUpdate) -> Result<(), NoteCommitmentTreeError> {
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
if self.inner.append(cm_u.into()) {
// Invalidate cached root
let cached_root = self
.cached_root
.get_mut()
.expect("a thread that previously held exclusive lock access panicked");
*cached_root = None;
Ok(())
} else {
Err(NoteCommitmentTreeError::FullTree)
}
}
change(state): Add note subtree indexes for new and existing blocks (#7437) * Copy the add_subtrees upgrade from the original branch * Copy the database write changes in shielded.rs from the original branch * Copy the tree API changes from the original branch * Simplify subtree APIs to avoid exposing frontiers * Fix a dead code warning by re-using existing methods * Use mpsc::Receiver<CancelFormatChange> in the subtree upgrade * Run the subtree upgrade on startup * Bump the database format version to 25.2.0 * Fix a confusing 'upgrade complete' log * Clarify some comments and error messages * Simplify prev_tree unwrap to avoid an (impossible?) concurrency bug * Use separate subtree writing functions * Use common note commitment list code * Fix subtree completion condition and add asserts * Simplify subtree API and avoid exposing Address * Fix API compatibility when Arcs are removed * Log when each subtree is added * If a format change is cancelled, don't mark the database as upgraded or do format checks * Log subtree progress about once every two minutes * Adds a state validity check for subtrees upgrade * Orchard is faster, decrease log interval * Clarify subtree index docs * Move a log to the correct location * Refactor subtree upgrade to remove duplicate inverted loop conditions * updates subtree state validity check * Add a subtree format check when there is no upgrade * Fix an off-by-one error with the final subtree check * Use error-level logs for database format checks * Skip format checks in tests that create invalid formats * fix state validity test * Add a concurrency comment to subtree by height methods * Add individual subtree state methods: reverts removing these methods in an earlier PR * fastmod "subtrees_by_index" "subtree_list_by_index_for_rpc" --------- Co-authored-by: arya2 <aryasolhi@gmail.com>
2023-09-05 09:52:06 -07:00
/// Returns frontier of non-empty tree, or None.
fn frontier(&self) -> Option<&NonEmptyFrontier<Node>> {
self.inner.value()
}
fix(state): Use correct end heights for end of block subtrees during the full sync (#7566) * Avoid manual handling of previous sapling trees by using iterator windows instead * Avoid manual sapling subtree index handling by comparing prev and current subtree indexes instead * Simplify adding notes by using the exact number of remaining notes * Simplify by skipping the first block, because it can't complete a subtree * Re-use existing tree update code * Apply the sapling changes to orchard subtree updates * add a reverse database column family iterator function * Make skipping the lowest tree independent of iteration order * Move new subtree checks into the iterator, rename to end_height * Split subtree calculation into a new method * Split the calculate and write methods * Quickly check the first subtree before running the full upgrade * Do the quick checks every time Zebra runs, and refactor slow check error handling * Do quick checks for orchard as well * Make orchard tree upgrade match sapling upgrade code * Upgrade subtrees in reverse height order * Bump the database patch version so the upgrade runs again * Reset previous subtree upgrade data before doing this one * Add extra checks to subtree calculation to diagnose errors * Use correct heights for subtrees completed at the end of a block * Add even more checks to diagnose issues * Instrument upgrade methods to improve diagnostics * Prevent modification of re-used trees * Debug with subtree positions as well * Fix an off-by-one error with completed subtrees * Fix typos and confusing comments Co-authored-by: Marek <mail@marek.onl> * Fix mistaken previous tree handling and end tree comments * Remove unnecessary subtraction in remaining leaves calc * Log heights when assertions fail * Fix new subtree detection filter * Move new subtree check into a method, cleanup unused code * Remove redundant assertions * Wait for subtree upgrade before testing RPCs * Fix subtree search in quick check * Temporarily upgrade subtrees in forward height order * Clarify some comments * Fix missing test imports * Fix subtree logging * Add a comment about a potential hang with future upgrades * Fix zebrad var ownership * Log more info when add_subtrees.rs fails * cargo fmt --all * Fix unrelated clippy::unnecessary_unwrap * cargo clippy --fix --all-features --all-targets; cargo fmt --all * Stop the quick check depending on tree de-duplication * Refactor waiting for the upgrade into functions * Wait for state upgrades whenever the cached state is updated * Wait for the testnet upgrade in the right place * Fix unused variable * Fix a subtree detection bug and comments * Remove an early reference to reverse direction * Stop skipping subtrees completed at the end of blocks * Actually fix new subtree code --------- Co-authored-by: Marek <mail@marek.onl>
2023-09-19 07:49:36 -07:00
/// Returns the position of the most recently appended leaf in the tree.
///
/// This method is used for debugging, use `incrementalmerkletree::Address` for tree operations.
pub fn position(&self) -> Option<u64> {
let Some(tree) = self.frontier() else {
// An empty tree doesn't have a previous leaf.
return None;
};
Some(tree.position().into())
}
/// Returns true if this tree has at least one new subtree, when compared with `prev_tree`.
pub fn contains_new_subtree(&self, prev_tree: &Self) -> bool {
// Use -1 for the index of the subtree with no notes, so the comparisons are valid.
let index = self.subtree_index().map_or(-1, |index| i32::from(index.0));
let prev_index = prev_tree
.subtree_index()
.map_or(-1, |index| i32::from(index.0));
// This calculation can't overflow, because we're using i32 for u16 values.
let index_difference = index - prev_index;
// There are 4 cases we need to handle:
// - lower index: never a new subtree
// - equal index: sometimes a new subtree
// - next index: sometimes a new subtree
// - greater than the next index: always a new subtree
//
// To simplify the function, we deal with the simple cases first.
// There can't be any new subtrees if the current index is strictly lower.
if index < prev_index {
return false;
}
// There is at least one new subtree, even if there is a spurious index difference.
if index_difference > 1 {
return true;
}
// If the indexes are equal, there can only be a new subtree if `self` just completed it.
if index == prev_index {
return self.is_complete_subtree();
}
// If `self` is the next index, check if the last note completed a subtree.
if self.is_complete_subtree() {
return true;
}
// Then check for spurious index differences.
fix(state): Use correct end heights for end of block subtrees during the full sync (#7566) * Avoid manual handling of previous sapling trees by using iterator windows instead * Avoid manual sapling subtree index handling by comparing prev and current subtree indexes instead * Simplify adding notes by using the exact number of remaining notes * Simplify by skipping the first block, because it can't complete a subtree * Re-use existing tree update code * Apply the sapling changes to orchard subtree updates * add a reverse database column family iterator function * Make skipping the lowest tree independent of iteration order * Move new subtree checks into the iterator, rename to end_height * Split subtree calculation into a new method * Split the calculate and write methods * Quickly check the first subtree before running the full upgrade * Do the quick checks every time Zebra runs, and refactor slow check error handling * Do quick checks for orchard as well * Make orchard tree upgrade match sapling upgrade code * Upgrade subtrees in reverse height order * Bump the database patch version so the upgrade runs again * Reset previous subtree upgrade data before doing this one * Add extra checks to subtree calculation to diagnose errors * Use correct heights for subtrees completed at the end of a block * Add even more checks to diagnose issues * Instrument upgrade methods to improve diagnostics * Prevent modification of re-used trees * Debug with subtree positions as well * Fix an off-by-one error with completed subtrees * Fix typos and confusing comments Co-authored-by: Marek <mail@marek.onl> * Fix mistaken previous tree handling and end tree comments * Remove unnecessary subtraction in remaining leaves calc * Log heights when assertions fail * Fix new subtree detection filter * Move new subtree check into a method, cleanup unused code * Remove redundant assertions * Wait for subtree upgrade before testing RPCs * Fix subtree search in quick check * Temporarily upgrade subtrees in forward height order * Clarify some comments * Fix missing test imports * Fix subtree logging * Add a comment about a potential hang with future upgrades * Fix zebrad var ownership * Log more info when add_subtrees.rs fails * cargo fmt --all * Fix unrelated clippy::unnecessary_unwrap * cargo clippy --fix --all-features --all-targets; cargo fmt --all * Stop the quick check depending on tree de-duplication * Refactor waiting for the upgrade into functions * Wait for state upgrades whenever the cached state is updated * Wait for the testnet upgrade in the right place * Fix unused variable * Fix a subtree detection bug and comments * Remove an early reference to reverse direction * Stop skipping subtrees completed at the end of blocks * Actually fix new subtree code --------- Co-authored-by: Marek <mail@marek.onl>
2023-09-19 07:49:36 -07:00
//
// There is one new subtree somewhere in the trees. It is either:
// - a new subtree at the end of the previous tree, or
// - a new subtree in this tree (but not at the end).
//
// Spurious index differences happen because the subtree index only increases when the
// first note is added to the new subtree. So we need to exclude subtrees completed by the
// last note commitment in the previous tree.
//
// We also need to exclude empty previous subtrees, because the index changes to zero when
// the first note is added, but a subtree wasn't completed.
if prev_tree.is_complete_subtree() || prev_index == -1 {
return false;
}
// A new subtree was completed by a note commitment that isn't in the previous tree.
true
}
/// Returns true if the most recently appended leaf completes the subtree
change(state): Add note subtree indexes for new and existing blocks (#7437) * Copy the add_subtrees upgrade from the original branch * Copy the database write changes in shielded.rs from the original branch * Copy the tree API changes from the original branch * Simplify subtree APIs to avoid exposing frontiers * Fix a dead code warning by re-using existing methods * Use mpsc::Receiver<CancelFormatChange> in the subtree upgrade * Run the subtree upgrade on startup * Bump the database format version to 25.2.0 * Fix a confusing 'upgrade complete' log * Clarify some comments and error messages * Simplify prev_tree unwrap to avoid an (impossible?) concurrency bug * Use separate subtree writing functions * Use common note commitment list code * Fix subtree completion condition and add asserts * Simplify subtree API and avoid exposing Address * Fix API compatibility when Arcs are removed * Log when each subtree is added * If a format change is cancelled, don't mark the database as upgraded or do format checks * Log subtree progress about once every two minutes * Adds a state validity check for subtrees upgrade * Orchard is faster, decrease log interval * Clarify subtree index docs * Move a log to the correct location * Refactor subtree upgrade to remove duplicate inverted loop conditions * updates subtree state validity check * Add a subtree format check when there is no upgrade * Fix an off-by-one error with the final subtree check * Use error-level logs for database format checks * Skip format checks in tests that create invalid formats * fix state validity test * Add a concurrency comment to subtree by height methods * Add individual subtree state methods: reverts removing these methods in an earlier PR * fastmod "subtrees_by_index" "subtree_list_by_index_for_rpc" --------- Co-authored-by: arya2 <aryasolhi@gmail.com>
2023-09-05 09:52:06 -07:00
pub fn is_complete_subtree(&self) -> bool {
let Some(tree) = self.frontier() else {
// An empty tree can't be a complete subtree.
return false;
};
tree.position()
.is_complete_subtree(TRACKED_SUBTREE_HEIGHT.into())
}
change(state): Add note subtree indexes for new and existing blocks (#7437) * Copy the add_subtrees upgrade from the original branch * Copy the database write changes in shielded.rs from the original branch * Copy the tree API changes from the original branch * Simplify subtree APIs to avoid exposing frontiers * Fix a dead code warning by re-using existing methods * Use mpsc::Receiver<CancelFormatChange> in the subtree upgrade * Run the subtree upgrade on startup * Bump the database format version to 25.2.0 * Fix a confusing 'upgrade complete' log * Clarify some comments and error messages * Simplify prev_tree unwrap to avoid an (impossible?) concurrency bug * Use separate subtree writing functions * Use common note commitment list code * Fix subtree completion condition and add asserts * Simplify subtree API and avoid exposing Address * Fix API compatibility when Arcs are removed * Log when each subtree is added * If a format change is cancelled, don't mark the database as upgraded or do format checks * Log subtree progress about once every two minutes * Adds a state validity check for subtrees upgrade * Orchard is faster, decrease log interval * Clarify subtree index docs * Move a log to the correct location * Refactor subtree upgrade to remove duplicate inverted loop conditions * updates subtree state validity check * Add a subtree format check when there is no upgrade * Fix an off-by-one error with the final subtree check * Use error-level logs for database format checks * Skip format checks in tests that create invalid formats * fix state validity test * Add a concurrency comment to subtree by height methods * Add individual subtree state methods: reverts removing these methods in an earlier PR * fastmod "subtrees_by_index" "subtree_list_by_index_for_rpc" --------- Co-authored-by: arya2 <aryasolhi@gmail.com>
2023-09-05 09:52:06 -07:00
/// Returns the subtree index at [`TRACKED_SUBTREE_HEIGHT`].
/// This is the number of complete or incomplete subtrees that are currently in the tree.
/// Returns `None` if the tree is empty.
#[allow(clippy::unwrap_in_result)]
pub fn subtree_index(&self) -> Option<NoteCommitmentSubtreeIndex> {
let tree = self.frontier()?;
let index = incrementalmerkletree::Address::above_position(
TRACKED_SUBTREE_HEIGHT.into(),
tree.position(),
)
change(state): Add note subtree indexes for new and existing blocks (#7437) * Copy the add_subtrees upgrade from the original branch * Copy the database write changes in shielded.rs from the original branch * Copy the tree API changes from the original branch * Simplify subtree APIs to avoid exposing frontiers * Fix a dead code warning by re-using existing methods * Use mpsc::Receiver<CancelFormatChange> in the subtree upgrade * Run the subtree upgrade on startup * Bump the database format version to 25.2.0 * Fix a confusing 'upgrade complete' log * Clarify some comments and error messages * Simplify prev_tree unwrap to avoid an (impossible?) concurrency bug * Use separate subtree writing functions * Use common note commitment list code * Fix subtree completion condition and add asserts * Simplify subtree API and avoid exposing Address * Fix API compatibility when Arcs are removed * Log when each subtree is added * If a format change is cancelled, don't mark the database as upgraded or do format checks * Log subtree progress about once every two minutes * Adds a state validity check for subtrees upgrade * Orchard is faster, decrease log interval * Clarify subtree index docs * Move a log to the correct location * Refactor subtree upgrade to remove duplicate inverted loop conditions * updates subtree state validity check * Add a subtree format check when there is no upgrade * Fix an off-by-one error with the final subtree check * Use error-level logs for database format checks * Skip format checks in tests that create invalid formats * fix state validity test * Add a concurrency comment to subtree by height methods * Add individual subtree state methods: reverts removing these methods in an earlier PR * fastmod "subtrees_by_index" "subtree_list_by_index_for_rpc" --------- Co-authored-by: arya2 <aryasolhi@gmail.com>
2023-09-05 09:52:06 -07:00
.index()
.try_into()
.expect("fits in u16");
Some(index)
}
fix(state): Use correct end heights for end of block subtrees during the full sync (#7566) * Avoid manual handling of previous sapling trees by using iterator windows instead * Avoid manual sapling subtree index handling by comparing prev and current subtree indexes instead * Simplify adding notes by using the exact number of remaining notes * Simplify by skipping the first block, because it can't complete a subtree * Re-use existing tree update code * Apply the sapling changes to orchard subtree updates * add a reverse database column family iterator function * Make skipping the lowest tree independent of iteration order * Move new subtree checks into the iterator, rename to end_height * Split subtree calculation into a new method * Split the calculate and write methods * Quickly check the first subtree before running the full upgrade * Do the quick checks every time Zebra runs, and refactor slow check error handling * Do quick checks for orchard as well * Make orchard tree upgrade match sapling upgrade code * Upgrade subtrees in reverse height order * Bump the database patch version so the upgrade runs again * Reset previous subtree upgrade data before doing this one * Add extra checks to subtree calculation to diagnose errors * Use correct heights for subtrees completed at the end of a block * Add even more checks to diagnose issues * Instrument upgrade methods to improve diagnostics * Prevent modification of re-used trees * Debug with subtree positions as well * Fix an off-by-one error with completed subtrees * Fix typos and confusing comments Co-authored-by: Marek <mail@marek.onl> * Fix mistaken previous tree handling and end tree comments * Remove unnecessary subtraction in remaining leaves calc * Log heights when assertions fail * Fix new subtree detection filter * Move new subtree check into a method, cleanup unused code * Remove redundant assertions * Wait for subtree upgrade before testing RPCs * Fix subtree search in quick check * Temporarily upgrade subtrees in forward height order * Clarify some comments * Fix missing test imports * Fix subtree logging * Add a comment about a potential hang with future upgrades * Fix zebrad var ownership * Log more info when add_subtrees.rs fails * cargo fmt --all * Fix unrelated clippy::unnecessary_unwrap * cargo clippy --fix --all-features --all-targets; cargo fmt --all * Stop the quick check depending on tree de-duplication * Refactor waiting for the upgrade into functions * Wait for state upgrades whenever the cached state is updated * Wait for the testnet upgrade in the right place * Fix unused variable * Fix a subtree detection bug and comments * Remove an early reference to reverse direction * Stop skipping subtrees completed at the end of blocks * Actually fix new subtree code --------- Co-authored-by: Marek <mail@marek.onl>
2023-09-19 07:49:36 -07:00
/// Returns the number of leaf nodes required to complete the subtree at
/// [`TRACKED_SUBTREE_HEIGHT`].
///
/// Returns `2^TRACKED_SUBTREE_HEIGHT` if the tree is empty.
#[allow(clippy::unwrap_in_result)]
pub fn remaining_subtree_leaf_nodes(&self) -> usize {
let remaining = match self.frontier() {
// If the subtree has at least one leaf node, the remaining number of nodes can be
// calculated using the maximum subtree position and the current position.
Some(tree) => {
let max_position = incrementalmerkletree::Address::above_position(
TRACKED_SUBTREE_HEIGHT.into(),
tree.position(),
)
.max_position();
max_position - tree.position().into()
}
// If the subtree has no nodes, the remaining number of nodes is the number of nodes in
// a subtree.
None => {
let subtree_address = incrementalmerkletree::Address::above_position(
TRACKED_SUBTREE_HEIGHT.into(),
// This position is guaranteed to be in the first subtree.
0.into(),
);
assert_eq!(
subtree_address.position_range_start(),
0.into(),
"address is not in the first subtree"
);
subtree_address.position_range_end()
}
};
u64::from(remaining).try_into().expect("fits in usize")
}
/// Returns subtree index and root if the most recently appended leaf completes the subtree
change(state): Add note subtree indexes for new and existing blocks (#7437) * Copy the add_subtrees upgrade from the original branch * Copy the database write changes in shielded.rs from the original branch * Copy the tree API changes from the original branch * Simplify subtree APIs to avoid exposing frontiers * Fix a dead code warning by re-using existing methods * Use mpsc::Receiver<CancelFormatChange> in the subtree upgrade * Run the subtree upgrade on startup * Bump the database format version to 25.2.0 * Fix a confusing 'upgrade complete' log * Clarify some comments and error messages * Simplify prev_tree unwrap to avoid an (impossible?) concurrency bug * Use separate subtree writing functions * Use common note commitment list code * Fix subtree completion condition and add asserts * Simplify subtree API and avoid exposing Address * Fix API compatibility when Arcs are removed * Log when each subtree is added * If a format change is cancelled, don't mark the database as upgraded or do format checks * Log subtree progress about once every two minutes * Adds a state validity check for subtrees upgrade * Orchard is faster, decrease log interval * Clarify subtree index docs * Move a log to the correct location * Refactor subtree upgrade to remove duplicate inverted loop conditions * updates subtree state validity check * Add a subtree format check when there is no upgrade * Fix an off-by-one error with the final subtree check * Use error-level logs for database format checks * Skip format checks in tests that create invalid formats * fix state validity test * Add a concurrency comment to subtree by height methods * Add individual subtree state methods: reverts removing these methods in an earlier PR * fastmod "subtrees_by_index" "subtree_list_by_index_for_rpc" --------- Co-authored-by: arya2 <aryasolhi@gmail.com>
2023-09-05 09:52:06 -07:00
pub fn completed_subtree_index_and_root(&self) -> Option<(NoteCommitmentSubtreeIndex, Node)> {
if !self.is_complete_subtree() {
return None;
}
let index = self.subtree_index()?;
let root = self.frontier()?.root(Some(TRACKED_SUBTREE_HEIGHT.into()));
Some((index, root))
}
/// Returns the current root of the tree, used as an anchor in Sapling
/// shielded transactions.
pub fn root(&self) -> Root {
if let Some(root) = self.cached_root() {
// Return cached root.
return root;
}
// Get exclusive access, compute the root, and cache it.
let mut write_root = self
.cached_root
.write()
.expect("a thread that previously held exclusive lock access panicked");
let read_root = write_root.as_ref().cloned();
match read_root {
// Another thread got write access first, return cached root.
Some(root) => root,
None => {
// Compute root and cache it.
let root = self.recalculate_root();
*write_root = Some(root);
root
}
}
}
/// Returns the current root of the tree, if it has already been cached.
#[allow(clippy::unwrap_in_result)]
pub fn cached_root(&self) -> Option<Root> {
*self
.cached_root
.read()
.expect("a thread that previously held exclusive lock access panicked")
}
/// Calculates and returns the current root of the tree, ignoring any caching.
pub fn recalculate_root(&self) -> Root {
Root::try_from(self.inner.root().0).unwrap()
}
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// Gets the Jubjub-based Pedersen hash of root node of this merkle tree of
/// note commitments.
pub fn hash(&self) -> [u8; 32] {
self.root().into()
}
/// An as-yet unused Sapling note commitment tree leaf node.
///
/// Distinct for Sapling, a distinguished hash value of:
///
/// Uncommitted^Sapling = I2LEBSP_l_MerkleSapling(1)
pub fn uncommitted() -> [u8; 32] {
jubjub::Fq::one().to_bytes()
}
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// Counts of note commitments added to the tree.
///
/// For Sapling, the tree is capped at 2^32.
pub fn count(&self) -> u64 {
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
self.inner
.value()
.map_or(0, |x| u64::from(x.position()) + 1)
}
/// Checks if the tree roots and inner data structures of `self` and `other` are equal.
///
/// # Panics
///
/// If they aren't equal, with a message explaining the differences.
///
/// Only for use in tests.
#[cfg(any(test, feature = "proptest-impl"))]
pub fn assert_frontier_eq(&self, other: &Self) {
// It's technically ok for the cached root not to be preserved,
// but it can result in expensive cryptographic operations,
// so we fail the tests if it happens.
assert_eq!(self.cached_root(), other.cached_root());
// Check the data in the internal data structure
assert_eq!(self.inner, other.inner);
// Check the RPC serialization format (not the same as the Zebra database format)
assert_eq!(SerializedTree::from(self), SerializedTree::from(other));
}
}
impl Clone for NoteCommitmentTree {
/// Clones the inner tree, and creates a new [`RwLock`](std::sync::RwLock)
/// with the cloned root data.
fn clone(&self) -> Self {
let cached_root = self.cached_root();
Self {
inner: self.inner.clone(),
cached_root: std::sync::RwLock::new(cached_root),
}
}
}
impl Default for NoteCommitmentTree {
fn default() -> Self {
Self {
Update shared NU5 dependencies, set the NU5 testnet activation network upgrade parameters (#2825) * Check return value of zcash_script_new_precomputed_tx * Set the NU5 testnet activation height to 1_590_000 * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Update Nu5 constants to new values * Update ZIP-244 test vectors for new branch ID * Squashed commit of the following: commit bdb120a249e3e889a913114a712505defdade1d4 Author: Deirdre Connolly <durumcrustulum@gmail.com> Date: Tue Oct 5 11:54:01 2021 -0400 Use pallas::Base::from_str_vartime() in sinsemilla tests commit e99fa4925857840fa65ccfb4a076ec412e416576 Author: Deirdre Connolly <durumcrustulum@gmail.com> Date: Tue Oct 5 11:45:24 2021 -0400 Compiles commit a5200181146bfd2aa1e09abea2caaa7a7ceb006e Author: Deirdre Connolly <durumcrustulum@gmail.com> Date: Tue Oct 5 10:15:17 2021 -0400 Incomplete upgrade of deps * Squashed commit of the following: commit 8d1b76ec5626517817c3a4d9f3950acc90a359df Author: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Date: Tue Oct 5 04:02:26 2021 +0000 Update `zcash_script` to support V5 transactions Use a newer version of `zcash_script` that has been updated to support V5 transactions. commit 371233628ae61e0c25d6ba8f31d9dba42823becb Author: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Date: Tue Oct 5 03:06:20 2021 +0000 Update Zcash dependencies Update some Zcash crates: - `halo2` - `incrementalmerkletree' (patch version) - `orchard` (patch version) - `zcash_history` (patch version) - `zcash_note_encryption` (patch version) - `zcash_primitives` (patch version) And also update the `group` dependency so that the code remains compatible. commit de5cf1ec40c3fc08670fc971cdf3e65e13d9f4c7 Author: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Date: Tue Oct 5 03:04:13 2021 +0000 Update error message assertion Use the updated message for the expected error variant. * Update `zcash_script` to support V5 transactions Use a newer version of `zcash_script` that has been updated to support V5 transactions. Co-authored-by: Conrado Gouvea <conrado@zfnd.org> Co-authored-by: teor <teor@riseup.net>
2021-10-05 18:08:41 -07:00
inner: bridgetree::Frontier::empty(),
cached_root: Default::default(),
}
}
}
impl Eq for NoteCommitmentTree {}
impl PartialEq for NoteCommitmentTree {
fn eq(&self, other: &Self) -> bool {
if let (Some(root), Some(other_root)) = (self.cached_root(), other.cached_root()) {
// Use cached roots if available
root == other_root
} else {
// Avoid expensive root recalculations which use multiple cryptographic hashes
self.inner == other.inner
}
}
}
impl From<Vec<jubjub::Fq>> for NoteCommitmentTree {
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// Computes the tree from a whole bunch of note commitments at once.
fn from(values: Vec<jubjub::Fq>) -> Self {
let mut tree = Self::default();
if values.is_empty() {
return tree;
}
for cm_u in values {
let _ = tree.append(cm_u);
}
tree
}
}
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// A serialized Sapling note commitment tree.
///
/// The format of the serialized data is compatible with
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
/// [`CommitmentTree`](incrementalmerkletree::frontier::CommitmentTree) from `librustzcash` and not
/// with [`Frontier`] from the crate
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// [`incrementalmerkletree`]. Zebra follows the former format in order to stay
/// consistent with `zcashd` in RPCs. Note that [`NoteCommitmentTree`] itself is
/// represented as [`Frontier`].
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
///
/// The formats are semantically equivalent. The primary difference between them
/// is that in [`Frontier`], the vector of parents is
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// dense (we know where the gaps are from the position of the leaf in the
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
/// overall tree); whereas in [`CommitmentTree`](incrementalmerkletree::frontier::CommitmentTree),
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
/// the vector of parent hashes is sparse with [`None`] values in the gaps.
///
/// The sparse format, used in this implementation, allows representing invalid
/// commitment trees while the dense format allows representing only valid
/// commitment trees.
///
/// It is likely that the dense format will be used in future RPCs, in which
/// case the current implementation will have to change and use the format
/// compatible with [`Frontier`] instead.
#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Serialize)]
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
pub struct SerializedTree(Vec<u8>);
impl From<&NoteCommitmentTree> for SerializedTree {
fn from(tree: &NoteCommitmentTree) -> Self {
let mut serialized_tree = vec![];
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
//
let legacy_tree = LegacyNoteCommitmentTree::from(tree.clone());
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
// Convert the note commitment tree represented as a frontier into the
// format compatible with `zcashd`.
//
// `librustzcash` has a function [`from_frontier()`][1], which returns a
// commitment tree in the sparse format. However, the returned tree
// always contains [`MERKLE_DEPTH`] parent nodes, even though some
// trailing parents are empty. Such trees are incompatible with Sapling
// commitment trees returned by `zcashd` because `zcashd` returns
// Sapling commitment trees without empty trailing parents. For this
// reason, Zebra implements its own conversion between the dense and
// sparse formats for Sapling.
//
// [1]: <https://github.com/zcash/librustzcash/blob/a63a37a/zcash_primitives/src/merkle_tree.rs#L125>
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
if let Some(frontier) = legacy_tree.inner.frontier {
let (left_leaf, right_leaf) = match frontier.leaf {
LegacyLeaf::Left(left_value) => (Some(left_value), None),
LegacyLeaf::Right(left_value, right_value) => (Some(left_value), Some(right_value)),
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
};
// Ommers are siblings of parent nodes along the branch from the
// most recent leaf to the root of the tree.
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
let mut ommers_iter = frontier.ommers.iter();
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
// Set bits in the binary representation of the position indicate
// the presence of ommers along the branch from the most recent leaf
// node to the root of the tree, except for the lowest bit.
build(deps): update ecc dependencies for `zcashd` 5.6.0, and create legacy state format compatibility layer (#7053) * update ecc dependencies no serialization * use zcash_primitives merke tree functions for serialization/deserialization in orchard and sapling trees * some more work in sapling/orchard serialization/deserialization * clippy * fix doc links * fix missing doc * make orchard trees serializa/deserialize as they were before upgrade * make sapling trees serialize/deserialize as they were before upgrade * use legacy for sprout * remove unused code * readd snapshot tests * repalce some code * upgrade zcash_proofs * remove legacy code for sprout * fix the count method * add root to serialize * fixes in as_bytes and from_bytes * use legacy code * add todo about pow2 tests * remove unused sprout code * fix doc typos * Add a recalculate_root() method to trees for tests * Rename test tree types to make them easier to change * Add TODOs for tests for old and new serialization formats * fix doc typos * add more test to note commitment trees * fix comment * fix leaf serializatiuon, reverse to old hashes in pow2 tests * fix serialization * put sapling SerializedTree code back * put orchard SerializedTree code back * clippy * add duplicated dependencies until zebra_script updates * fix a doc link * minor cleanup * remove todo comment from tests * add one more check to tests * update zebra_script * update deny.toml * replace custom function with library * fix some tests * update docs * Remove duplicate dependencies from deny.toml Based on the list at: https://github.com/ZcashFoundation/zebra/actions/runs/5557139662/jobs/10150543673?pr=7053#step:5:14 --------- Co-authored-by: teor <teor@riseup.net>
2023-07-17 15:06:27 -07:00
let mut position: u64 = (frontier.position.0)
.try_into()
.expect("old usize position always fit in u64");
feat(rpc): Implement `z_gettreestate` RPC (#3990) * Impl the elementary structure of the `z_gettreestate` RPC * Fix merging bugs * Fix a merge bug * Fix a merge bug * Move a derive attribute Co-authored-by: teor <teor@riseup.net> * Clarify the support of negative heights * Add Orchard note commitment trees to the response * Add the time to the response * Finalize the `z_gettreestate` RPC * Add a note that verified blocks have coinbase height * Refactor `from_str` for `HashOrHeight` * Fix a mistake in the docs Co-authored-by: teor <teor@riseup.net> * Clarify request types Co-authored-by: teor <teor@riseup.net> * Simplify `hash_or_height` conversion to height Co-authored-by: teor <teor@riseup.net> * Add a TODO about optimization Co-authored-by: teor <teor@riseup.net> * Add a doc comment * Make sure Sapling & Orchard trees don't get mixed up * Serialize Sapling commitment trees * Refactor some comments * Serialize Orchard commitment trees * Serialize block heights * Simplify the serialization of commitment trees * Remove the block time from the RPC response * Simplify the serialization of block heights * Put Sapling & Orchard requests together * Remove a redundant TODO * Add block times to the RPC response * Derive `Clone, Debug, Eq, PartialEq` for `GetTreestate` Co-authored-by: teor <teor@riseup.net> * Derive `Clone`, `Debug`, `Eq` and `PartialEq` for `SerializedTree` * Document the fields of `GetTreestate` * Skip the serialization of empty trees This ensures compatibility with `zcashd` in the `z_gettreestate` RPC. * Document the `impl` of `merkle_tree::Hashable` for nodes * Make the structure of the JSON response consistent with `zcashd` * Derive `Eq` for nodes Co-authored-by: teor <teor@riseup.net> * Convert Sapling commitment trees to a format compatible with zcashd * Refactor the conversion of Sapling commitment trees * Refactor some comments * Refactor comments * Add a description of the conversion Co-authored-by: Conrado Gouvea <conrado@zfnd.org> * Fix comment indenting * Document the conversion between the dense and sparse formats Co-authored-by: teor <teor@riseup.net> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2022-05-12 00:00:12 -07:00
// The lowest bit does not indicate the presence of any ommers. We
// clear it so that we can test if there are no set bits left in
// [`position`].
position &= !1;
// Run through the bits of [`position`], and push an ommer for each
// set bit, or `None` otherwise. In contrast to the 'zcashd' code
// linked above, we want to skip any trailing `None` parents at the
// top of the tree. To do that, we clear the bits as we go through
// them, and break early if the remaining bits are all zero (i.e.
// [`position`] is zero).
let mut parents = vec![];
for i in 1..MERKLE_DEPTH {
// Test each bit in [`position`] individually. Don't test the
// lowest bit since it doesn't actually indicate the position of
// any ommer.
let bit_mask = 1 << i;
if position & bit_mask == 0 {
parents.push(None);
} else {
parents.push(ommers_iter.next());
// Clear the set bit so that we can test if there are no set
// bits left.
position &= !bit_mask;
// If there are no set bits left, exit early so that there
// are no empty trailing parent nodes in the serialized
// tree.
if position == 0 {
break;
}
}
}
// Serialize the converted note commitment tree.
Optional::write(&mut serialized_tree, left_leaf, |tree, leaf| {
leaf.write(tree)
})
.expect("A leaf in a note commitment tree should be serializable");
Optional::write(&mut serialized_tree, right_leaf, |tree, leaf| {
leaf.write(tree)
})
.expect("A leaf in a note commitment tree should be serializable");
Vector::write(&mut serialized_tree, &parents, |tree, parent| {
Optional::write(tree, *parent, |tree, parent| parent.write(tree))
})
.expect("Parent nodes in a note commitment tree should be serializable");
}
Self(serialized_tree)
}
}
impl From<Option<Arc<NoteCommitmentTree>>> for SerializedTree {
fn from(maybe_tree: Option<Arc<NoteCommitmentTree>>) -> Self {
match maybe_tree {
Some(tree) => tree.as_ref().into(),
None => Self(vec![]),
}
}
}
impl AsRef<[u8]> for SerializedTree {
fn as_ref(&self) -> &[u8] {
&self.0
}
}