From b2139c0b977a7030e2c560d6cef80765e50e166c Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 16 Feb 2023 17:06:55 -0700 Subject: [PATCH] Add roundtrip and golden tests for v1 `MerkleBridge` serialization. --- zcash_primitives/src/merkle_tree.rs | 34 +-- .../src/merkle_tree/incremental.rs | 202 +++++++++++++++++- 2 files changed, 217 insertions(+), 19 deletions(-) diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 5e638c1f5..2e55cab39 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -1223,13 +1223,14 @@ mod tests { pub mod testing { use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use core::fmt::Debug; + use incrementalmerkletree::{self, Altitude}; use proptest::collection::vec; use proptest::prelude::*; use std::collections::hash_map::DefaultHasher; use std::hash::Hasher; use std::io::{self, Read, Write}; - use super::{CommitmentTree, Hashable}; + use super::{CommitmentTree, HashSer, Hashable}; pub fn arb_commitment_tree>( min_size: usize, @@ -1250,7 +1251,21 @@ pub mod testing { #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub(crate) struct TestNode(pub(crate) u64); - impl Hashable for TestNode { + impl incrementalmerkletree::Hashable for TestNode { + fn combine(alt: Altitude, a: &TestNode, b: &TestNode) -> TestNode { + let mut hasher = DefaultHasher::new(); + hasher.write_u8(alt.into()); + hasher.write_u64(a.0); + hasher.write_u64(b.0); + TestNode(hasher.finish()) + } + + fn empty_leaf() -> TestNode { + TestNode(0) + } + } + + impl HashSer for TestNode { fn read(mut reader: R) -> io::Result { reader.read_u64::().map(TestNode) } @@ -1258,20 +1273,5 @@ pub mod testing { fn write(&self, mut writer: W) -> io::Result<()> { writer.write_u64::(self.0) } - - fn combine(_: usize, a: &TestNode, b: &TestNode) -> TestNode { - let mut hasher = DefaultHasher::new(); - hasher.write_u64(a.0); - hasher.write_u64(b.0); - TestNode(hasher.finish()) - } - - fn blank() -> TestNode { - TestNode(0) - } - - fn empty_root(alt: usize) -> TestNode { - (0..alt).fold(Self::blank(), |v, lvl| Self::combine(lvl, &v, &v)) - } } } diff --git a/zcash_primitives/src/merkle_tree/incremental.rs b/zcash_primitives/src/merkle_tree/incremental.rs index daf7083c2..b70718b50 100644 --- a/zcash_primitives/src/merkle_tree/incremental.rs +++ b/zcash_primitives/src/merkle_tree/incremental.rs @@ -214,13 +214,17 @@ pub fn read_bridge( #[cfg(test)] mod tests { + use hex; use proptest::prelude::*; - use incrementalmerkletree::bridgetree::Frontier; + use incrementalmerkletree::{ + bridgetree::{BridgeTree, Frontier}, + Tree, + }; use super::*; use crate::{ - merkle_tree::testing::arb_commitment_tree, + merkle_tree::testing::{arb_commitment_tree, TestNode}, sapling::{testing as sapling, Node}, }; @@ -248,4 +252,198 @@ mod tests { assert_eq!(read, original); } } + + #[test] + fn test_bridge_roundtrip() { + let mut t: BridgeTree = BridgeTree::new(10); + let mut to_unwitness = vec![]; + let mut has_auth_path = vec![]; + for i in 0usize..100 { + assert!( + t.append(&TestNode(i.try_into().unwrap())), + "Append should succeed." + ); + if i % 5 == 0 { + t.checkpoint(); + } + if i % 7 == 0 { + t.witness(); + if i > 0 && i % 2 == 0 { + to_unwitness.push(Position::from(i)); + } else { + has_auth_path.push(Position::from(i)); + } + } + if i % 11 == 0 && !to_unwitness.is_empty() { + let pos = to_unwitness.remove(0); + t.remove_witness(pos); + } + } + + for (i, b) in t + .prior_bridges() + .iter() + .chain(t.current_bridge().iter()) + .enumerate() + { + let mut buffer = vec![]; + write_bridge(&mut buffer, b).unwrap(); + let b0 = read_bridge(&buffer[..]).unwrap(); + assert_eq!(b, &b0); + let buffer2 = hex::decode(&BRIDGE_V1_VECTORS[i]).unwrap(); + let b2 = read_bridge(&buffer2[..]).unwrap(); + assert_eq!(b, &b2); + } + + let latest_root = t.root(0).unwrap(); + for (pos, witness) in BRIDGE_V1_WITNESSES { + let path = t + .authentication_path(Position::from(*pos), &latest_root) + .unwrap(); + assert_eq!(witness.to_vec(), path); + } + } + + const BRIDGE_V1_VECTORS: &[&str] = &[ + "010000000000000000000000000000000000000000", + "01010000000000000000010000000000000000000000000000000002000000000000000201000000000000000cf29c71c9b7c4a50500000000000000040000000000000001050000000000000001545227c621102b3a", + "010105000000000000000100000000000000000000000000000000030000000000000001948e8c8cb96eed280700000000000000060000000000000001070000000000000002bae878935340beb7545227c621102b3a", + "010107000000000000000200000000000000000000000000000000030000000000000000070000000000000007000000000000000000000000000000000a000000000000000a000000000000000002157a46a02f6b8e34c730d7a51e3a8378", + "01010a000000000000000200000000000000000000000000000000030000000000000000070000000000000007000000000000000000000000000000000e000000000000000e000000000000000003779388f05d9525bb33fac4dcb323ec8bc730d7a51e3a8378", + "01010e000000000000000300000000000000000000000000000000040000000000000001c49580ae5e5e758307000000000000000700000000000000010000000000000001c49580ae5e5e75830e000000000000000e000000000000000100000000000000010f000000000000000f000000000000000e00000000000000010f0000000000000003779388f05d9525bb33fac4dcb323ec8bc730d7a51e3a8378", + "01010f000000000000000300000000000000000000000000000000040000000000000000070000000000000007000000000000000100000000000000000e000000000000000e0000000000000001000000000000000014000000000000001400000000000000000281be7679141b8edda519e57e99af06e2", + "010114000000000000000300000000000000000000000000000000040000000000000000070000000000000007000000000000000100000000000000000e000000000000000e00000000000000010000000000000000150000000000000014000000000000000115000000000000000281be7679141b8edda519e57e99af06e2", + "0101150000000000000003000000000000000000000000000000000400000000000000000700000000000000070000000000000001000000000000000015000000000000001500000000000000010000000000000001fdf772cabf2d5b20190000000000000018000000000000000119000000000000000244365e47c1afcfa1a519e57e99af06e2", + "01011900000000000000030000000000000000000000000000000004000000000000000007000000000000000700000000000000010000000000000000150000000000000015000000000000000100000000000000001c000000000000001c000000000000000003174b903560b67a6744365e47c1afcfa1a519e57e99af06e2", + "01011c00000000000000040000000000000000000000000000000004000000000000000007000000000000000700000000000000010000000000000000150000000000000015000000000000000100000000000000001c000000000000001c000000000000000100000000000000011d000000000000001e000000000000001e000000000000000004cfe7a4133f88607d174b903560b67a6744365e47c1afcfa1a519e57e99af06e2", + "01011e00000000000000030000000000000000000000000000000005000000000000000175938fb118b4555d0700000000000000070000000000000002000000000000000175938fb118b4555d15000000000000001500000000000000020000000000000001c050bf17c144495d2300000000000000220000000000000001230000000000000002f22dbb4a83f3b28318bd1c4cf1fd912e", + "0101230000000000000004000000000000000000000000000000000500000000000000000700000000000000070000000000000002000000000000000015000000000000001500000000000000020000000000000000230000000000000023000000000000000100000000000000017cf828deead5aa3d280000000000000028000000000000000002e28c91f60fbf69d518bd1c4cf1fd912e", + "0101280000000000000004000000000000000000000000000000000500000000000000000700000000000000070000000000000002000000000000000015000000000000001500000000000000020000000000000000230000000000000023000000000000000100000000000000002a000000000000002a000000000000000003e16610644840a918e28c91f60fbf69d518bd1c4cf1fd912e", + "01012a0000000000000004000000000000000000000000000000000500000000000000000700000000000000070000000000000002000000000000000015000000000000001500000000000000020000000000000000230000000000000023000000000000000100000000000000002d000000000000002c00000000000000012d0000000000000003afd0751401aff593e28c91f60fbf69d518bd1c4cf1fd912e", + "01012d000000000000000400000000000000000000000000000000050000000000000000070000000000000007000000000000000200000000000000001500000000000000150000000000000002000000000000000023000000000000002300000000000000020000000000000001dd486e048f1e6c2131000000000000003000000000000000013100000000000000029f16b2397db7491d18bd1c4cf1fd912e", + "0101310000000000000005000000000000000000000000000000000500000000000000000700000000000000070000000000000002000000000000000015000000000000001500000000000000020000000000000000230000000000000023000000000000000200000000000000003100000000000000310000000000000000000000000000000032000000000000003200000000000000000356370c5489a364b29f16b2397db7491d18bd1c4cf1fd912e", + "010132000000000000000500000000000000000000000000000000050000000000000000070000000000000007000000000000000200000000000000001500000000000000150000000000000002000000000000000023000000000000002300000000000000020000000000000000310000000000000031000000000000000200000000000000024f6ce1b1025daa00c2db272cc44c77c6370000000000000036000000000000000137000000000000000491c03add43411617ff8c00dfd0bc84289f16b2397db7491d18bd1c4cf1fd912e", + "0101370000000000000005000000000000000000000000000000000500000000000000000700000000000000070000000000000002000000000000000015000000000000001500000000000000020000000000000000230000000000000023000000000000000200000000000000003100000000000000310000000000000002000000000000000038000000000000003800000000000000000335cff7ed860ba07e9f16b2397db7491d18bd1c4cf1fd912e", + "010138000000000000000600000000000000000000000000000000050000000000000000070000000000000007000000000000000200000000000000001500000000000000150000000000000002000000000000000023000000000000002300000000000000020000000000000000310000000000000031000000000000000200000000000000003800000000000000380000000000000002000000000000000239000000000000001f6951d61f683ea73c000000000000003c0000000000000000047cfc0f73b07bd1ef35cff7ed860ba07e9f16b2397db7491d18bd1c4cf1fd912e", + "01013c000000000000000600000000000000000000000000000000060000000000000001f788446318d5f99907000000000000000700000000000000030000000000000001f788446318d5f99915000000000000001500000000000000030000000000000001f788446318d5f99923000000000000002300000000000000030000000000000001fb8290b35ee7b7dd31000000000000003100000000000000030000000000000001ea30e73bc03ac3c638000000000000003800000000000000030000000000000001852e67bafeb639803f000000000000003e00000000000000013f00000000000000050a984f21271cd02d7cfc0f73b07bd1ef35cff7ed860ba07e9f16b2397db7491d18bd1c4cf1fd912e", + "01013f00000000000000070000000000000000000000000000000006000000000000000007000000000000000700000000000000030000000000000000150000000000000015000000000000000300000000000000002300000000000000230000000000000003000000000000000031000000000000003100000000000000030000000000000000380000000000000038000000000000000300000000000000003f000000000000003f000000000000000000000000000000004100000000000000400000000000000001410000000000000001af35cc5f4335f3a7", + "010141000000000000000600000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f0000000000000000000000000000000046000000000000004600000000000000000331fc52e580f35e5348d31a06aa5a4470af35cc5f4335f3a7", + "010146000000000000000700000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004600000000000000460000000000000001000000000000000147000000000000004b000000000000004a00000000000000014b0000000000000003fe1c911e7cebb841b8b5aeae9a67d003af35cc5f4335f3a7", + "01014b000000000000000700000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f00000000000000000000000000000000460000000000000046000000000000000100000000000000004d000000000000004c00000000000000014d000000000000000347a60f231e2896ceb8b5aeae9a67d003af35cc5f4335f3a7", + "01014d000000000000000700000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004d000000000000004d000000000000000100000000000000011387f5de1c3253dd500000000000000050000000000000000002428877913fee798baf35cc5f4335f3a7", + "010150000000000000000700000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004d000000000000004d00000000000000010000000000000000540000000000000054000000000000000003e22700e31d13d582428877913fee798baf35cc5f4335f3a7", + "010154000000000000000800000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004d000000000000004d000000000000000100000000000000005400000000000000540000000000000001000000000000000155000000000000005500000000000000540000000000000001550000000000000003e22700e31d13d582428877913fee798baf35cc5f4335f3a7", + "010155000000000000000700000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004d000000000000004d000000000000000100000000000000005a000000000000005a00000000000000000498e2ef95e82f2d3e901d6a966885931b428877913fee798baf35cc5f4335f3a7", + "01015a000000000000000700000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004d000000000000004d000000000000000100000000000000005b000000000000005a00000000000000015b000000000000000498e2ef95e82f2d3e901d6a966885931b428877913fee798baf35cc5f4335f3a7", + "01015b000000000000000800000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004d000000000000004d00000000000000020000000000000001e7e0fcdfe98c29685b000000000000005b00000000000000010000000000000001d8900fcea5e695a55f000000000000005e00000000000000015f0000000000000005c3c19bd287343ee12218736715dbc702901d6a966885931b428877913fee798baf35cc5f4335f3a7", + "01015f000000000000000800000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004d000000000000004d000000000000000200000000000000005b000000000000005b000000000000000100000000000000006200000000000000620000000000000000036aa28f62b4a6071a082530c7c14f49acaf35cc5f4335f3a7", + "010162000000000000000800000000000000000000000000000000060000000000000000070000000000000007000000000000000300000000000000001500000000000000150000000000000003000000000000000023000000000000002300000000000000030000000000000000310000000000000031000000000000000300000000000000003f000000000000003f000000000000000000000000000000004d000000000000004d000000000000000200000000000000005b000000000000005b0000000000000001000000000000000063000000000000006200000000000000016300000000000000036aa28f62b4a6071a082530c7c14f49acaf35cc5f4335f3a7", + ]; + + const BRIDGE_V1_WITNESSES: &[(usize, [TestNode; 8])] = &[ + ( + 0, + [ + TestNode(1), + TestNode(11944874187515818508), + TestNode(2949135074203569812), + TestNode(9472581151991305668), + TestNode(6725479636698895221), + TestNode(11095133457725294839), + TestNode(14133087432678894597), + TestNode(5741638299150577022), + ], + ), + ( + 7, + [ + TestNode(6), + TestNode(13240090682216474810), + TestNode(4191461615442809428), + TestNode(9472581151991305668), + TestNode(6725479636698895221), + TestNode(11095133457725294839), + TestNode(14133087432678894597), + TestNode(5741638299150577022), + ], + ), + ( + 21, + [ + TestNode(20), + TestNode(2331507533852899325), + TestNode(15964727503826108033), + TestNode(6721979514944966848), + TestNode(16286898176225778085), + TestNode(11095133457725294839), + TestNode(14133087432678894597), + TestNode(5741638299150577022), + ], + ), + ( + 35, + [ + TestNode(34), + TestNode(9489915110043102706), + TestNode(4443599187080706172), + TestNode(2408333500339865821), + TestNode(15976492597045658363), + TestNode(3355742410173627672), + TestNode(14133087432678894597), + TestNode(5741638299150577022), + ], + ), + ( + 49, + [ + TestNode(48), + TestNode(47953012196469839), + TestNode(14300983547176410050), + TestNode(14322355837281448170), + TestNode(2110419648866555551), + TestNode(3355742410173627672), + TestNode(14133087432678894597), + TestNode(5741638299150577022), + ], + ), + ( + 63, + [ + TestNode(62), + TestNode(3301169481250740234), + TestNode(17280729242972191868), + TestNode(9124305519198588725), + TestNode(2110419648866555551), + TestNode(3355742410173627672), + TestNode(14133087432678894597), + TestNode(5741638299150577022), + ], + ), + ( + 77, + [ + TestNode(76), + TestNode(15948145805030164243), + TestNode(14886129728222111303), + TestNode(274833491322910136), + TestNode(7505685190102802663), + TestNode(2256868868291095598), + TestNode(12102075187160954287), + TestNode(5741638299150577022), + ], + ), + ( + 91, + [ + TestNode(90), + TestNode(4480289880297955992), + TestNode(11931696387589116120), + TestNode(1987078544847150480), + TestNode(10050326000244852802), + TestNode(2256868868291095598), + TestNode(12102075187160954287), + TestNode(5741638299150577022), + ], + ), + ]; }