From f86a65d7cbee08813114a6a639314df65a79bd73 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Fri, 8 Apr 2022 12:48:03 -0600 Subject: [PATCH] Make Orchard `finalState` serialization format match Sapling. For consistency, we serialize the `finalState` field in the same (sparse) encoding as Sapling and Sprout use. In the future we may want to update this to the dense encoding that incrementalmerkletree::bridgetree::Frontier uses, but that's not necessary for the moment. --- .cargo/config.offline | 2 +- Cargo.lock | 16 +++++------ Cargo.toml | 12 ++++---- qa/rpc-tests/finalsaplingroot.py | 2 +- src/rpc/blockchain.cpp | 2 +- .../rust/orchard/incremental_merkle_tree.h | 9 ++++++ src/rust/src/incremental_merkle_tree_ffi.rs | 28 ++++++++++++++++++- src/zcash/IncrementalMerkleTree.hpp | 17 +++++++++++ 8 files changed, 70 insertions(+), 18 deletions(-) diff --git a/.cargo/config.offline b/.cargo/config.offline index 18bafeae7..01d8840e1 100644 --- a/.cargo/config.offline +++ b/.cargo/config.offline @@ -6,7 +6,7 @@ replace-with = "vendored-sources" [source."https://github.com/zcash/librustzcash.git"] git = "https://github.com/zcash/librustzcash.git" -rev = "43c18d000fcbe45363b2d53585d5102841eff99e" +rev = "d5c5f048947d211c2fbef23ce986b329b91d1aa5" replace-with = "vendored-sources" [source."https://github.com/nuttycom/hdwallet.git"] diff --git a/Cargo.lock b/Cargo.lock index 80f751cd7..a42d5263d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -562,7 +562,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "equihash" version = "0.1.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=43c18d000fcbe45363b2d53585d5102841eff99e#43c18d000fcbe45363b2d53585d5102841eff99e" +source = "git+https://github.com/zcash/librustzcash.git?rev=d5c5f048947d211c2fbef23ce986b329b91d1aa5#d5c5f048947d211c2fbef23ce986b329b91d1aa5" dependencies = [ "blake2b_simd", "byteorder", @@ -571,7 +571,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.0.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=43c18d000fcbe45363b2d53585d5102841eff99e#43c18d000fcbe45363b2d53585d5102841eff99e" +source = "git+https://github.com/zcash/librustzcash.git?rev=d5c5f048947d211c2fbef23ce986b329b91d1aa5#d5c5f048947d211c2fbef23ce986b329b91d1aa5" dependencies = [ "blake2b_simd", ] @@ -2240,7 +2240,7 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.0.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=43c18d000fcbe45363b2d53585d5102841eff99e#43c18d000fcbe45363b2d53585d5102841eff99e" +source = "git+https://github.com/zcash/librustzcash.git?rev=d5c5f048947d211c2fbef23ce986b329b91d1aa5#d5c5f048947d211c2fbef23ce986b329b91d1aa5" dependencies = [ "bech32", "bs58", @@ -2251,7 +2251,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.0.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=43c18d000fcbe45363b2d53585d5102841eff99e#43c18d000fcbe45363b2d53585d5102841eff99e" +source = "git+https://github.com/zcash/librustzcash.git?rev=d5c5f048947d211c2fbef23ce986b329b91d1aa5#d5c5f048947d211c2fbef23ce986b329b91d1aa5" dependencies = [ "byteorder", "nonempty", @@ -2260,7 +2260,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=43c18d000fcbe45363b2d53585d5102841eff99e#43c18d000fcbe45363b2d53585d5102841eff99e" +source = "git+https://github.com/zcash/librustzcash.git?rev=d5c5f048947d211c2fbef23ce986b329b91d1aa5#d5c5f048947d211c2fbef23ce986b329b91d1aa5" dependencies = [ "bigint", "blake2b_simd", @@ -2270,7 +2270,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.1.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=43c18d000fcbe45363b2d53585d5102841eff99e#43c18d000fcbe45363b2d53585d5102841eff99e" +source = "git+https://github.com/zcash/librustzcash.git?rev=d5c5f048947d211c2fbef23ce986b329b91d1aa5#d5c5f048947d211c2fbef23ce986b329b91d1aa5" dependencies = [ "chacha20", "chacha20poly1305", @@ -2281,7 +2281,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.5.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=43c18d000fcbe45363b2d53585d5102841eff99e#43c18d000fcbe45363b2d53585d5102841eff99e" +source = "git+https://github.com/zcash/librustzcash.git?rev=d5c5f048947d211c2fbef23ce986b329b91d1aa5#d5c5f048947d211c2fbef23ce986b329b91d1aa5" dependencies = [ "aes", "bip0039", @@ -2317,7 +2317,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.5.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=43c18d000fcbe45363b2d53585d5102841eff99e#43c18d000fcbe45363b2d53585d5102841eff99e" +source = "git+https://github.com/zcash/librustzcash.git?rev=d5c5f048947d211c2fbef23ce986b329b91d1aa5#d5c5f048947d211c2fbef23ce986b329b91d1aa5" dependencies = [ "bellman", "blake2b_simd", diff --git a/Cargo.toml b/Cargo.toml index db57715b4..ab97fdf86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,9 +87,9 @@ codegen-units = 1 [patch.crates-io] hdwallet = { git = "https://github.com/nuttycom/hdwallet", rev = "9b4c1bdbe0517e3a7a8f285d6048a37d472ba3bc" } -zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "43c18d000fcbe45363b2d53585d5102841eff99e" } -zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "43c18d000fcbe45363b2d53585d5102841eff99e" } -zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "43c18d000fcbe45363b2d53585d5102841eff99e" } -zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "43c18d000fcbe45363b2d53585d5102841eff99e" } -zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "43c18d000fcbe45363b2d53585d5102841eff99e" } -zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "43c18d000fcbe45363b2d53585d5102841eff99e" } +zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "d5c5f048947d211c2fbef23ce986b329b91d1aa5" } +zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "d5c5f048947d211c2fbef23ce986b329b91d1aa5" } +zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "d5c5f048947d211c2fbef23ce986b329b91d1aa5" } +zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "d5c5f048947d211c2fbef23ce986b329b91d1aa5" } +zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "d5c5f048947d211c2fbef23ce986b329b91d1aa5" } +zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "d5c5f048947d211c2fbef23ce986b329b91d1aa5" } diff --git a/qa/rpc-tests/finalsaplingroot.py b/qa/rpc-tests/finalsaplingroot.py index 789012284..b028947c0 100755 --- a/qa/rpc-tests/finalsaplingroot.py +++ b/qa/rpc-tests/finalsaplingroot.py @@ -224,7 +224,7 @@ class FinalSaplingRootTest(BitcoinTestFramework): assert "skipHash" not in treestate["orchard"] assert_equal(new_treestate["orchard"]["commitments"]["finalRoot"], ORCHARD_TREE_EMPTY_ROOT) - assert_equal(new_treestate["orchard"]["commitments"]["finalState"], "00") + assert_equal(new_treestate["orchard"]["commitments"]["finalState"], "000000") pass diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c4b6a556d..0e6a24e77 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1343,7 +1343,7 @@ UniValue z_gettreestate(const UniValue& params, bool fHelp) OrchardMerkleFrontier tree; if (pcoinsTip->GetOrchardAnchorAt(pindex->hashFinalOrchardRoot, tree)) { CDataStream s(SER_NETWORK, PROTOCOL_VERSION); - s << tree; + s << OrchardMerkleFrontierLegacySer(tree); orchard_commitments.pushKV("finalState", HexStr(s.begin(), s.end())); } else { // Set skipHash to the most recent block that has a finalState. diff --git a/src/rust/include/rust/orchard/incremental_merkle_tree.h b/src/rust/include/rust/orchard/incremental_merkle_tree.h index d0d07524b..8cb473884 100644 --- a/src/rust/include/rust/orchard/incremental_merkle_tree.h +++ b/src/rust/include/rust/orchard/incremental_merkle_tree.h @@ -52,6 +52,15 @@ bool orchard_merkle_frontier_serialize( void* stream, write_callback_t write_cb); +// Serializes an Orchard Merkle frontier to a stream using the +// zcash_primitives::merkle_tree::CommitmentTree sparse encoding. +// +// Returns `false` if an error occurs while writing to the stream. +bool orchard_merkle_frontier_serialize_legacy( + const OrchardMerkleFrontierPtr* tree_ptr, + void* stream, + write_callback_t write_cb); + // For each action in the provided bundle, append its // commitment to the frontier. // diff --git a/src/rust/src/incremental_merkle_tree_ffi.rs b/src/rust/src/incremental_merkle_tree_ffi.rs index f70a2003f..5a70b6388 100644 --- a/src/rust/src/incremental_merkle_tree_ffi.rs +++ b/src/rust/src/incremental_merkle_tree_ffi.rs @@ -5,7 +5,10 @@ use std::ptr; use orchard::{bundle::Authorized, tree::MerkleHashOrchard}; use tracing::error; use zcash_primitives::{ - merkle_tree::incremental::{read_frontier_v1, write_frontier_v1}, + merkle_tree::{ + incremental::{read_frontier_v1, write_frontier_v1}, + CommitmentTree, + }, transaction::components::Amount, }; @@ -80,6 +83,29 @@ pub extern "C" fn orchard_merkle_frontier_serialize( } } +#[no_mangle] +pub extern "C" fn orchard_merkle_frontier_serialize_legacy( + frontier: *const bridgetree::Frontier, + stream: Option, + write_cb: Option, +) -> bool { + let frontier = unsafe { + frontier + .as_ref() + .expect("Orchard note commitment tree pointer may not be null.") + }; + + let writer = CppStreamWriter::from_raw_parts(stream, write_cb.unwrap()); + let commitment_tree = CommitmentTree::from_frontier(frontier); + match commitment_tree.write(writer) { + Ok(()) => true, + Err(e) => { + error!("{}", e); + false + } + } +} + #[no_mangle] pub extern "C" fn orchard_merkle_frontier_append_bundle( tree: *mut bridgetree::Frontier, diff --git a/src/zcash/IncrementalMerkleTree.hpp b/src/zcash/IncrementalMerkleTree.hpp index e8fa7e912..0f61730a6 100644 --- a/src/zcash/IncrementalMerkleTree.hpp +++ b/src/zcash/IncrementalMerkleTree.hpp @@ -260,6 +260,7 @@ typedef libzcash::IncrementalWitness SaplingTestingWitness; class OrchardWallet; +class OrchardMerkleFrontierLegacySer; class OrchardMerkleFrontier { @@ -269,6 +270,7 @@ private: std::unique_ptr inner; friend class OrchardWallet; + friend class OrchardMerkleFrontierLegacySer; public: OrchardMerkleFrontier() : inner(orchard_merkle_frontier_empty(), orchard_merkle_frontier_free) {} @@ -332,4 +334,19 @@ public: } }; +class OrchardMerkleFrontierLegacySer { +private: + const OrchardMerkleFrontier& frontier; +public: + OrchardMerkleFrontierLegacySer(const OrchardMerkleFrontier& frontier): frontier(frontier) {} + + template + void Serialize(Stream& s) const { + RustStream rs(s); + if (!orchard_merkle_frontier_serialize_legacy(frontier.inner.get(), &rs, RustStream::write_callback)) { + throw std::ios_base::failure("Failed to serialize Orchard merkle frontier in legacy format."); + } + } +}; + #endif /* ZC_INCREMENTALMERKLETREE_H_ */