mirror of
https://github.com/mii443/merkle.rs.git
synced 2025-08-22 16:05:30 +00:00
Port to ring. (#15)
This commit is contained in:
committed by
Frederic Jacobs
parent
e621241f2f
commit
4503258724
@ -14,7 +14,7 @@ homepage = "https://github.com/SpinResearch/merkle.rs"
|
||||
repository = "https://github.com/SpinResearch/merkle.rs"
|
||||
|
||||
[dependencies]
|
||||
rust-crypto = "^0.2.36"
|
||||
ring = "0.6.0-alpha"
|
||||
protobuf = { version = "^1.0.0", optional = true }
|
||||
|
||||
[features]
|
||||
|
@ -6,17 +6,20 @@ extern crate test;
|
||||
extern crate rand;
|
||||
|
||||
extern crate merkle;
|
||||
extern crate crypto;
|
||||
extern crate ring;
|
||||
|
||||
use test::Bencher;
|
||||
use rand::Rng;
|
||||
|
||||
use ring::digest::{Algorithm, SHA512};
|
||||
|
||||
use merkle::MerkleTree;
|
||||
use crypto::sha3::Sha3;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
static digest: &'static Algorithm = &SHA512;
|
||||
|
||||
#[bench]
|
||||
fn bench_small_str_tree(b: &mut Bencher) {
|
||||
let digest = Sha3::sha3_256();
|
||||
let values = vec!["one", "two", "three", "four"];
|
||||
|
||||
b.iter(|| {
|
||||
@ -26,7 +29,6 @@ fn bench_small_str_tree(b: &mut Bencher) {
|
||||
|
||||
#[bench]
|
||||
fn bench_small_str_proof_gen(b: &mut Bencher) {
|
||||
let digest = Sha3::sha3_256();
|
||||
let values = vec!["one", "two", "three", "four"];
|
||||
let tree = MerkleTree::from_vec(digest, values.clone()).unwrap();
|
||||
|
||||
@ -40,7 +42,6 @@ fn bench_small_str_proof_gen(b: &mut Bencher) {
|
||||
|
||||
#[bench]
|
||||
fn bench_small_str_proof_check(b: &mut Bencher) {
|
||||
let digest = Sha3::sha3_256();
|
||||
let values = vec!["one", "two", "three", "four"];
|
||||
let tree = MerkleTree::from_vec(digest, values.clone()).unwrap();
|
||||
let proofs = values.iter().map(|v| tree.gen_proof(v).unwrap()).collect::<Vec<_>>();
|
||||
@ -54,7 +55,6 @@ fn bench_small_str_proof_check(b: &mut Bencher) {
|
||||
|
||||
#[bench]
|
||||
fn bench_big_rnd_tree(b: &mut Bencher) {
|
||||
let digest = Sha3::sha3_256();
|
||||
let mut values = vec![vec![0u8; 256]; 160];
|
||||
let mut rng = rand::IsaacRng::new_unseeded();
|
||||
|
||||
@ -69,7 +69,6 @@ fn bench_big_rnd_tree(b: &mut Bencher) {
|
||||
|
||||
#[bench]
|
||||
fn bench_big_rnd_proof_gen(b: &mut Bencher) {
|
||||
let digest = Sha3::sha3_256();
|
||||
let mut values = vec![vec![0u8; 256]; 160];
|
||||
let mut rng = rand::IsaacRng::new_unseeded();
|
||||
|
||||
@ -89,7 +88,6 @@ fn bench_big_rnd_proof_gen(b: &mut Bencher) {
|
||||
|
||||
#[bench]
|
||||
fn bench_big_rnd_proof_check(b: &mut Bencher) {
|
||||
let digest = Sha3::sha3_256();
|
||||
let mut values = vec![vec![0u8; 256]; 160];
|
||||
let mut rng = rand::IsaacRng::new_unseeded();
|
||||
|
||||
|
30
src/hashutils.rs
Normal file
30
src/hashutils.rs
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
use ring::digest::{ Algorithm, Context };
|
||||
|
||||
/// The sole purpose of this trait is to extend the standard
|
||||
/// `ring::algo::Algorithm` type with a couple utility functions.
|
||||
pub trait HashUtils {
|
||||
|
||||
/// Compute the hash the given byte array
|
||||
fn hash_bytes(&'static self, bytes: &[u8]) -> Vec<u8>;
|
||||
|
||||
/// Compute the hash of the concatenation of `left` and `right`
|
||||
fn combine_hashes(&'static self, left: &[u8], right: &[u8]) -> Vec<u8>;
|
||||
}
|
||||
|
||||
impl HashUtils for Algorithm {
|
||||
|
||||
fn hash_bytes(&'static self, bytes: &[u8]) -> Vec<u8> {
|
||||
let mut context = Context::new(self);
|
||||
context.update(bytes);
|
||||
context.finish().as_ref().into()
|
||||
}
|
||||
|
||||
fn combine_hashes(&'static self, left: &[u8], right: &[u8]) -> Vec<u8> {
|
||||
let mut context = Context::new(self);
|
||||
let combined = [left, right].concat();
|
||||
context.update(&combined);
|
||||
context.finish().as_ref().into()
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
//! *merkle* implements a Merkle Tree in Rust.
|
||||
|
||||
extern crate crypto;
|
||||
extern crate ring;
|
||||
|
||||
#[cfg(feature = "serialization-protobuf")]
|
||||
extern crate protobuf;
|
||||
@ -19,7 +19,7 @@ pub use merkletree::MerkleTree;
|
||||
mod proof;
|
||||
pub use proof::Proof;
|
||||
|
||||
mod merkledigest;
|
||||
mod hashutils;
|
||||
|
||||
mod tree;
|
||||
|
||||
|
@ -1,38 +0,0 @@
|
||||
use crypto::digest::Digest;
|
||||
|
||||
/// The sole purpose of this trait is to extend the standard
|
||||
/// `crypto::digest::Digest` with a couple utility functions.
|
||||
pub trait MerkleDigest {
|
||||
|
||||
/// Compute the hash the given byte array
|
||||
fn hash_bytes(&mut self, bytes: &[u8]) -> Vec<u8>;
|
||||
|
||||
/// Compute the hash of the concatenation of `left` and `right`
|
||||
fn combine_hashes(&mut self, left: &[u8], right: &[u8]) -> Vec<u8>;
|
||||
}
|
||||
|
||||
impl <D> MerkleDigest for D where D: Digest {
|
||||
|
||||
fn hash_bytes(&mut self, bytes: &[u8]) -> Vec<u8> {
|
||||
let mut hash = vec![0; self.output_bytes()];
|
||||
|
||||
self.reset();
|
||||
self.input(bytes);
|
||||
self.result(&mut hash);
|
||||
self.reset();
|
||||
|
||||
hash
|
||||
}
|
||||
|
||||
fn combine_hashes(&mut self, left: &[u8], right: &[u8]) -> Vec<u8> {
|
||||
let mut hash = vec![0; self.output_bytes()];
|
||||
|
||||
self.reset();
|
||||
self.input(left);
|
||||
self.input(right);
|
||||
self.result(&mut hash);
|
||||
self.reset();
|
||||
|
||||
hash
|
||||
}
|
||||
}
|
@ -1,18 +1,19 @@
|
||||
|
||||
use crypto::digest::Digest;
|
||||
use ring::digest::Algorithm;
|
||||
|
||||
use tree::Tree;
|
||||
use merkledigest::MerkleDigest;
|
||||
use hashutils::HashUtils;
|
||||
|
||||
use proof::{ Proof, Lemma };
|
||||
|
||||
/// A Merkle tree is a binary tree, with values of type `T` at the leafs,
|
||||
/// and where every node holds the hash of the concatenation of the hashes of
|
||||
/// its children nodes.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MerkleTree<D, T> {
|
||||
/// The hashing function used by this Merkle tree
|
||||
digest: D,
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MerkleTree<T> {
|
||||
|
||||
/// The hashing algorithm used by this Merkle tree
|
||||
pub algorithm: &'static Algorithm,
|
||||
|
||||
/// The root of the inner binary tree
|
||||
root: Tree<T>,
|
||||
@ -24,11 +25,11 @@ pub struct MerkleTree<D, T> {
|
||||
count: usize
|
||||
}
|
||||
|
||||
impl <D, T> MerkleTree<D, T> where D: Digest + Clone, T: Into<Vec<u8>> + Clone {
|
||||
impl <T> MerkleTree<T> where T: Into<Vec<u8>> + Clone {
|
||||
|
||||
/// Constructs a Merkle Tree from a vector of data blocks.
|
||||
/// Returns None if `values` is empty.
|
||||
pub fn from_vec(mut digest: D, values: Vec<T>) -> Option<Self> {
|
||||
pub fn from_vec(algo: &'static Algorithm, values: Vec<T>) -> Option<Self> {
|
||||
if values.is_empty() {
|
||||
return None
|
||||
}
|
||||
@ -38,7 +39,7 @@ impl <D, T> MerkleTree<D, T> where D: Digest + Clone, T: Into<Vec<u8>> + Clone {
|
||||
let mut cur = Vec::with_capacity(count);
|
||||
|
||||
for v in values {
|
||||
let leaf = Tree::make_leaf(&mut digest, v);
|
||||
let leaf = Tree::make_leaf(algo, v);
|
||||
cur.push(leaf);
|
||||
}
|
||||
|
||||
@ -52,7 +53,7 @@ impl <D, T> MerkleTree<D, T> where D: Digest + Clone, T: Into<Vec<u8>> + Clone {
|
||||
let left = cur.remove(0);
|
||||
let right = cur.remove(0);
|
||||
|
||||
let combined_hash = digest.combine_hashes(
|
||||
let combined_hash = algo.combine_hashes(
|
||||
left.hash(),
|
||||
right.hash()
|
||||
);
|
||||
@ -77,18 +78,13 @@ impl <D, T> MerkleTree<D, T> where D: Digest + Clone, T: Into<Vec<u8>> + Clone {
|
||||
let root = cur.remove(0);
|
||||
|
||||
Some(MerkleTree {
|
||||
digest: digest,
|
||||
algorithm: algo,
|
||||
root: root,
|
||||
height: height,
|
||||
count: count
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the hash function used in this Merkle tree
|
||||
pub fn digest(&self) -> &D {
|
||||
&self.digest
|
||||
}
|
||||
|
||||
/// Returns the root hash of Merkle tree
|
||||
pub fn root_hash(&self) -> &Vec<u8> {
|
||||
self.root.hash()
|
||||
@ -106,13 +102,12 @@ impl <D, T> MerkleTree<D, T> where D: Digest + Clone, T: Into<Vec<u8>> + Clone {
|
||||
|
||||
/// Generate an inclusion proof for the given value.
|
||||
/// Returns `None` if the given value is not found in the tree.
|
||||
pub fn gen_proof(&self, value: T) -> Option<Proof<D, T>> {
|
||||
let mut digest = self.digest.clone();
|
||||
pub fn gen_proof(&self, value: T) -> Option<Proof<T>> {
|
||||
let root_hash = self.root_hash().clone();
|
||||
let node_hash = digest.hash_bytes(&value.clone().into());
|
||||
let node_hash = self.algorithm.hash_bytes(&value.clone().into());
|
||||
|
||||
Lemma::new(&self.root, &node_hash).map(|lemma|
|
||||
Proof::new(digest, root_hash, lemma, value)
|
||||
Proof::new(self.algorithm, root_hash, lemma, value)
|
||||
)
|
||||
}
|
||||
|
||||
|
38
src/proof.rs
38
src/proof.rs
@ -1,16 +1,16 @@
|
||||
|
||||
use crypto::digest::Digest;
|
||||
use ring::digest::Algorithm;
|
||||
|
||||
use tree::Tree;
|
||||
use merkledigest::MerkleDigest;
|
||||
use hashutils::HashUtils;
|
||||
|
||||
/// An inclusion proof represent the fact that a `value` is a member
|
||||
/// of a `MerkleTree` with root hash `root_hash`, and hash function `digest`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Proof<D, T> {
|
||||
pub struct Proof<T> {
|
||||
|
||||
/// The hash function used in the original `MerkleTree`
|
||||
pub digest: D,
|
||||
/// The hashing algorithm used in the original `MerkleTree`
|
||||
pub algorithm: &'static Algorithm,
|
||||
|
||||
/// The hash of the root of the original `MerkleTree`
|
||||
pub root_hash: Vec<u8>,
|
||||
@ -22,12 +22,12 @@ pub struct Proof<D, T> {
|
||||
pub value: T
|
||||
}
|
||||
|
||||
impl <D, T> Proof<D, T> {
|
||||
impl <T> Proof<T> {
|
||||
|
||||
/// Constructs a new `Proof`
|
||||
pub fn new(digest: D, root_hash: Vec<u8>, lemma: Lemma, value: T) -> Self {
|
||||
pub fn new(algo: &'static Algorithm, root_hash: Vec<u8>, lemma: Lemma, value: T) -> Self {
|
||||
Proof {
|
||||
digest: digest,
|
||||
algorithm: algo,
|
||||
root_hash: root_hash,
|
||||
lemma: lemma,
|
||||
value: value
|
||||
@ -36,15 +36,15 @@ impl <D, T> Proof<D, T> {
|
||||
|
||||
/// Checks whether this inclusion proof is well-formed,
|
||||
/// and whether its root hash matches the given `root_hash`.
|
||||
pub fn validate(&self, root_hash: &[u8]) -> bool where D: Digest + Clone {
|
||||
pub fn validate(&self, root_hash: &[u8]) -> bool {
|
||||
if self.root_hash != root_hash || self.lemma.node_hash != root_hash {
|
||||
return false
|
||||
}
|
||||
|
||||
self.validate_lemma(&self.lemma, &mut self.digest.clone())
|
||||
self.validate_lemma(&self.lemma)
|
||||
}
|
||||
|
||||
fn validate_lemma(&self, lemma: &Lemma, digest: &mut D) -> bool where D: Digest {
|
||||
fn validate_lemma(&self, lemma: &Lemma) -> bool {
|
||||
match lemma.sub_lemma {
|
||||
|
||||
None =>
|
||||
@ -56,13 +56,13 @@ impl <D, T> Proof<D, T> {
|
||||
false,
|
||||
|
||||
Some(Positioned::Left(ref hash)) => {
|
||||
let hashes_match = digest.combine_hashes(hash, &sub.node_hash) == lemma.node_hash;
|
||||
hashes_match && self.validate_lemma(sub, digest)
|
||||
let hashes_match = self.algorithm.combine_hashes(hash, &sub.node_hash) == lemma.node_hash;
|
||||
hashes_match && self.validate_lemma(sub)
|
||||
}
|
||||
|
||||
Some(Positioned::Right(ref hash)) => {
|
||||
let hashes_match = digest.combine_hashes(&sub.node_hash, hash) == lemma.node_hash;
|
||||
hashes_match && self.validate_lemma(sub, digest)
|
||||
let hashes_match = self.algorithm.combine_hashes(&sub.node_hash, hash) == lemma.node_hash;
|
||||
hashes_match && self.validate_lemma(sub)
|
||||
}
|
||||
|
||||
}
|
||||
@ -85,7 +85,9 @@ pub struct Lemma {
|
||||
impl Lemma {
|
||||
|
||||
/// Attempts to generate a proof that the a value with hash `needle` is a member of the given `tree`.
|
||||
pub fn new<T>(tree: &Tree<T>, needle: &[u8]) -> Option<Lemma> where T: Into<Vec<u8>> + Clone {
|
||||
pub fn new<T>(tree: &Tree<T>, needle: &[u8]) -> Option<Lemma>
|
||||
where T: Into<Vec<u8>> + Clone {
|
||||
|
||||
match *tree {
|
||||
Tree::Leaf { ref hash, .. } =>
|
||||
Lemma::new_leaf_proof(hash, needle),
|
||||
@ -107,7 +109,9 @@ impl Lemma {
|
||||
}
|
||||
}
|
||||
|
||||
fn new_tree_proof<T>(hash: &[u8], needle: &[u8], left: &Tree<T>, right: &Tree<T>) -> Option<Lemma> where T: Into<Vec<u8>> + Clone {
|
||||
fn new_tree_proof<T>(hash: &[u8], needle: &[u8], left: &Tree<T>, right: &Tree<T>) -> Option<Lemma>
|
||||
where T: Into<Vec<u8>> + Clone {
|
||||
|
||||
Lemma::new(left, needle)
|
||||
.map(|lemma| {
|
||||
let right_hash = right.hash().clone();
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
mod proof;
|
||||
|
||||
use ring::digest::Algorithm;
|
||||
|
||||
use proof::{ Proof, Lemma, Positioned };
|
||||
pub use self::proof::{ ProofProto, LemmaProto };
|
||||
|
||||
@ -8,13 +10,13 @@ use protobuf::Message;
|
||||
use protobuf::error::ProtobufResult;
|
||||
use protobuf::core::parse_from_bytes;
|
||||
|
||||
impl <D, T> Proof<D, T> {
|
||||
impl <T> Proof<T> {
|
||||
|
||||
/// Constructs a `Proof` struct from its Protobuf representation.
|
||||
pub fn from_protobuf(digest: D, proto: ProofProto) -> Option<Self>
|
||||
pub fn from_protobuf(algorithm: &'static Algorithm, proto: ProofProto) -> Option<Self>
|
||||
where T: From<Vec<u8>>
|
||||
{
|
||||
proto.into_proof(digest)
|
||||
proto.into_proof(algorithm)
|
||||
}
|
||||
|
||||
/// Encode this `Proof` to its Protobuf representation.
|
||||
@ -25,10 +27,10 @@ impl <D, T> Proof<D, T> {
|
||||
}
|
||||
|
||||
/// Parse a `Proof` from its Protobuf binary representation.
|
||||
pub fn parse_from_bytes(bytes: &[u8], digest: D) -> ProtobufResult<Option<Proof<D, T>>>
|
||||
pub fn parse_from_bytes(bytes: &[u8], algorithm: &'static Algorithm) -> ProtobufResult<Option<Self>>
|
||||
where T: From<Vec<u8>>
|
||||
{
|
||||
parse_from_bytes::<ProofProto>(bytes).map(|proto| proto.into_proof(digest))
|
||||
parse_from_bytes::<ProofProto>(bytes).map(|proto| proto.into_proof(algorithm))
|
||||
}
|
||||
|
||||
/// Serialize this `Proof` with Protobuf.
|
||||
@ -40,7 +42,7 @@ impl <D, T> Proof<D, T> {
|
||||
|
||||
impl ProofProto {
|
||||
|
||||
pub fn from_proof<D, T>(proof: Proof<D, T>) -> Self
|
||||
pub fn from_proof<T>(proof: Proof<T>) -> Self
|
||||
where T: Into<Vec<u8>>
|
||||
{
|
||||
let mut proto = Self::new();
|
||||
@ -56,7 +58,7 @@ impl ProofProto {
|
||||
proto
|
||||
}
|
||||
|
||||
pub fn into_proof<D, T>(mut self, digest: D) -> Option<Proof<D, T>>
|
||||
pub fn into_proof<T>(mut self, algorithm: &'static Algorithm) -> Option<Proof<T>>
|
||||
where T: From<Vec<u8>>
|
||||
{
|
||||
if !self.has_root_hash() || !self.has_lemma() {
|
||||
@ -65,7 +67,7 @@ impl ProofProto {
|
||||
|
||||
self.take_lemma().into_lemma().map(|lemma| {
|
||||
Proof::new(
|
||||
digest,
|
||||
algorithm,
|
||||
self.take_root_hash(),
|
||||
lemma,
|
||||
self.take_value().into()
|
||||
|
64
src/tests.rs
64
src/tests.rs
@ -1,16 +1,17 @@
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use crypto::sha3::Sha3;
|
||||
use ring::digest::{ Algorithm, SHA512 };
|
||||
|
||||
use merkletree::MerkleTree;
|
||||
use merkledigest::MerkleDigest;
|
||||
use hashutils::HashUtils;
|
||||
use proof::Positioned;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
static digest: &'static Algorithm = &SHA512;
|
||||
|
||||
#[test]
|
||||
fn test_from_str_vec() {
|
||||
let mut digest = Sha3::sha3_256();
|
||||
|
||||
let values = vec!["one", "two", "three", "four"];
|
||||
|
||||
let hashes = vec![
|
||||
@ -21,7 +22,7 @@ fn test_from_str_vec() {
|
||||
];
|
||||
|
||||
let count = values.len();
|
||||
let tree = MerkleTree::from_vec(Sha3::sha3_256(), values).unwrap();
|
||||
let tree = MerkleTree::from_vec(digest, values).unwrap();
|
||||
|
||||
let h01 = digest.combine_hashes(&hashes[0], &hashes[1]);
|
||||
let h23 = digest.combine_hashes(&hashes[2], &hashes[3]);
|
||||
@ -38,16 +39,15 @@ fn test_from_str_vec() {
|
||||
#[should_panic]
|
||||
fn test_from_vec_empty() {
|
||||
let values: Vec<Vec<u8>> = vec![];
|
||||
MerkleTree::from_vec(Sha3::sha3_256(), values).unwrap();
|
||||
MerkleTree::from_vec(digest, values).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_vec1() {
|
||||
let values = vec!["hello, world".to_string()];
|
||||
let tree = MerkleTree::from_vec(Sha3::sha3_256(), values).unwrap();
|
||||
let tree = MerkleTree::from_vec(digest, values).unwrap();
|
||||
|
||||
let mut d = Sha3::sha3_256();
|
||||
let root_hash = &d.hash_bytes(&"hello, world".as_bytes());
|
||||
let root_hash = &digest.hash_bytes(&"hello, world".as_bytes());
|
||||
|
||||
assert_eq!(tree.count(), 1);
|
||||
assert_eq!(tree.height(), 0);
|
||||
@ -58,19 +58,17 @@ fn test_from_vec1() {
|
||||
#[test]
|
||||
fn test_from_vec3() {
|
||||
let values = vec![vec![1], vec![2], vec![3]];
|
||||
let tree = MerkleTree::from_vec(Sha3::sha3_256(), values).unwrap();
|
||||
|
||||
let mut d = Sha3::sha3_256();
|
||||
let tree = MerkleTree::from_vec(digest, values).unwrap();
|
||||
|
||||
let hashes = vec![
|
||||
d.hash_bytes(&vec![1]),
|
||||
d.hash_bytes(&vec![2]),
|
||||
d.hash_bytes(&vec![3])
|
||||
digest.hash_bytes(&vec![1]),
|
||||
digest.hash_bytes(&vec![2]),
|
||||
digest.hash_bytes(&vec![3])
|
||||
];
|
||||
|
||||
let h01 = &d.combine_hashes(&hashes[0], &hashes[1]);
|
||||
let h01 = &digest.combine_hashes(&hashes[0], &hashes[1]);
|
||||
let h2 = &hashes[2];
|
||||
let root_hash = &d.combine_hashes(h01, h2);
|
||||
let root_hash = &digest.combine_hashes(h01, h2);
|
||||
|
||||
assert_eq!(tree.count(), 3);
|
||||
assert_eq!(tree.height(), 2);
|
||||
@ -80,22 +78,20 @@ fn test_from_vec3() {
|
||||
#[test]
|
||||
fn test_from_vec9() {
|
||||
let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
|
||||
let tree = MerkleTree::from_vec(Sha3::sha3_256(), values.clone()).unwrap();
|
||||
let tree = MerkleTree::from_vec(digest, values.clone()).unwrap();
|
||||
|
||||
let mut d = Sha3::sha3_256();
|
||||
let hashes = values.iter().map(|v| digest.hash_bytes(v)).collect::<Vec<_>>();
|
||||
|
||||
let hashes = values.iter().map(|v| d.hash_bytes(v)).collect::<Vec<_>>();
|
||||
|
||||
let h01 = &d.combine_hashes(&hashes[0], &hashes[1]);
|
||||
let h23 = &d.combine_hashes(&hashes[2], &hashes[3]);
|
||||
let h45 = &d.combine_hashes(&hashes[4], &hashes[5]);
|
||||
let h67 = &d.combine_hashes(&hashes[6], &hashes[7]);
|
||||
let h01 = digest.combine_hashes(&hashes[0], &hashes[1]);
|
||||
let h23 = digest.combine_hashes(&hashes[2], &hashes[3]);
|
||||
let h45 = digest.combine_hashes(&hashes[4], &hashes[5]);
|
||||
let h67 = digest.combine_hashes(&hashes[6], &hashes[7]);
|
||||
let h8 = &hashes[8];
|
||||
let h0123 = &d.combine_hashes(h01, h23);
|
||||
let h4567 = &d.combine_hashes(h45, h67);
|
||||
let h1to7 = &d.combine_hashes(h0123, h4567);
|
||||
let h0123 = digest.combine_hashes(&h01, &h23);
|
||||
let h4567 = digest.combine_hashes(&h45, &h67);
|
||||
let h1to7 = digest.combine_hashes(&h0123, &h4567);
|
||||
|
||||
let root_hash = &d.combine_hashes(h1to7, h8);
|
||||
let root_hash = &digest.combine_hashes(&h1to7, &h8);
|
||||
|
||||
assert_eq!(tree.count(), 9);
|
||||
assert_eq!(tree.height(), 4);
|
||||
@ -105,7 +101,7 @@ fn test_from_vec9() {
|
||||
#[test]
|
||||
fn test_valid_proof() {
|
||||
let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
|
||||
let tree = MerkleTree::from_vec(Sha3::sha3_256(), values.clone()).unwrap();
|
||||
let tree = MerkleTree::from_vec(digest, values.clone()).unwrap();
|
||||
let root_hash = tree.root_hash();
|
||||
|
||||
for value in values {
|
||||
@ -119,7 +115,7 @@ fn test_valid_proof() {
|
||||
#[test]
|
||||
fn test_valid_proof_str() {
|
||||
let values = vec!["Hello", "my", "name", "is", "Rusty"];
|
||||
let tree = MerkleTree::from_vec(Sha3::sha3_256(), values.clone()).unwrap();
|
||||
let tree = MerkleTree::from_vec(digest, values.clone()).unwrap();
|
||||
let root_hash = tree.root_hash();
|
||||
|
||||
let value = "Rusty";
|
||||
@ -133,10 +129,10 @@ fn test_valid_proof_str() {
|
||||
#[test]
|
||||
fn test_wrong_proof() {
|
||||
let values1 = vec![vec![1], vec![2], vec![3], vec![4]];
|
||||
let tree1 = MerkleTree::from_vec(Sha3::sha3_256(), values1.clone()).unwrap();
|
||||
let tree1 = MerkleTree::from_vec(digest, values1.clone()).unwrap();
|
||||
|
||||
let values2 = vec![vec![4], vec![5], vec![6], vec![7]];
|
||||
let tree2 = MerkleTree::from_vec(Sha3::sha3_256(), values2.clone()).unwrap();
|
||||
let tree2 = MerkleTree::from_vec(digest, values2.clone()).unwrap();
|
||||
|
||||
let root_hash = tree2.root_hash();
|
||||
|
||||
@ -151,7 +147,7 @@ fn test_wrong_proof() {
|
||||
#[test]
|
||||
fn test_mutate_proof_first_lemma() {
|
||||
let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
|
||||
let tree = MerkleTree::from_vec(Sha3::sha3_256(), values.clone()).unwrap();
|
||||
let tree = MerkleTree::from_vec(digest, values.clone()).unwrap();
|
||||
let root_hash = tree.root_hash();
|
||||
|
||||
let mut i = 0;
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crypto::digest::Digest;
|
||||
|
||||
use merkledigest::MerkleDigest;
|
||||
use ring::digest::Algorithm;
|
||||
|
||||
use hashutils::HashUtils;
|
||||
|
||||
pub use proof::{
|
||||
Proof,
|
||||
@ -34,8 +35,8 @@ impl <T> Tree<T> where T: Into<Vec<u8>> + Clone {
|
||||
}
|
||||
|
||||
/// Create a new leaf
|
||||
pub fn make_leaf<D: Digest>(digest: &mut D, value: T) -> Tree<T> {
|
||||
let hash = digest.hash_bytes(&value.clone().into());
|
||||
pub fn make_leaf(algo: &'static Algorithm, value: T) -> Tree<T> {
|
||||
let hash = algo.hash_bytes(&value.clone().into());
|
||||
Tree::new(hash, value)
|
||||
}
|
||||
|
||||
|
@ -1,24 +1,27 @@
|
||||
|
||||
#![cfg(feature="serialization-protobuf")]
|
||||
|
||||
extern crate crypto;
|
||||
extern crate ring;
|
||||
extern crate merkle;
|
||||
extern crate protobuf;
|
||||
|
||||
use crypto::sha3::Sha3;
|
||||
use ring::digest::{ Algorithm, SHA512 };
|
||||
|
||||
use merkle::{ MerkleTree, Proof };
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
static digest: &'static Algorithm = &SHA512;
|
||||
|
||||
#[test]
|
||||
fn test_protobuf_inverse() {
|
||||
let digest = Sha3::sha3_256();
|
||||
let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
|
||||
|
||||
let tree = MerkleTree::from_vec(digest.clone(), values.clone()).unwrap();
|
||||
let tree = MerkleTree::from_vec(digest, values.clone()).unwrap();
|
||||
|
||||
for value in values {
|
||||
let proof = tree.gen_proof(value).unwrap();
|
||||
let bytes = proof.clone().write_to_bytes().unwrap();
|
||||
let res = Proof::<Sha3, Vec<u8>>::parse_from_bytes(&bytes, digest).unwrap().unwrap();
|
||||
let res = Proof::<Vec<u8>>::parse_from_bytes(&bytes, digest).unwrap().unwrap();
|
||||
|
||||
assert_eq!(proof.root_hash, res.root_hash);
|
||||
assert_eq!(proof.value, res.value);
|
||||
|
Reference in New Issue
Block a user