mirror of
https://github.com/tlsnotary/rs-merkle.git
synced 2026-01-06 21:43:57 -05:00
feat: add documentation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
.idea/
|
||||
doc/
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "rs-merkle"
|
||||
name = "rs_merkle"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
|
||||
4
src/algorithms/mod.rs
Normal file
4
src/algorithms/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
//! This module contains built-in implementations of `rs_merkle::Hasher`
|
||||
mod sha256;
|
||||
|
||||
pub use sha256::Sha256Algorithm as Sha256;
|
||||
17
src/algorithms/sha256.rs
Normal file
17
src/algorithms/sha256.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use sha2::{Sha256, Digest, digest::FixedOutput};
|
||||
use crate::Hasher;
|
||||
|
||||
/// Sha256 implementation of the `rs_merkle::Hasher` trait
|
||||
#[derive(Clone)]
|
||||
pub struct Sha256Algorithm {}
|
||||
|
||||
impl Hasher for Sha256Algorithm {
|
||||
type Hash = [u8; 32];
|
||||
|
||||
fn hash(data: &Vec<u8>) -> [u8; 32] {
|
||||
let mut hasher = Sha256::new();
|
||||
|
||||
hasher.update(data);
|
||||
<[u8; 32]>::from(hasher.finalize_fixed())
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,57 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
|
||||
/// Hasher is a trait used to provide a hashing algorithm for the library.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This example shows how to implement sha256 algorithm
|
||||
///
|
||||
/// ```
|
||||
/// use rs_merkle::{Hasher};
|
||||
/// use sha2::{Sha256, Digest, digest::FixedOutput};
|
||||
///
|
||||
/// #[derive(Clone)]
|
||||
/// pub struct Sha256Algorithm {}
|
||||
///
|
||||
/// impl Hasher for Sha256Algorithm {
|
||||
/// type Hash = [u8; 32];
|
||||
///
|
||||
/// fn hash(data: &Vec<u8>) -> [u8; 32] {
|
||||
/// let mut hasher = Sha256::new();
|
||||
///
|
||||
/// hasher.update(data);
|
||||
/// <[u8; 32]>::from(hasher.finalize_fixed())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait Hasher {
|
||||
type Hash: Copy + Into<Vec<u8>> + PartialEq + TryFrom<Vec<u8>>;
|
||||
/// This type is used as a hash type in the library.
|
||||
/// It is recommended to use fixed size u8 array as hash. For example,
|
||||
/// for sha256 the type would be `[u8; 32]`, representing 32 bytes,
|
||||
/// which is the size of sha256 digest. Also, fixed sized arrays of `u8`
|
||||
/// by default satisfy all trait bounds required by this type.
|
||||
///
|
||||
/// # Trait bounds
|
||||
/// `Copy` is required as the hash needs to be copied to be concatenated/propagated
|
||||
/// when constructing nodes.
|
||||
/// `PartialEq` is required to compare equality when verifying proof.
|
||||
/// `Into<Vec<u8>>` is required to be able to serialize proof.
|
||||
/// `TryFrom<Vec<u8>>` is required to parse hashes from a serialized proof.
|
||||
type Hash: Copy + PartialEq + Into<Vec<u8>> + TryFrom<Vec<u8>>;
|
||||
|
||||
/// This associated function takes arbitrary bytes and returns hash of it.
|
||||
/// Used by `concat_and_hash` function to build a tree from concatenated hashes
|
||||
fn hash(data: &Vec<u8>) -> Self::Hash;
|
||||
|
||||
fn hash_size() -> usize {
|
||||
mem::size_of::<Self::Hash>()
|
||||
}
|
||||
|
||||
// This is a default solidity implementation
|
||||
/// Used by `MerkleTree` and `MerkleProof` when calculating the root.
|
||||
/// The provided default implementation follows propagates left node if it doesn't
|
||||
/// have a sibling.
|
||||
///
|
||||
/// For the tree to be compatible with different types of proofs this function
|
||||
/// needs to be overridden. For example, in Bitcoin implementation,
|
||||
/// if the left node doesn't have a sibling it is concatenated to itself and
|
||||
/// then hashed instead of just being propagated to the next level.
|
||||
fn concat_and_hash(left: Option<&Self::Hash>, right: Option<&Self::Hash>) -> Self::Hash {
|
||||
let mut concatenated: Vec<u8> = left.expect("Left node should always be present, otherwise it's impossible to calculate hash").clone().into();
|
||||
|
||||
@@ -23,4 +64,11 @@ pub trait Hasher {
|
||||
None => left.unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the byte size of `Self::Hash`. Default implementation returns
|
||||
/// `mem::size_of::<Self::Hash>()`. Usually doesn't need to be overridden.
|
||||
/// Used internally by `MerkleProof` to parse hashes from a serialized proof.
|
||||
fn hash_size() -> usize {
|
||||
mem::size_of::<Self::Hash>()
|
||||
}
|
||||
}
|
||||
13
src/lib.rs
13
src/lib.rs
@@ -1,3 +1,11 @@
|
||||
//! Merkle Trees, also known as Hash Trees, are used to verify that two or more parties have
|
||||
//! the same data without exchanging the entire data collection.
|
||||
//!
|
||||
//! Merkle Trees are used in Git, Mercurial,ZFS, IPFS, Bitcoin, Ethereum, Cassandra and many more.
|
||||
//! In Git, for example, Merkle Trees are used to find a delta between the local and remote states,
|
||||
//! and transfer only the delta. In Bitcoin, Merkle Trees are used to verify that a transaction was
|
||||
//! included into the block without downloading the whole block contents.
|
||||
|
||||
pub use hasher::Hasher;
|
||||
pub use merkle_proof::MerkleProof;
|
||||
pub use merkle_tree::MerkleTree;
|
||||
@@ -6,6 +14,7 @@ mod merkle_tree;
|
||||
mod merkle_proof;
|
||||
mod hasher;
|
||||
|
||||
pub mod utils;
|
||||
mod error;
|
||||
pub mod algorithms;
|
||||
pub mod error;
|
||||
mod utils;
|
||||
|
||||
|
||||
@@ -5,42 +5,37 @@ use crate::{Hasher, utils};
|
||||
pub use crate::error::Error;
|
||||
pub use crate::error::ErrorKind;
|
||||
|
||||
/// `MerkleProof` is used to parse, verify, calculate a root for merkle proofs.
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
/// MerkleProof requires specifying hashing algorithm and hash size in order to work.
|
||||
/// Check out the `Hasher` trait for examples. rs_merkle provides some built in `Hasher`
|
||||
/// implementations, for example `rs_merkle::algorithms::Sha256`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rs_merkle::{MerkleProof, algorithms::Sha256};
|
||||
/// let proof_hashes: Vec<[u8; 32]> = vec![
|
||||
///
|
||||
/// ];
|
||||
///
|
||||
/// let proof = MerkleProof::<Sha256>::new(proof_hashes);
|
||||
///```
|
||||
pub struct MerkleProof<T: Hasher> {
|
||||
proof_hashes: Vec<T::Hash>,
|
||||
_hasher: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Hasher> MerkleProof<T> {
|
||||
/// MerkleProof requires specifying hashing algorithm and hash size in order to work.
|
||||
/// It uses Hasher trait from the crate to do that. An sha256 implementation of Hasher
|
||||
/// could look like this:
|
||||
/// ```
|
||||
/// use rs_merkle::Hasher;
|
||||
/// use sha2::{Sha256, Digest, digest::FixedOutput};
|
||||
///
|
||||
/// #[derive(Clone)]
|
||||
/// pub struct Sha256Hasher {}
|
||||
///
|
||||
/// impl Hasher for Sha256Hasher {
|
||||
/// // The size of sha256 is 32 bytes
|
||||
/// type Hash = [u8; 32];
|
||||
///
|
||||
/// fn hash(data: &Vec<u8>) -> [u8; 32] {
|
||||
/// let mut hasher = Sha256::new();
|
||||
///
|
||||
/// hasher.update(data);
|
||||
/// <[u8; 32]>::from(hasher.finalize_fixed())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn new(proof_hashes: Vec<T::Hash>) -> Self {
|
||||
MerkleProof {
|
||||
proof_hashes,
|
||||
_hasher: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses proof serialized as bytes
|
||||
///
|
||||
pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, Error> {
|
||||
let hash_size = T::hash_size();
|
||||
|
||||
@@ -68,6 +63,7 @@ impl<T: Hasher> MerkleProof<T> {
|
||||
Ok(Self::new(proof_hashes_slices))
|
||||
}
|
||||
|
||||
/// Returns
|
||||
pub fn proof_hashes(&self) -> &Vec<T::Hash> {
|
||||
&self.proof_hashes
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{utils, MerkleProof, Hasher};
|
||||
use crate::utils::indices::parent_indices;
|
||||
|
||||
/// `MerkleTree`
|
||||
#[derive(Clone)]
|
||||
pub struct MerkleTree<T: Hasher> {
|
||||
layers: Vec<Vec<T::Hash>>,
|
||||
@@ -26,15 +27,18 @@ impl<T: Hasher> MerkleTree<T> {
|
||||
tree
|
||||
}
|
||||
|
||||
/// Takes leaves (item hashes) as an argument and build a Merkle Tree from them
|
||||
pub fn new(leaves: &Vec<T::Hash>) -> Self {
|
||||
let layers = Self::build_tree(leaves);
|
||||
Self { layers }
|
||||
}
|
||||
|
||||
/// Returns Merkle tree root
|
||||
pub fn root(&self) -> Option<&T::Hash> {
|
||||
self.layers.last()?.first()
|
||||
}
|
||||
|
||||
/// Returns Merkle tree root serialized as a hex string
|
||||
pub fn hex_root(&self) -> Option<String> {
|
||||
let root = self.root()?;
|
||||
Some(utils::collections::to_hex_string(root))
|
||||
@@ -46,20 +50,14 @@ impl<T: Hasher> MerkleTree<T> {
|
||||
self.layers.len() - 1
|
||||
}
|
||||
|
||||
/// Proof consists of all siblings hashes that aren't in the set we're trying to prove
|
||||
///
|
||||
/// # Implementation
|
||||
///
|
||||
/// 1. Get all sibling indices. Those are the indices we need to get to the root
|
||||
/// 2. Filter all nodes that doesn't require an additional hash
|
||||
/// 3. Get all hashes for indices from step 2
|
||||
/// 4. Remove empty spaces (the leftmost nodes that do not have anything to the right)
|
||||
/// Returns merkle proof required to prove inclusion of items at given indices
|
||||
pub fn proof(&self, leaf_indices: &Vec<usize>) -> MerkleProof<T> {
|
||||
let mut current_layer_indices = leaf_indices.to_vec();
|
||||
let mut proof_hashes: Vec<T::Hash> = Vec::new();
|
||||
let mut proof_hashes = Vec::<T::Hash>::new();
|
||||
|
||||
for tree_layer in &self.layers {
|
||||
let siblings = utils::indices::sibling_indices(¤t_layer_indices);
|
||||
// Filter all nodes that do not require an additional hash to be calculated
|
||||
let proof_indices = utils::collections::difference(&siblings, ¤t_layer_indices);
|
||||
|
||||
for index in proof_indices {
|
||||
@@ -67,6 +65,8 @@ impl<T: Hasher> MerkleTree<T> {
|
||||
Some(hash) => {
|
||||
proof_hashes.push(hash.clone());
|
||||
},
|
||||
// This means that there's no right sibling to the current index, thus
|
||||
// we don't need to include anything in the proof for that index
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
@@ -78,14 +78,18 @@ impl<T: Hasher> MerkleTree<T> {
|
||||
proof
|
||||
}
|
||||
|
||||
/// Returns tree leaves, i.e. the bottom level
|
||||
pub fn leaves(&self) -> Option<&Vec<T::Hash>> {
|
||||
self.layers().first()
|
||||
}
|
||||
|
||||
/// Returns the whole tree, where the first layer is leaves and
|
||||
/// consequent layers are nodes.
|
||||
pub fn layers(&self) -> &Vec<Vec<T::Hash>> {
|
||||
&self.layers
|
||||
}
|
||||
|
||||
/// Same as `layers`, but serializes each hash as a hex string
|
||||
pub fn hex_layers(&self) -> Vec<Vec<String>> {
|
||||
self.layers()
|
||||
.iter()
|
||||
|
||||
@@ -2,9 +2,8 @@ fn byte_to_hex(byte: &u8) -> String {
|
||||
format!("{:02x}", byte)
|
||||
}
|
||||
|
||||
/// Serializes bytes into a hex string
|
||||
pub fn to_hex_string<T: Clone + Into<Vec<u8>>>(bytes: &T) -> String {
|
||||
// let keks: Vec<u8> = bytes.clone().into();
|
||||
|
||||
let hex_vec: Vec<String> = bytes.clone().into()
|
||||
.iter()
|
||||
.map(byte_to_hex)
|
||||
@@ -13,30 +12,9 @@ pub fn to_hex_string<T: Clone + Into<Vec<u8>>>(bytes: &T) -> String {
|
||||
hex_vec.join("")
|
||||
}
|
||||
|
||||
// IMPORTANT! This function doesn't use HashSet because for the tree
|
||||
// it is important to maintain original order
|
||||
pub fn difference(a: &Vec<usize>, b: &Vec<usize>) -> Vec<usize> {
|
||||
/// Find a difference between two vectors and return a third vector
|
||||
/// containing the difference. This function preserves the first
|
||||
/// vector order.
|
||||
pub fn difference<T: Clone + PartialEq>(a: &Vec<T>, b: &Vec<T>) -> Vec<T> {
|
||||
a.iter().cloned().filter(|x| !b.contains(x)).collect()
|
||||
}
|
||||
|
||||
fn combine<T: Clone>(active: Vec<T>, rest: Vec<T>, mut combinations: Vec<Vec<T>>) -> Vec<Vec<T>> {
|
||||
return if rest.is_empty() {
|
||||
if active.is_empty() {
|
||||
combinations
|
||||
} else {
|
||||
combinations.push(active);
|
||||
combinations
|
||||
}
|
||||
} else {
|
||||
let mut next = active.clone();
|
||||
next.push(rest.get(0).unwrap().clone());
|
||||
|
||||
combinations = combine(next, rest.clone().drain(1..).collect(), combinations);
|
||||
combinations = combine(active, rest.clone().drain(1..).collect(), combinations);
|
||||
combinations
|
||||
}
|
||||
}
|
||||
|
||||
pub fn combinations<T: Clone>(vec: Vec<T>) -> Vec<Vec<T>> {
|
||||
combine(Vec::new(), vec, Vec::new())
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
//! Utilities used internally to manipulate tree indices
|
||||
pub mod indices;
|
||||
pub mod collections;
|
||||
@@ -1,20 +1,5 @@
|
||||
use rayon::prelude::*;
|
||||
use rs_merkle::{Hasher, MerkleTree, utils};
|
||||
use sha2::{Sha256, Digest, digest::FixedOutput};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Sha256Hasher {}
|
||||
|
||||
impl Hasher for Sha256Hasher {
|
||||
type Hash = [u8; 32];
|
||||
|
||||
fn hash(data: &Vec<u8>) -> [u8; 32] {
|
||||
let mut hasher = Sha256::new();
|
||||
|
||||
hasher.update(data);
|
||||
<[u8; 32]>::from(hasher.finalize_fixed())
|
||||
}
|
||||
}
|
||||
use rs_merkle::{Hasher, MerkleTree, algorithms::Sha256};
|
||||
|
||||
pub struct TestData {
|
||||
pub leaf_values: Vec<String>,
|
||||
@@ -22,12 +7,35 @@ pub struct TestData {
|
||||
pub leaf_hashes: Vec<[u8; 32]>,
|
||||
}
|
||||
|
||||
fn combine<T: Clone>(active: Vec<T>, rest: Vec<T>, mut combinations: Vec<Vec<T>>) -> Vec<Vec<T>> {
|
||||
return if rest.is_empty() {
|
||||
if active.is_empty() {
|
||||
combinations
|
||||
} else {
|
||||
combinations.push(active);
|
||||
combinations
|
||||
}
|
||||
} else {
|
||||
let mut next = active.clone();
|
||||
next.push(rest.get(0).unwrap().clone());
|
||||
|
||||
combinations = combine(next, rest.clone().drain(1..).collect(), combinations);
|
||||
combinations = combine(active, rest.clone().drain(1..).collect(), combinations);
|
||||
combinations
|
||||
}
|
||||
}
|
||||
|
||||
/// Create all possible combinations of elements inside a vector without duplicates
|
||||
pub fn combinations<T: Clone>(vec: Vec<T>) -> Vec<Vec<T>> {
|
||||
combine(Vec::new(), vec, Vec::new())
|
||||
}
|
||||
|
||||
pub fn setup() -> TestData {
|
||||
let leaf_values = ["a", "b", "c", "d", "e", "f"];
|
||||
let expected_root_hex = "1f7379539707bcaea00564168d1d4d626b09b73f8a2a365234c62d763f854da2";
|
||||
let leaf_hashes = leaf_values
|
||||
.iter()
|
||||
.map(|x| Sha256Hasher::hash(x.as_bytes().to_vec().as_ref()))
|
||||
.map(|x| Sha256::hash(x.as_bytes().to_vec().as_ref()))
|
||||
.collect();
|
||||
|
||||
TestData {
|
||||
@@ -39,7 +47,7 @@ pub fn setup() -> TestData {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ProofTestCases {
|
||||
pub merkle_tree: MerkleTree<Sha256Hasher>,
|
||||
pub merkle_tree: MerkleTree<Sha256>,
|
||||
pub cases: Vec<MerkleProofTestCase>
|
||||
}
|
||||
|
||||
@@ -70,10 +78,10 @@ pub fn setup_proof_test_cases() -> Vec<ProofTestCases> {
|
||||
|
||||
let leaves: Vec<[u8; 32]> = tree_elements
|
||||
.iter()
|
||||
.map(|x| Sha256Hasher::hash(x.as_bytes().to_vec().as_ref()))
|
||||
.map(|x| Sha256::hash(x.as_bytes().to_vec().as_ref()))
|
||||
.collect();
|
||||
|
||||
let merkle_tree = MerkleTree::<Sha256Hasher>::new(&leaves);
|
||||
let merkle_tree = MerkleTree::<Sha256>::new(&leaves);
|
||||
|
||||
let indices = tree_elements
|
||||
.iter()
|
||||
@@ -81,7 +89,7 @@ pub fn setup_proof_test_cases() -> Vec<ProofTestCases> {
|
||||
.map(|(index, _)| index)
|
||||
.collect();
|
||||
|
||||
let possible_proof_index_combinations = utils::collections::combinations(indices);
|
||||
let possible_proof_index_combinations = combinations(indices);
|
||||
|
||||
let cases: Vec<MerkleProofTestCase> = possible_proof_index_combinations
|
||||
.par_iter()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
mod common;
|
||||
|
||||
pub mod root {
|
||||
use crate::{common, common::Sha256Hasher};
|
||||
use rs_merkle::{MerkleTree};
|
||||
use crate::common;
|
||||
use rs_merkle::{MerkleTree, algorithms::Sha256};
|
||||
use std::time::Instant;
|
||||
use rayon::prelude::*;
|
||||
|
||||
@@ -14,7 +14,7 @@ pub mod root {
|
||||
let indices_to_prove = vec![3, 4];
|
||||
let leaves_to_prove = indices_to_prove.iter().cloned().map(|i| leaf_hashes.get(i).unwrap().clone()).collect();
|
||||
|
||||
let merkle_tree = MerkleTree::<Sha256Hasher>::new(&test_data.leaf_hashes);
|
||||
let merkle_tree = MerkleTree::<Sha256>::new(&test_data.leaf_hashes);
|
||||
let proof = merkle_tree.proof(&indices_to_prove);
|
||||
let extracted_root = proof.hex_root(&indices_to_prove, &leaves_to_prove, test_data.leaf_values.len());
|
||||
|
||||
@@ -27,12 +27,12 @@ pub mod root {
|
||||
|
||||
let test_run_started = Instant::now();
|
||||
test_cases.par_iter().for_each(|test_case| {
|
||||
let merkle_tree = &test_case.merkle_tree;
|
||||
let merkle_tree = &test_case.merkle_tree;
|
||||
let root = merkle_tree.root().unwrap().clone();
|
||||
|
||||
test_case.cases.par_iter().for_each(|case| {
|
||||
let proof = merkle_tree.proof(&case.leaf_indices_to_prove);
|
||||
let root = merkle_tree.hex_root().unwrap();
|
||||
let extracted_root = proof.hex_root(&case.leaf_indices_to_prove, &case.leaf_hashes_to_prove, merkle_tree.leaves().unwrap().len());
|
||||
let extracted_root = proof.root(&case.leaf_indices_to_prove, &case.leaf_hashes_to_prove, merkle_tree.leaves().unwrap().len());
|
||||
|
||||
assert_eq!(extracted_root, root)
|
||||
});
|
||||
@@ -42,8 +42,8 @@ pub mod root {
|
||||
}
|
||||
|
||||
pub mod to_bytes {
|
||||
use crate::{common, common::Sha256Hasher};
|
||||
use rs_merkle::MerkleTree;
|
||||
use crate::common;
|
||||
use rs_merkle::{MerkleTree, algorithms::Sha256};
|
||||
|
||||
#[test]
|
||||
pub fn should_correctly_serialize_to_bytes() {
|
||||
@@ -60,7 +60,7 @@ pub mod to_bytes {
|
||||
|
||||
let test_data = common::setup();
|
||||
let indices_to_prove = vec![3, 4];
|
||||
let merkle_tree = MerkleTree::<Sha256Hasher>::new(&test_data.leaf_hashes);
|
||||
let merkle_tree = MerkleTree::<Sha256>::new(&test_data.leaf_hashes);
|
||||
let proof = merkle_tree.proof(&indices_to_prove);
|
||||
|
||||
let bytes = proof.to_bytes();
|
||||
@@ -70,8 +70,8 @@ pub mod to_bytes {
|
||||
}
|
||||
|
||||
pub mod from_bytes {
|
||||
use rs_merkle::MerkleProof;
|
||||
use crate::common::Sha256Hasher;
|
||||
use rs_merkle::{MerkleProof, algorithms::Sha256};
|
||||
use crate::common;
|
||||
|
||||
#[test]
|
||||
pub fn should_return_result_with_proof() {
|
||||
@@ -92,7 +92,7 @@ pub mod from_bytes {
|
||||
151, 121, 247, 157, 196, 163, 215, 233, 57, 99, 249, 74
|
||||
];
|
||||
|
||||
let proof = MerkleProof::<Sha256Hasher>::from_bytes(bytes).unwrap();
|
||||
let proof = MerkleProof::<Sha256>::from_bytes(bytes).unwrap();
|
||||
let hex_hashes = proof.hex_proof_hashes();
|
||||
|
||||
assert_eq!(hex_hashes, expected_proof_hashes);
|
||||
@@ -110,7 +110,7 @@ pub mod from_bytes {
|
||||
72, 113, 79, 34, 24, 15, 37, 173, 131, 101, 181, 63,
|
||||
];
|
||||
|
||||
let err = MerkleProof::<Sha256Hasher>::from_bytes(bytes).err().unwrap();
|
||||
let err = MerkleProof::<Sha256>::from_bytes(bytes).err().unwrap();
|
||||
|
||||
assert_eq!(err.message(), "Proof of size 84 bytes can not be divided into chunks of 32 bytes");
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
mod common;
|
||||
|
||||
pub mod root {
|
||||
use crate::{common, common::Sha256Hasher};
|
||||
use rs_merkle::{MerkleTree};
|
||||
use crate::common;
|
||||
use rs_merkle::{MerkleTree, algorithms::Sha256};
|
||||
|
||||
#[test]
|
||||
pub fn should_return_a_correct_root() {
|
||||
let test_data = common::setup();
|
||||
|
||||
let merkle_tree = MerkleTree::<Sha256Hasher>::new(&test_data.leaf_hashes);
|
||||
let merkle_tree = MerkleTree::<Sha256>::new(&test_data.leaf_hashes);
|
||||
let hex_root = merkle_tree.hex_root().unwrap();
|
||||
|
||||
assert_eq!(hex_root, test_data.expected_root_hex);
|
||||
@@ -16,14 +16,14 @@ pub mod root {
|
||||
}
|
||||
|
||||
pub mod tree_depth {
|
||||
use crate::{common, common::Sha256Hasher};
|
||||
use rs_merkle::MerkleTree;
|
||||
use crate::common;
|
||||
use rs_merkle::{MerkleTree, algorithms::Sha256};
|
||||
|
||||
#[test]
|
||||
pub fn should_return_a_correct_tree_depth() {
|
||||
let test_data = common::setup();
|
||||
|
||||
let merkle_tree = MerkleTree::<Sha256Hasher>::new(&test_data.leaf_hashes);
|
||||
let merkle_tree = MerkleTree::<Sha256>::new(&test_data.leaf_hashes);
|
||||
|
||||
let depth = merkle_tree.depth();
|
||||
assert_eq!(depth, 3)
|
||||
@@ -31,8 +31,8 @@ pub mod tree_depth {
|
||||
}
|
||||
|
||||
pub mod proof {
|
||||
use crate::{common, common::Sha256Hasher};
|
||||
use rs_merkle::MerkleTree;
|
||||
use crate::common;
|
||||
use rs_merkle::{MerkleTree, algorithms::Sha256};
|
||||
|
||||
#[test]
|
||||
pub fn should_return_a_correct_proof() {
|
||||
@@ -44,7 +44,7 @@ pub mod proof {
|
||||
"e5a01fee14e0ed5c48714f22180f25ad8365b53f9779f79dc4a3d7e93963f94a",
|
||||
];
|
||||
|
||||
let merkle_tree = MerkleTree::<Sha256Hasher>::new(&test_data.leaf_hashes);
|
||||
let merkle_tree = MerkleTree::<Sha256>::new(&test_data.leaf_hashes);
|
||||
let proof = merkle_tree.proof(&indices_to_prove);
|
||||
let proof_hashes = proof.hex_proof_hashes();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user