Skip to content

Commit

Permalink
feat: Replace hasher trait with hasher crate. (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
yejiayu authored and mohanson committed Jul 3, 2019
1 parent 5eecc37 commit 7339d3d
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 77 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cita_trie"
version = "1.0.1"
version = "2.0.0"
authors = ["yejiayu <[email protected]>"]
description = "Modified Patricia Tree (aka Trie)."
license = "Apache-2.0"
Expand All @@ -14,8 +14,8 @@ documentation = "https://docs.rs/cita_trie"
[dependencies]
parking_lot = "0.8"
rlp = "0.3.0"
tiny-keccak = "1.4.2"
hashbrown = "0.3.0"
hasher = { version = "0.1", features = ["hash-keccak"] }

[dev-dependencies]
rand = "0.6.3"
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,28 @@ The implementation is strongly inspired by [go-ethereum trie](https://github.com
```rust
use std::sync::Arc;

use hasher::{Hasher, HasherKeccak}; // https://crates.io/crates/hasher

use cita_trie::MemoryDB;
use cita_trie::{PatriciaTrie, Trie};
use cita_trie::Keccak256Hash;

fn main() {
let memdb = Arc::new(MemoryDB::new(true));
let hahser = Arc::new(HasherKeccak::new());

let key = "test-key".as_bytes();
let value = "test-value".as_bytes();

let root = {
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::clone(&memdb));
let mut trie = PatriciaTrie::new(Arc::clone(&memdb), Arc::clone(&hasher));
trie.insert(key, value).unwrap();

let v = trie.get(key).unwrap();
assert_eq!(Some(value.to_vec()), v);
trie.root().unwrap()
};

let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::clone(&memdb));
let mut trie = PatriciaTrie::from(Arc::clone(&memdb), Arc::clone(&hasher), &root);
let exists = trie.contains(key).unwrap();
assert_eq!(exists, true);
let removed = trie.remove(key).unwrap();
Expand Down Expand Up @@ -96,8 +98,7 @@ Found 11 outliers among 100 measurements (11.00%)
```

### Custom hash algorithm

[Refer](https://github.com/cryptape/cita-trie/blob/master/src/lib.rs)
See: https://crates.io/crates/hasher

### Custom storage

Expand Down
68 changes: 68 additions & 0 deletions benches/insert_benchmark.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::sync::Arc;

use criterion::{criterion_group, criterion_main, Criterion};

use hasher::HasherKeccak;
use uuid::Uuid;

use cita_trie::MemoryDB;
use cita_trie::{PatriciaTrie, Trie};

fn insert_worse_case_benchmark(c: &mut Criterion) {
c.bench_function("cita-trie insert one", |b| {
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

b.iter(|| {
let key = Uuid::new_v4().as_bytes().to_vec();
let value = Uuid::new_v4().as_bytes().to_vec();
trie.insert(key, value).unwrap()
})
});

c.bench_function("cita-trie insert 1k", |b| {
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

let (keys, values) = random_data(1000);
b.iter(|| {
for i in 0..keys.len() {
trie.insert(keys[i].clone(), values[i].clone()).unwrap()
}
});
});

c.bench_function("cita-trie insert 10k", |b| {
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

let (keys, values) = random_data(10000);
b.iter(|| {
for i in 0..keys.len() {
trie.insert(keys[i].clone(), values[i].clone()).unwrap()
}
});
});
}

fn random_data(n: usize) -> (Vec<Vec<u8>>, Vec<Vec<u8>>) {
let mut keys = Vec::with_capacity(n);
let mut values = Vec::with_capacity(n);
for _ in 0..n {
let key = Uuid::new_v4().as_bytes().to_vec();
let value = Uuid::new_v4().as_bytes().to_vec();
keys.push(key);
values.push(value);
}

(keys, values)
}

criterion_group!(benches, insert_worse_case_benchmark);
criterion_main!(benches);
32 changes: 25 additions & 7 deletions benches/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ use std::sync::Arc;

use criterion::{criterion_group, criterion_main, Criterion};

use hasher::HasherKeccak;
use uuid::Uuid;

use cita_trie::Keccak256Hash;
use cita_trie::MemoryDB;
use cita_trie::{PatriciaTrie, Trie};

fn insert_worse_case_benchmark(c: &mut Criterion) {
c.bench_function("insert one", |b| {
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::new(MemoryDB::new(false)));
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

b.iter(|| {
let key = Uuid::new_v4().as_bytes().to_vec();
Expand All @@ -20,7 +23,10 @@ fn insert_worse_case_benchmark(c: &mut Criterion) {
});

c.bench_function("insert 1k", |b| {
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::new(MemoryDB::new(false)));
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

let (keys, values) = random_data(1000);
b.iter(|| {
Expand All @@ -31,7 +37,10 @@ fn insert_worse_case_benchmark(c: &mut Criterion) {
});

c.bench_function("insert 10k", |b| {
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::new(MemoryDB::new(false)));
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

let (keys, values) = random_data(10000);
b.iter(|| {
Expand All @@ -42,7 +51,10 @@ fn insert_worse_case_benchmark(c: &mut Criterion) {
});

c.bench_function("get based 10k", |b| {
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::new(MemoryDB::new(false)));
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

let (keys, values) = random_data(10000);
for i in 0..keys.len() {
Expand All @@ -56,7 +68,10 @@ fn insert_worse_case_benchmark(c: &mut Criterion) {
});

c.bench_function("remove 1k", |b| {
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::new(MemoryDB::new(false)));
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

let (keys, values) = random_data(1000);
for i in 0..keys.len() {
Expand All @@ -71,7 +86,10 @@ fn insert_worse_case_benchmark(c: &mut Criterion) {
});

c.bench_function("remove 10k", |b| {
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::new(MemoryDB::new(false)));
let mut trie = PatriciaTrie::new(
Arc::new(MemoryDB::new(false)),
Arc::new(HasherKeccak::new()),
);

let (keys, values) = random_data(10000);
for i in 0..keys.len() {
Expand Down
26 changes: 6 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,29 @@
//!
//! ```rust
//! use std::sync::Arc;
//!
//! use hasher::{Hasher, HasherKeccak}; // https://crates.io/crates/hasher
//!
//! use cita_trie::MemoryDB;
//! use cita_trie::{PatriciaTrie, Trie};
//! use cita_trie::Keccak256Hash;
//! fn main() {
//! let memdb = Arc::new(MemoryDB::new(true));
//! let hasher = Arc::new(HasherKeccak::new());
//!
//! let key = "test-key".as_bytes();
//! let value = "test-value".as_bytes();
//!
//! let root = {
//! let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::clone(&memdb));
//! let mut trie = PatriciaTrie::new(Arc::clone(&memdb), Arc::clone(&hasher));
//! trie.insert(key.to_vec(), value.to_vec()).unwrap();
//!
//! let v = trie.get(key).unwrap();
//! assert_eq!(Some(value.to_vec()), v);
//! trie.root().unwrap()
//! };
//!
//! let mut trie = PatriciaTrie::<_, Keccak256Hash>::from(Arc::clone(&memdb), &root).unwrap();
//! let mut trie = PatriciaTrie::from(Arc::clone(&memdb), Arc::clone(&hasher), &root).unwrap();
//! let exists = trie.contains(key).unwrap();
//! assert_eq!(exists, true);
//! let removed = trie.remove(key).unwrap();
Expand All @@ -44,19 +46,3 @@ mod trie;
pub use db::{MemoryDB, DB};
pub use errors::{MemDBError, TrieError};
pub use trie::{PatriciaTrie, Trie};

pub trait Hasher {
const LENGTH: usize;

fn digest(data: &[u8]) -> Vec<u8>;
}

pub struct Keccak256Hash;

impl Hasher for Keccak256Hash {
const LENGTH: usize = 32;

fn digest(data: &[u8]) -> Vec<u8> {
tiny_keccak::keccak256(data).to_vec()
}
}
16 changes: 9 additions & 7 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ mod trie_tests {
use rand::Rng;
use std::sync::Arc;

use hasher::HasherKeccak;

use crate::db::MemoryDB;
use crate::trie::{PatriciaTrie, Trie};
use crate::Keccak256Hash;

fn assert_root(data: Vec<(&[u8], &[u8])>, hash: &str) {
let memdb = Arc::new(MemoryDB::new(true));
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(Arc::clone(&memdb));
let mut trie = PatriciaTrie::new(Arc::clone(&memdb), Arc::new(HasherKeccak::new()));
for (k, v) in data.into_iter() {
trie.insert(k.to_vec(), v.to_vec()).unwrap();
}
let r = trie.root().unwrap();
let rs = format!("0x{}", hex::encode(r.clone()));
assert_eq!(rs.as_str(), hash);
let mut trie = PatriciaTrie::<_, Keccak256Hash>::from(Arc::clone(&memdb), &r).unwrap();
let mut trie =
PatriciaTrie::from(Arc::clone(&memdb), Arc::new(HasherKeccak::new()), &r).unwrap();
let r2 = trie.root().unwrap();
let rs2 = format!("0x{}", hex::encode(r2));
assert_eq!(rs2.as_str(), hash);
Expand Down Expand Up @@ -550,7 +552,7 @@ mod trie_tests {
#[test]
fn test_proof_basic() {
let memdb = Arc::new(MemoryDB::new(true));
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(memdb);
let mut trie = PatriciaTrie::new(Arc::clone(&memdb), Arc::new(HasherKeccak::new()));
trie.insert(b"doe".to_vec(), b"reindeer".to_vec()).unwrap();
trie.insert(b"dog".to_vec(), b"puppy".to_vec()).unwrap();
trie.insert(b"dogglesworth".to_vec(), b"cat".to_vec())
Expand Down Expand Up @@ -611,7 +613,7 @@ mod trie_tests {
#[test]
fn test_proof_random() {
let memdb = Arc::new(MemoryDB::new(true));
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(memdb);
let mut trie = PatriciaTrie::new(Arc::clone(&memdb), Arc::new(HasherKeccak::new()));
let mut rng = rand::thread_rng();
let mut keys = vec![];
for _ in 0..100 {
Expand All @@ -636,7 +638,7 @@ mod trie_tests {
#[test]
fn test_proof_empty_trie() {
let memdb = Arc::new(MemoryDB::new(true));
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(memdb);
let mut trie = PatriciaTrie::new(Arc::clone(&memdb), Arc::new(HasherKeccak::new()));
trie.root().unwrap();
let proof = trie.get_proof(b"not-exist").unwrap();
assert_eq!(proof.len(), 0);
Expand All @@ -645,7 +647,7 @@ mod trie_tests {
#[test]
fn test_proof_one_element() {
let memdb = Arc::new(MemoryDB::new(true));
let mut trie = PatriciaTrie::<_, Keccak256Hash>::new(memdb);
let mut trie = PatriciaTrie::new(Arc::clone(&memdb), Arc::new(HasherKeccak::new()));
trie.insert(b"k".to_vec(), b"v".to_vec()).unwrap();
let root = trie.root().unwrap();
let proof = trie.get_proof(b"k").unwrap();
Expand Down
Loading

0 comments on commit 7339d3d

Please sign in to comment.