extern crate bloock_smt; use crate::h256_rocksdb_blake2b::common; use bitvec::prelude::bitvec; use bloock_merge::hash_algorithms::blake2b::Blake2b; use bloock_smt::error::SmtError; use bloock_smt::proof::Proof; use bloock_smt::tree::SparseMerkleTree; use bloock_storage::kv::kv_rocks::RocksDB as Database; use bloock_types::bytes::h256::H256; /* get_multiproof() ========= ========= ========= */ #[test] fn test_multiproof_simple_left() { let mut db = common::init_rocksdb("multiproof_simple_left"); common::init_tree_0_1(&mut db); let value_proof_leaves: Vec = vec![[1u8; 32]]; let leaves: Vec = vec![[0u8; 32]]; let sparse = SparseMerkleTree::::load( [ 3, 127, 45, 161, 237, 218, 238, 67, 106, 133, 220, 204, 7, 34, 69, 228, 123, 196, 15, 21, 154, 156, 67, 94, 39, 81, 41, 150, 54, 177, 239, 3, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(leaves).unwrap(); assert_eq!( proof.hashes, value_proof_leaves, "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![1, 1], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![0, 1], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_simple_left"); } #[test] fn test_multiproof_simple_right() { let mut db = common::init_rocksdb("multiproof_simple_right"); common::init_tree_0_1(&mut db); let value_proof_leaves: Vec = vec![[0u8; 32]]; let leaves: Vec = vec![[1u8; 32]]; let sparse = SparseMerkleTree::::load( [ 3, 127, 45, 161, 237, 218, 238, 67, 106, 133, 220, 204, 7, 34, 69, 228, 123, 196, 15, 21, 154, 156, 67, 94, 39, 81, 41, 150, 54, 177, 239, 3, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(leaves).unwrap(); assert_eq!( proof.hashes, value_proof_leaves, "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![1, 1], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![1, 0], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_simple_right"); } #[test] fn test_multiproof_4leaves_0() { let mut db = common::init_rocksdb("multiproof_4leaves_0"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[0u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![ [1; 32], [ 55, 204, 95, 10, 183, 75, 225, 169, 26, 216, 79, 149, 29, 195, 120, 173, 46, 167, 91, 31, 187, 141, 101, 53, 137, 34, 143, 106, 45, 167, 226, 120, ], ], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![2, 2, 1], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![0, 1, 1], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_0"); } #[test] fn test_multiproof_4leaves_1() { let mut db = common::init_rocksdb("multiproof_4leaves_1"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[1u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![ [0; 32], [ 55, 204, 95, 10, 183, 75, 225, 169, 26, 216, 79, 149, 29, 195, 120, 173, 46, 167, 91, 31, 187, 141, 101, 53, 137, 34, 143, 106, 45, 167, 226, 120, ], ], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![2, 2, 1], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![1, 0, 1], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_1"); } #[test] fn test_multiproof_4leaves_2() { let mut db = common::init_rocksdb("multiproof_4leaves_2"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[2u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![ [ 3, 127, 45, 161, 237, 218, 238, 67, 106, 133, 220, 204, 7, 34, 69, 228, 123, 196, 15, 21, 154, 156, 67, 94, 39, 81, 41, 150, 54, 177, 239, 3, ], [3; 32] ], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![1, 2, 2], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![1, 0, 1], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_2"); } #[test] fn test_multiproof_4leaves_3() { let mut db = common::init_rocksdb("multiproof_4leaves_3"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[3u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![ [ 3, 127, 45, 161, 237, 218, 238, 67, 106, 133, 220, 204, 7, 34, 69, 228, 123, 196, 15, 21, 154, 156, 67, 94, 39, 81, 41, 150, 54, 177, 239, 3, ], [2; 32] ], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![1, 2, 2], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![1, 1, 0], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_3"); } #[test] fn test_multiproof_4leaves_xx00() { let mut db = common::init_rocksdb("multiproof_4leaves_XX00"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[0u8; 32], [1u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![[ 55, 204, 95, 10, 183, 75, 225, 169, 26, 216, 79, 149, 29, 195, 120, 173, 46, 167, 91, 31, 187, 141, 101, 53, 137, 34, 143, 106, 45, 167, 226, 120, ],], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![2, 2, 1], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![0, 0, 1], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_XX00"); } #[test] fn test_multiproof_4leaves_x0x0() { let mut db = common::init_rocksdb("multiproof_4leaves_X0X0"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[0u8; 32], [2u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![[1; 32], [3; 32]], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![2, 2, 2, 2,], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![0, 1, 0, 1], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_X0X0"); } #[test] fn test_multiproof_4leaves_0x0x() { let mut db = common::init_rocksdb("multiproof_4leaves_0X0X"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[1u8; 32], [3u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![[0; 32], [2; 32]], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![2, 2, 2, 2,], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![1, 0, 1, 0], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_0X0X"); } #[test] fn test_multiproof_4leaves_00xx() { let mut db = common::init_rocksdb("multiproof_4leaves_00XX"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[2u8; 32], [3u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![[ 3, 127, 45, 161, 237, 218, 238, 67, 106, 133, 220, 204, 7, 34, 69, 228, 123, 196, 15, 21, 154, 156, 67, 94, 39, 81, 41, 150, 54, 177, 239, 3, ]], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![1, 2, 2,], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![1, 0, 0], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_00XX"); } #[test] fn test_multiproof_4leaves_x00x() { let mut db = common::init_rocksdb("multiproof_4leaves_X00X"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[0u8; 32], [3u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![[1; 32], [2; 32]], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![2, 2, 2, 2], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![0, 1, 1, 0], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_X00X"); } #[test] fn test_multiproof_4leaves_0xx0() { let mut db = common::init_rocksdb("multiproof_4leaves_0XX0"); common::init_tree_0_1_2_3(&mut db); let sparse = SparseMerkleTree::::load( [ 236, 45, 107, 94, 128, 193, 173, 148, 130, 182, 250, 30, 47, 54, 61, 144, 13, 74, 126, 158, 114, 161, 132, 252, 253, 103, 236, 44, 168, 232, 117, 234, ], &mut db, ) .unwrap(); let proof = sparse.get_multiproof(vec![[1u8; 32], [2u8; 32]]).unwrap(); assert_eq!( proof.hashes, vec![[0; 32], [3; 32]], "Proof nodes difference between returned and expected." ); assert_eq!( proof.depths, vec![2, 2, 2, 2], "Tree depths difference between returned and expected." ); assert_eq!( proof.bitmap, bitvec![1, 0, 0, 1], "Bitmap difference between returned and expected." ); common::delete_folder("multiproof_4leaves_0XX0"); } #[test] fn test_multiproof_leaf_not_found_simple() { let mut db = common::init_rocksdb("multiproof_leaf_not_found_simple"); common::init_tree_0_1(&mut db); let sparse = SparseMerkleTree::::load( [ 3, 127, 45, 161, 237, 218, 238, 67, 106, 133, 220, 204, 7, 34, 69, 228, 123, 196, 15, 21, 154, 156, 67, 94, 39, 81, 41, 150, 54, 177, 239, 3, ], &mut db, ) .unwrap(); assert_eq!( false, sparse.get_multiproof(vec![[3u8; 32]]).is_ok(), "get_multiproof did not complain about a non existing leaf in the tree." ); common::delete_folder("multiproof_leaf_not_found_simple"); } #[test] fn test_multiproof_not_found_leaf() { let mut db = common::init_rocksdb("multiproof_not_found_leaf"); common::init_tree_16_17_21_23_36_38_64(&mut db); let sparse = SparseMerkleTree::::load( [ 35, 209, 213, 105, 108, 19, 197, 99, 187, 231, 253, 55, 211, 5, 220, 28, 198, 20, 52, 38, 83, 125, 34, 0, 142, 214, 168, 100, 28, 144, 1, 49, ], &mut db, ) .unwrap(); assert_eq!( false, sparse.get_multiproof(vec![[90u8; 32]]).is_ok(), "get_multiproof did not complain about a non existing leaf in the tree." ); common::delete_folder("multiproof_not_found_leaf"); } #[test] fn test_multiproof_not_found_leaf2() { let mut db = common::init_rocksdb("multiproof_not_found_leaf2"); common::init_tree_16_17_21_23_36_38_64(&mut db); let sparse = SparseMerkleTree::::load( [ 35, 209, 213, 105, 108, 19, 197, 99, 187, 231, 253, 55, 211, 5, 220, 28, 198, 20, 52, 38, 83, 125, 34, 0, 142, 214, 168, 100, 28, 144, 1, 49, ], &mut db, ) .unwrap(); assert_eq!( false, sparse.get_multiproof(vec![[154u8; 32]]).is_ok(), "get_multiproof did not complain about a non existing leaf in the tree." ); common::delete_folder("multiproof_not_found_leaf2"); } #[test] fn test_multiproof_empty_source_root() { let mut db = common::init_rocksdb("multiproof_empty_source_root"); let sparse = SparseMerkleTree::::new(&mut db, None).unwrap(); let my_err = sparse.get_multiproof(vec![[154u8; 32]]); assert!( my_err.is_err(), "get_multiproof did not complain about a non existing leaf in the tree." ); assert_eq!( my_err.err().unwrap(), SmtError::NotFound { key: String::from("Root"), }, "get_multiproof did not complain about a non existing leaf in the tree." ); common::delete_folder("multiproof_empty_source_root"); } /* ========= ========= ========= ========= */ /* multiproof on checkpoints ========= ========= ========= */ #[test] fn test_checkpoint_leaf() { let mut db = common::init_rocksdb("checkpoint_leaf"); common::init_tree_1(&mut db); let mut smt = SparseMerkleTree::::load([1u8; 32], &mut db).unwrap(); assert!(smt.add_leaves(vec![[0; 32]]).is_ok()); let cp_smt = SparseMerkleTree::::load([1u8; 32], &mut db).unwrap(); let proof = cp_smt .get_multiproof(vec![[1u8; 32]]) .expect("get_multiproof went wrong."); assert_eq!(proof.leaves, vec![[1u8; 32]], "Error at leaves."); assert_eq!(proof.hashes, Vec::::new(), "Error at hashes."); assert_eq!(proof.depths, vec![0], "Error at depths."); assert_eq!(proof.bitmap, bitvec![0], "Error at bitmap."); assert_eq!(proof.root, [1u8; 32], "Error at root."); common::delete_folder("checkpoint_leaf"); } #[test] fn test_checkpoint_intermediate_case_2() { let mut db = common::init_rocksdb("checkpoint_intermediate_case_2"); common::init_tree_1_2(&mut db); let root = [ 48, 182, 0, 251, 31, 12, 192, 179, 240, 252, 40, 205, 203, 115, 137, 64, 90, 102, 89, 190, 129, 199, 213, 197, 144, 87, 37, 170, 58, 81, 25, 206, ]; let mut smt = SparseMerkleTree::::load(root, &mut db).unwrap(); assert!(smt.add_leaves(vec![[0; 32]]).is_ok()); let cp_smt = SparseMerkleTree::::load(root, &mut db).unwrap(); let proof = cp_smt .get_multiproof(vec![[1u8; 32]]) .expect("get_multiproof went wrong."); assert_eq!(proof.leaves, vec![[1u8; 32]], "Error at leaves."); assert_eq!(proof.hashes, vec![[2u8; 32]], "Error at hashes."); assert_eq!(proof.depths, vec![1, 1], "Error at depths."); assert_eq!(proof.bitmap, bitvec![0, 1], "Error at bitmap."); assert_eq!(proof.root, root, "Error at root."); common::delete_folder("checkpoint_intermediate_case_2"); } #[test] fn test_checkpoint_intermediate_case_1() { let mut db = common::init_rocksdb("checkpoint_intermediate_case_1"); common::init_tree_1_2(&mut db); let root = [ 48, 182, 0, 251, 31, 12, 192, 179, 240, 252, 40, 205, 203, 115, 137, 64, 90, 102, 89, 190, 129, 199, 213, 197, 144, 87, 37, 170, 58, 81, 25, 206, ]; let mut smt = SparseMerkleTree::::load(root, &mut db).unwrap(); assert!(smt.add_leaves(vec![[4; 32]]).is_ok()); let cp_smt = SparseMerkleTree::::load(root, &mut db).unwrap(); let proof = cp_smt .get_multiproof(vec![[1u8; 32]]) .expect("get_multiproof went wrong."); assert_eq!(proof.leaves, vec![[1u8; 32]], "Error at leaves."); assert_eq!(proof.hashes, vec![[2u8; 32]], "Error at hashes."); assert_eq!(proof.depths, vec![1, 1], "Error at depths."); assert_eq!(proof.bitmap, bitvec![0, 1], "Error at bitmap."); assert_eq!(proof.root, root, "Error at root."); common::delete_folder("checkpoint_intermediate_case_1"); } /* ========= ========= ========= ========= */ #[test] //#[ignore] fn test_go_mad_proof_concat() { pub use hex; use rand::Rng; use std::convert::TryInto; let mut rng = rand::thread_rng(); let charset: &[u8] = b"ABCDEF0123456789"; let n_iterations: usize = 10; let n_trees: usize = 10; let n_leaves_per_tree: usize = 250; for _ in 0..n_iterations { { let mut vec_roots: Vec = vec![]; let mut vec_roots_proof: Vec = vec![]; let mut vec_proofs: Vec> = vec![]; let mut db = common::init_rocksdb("go_mad_proof_concat_shards"); for _ in 0..n_trees { let mut td_leaves = vec![]; let mut smt = SparseMerkleTree::::new(&mut db, None).unwrap(); let mut leaves: Vec = Vec::::new(); for _ in 0..n_leaves_per_tree { let leaf: [u8; 32] = hex::decode( (0..64) .map(|_| { let idx = rng.gen_range(0, charset.len()); charset[idx] as char }) .collect::(), ) .unwrap()[0..32] .try_into() .expect("Impossible error!"); leaves.push(leaf); } let r = rng.gen_range(1, 5); for i in 0..leaves.len() { if rng.gen_range(0, n_leaves_per_tree) > n_leaves_per_tree / r { td_leaves.push(leaves[i]); } } if smt.add_leaves(leaves).is_err() { panic!("adding some leaves went really wrong."); } vec_roots.push(smt.get_root().unwrap()); if !td_leaves.is_empty() { let mp = match smt.get_multiproof(td_leaves) { Ok(p) => p, Err(_) => panic!("could not generate leave proof."), }; vec_proofs.push(mp); vec_roots_proof.push(smt.get_root().unwrap()); } } common::delete_folder("go_mad_proof_concat_shards"); let mut db = common::init_rocksdb("go_mad_proof_concat_anchor"); let mut smt = SparseMerkleTree::::new(&mut db, None).unwrap(); let vec_proofs: Vec> = vec![]; if smt.add_leaves(vec_roots).is_err() { panic!("adding leaves in anchor tree went really wrong."); } let proof_main = match smt.get_multiproof(vec_roots_proof) { Ok(p) => p, Err(_) => panic!("could not generate main proof."), }; let proof_main = Proof::::assemble_proofs(proof_main, vec_proofs).unwrap(); assert_eq!( true, proof_main.verify(&smt.get_root().unwrap()), "Verify did not go properly." ); common::delete_folder("go_mad_proof_concat_anchor"); } } } #[test] //#[ignore] fn test_go_mad_proof_checkpoint() { pub use hex; use rand::Rng; use std::convert::TryInto; let mut rng = rand::thread_rng(); let charset: &[u8] = b"ABCDEF0123456789"; let n_iterations: usize = 10; let n_insertions: usize = 50; let n_leaves_per_ins: usize = 100; for _ in 0..n_iterations { let mut leaves_all = vec![]; let mut checkpoints: Vec = vec![]; let mut db = common::init_rocksdb("full_go_mad_proof_checkpoint"); { let mut smt = SparseMerkleTree::::new(&mut db, None).unwrap(); for i in 0..n_insertions { let mut leaves: Vec = Vec::::new(); for _ in 0..n_leaves_per_ins { let leaf: [u8; 32] = hex::decode( (0..64) .map(|_| { let idx = rng.gen_range(0, charset.len()); charset[idx] as char }) .collect::(), ) .unwrap()[0..32] .try_into() .expect("Impossible error!"); leaves.push(leaf); leaves_all.push(leaf); } println!("\n({:?}) All leaves: {:?}", i, leaves_all); println!("\nAdd leaves"); match smt.add_leaves(leaves.clone()) { Ok(_) => {} Err(e) => panic!("{:?} => {:?}", e.to_string(), i), } checkpoints.push(smt.get_root().unwrap()); } } println!("\nCHECKPOINTS: {:?}\n", checkpoints); for i in 0..n_insertions { println!("\nCHECKPOINT: {:?}\n", checkpoints[i]); println!( "\nLeaves: {:?}\n", leaves_all[0..(i + 1) * n_insertions].to_vec() ); let smt = SparseMerkleTree::::load(checkpoints[i], &mut db).unwrap(); println!("All leaves proof"); let proof = match smt.get_multiproof(leaves_all[0..(i + 1) * n_insertions].to_vec()) { Ok(p) => p, Err(e) => panic!(e.to_string()), }; println!("All leaves verify\n"); assert_eq!(proof.verify(&smt.get_root().unwrap()), true, "false"); } common::delete_folder("full_go_mad_proof_checkpoint"); } }