split into files

This commit is contained in:
dtsbourg
2016-11-11 16:26:39 +01:00
parent cb787aeec1
commit 9369ef3663
4 changed files with 173 additions and 148 deletions

View File

@ -2,154 +2,19 @@
#![allow(dead_code)]
pub extern crate crypto;
use crypto::digest::Digest;
pub trait Hashable {
fn to_bytes(&self) -> Vec<u8>;
}
mod tree;
pub use tree::{
Tree,
Hashable,
MerkleDigest,
};
pub trait MerkleDigest {
fn hash_bytes(&mut self, bytes: &Vec<u8>) -> Vec<u8>;
fn combine_hashes(&mut self, left: &Vec<u8>, right: &Vec<u8>) -> Vec<u8>;
}
impl <D> MerkleDigest for D where D: Digest {
fn hash_bytes(&mut self, bytes: &Vec<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: &Vec<u8>, right: &Vec<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
}
}
enum Tree<T> {
Leaf {
hash: Vec<u8>,
value: T
},
Node {
hash: Vec<u8>,
left: Box<Tree<T>>,
right: Box<Tree<T>>
}
}
impl <T> Tree<T> where T: Hashable {
fn new(hash: Vec<u8>, value: T) -> Self {
Tree::Leaf {
hash: hash,
value: value
}
}
fn get_hash(&self) -> &Vec<u8> {
match *self {
Tree::Leaf { ref hash, value: _ } => hash,
Tree::Node { ref hash, left: _, right: _ } => hash
}
}
}
fn make_leaf<D, T>(digest: &mut D, value: T) -> Tree<T> where D: Digest, T: Hashable {
let hash = digest.hash_bytes(&value.to_bytes());
Tree::new(hash, value)
}
pub struct MerkleTree<D, T> {
digest: D,
tree: Tree<T>,
height: usize,
count: usize
}
impl <D, T> MerkleTree<D, T> where D: Digest, T: Hashable {
pub fn from_vec(mut digest: D, values: Vec<T>) -> Self {
if values.is_empty() {
panic!("Cannot build a Merkle tree from an empty vector.");
}
let count = values.len();
let mut height = 0;
if count == 1 {
height = 1;
}
let mut cur = Vec::with_capacity(count);
for v in values.into_iter().rev() {
let leaf = make_leaf(&mut digest, v);
cur.push(leaf);
}
cur.reverse();
while cur.len() > 1 {
let mut next = Vec::new();
while cur.len() > 0 {
if cur.len() == 1 {
next.push(cur.remove(0));
}
else {
let left = cur.remove(0);
let right = cur.remove(0);
let combined_hash = digest.combine_hashes(
left.get_hash(),
right.get_hash()
);
let node = Tree::Node {
hash: combined_hash,
left: Box::new(left),
right: Box::new(right)
};
next.push(node);
}
}
height = height + 1;
cur = next;
}
assert!(cur.len() == 1);
let tree = cur.remove(0);
MerkleTree {
digest: digest,
tree: tree,
height: height,
count: count
}
}
fn root_hash(&self) -> &Vec<u8> {
self.tree.get_hash()
}
}
mod merkletree;
pub use merkletree::{
MerkleTree
};
#[cfg(test)]
mod tests;

83
src/merkletree.rs Normal file
View File

@ -0,0 +1,83 @@
extern crate crypto;
use crypto::digest::Digest;
pub use tree::{
Tree,
Hashable,
MerkleDigest,
};
pub struct MerkleTree<D, T> {
digest: D,
tree: Tree<T>,
pub height: usize,
pub count: usize
}
impl <D, T> MerkleTree<D, T> where D: Digest, T: Hashable {
pub fn from_vec(mut digest: D, values: Vec<T>) -> Self {
if values.is_empty() {
panic!("Cannot build a Merkle tree from an empty vector.");
}
let count = values.len();
let mut height = 0;
if count == 1 {
height = 1;
}
let mut cur = Vec::with_capacity(count);
for v in values.into_iter().rev() {
let leaf = Tree::make_leaf(&mut digest, v);
cur.push(leaf);
}
cur.reverse();
while cur.len() > 1 {
let mut next = Vec::new();
while cur.len() > 0 {
if cur.len() == 1 {
next.push(cur.remove(0));
}
else {
let left = cur.remove(0);
let right = cur.remove(0);
let combined_hash = digest.combine_hashes(
left.get_hash(),
right.get_hash()
);
let node = Tree::Node {
hash: combined_hash,
left: Box::new(left),
right: Box::new(right)
};
next.push(node);
}
}
height = height + 1;
cur = next;
}
assert!(cur.len() == 1);
let tree = cur.remove(0);
MerkleTree {
digest: digest,
tree: tree,
height: height,
count: count
}
}
pub fn root_hash(&self) -> &Vec<u8> {
self.tree.get_hash()
}
}

View File

@ -3,9 +3,14 @@
use crypto::sha3::Sha3;
use MerkleTree;
use MerkleDigest;
use Hashable;
use tree::{
Hashable,
MerkleDigest,
};
use merkletree::{
MerkleTree
};
impl Hashable for String {
fn to_bytes(&self) -> Vec<u8> {

72
src/tree.rs Normal file
View File

@ -0,0 +1,72 @@
extern crate crypto;
use crypto::digest::Digest;
pub trait Hashable {
fn to_bytes(&self) -> Vec<u8>;
}
pub enum Tree<T> {
Leaf {
hash: Vec<u8>,
value: T
},
Node {
hash: Vec<u8>,
left: Box<Tree<T>>,
right: Box<Tree<T>>
}
}
impl <T> Tree<T> where T: Hashable {
pub fn new(hash: Vec<u8>, value: T) -> Self {
Tree::Leaf {
hash: hash,
value: value
}
}
pub fn get_hash(&self) -> &Vec<u8> {
match *self {
Tree::Leaf { ref hash, value: _ } => hash,
Tree::Node { ref hash, left: _, right: _ } => hash
}
}
pub fn make_leaf<D: Digest>(digest: &mut D, value: T) -> Tree<T> {
let hash = digest.hash_bytes(&value.to_bytes());
Tree::new(hash, value)
}
}
pub trait MerkleDigest {
fn hash_bytes(&mut self, bytes: &Vec<u8>) -> Vec<u8>;
fn combine_hashes(&mut self, left: &Vec<u8>, right: &Vec<u8>) -> Vec<u8>;
}
impl <D> MerkleDigest for D where D: Digest {
fn hash_bytes(&mut self, bytes: &Vec<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: &Vec<u8>, right: &Vec<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
}
}