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

756 lines
26 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 Action
//! 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};
change(nu5): use new V5 transaction script verification API (#3799) * update librustzcash; adapt to new API * add ticket reference for removing zcash_proofs duplicated dependencies * update to new zcash_script V5 API * use zp_tx shorthand * update to Zcash 4.7.0 dependencies * update protocol versions * feat(rpc): Implement `getblockchaininfo` RPC method (#3891) * Implement `getblockchaininfo` RPC method * add a test for `get_blockchain_info` * fix tohex/fromhex * move comment * Update lightwalletd acceptance test for getblockchaininfo RPC (#3914) * change(rpc): Return getblockchaininfo network upgrades in height order (#3915) * Update lightwalletd acceptance test for getblockchaininfo RPC * Update some doc comments for network upgrades * List network upgrades in order in the getblockchaininfo RPC Also: - Use a constant for the "missing consensus branch ID" RPC value - Simplify fetching consensus branch IDs - Make RPC type derives consistent - Update RPC type documentation * Make RPC type derives consistent * Fix a confusing test comment * get hashand height at the same time * fix estimated_height * fix lint * add extra check Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix typo Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * split test Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix(rpc): ignore an expected error in the RPC acceptance tests (#3961) * Add ignored regexes to test command failure regex methods * Ignore empty chain error in getblockchaininfo We expect this error when zebrad starts up with an empty state. Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Make sync error logs more user-friendly (#3944) - use info level, there is nothing the user needs to do, particularly for a single error - explain that the errors are temporary - hide backtraces, because they look like crashes * Update test.patch.yml with lightwalletd job (#3970) * Update test.patch.yml with lightwalletd job * Remove a workflow condition that will always be false In general, patch workflows need the opposite conditions to the original workflow. But in this case, we know the result of the condition will always be true, so we can just delete it. Co-authored-by: teor <teor@riseup.net> * fix(doc): Fix bugs in the lightwalletd database design (#3964) * Re-order column families in design in dependency order * Minor RFC design tweaks and fixes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Repoint zebra image links to our new zfnd.org site for now (#3949) * Repoint zebra image links to our new zfnd.org site for now * Remove images/ Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Fix typos (#3956) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * bump database version to trigger testnet rollback * reduce minimum protocol version for now (will be changed later) * update dependencies * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * update versions to match zcash 4.7.0 * deny.toml: update 'darling' Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com> Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com> Co-authored-by: Dimitris Apostolou <dimitris.apostolou@icloud.com>
2022-04-18 17:14:16 -07:00
use halo2::pasta::{group::ff::PrimeField, pallas};
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::Hashable;
use lazy_static::lazy_static;
use thiserror::Error;
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::{write_commitment_tree, HashSer};
use super::sinsemilla::*;
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},
};
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::LegacyNoteCommitmentTree;
/// The type that is used to update the note commitment tree.
///
/// Unfortunately, this is not the same as `orchard::NoteCommitment`.
pub type NoteCommitmentUpdate = pallas::Base;
pub(super) const MERKLE_DEPTH: u8 = 32;
2021-03-10 13:39:31 -08:00
/// MerkleCRH^Orchard Hash Function
///
2021-03-10 13:39:31 -08:00
/// Used to hash incremental Merkle tree hash values for Orchard.
///
/// MerkleCRH^Orchard: {0..MerkleDepth^Orchard 1} × P𝑥 × P𝑥 → P𝑥
///
/// MerkleCRH^Orchard(layer, left, right) := 0 if hash == ⊥; hash otherwise
///
/// where hash = SinsemillaHash("z.cash:Orchard-MerkleCRH", l || left || right),
/// l = I2LEBSP_10(MerkleDepth^Orchard 1 layer), and left, right, and
/// the output are the x-coordinates of Pallas affine points.
2021-03-10 13:39:31 -08:00
///
/// <https://zips.z.cash/protocol/protocol.pdf#orchardmerklecrh>
/// <https://zips.z.cash/protocol/protocol.pdf#constants>
fn merkle_crh_orchard(layer: u8, left: pallas::Base, right: pallas::Base) -> pallas::Base {
let mut s = bitvec![u8, Lsb0;];
// Prefix: l = I2LEBSP_10(MerkleDepth^Orchard 1 layer)
let l = MERKLE_DEPTH - 1 - layer;
s.extend_from_bitslice(&BitArray::<_, Lsb0>::from([l, 0])[0..10]);
s.extend_from_bitslice(&BitArray::<_, Lsb0>::from(left.to_repr())[0..255]);
s.extend_from_bitslice(&BitArray::<_, Lsb0>::from(right.to_repr())[0..255]);
match sinsemilla_hash(b"z.cash:Orchard-MerkleCRH", &s) {
Some(h) => h,
None => pallas::Base::zero(),
}
}
lazy_static! {
/// List of "empty" Orchard 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<pallas::Base> = {
// 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_orchard(layer, v[0], v[0]);
v.insert(0, next);
}
v
};
}
2021-03-10 13:39:31 -08:00
/// Orchard note commitment tree root node hash.
///
2021-03-10 13:39:31 -08:00
/// The root hash in LEBS2OSP256(rt) encoding of the Orchard note commitment
/// tree corresponding to the final Orchard 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::Base")] pub(crate) pallas::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_repr()))
.finish()
}
}
impl From<Root> for [u8; 32] {
fn from(root: Root) -> Self {
root.0.into()
}
}
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 From<&Root> for [u8; 32] {
fn from(root: &Root) -> Self {
(*root).into()
}
}
impl Hash for Root {
fn hash<H: Hasher>(&self, state: &mut H) {
change(nu5): use new V5 transaction script verification API (#3799) * update librustzcash; adapt to new API * add ticket reference for removing zcash_proofs duplicated dependencies * update to new zcash_script V5 API * use zp_tx shorthand * update to Zcash 4.7.0 dependencies * update protocol versions * feat(rpc): Implement `getblockchaininfo` RPC method (#3891) * Implement `getblockchaininfo` RPC method * add a test for `get_blockchain_info` * fix tohex/fromhex * move comment * Update lightwalletd acceptance test for getblockchaininfo RPC (#3914) * change(rpc): Return getblockchaininfo network upgrades in height order (#3915) * Update lightwalletd acceptance test for getblockchaininfo RPC * Update some doc comments for network upgrades * List network upgrades in order in the getblockchaininfo RPC Also: - Use a constant for the "missing consensus branch ID" RPC value - Simplify fetching consensus branch IDs - Make RPC type derives consistent - Update RPC type documentation * Make RPC type derives consistent * Fix a confusing test comment * get hashand height at the same time * fix estimated_height * fix lint * add extra check Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix typo Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * split test Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix(rpc): ignore an expected error in the RPC acceptance tests (#3961) * Add ignored regexes to test command failure regex methods * Ignore empty chain error in getblockchaininfo We expect this error when zebrad starts up with an empty state. Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Make sync error logs more user-friendly (#3944) - use info level, there is nothing the user needs to do, particularly for a single error - explain that the errors are temporary - hide backtraces, because they look like crashes * Update test.patch.yml with lightwalletd job (#3970) * Update test.patch.yml with lightwalletd job * Remove a workflow condition that will always be false In general, patch workflows need the opposite conditions to the original workflow. But in this case, we know the result of the condition will always be true, so we can just delete it. Co-authored-by: teor <teor@riseup.net> * fix(doc): Fix bugs in the lightwalletd database design (#3964) * Re-order column families in design in dependency order * Minor RFC design tweaks and fixes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Repoint zebra image links to our new zfnd.org site for now (#3949) * Repoint zebra image links to our new zfnd.org site for now * Remove images/ Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Fix typos (#3956) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * bump database version to trigger testnet rollback * reduce minimum protocol version for now (will be changed later) * update dependencies * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * update versions to match zcash 4.7.0 * deny.toml: update 'darling' Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com> Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com> Co-authored-by: Dimitris Apostolou <dimitris.apostolou@icloud.com>
2022-04-18 17:14:16 -07:00
self.0.to_repr().hash(state)
}
}
impl PartialEq for Root {
fn eq(&self, other: &Self) -> bool {
// TODO: should we compare canonical forms here using `.to_repr()`?
self.0 == other.0
}
}
impl TryFrom<[u8; 32]> for Root {
type Error = SerializationError;
fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
change(nu5): use new V5 transaction script verification API (#3799) * update librustzcash; adapt to new API * add ticket reference for removing zcash_proofs duplicated dependencies * update to new zcash_script V5 API * use zp_tx shorthand * update to Zcash 4.7.0 dependencies * update protocol versions * feat(rpc): Implement `getblockchaininfo` RPC method (#3891) * Implement `getblockchaininfo` RPC method * add a test for `get_blockchain_info` * fix tohex/fromhex * move comment * Update lightwalletd acceptance test for getblockchaininfo RPC (#3914) * change(rpc): Return getblockchaininfo network upgrades in height order (#3915) * Update lightwalletd acceptance test for getblockchaininfo RPC * Update some doc comments for network upgrades * List network upgrades in order in the getblockchaininfo RPC Also: - Use a constant for the "missing consensus branch ID" RPC value - Simplify fetching consensus branch IDs - Make RPC type derives consistent - Update RPC type documentation * Make RPC type derives consistent * Fix a confusing test comment * get hashand height at the same time * fix estimated_height * fix lint * add extra check Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix typo Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * split test Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix(rpc): ignore an expected error in the RPC acceptance tests (#3961) * Add ignored regexes to test command failure regex methods * Ignore empty chain error in getblockchaininfo We expect this error when zebrad starts up with an empty state. Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Make sync error logs more user-friendly (#3944) - use info level, there is nothing the user needs to do, particularly for a single error - explain that the errors are temporary - hide backtraces, because they look like crashes * Update test.patch.yml with lightwalletd job (#3970) * Update test.patch.yml with lightwalletd job * Remove a workflow condition that will always be false In general, patch workflows need the opposite conditions to the original workflow. But in this case, we know the result of the condition will always be true, so we can just delete it. Co-authored-by: teor <teor@riseup.net> * fix(doc): Fix bugs in the lightwalletd database design (#3964) * Re-order column families in design in dependency order * Minor RFC design tweaks and fixes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Repoint zebra image links to our new zfnd.org site for now (#3949) * Repoint zebra image links to our new zfnd.org site for now * Remove images/ Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Fix typos (#3956) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * bump database version to trigger testnet rollback * reduce minimum protocol version for now (will be changed later) * update dependencies * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * update versions to match zcash 4.7.0 * deny.toml: update 'darling' Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com> Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com> Co-authored-by: Dimitris Apostolou <dimitris.apostolou@icloud.com>
2022-04-18 17:14:16 -07:00
let possible_point = pallas::Base::from_repr(bytes);
if possible_point.is_some().into() {
Ok(Self(possible_point.unwrap()))
} else {
Err(SerializationError::Parse(
"Invalid pallas::Base value for Orchard 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 Orchard Incremental Note Commitment Tree.
#[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(pallas::Base);
impl Node {
/// Calls `to_repr()` on inner value.
pub fn to_repr(&self) -> [u8; 32] {
self.0.to_repr()
}
/// Return the node bytes in big-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.to_repr()
}
}
impl TryFrom<&[u8]> for Node {
type Error = &'static str;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
<[u8; 32]>::try_from(bytes)
.map_err(|_| "wrong byte slice len")?
.try_into()
}
}
impl TryFrom<[u8; 32]> for Node {
type Error = &'static str;
fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
Option::<pallas::Base>::from(pallas::Base::from_repr(bytes))
.map(Node)
.ok_or("invalid Pallas field element")
}
}
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("orchard::Node")
.field(&self.encode_hex::<String>())
.finish()
}
}
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 Orchard note commitment trees as [`Frontier`][1]s while the
/// [`z_gettreestate`][2] RPC requires [`CommitmentTree`][3]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
/// [`HashSer`] 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]: bridgetree::Frontier
/// [2]: https://zcash.github.io/rpc/z_gettreestate.html
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
/// [3]: incrementalmerkletree::frontier::CommitmentTree
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 repr = [0u8; 32];
reader.read_exact(&mut repr)?;
let maybe_node = pallas::Base::from_repr(repr).map(Self);
<Option<_>>::from(maybe_node).ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"Non-canonical encoding of Pallas base field value.",
)
})
}
fn write<W: io::Write>(&self, mut writer: W) -> io::Result<()> {
writer.write_all(&self.0.to_repr())
}
}
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_orchard(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<pallas::Base> for Node {
fn from(x: pallas::Base) -> Self {
Node(x)
}
}
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,
{
change(nu5): use new V5 transaction script verification API (#3799) * update librustzcash; adapt to new API * add ticket reference for removing zcash_proofs duplicated dependencies * update to new zcash_script V5 API * use zp_tx shorthand * update to Zcash 4.7.0 dependencies * update protocol versions * feat(rpc): Implement `getblockchaininfo` RPC method (#3891) * Implement `getblockchaininfo` RPC method * add a test for `get_blockchain_info` * fix tohex/fromhex * move comment * Update lightwalletd acceptance test for getblockchaininfo RPC (#3914) * change(rpc): Return getblockchaininfo network upgrades in height order (#3915) * Update lightwalletd acceptance test for getblockchaininfo RPC * Update some doc comments for network upgrades * List network upgrades in order in the getblockchaininfo RPC Also: - Use a constant for the "missing consensus branch ID" RPC value - Simplify fetching consensus branch IDs - Make RPC type derives consistent - Update RPC type documentation * Make RPC type derives consistent * Fix a confusing test comment * get hashand height at the same time * fix estimated_height * fix lint * add extra check Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix typo Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * split test Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix(rpc): ignore an expected error in the RPC acceptance tests (#3961) * Add ignored regexes to test command failure regex methods * Ignore empty chain error in getblockchaininfo We expect this error when zebrad starts up with an empty state. Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Make sync error logs more user-friendly (#3944) - use info level, there is nothing the user needs to do, particularly for a single error - explain that the errors are temporary - hide backtraces, because they look like crashes * Update test.patch.yml with lightwalletd job (#3970) * Update test.patch.yml with lightwalletd job * Remove a workflow condition that will always be false In general, patch workflows need the opposite conditions to the original workflow. But in this case, we know the result of the condition will always be true, so we can just delete it. Co-authored-by: teor <teor@riseup.net> * fix(doc): Fix bugs in the lightwalletd database design (#3964) * Re-order column families in design in dependency order * Minor RFC design tweaks and fixes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Repoint zebra image links to our new zfnd.org site for now (#3949) * Repoint zebra image links to our new zfnd.org site for now * Remove images/ Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Fix typos (#3956) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * bump database version to trigger testnet rollback * reduce minimum protocol version for now (will be changed later) * update dependencies * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * update versions to match zcash 4.7.0 * deny.toml: update 'darling' Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com> Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com> Co-authored-by: Dimitris Apostolou <dimitris.apostolou@icloud.com>
2022-04-18 17:14:16 -07:00
self.0.to_repr().serialize(serializer)
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<'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)?;
change(nu5): use new V5 transaction script verification API (#3799) * update librustzcash; adapt to new API * add ticket reference for removing zcash_proofs duplicated dependencies * update to new zcash_script V5 API * use zp_tx shorthand * update to Zcash 4.7.0 dependencies * update protocol versions * feat(rpc): Implement `getblockchaininfo` RPC method (#3891) * Implement `getblockchaininfo` RPC method * add a test for `get_blockchain_info` * fix tohex/fromhex * move comment * Update lightwalletd acceptance test for getblockchaininfo RPC (#3914) * change(rpc): Return getblockchaininfo network upgrades in height order (#3915) * Update lightwalletd acceptance test for getblockchaininfo RPC * Update some doc comments for network upgrades * List network upgrades in order in the getblockchaininfo RPC Also: - Use a constant for the "missing consensus branch ID" RPC value - Simplify fetching consensus branch IDs - Make RPC type derives consistent - Update RPC type documentation * Make RPC type derives consistent * Fix a confusing test comment * get hashand height at the same time * fix estimated_height * fix lint * add extra check Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix typo Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * split test Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * fix(rpc): ignore an expected error in the RPC acceptance tests (#3961) * Add ignored regexes to test command failure regex methods * Ignore empty chain error in getblockchaininfo We expect this error when zebrad starts up with an empty state. Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Make sync error logs more user-friendly (#3944) - use info level, there is nothing the user needs to do, particularly for a single error - explain that the errors are temporary - hide backtraces, because they look like crashes * Update test.patch.yml with lightwalletd job (#3970) * Update test.patch.yml with lightwalletd job * Remove a workflow condition that will always be false In general, patch workflows need the opposite conditions to the original workflow. But in this case, we know the result of the condition will always be true, so we can just delete it. Co-authored-by: teor <teor@riseup.net> * fix(doc): Fix bugs in the lightwalletd database design (#3964) * Re-order column families in design in dependency order * Minor RFC design tweaks and fixes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Repoint zebra image links to our new zfnd.org site for now (#3949) * Repoint zebra image links to our new zfnd.org site for now * Remove images/ Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Fix typos (#3956) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * bump database version to trigger testnet rollback * reduce minimum protocol version for now (will be changed later) * update dependencies * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * update versions to match zcash 4.7.0 * deny.toml: update 'darling' Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com> Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com> Co-authored-by: Dimitris Apostolou <dimitris.apostolou@icloud.com>
2022-04-18 17:14:16 -07:00
Option::<pallas::Base>::from(pallas::Base::from_repr(bytes))
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
.map(Node)
.ok_or_else(|| serde::de::Error::custom("invalid Pallas field element"))
}
}
#[derive(Error, Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[allow(missing_docs)]
pub enum NoteCommitmentTreeError {
#[error("The note commitment tree is full")]
FullTree,
}
/// Orchard 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
///
/// > [NU5 onward] A block MUST NOT add Orchard note commitments that would result in the Orchard note
/// > commitment tree exceeding its capacity of 2^(MerkleDepth^Orchard) leaf nodes.
///
/// <https://zips.z.cash/protocol/protocol.pdf#merkletree>
///
/// Note: MerkleDepth^Orchard = MERKLE_DEPTH = 32.
inner: bridgetree::Frontier<Node, MERKLE_DEPTH>,
/// A cached root of the tree.
///
/// 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 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 x-coordinate to the tree.
///
/// The leaves of the tree are actually a base field element, the
/// x-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_x: 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_x.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` if the tree is empty.
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 Orchard
/// 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(self.inner.root().0)
}
/// Get the Pallas-based Sinsemilla hash / root node of this merkle tree of
/// note commitments.
pub fn hash(&self) -> [u8; 32] {
self.root().into()
}
/// An as-yet unused Orchard note commitment tree leaf node.
///
/// Distinct for Orchard, a distinguished hash value of:
///
/// Uncommitted^Orchard = I2LEBSP_l_MerkleOrchard(2)
pub fn uncommitted() -> pallas::Base {
pallas::Base::one().double()
}
/// Count of note commitments added to the tree.
///
/// For Orchard, 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` 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<pallas::Base>> for NoteCommitmentTree {
/// Compute the tree from a whole bunch of note commitments at once.
fn from(values: Vec<pallas::Base>) -> Self {
let mut tree = Self::default();
if values.is_empty() {
return tree;
}
for cm_x in values {
let _ = tree.append(cm_x);
}
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 Orchard 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
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
/// with [`Frontier`](bridgetree::Frontier) from the crate
/// [`incrementalmerkletree`]. Zebra follows the former format in order to stay
/// consistent with `zcashd` in RPCs. Note that [`NoteCommitmentTree`] itself is
/// represented as [`Frontier`](bridgetree::Frontier).
///
/// The formats are semantically equivalent. The primary difference between them
/// is that in [`Frontier`](bridgetree::Frontier), the vector of parents is
/// 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`](bridgetree::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![];
// Skip the serialization of empty trees.
//
// Note: This ensures compatibility with `zcashd` in the
// [`z_gettreestate`][1] RPC.
//
// [1]: https://zcash.github.io/rpc/z_gettreestate.html
if tree.inner == bridgetree::Frontier::empty() {
return Self(serialized_tree);
}
// Convert the note commitment tree from
// [`Frontier`](bridgetree::Frontier) to
// [`CommitmentTree`](merkle_tree::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
let tree = incrementalmerkletree::frontier::CommitmentTree::from_frontier(&tree.inner);
write_commitment_tree(&tree, &mut serialized_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
.expect("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::new()),
}
}
}
impl AsRef<[u8]> for SerializedTree {
fn as_ref(&self) -> &[u8] {
&self.0
}
}