Skip to content

Commit

Permalink
[triehash] Migrate to 2018 edition (#214)
Browse files Browse the repository at this point in the history
* Migrate triehash to 2018 edition

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* Update travis ci config

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* Improve if-else with iterator

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* Revert ci config

Signed-off-by: koushiro <koushiro.cqx@gmail.com>
  • Loading branch information
koushiro authored and dvdplm committed Sep 5, 2019
1 parent 63b6ee3 commit d272425
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 138 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ script:
- cd parity-util-mem/ && cargo test --features=jemalloc-global && cd ..
- cd parity-util-mem/ && cargo test --features=mimalloc-global && cd ..
- cd rlp/ && cargo test --no-default-features && cargo check --benches && cd ..
- cd triehash/ && cargo check --benches && cd ..
12 changes: 10 additions & 2 deletions triehash/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@ authors = ["Parity Technologies <admin@parity.io>"]
description = "In-memory patricia trie operations"
repository = "https://github.com/paritytech/parity-common"
license = "GPL-3.0"
edition = "2018"

[dependencies]
hash-db = "0.15"
rlp = { version = "0.4", path = "../rlp" }

[dev-dependencies]
criterion = "0.3"
keccak-hasher = "0.15"
tiny-keccak = "1.4.2"
ethereum-types = { version = "0.7", path = "../ethereum-types" }
tiny-keccak = "1.5"
trie-standardmap = "0.15"
hex-literal = "0.2"
ethereum-types = { version = "0.7", path = "../ethereum-types" }

[[bench]]
name = "triehash"
path = "benches/triehash.rs"
harness = false
169 changes: 72 additions & 97 deletions triehash/benches/triehash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

#![feature(test)]

extern crate ethereum_types;
extern crate keccak_hasher;
extern crate test;
extern crate tiny_keccak;
extern crate trie_standardmap;
extern crate triehash;

use criterion::{criterion_group, criterion_main, Criterion};
use ethereum_types::H256;
use keccak_hasher::KeccakHasher;
use test::Bencher;
use tiny_keccak::keccak256;
use trie_standardmap::{Alphabet, ValueMode, StandardMap};
use trie_standardmap::{Alphabet, StandardMap, ValueMode};
use triehash::trie_root;

fn random_word(alphabet: &[u8], min_count: usize, diff_count: usize, seed: &mut H256) -> Vec<u8> {
assert!(min_count + diff_count <= 32);
*seed = H256(keccak256(&seed));
*seed = H256(keccak256(seed.as_bytes()));
let r = min_count + (seed[31] as usize % (diff_count + 1));
let mut ret: Vec<u8> = Vec::with_capacity(r);
for i in 0..r {
Expand All @@ -43,107 +34,91 @@ fn random_word(alphabet: &[u8], min_count: usize, diff_count: usize, seed: &mut

fn random_bytes(min_count: usize, diff_count: usize, seed: &mut H256) -> Vec<u8> {
assert!(min_count + diff_count <= 32);
*seed = H256(keccak256(&seed));
*seed = H256(keccak256(seed.as_bytes()));
let r = min_count + (seed[31] as usize % (diff_count + 1));
seed[0..r].to_vec()
}

fn random_value(seed: &mut H256) -> Vec<u8> {
*seed = H256(keccak256(&seed));
*seed = H256(keccak256(seed.as_bytes()));
match seed[0] % 2 {
1 => vec![seed[31];1],
_ => seed.to_vec(),
_ => seed.as_bytes().to_vec(),
}
}

#[bench]
fn triehash_insertions_32_mir_1k(b: &mut Bencher) {
let st = StandardMap {
alphabet: Alphabet::All,
min_key: 32,
journal_key: 0,
value_mode: ValueMode::Mirror,
count: 1000,
};
let d = st.make();
b.iter(&mut ||{
let _ = trie_root::<KeccakHasher, _, _, _>(d.clone()).clone();
fn bench_insertions(c: &mut Criterion) {
c.bench_function("32_mir_1k", |b| {
let st = StandardMap {
alphabet: Alphabet::All,
min_key: 32,
journal_key: 0,
value_mode: ValueMode::Mirror,
count: 1000,
};
let d = st.make();
b.iter(|| trie_root::<KeccakHasher, _, _, _>(d.clone()));
});
}

#[bench]
fn triehash_insertions_32_ran_1k(b: &mut Bencher) {
let st = StandardMap {
alphabet: Alphabet::All,
min_key: 32,
journal_key: 0,
value_mode: ValueMode::Random,
count: 1000,
};
let d = st.make();
b.iter(&mut ||{
let _ = trie_root::<KeccakHasher, _, _, _>(d.clone()).clone();
c.bench_function("32_ran_1k", |b| {
let st = StandardMap {
alphabet: Alphabet::All,
min_key: 32,
journal_key: 0,
value_mode: ValueMode::Random,
count: 1000,
};
let d = st.make();
b.iter(|| trie_root::<KeccakHasher, _, _, _>(d.clone()));
});
}

#[bench]
fn triehash_insertions_six_high(b: &mut Bencher) {
let mut d: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut seed = H256::new();
for _ in 0..1000 {
let k = random_bytes(6, 0, &mut seed);
let v = random_value(&mut seed);
d.push((k, v))
}

b.iter(&||{
let _ = trie_root::<KeccakHasher, _, _, _>(d.clone());
})
}
c.bench_function("six_high", |b| {
let mut d: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut seed = H256::default();
for _ in 0..1000 {
let k = random_bytes(6, 0, &mut seed);
let v = random_value(&mut seed);
d.push((k, v))
}
b.iter(|| trie_root::<KeccakHasher, _, _, _>(d.clone()));
});

#[bench]
fn triehash_insertions_six_mid(b: &mut Bencher) {
let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
let mut d: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut seed = H256::new();
for _ in 0..1000 {
let k = random_word(alphabet, 6, 0, &mut seed);
let v = random_value(&mut seed);
d.push((k, v))
}
b.iter(||{
let _ = trie_root::<KeccakHasher, _, _, _>(d.clone());
})
}
c.bench_function("six_mid", |b| {
let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
let mut d: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut seed = H256::default();
for _ in 0..1000 {
let k = random_word(alphabet, 6, 0, &mut seed);
let v = random_value(&mut seed);
d.push((k, v))
}
b.iter(|| trie_root::<KeccakHasher, _, _, _>(d.clone()));
});

#[bench]
fn triehash_insertions_random_mid(b: &mut Bencher) {
let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
let mut d: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut seed = H256::new();
for _ in 0..1000 {
let k = random_word(alphabet, 1, 5, &mut seed);
let v = random_value(&mut seed);
d.push((k, v))
}
c.bench_function("random_mid", |b| {
let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
let mut d: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut seed = H256::default();
for _ in 0..1000 {
let k = random_word(alphabet, 1, 5, &mut seed);
let v = random_value(&mut seed);
d.push((k, v))
}
b.iter(|| trie_root::<KeccakHasher, _, _, _>(d.clone()));
});

b.iter(||{
let _ = trie_root::<KeccakHasher, _, _, _>(d.clone());
})
c.bench_function("six_low", |b| {
let alphabet = b"abcdef";
let mut d: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut seed = H256::default();
for _ in 0..1000 {
let k = random_word(alphabet, 6, 0, &mut seed);
let v = random_value(&mut seed);
d.push((k, v))
}
b.iter(|| trie_root::<KeccakHasher, _, _, _>(d.clone()));
});
}

#[bench]
fn triehash_insertions_six_low(b: &mut Bencher) {
let alphabet = b"abcdef";
let mut d: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut seed = H256::new();
for _ in 0..1000 {
let k = random_word(alphabet, 6, 0, &mut seed);
let v = random_value(&mut seed);
d.push((k, v))
}

b.iter(||{
let _ = trie_root::<KeccakHasher, _, _, _>(d.clone());
})
}
criterion_group!(benches, bench_insertions);
criterion_main!(benches);
72 changes: 33 additions & 39 deletions triehash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,10 @@
//!
//! This module should be used to generate trie root hash.

extern crate hash_db;
extern crate rlp;
#[cfg(test)]
extern crate keccak_hasher;
#[cfg(test)]
#[macro_use]
extern crate hex_literal;

use std::collections::BTreeMap;
use std::cmp;
use std::collections::BTreeMap;
use std::iter::once;

use hash_db::Hasher;
use rlp::RlpStream;

Expand Down Expand Up @@ -96,7 +89,6 @@ where
H: Hasher,
<H as hash_db::Hasher>::Out: cmp::Ord,
{

// first put elements into btree to sort them and to remove duplicates
let input = input
.into_iter()
Expand Down Expand Up @@ -240,20 +232,16 @@ where
stream.begin_list(17);

// if first key len is equal to prefix_len, move to next element
let mut begin = match pre_len == key.len() {
true => 1,
false => 0
};
let mut begin = if pre_len == key.len() { 1 } else { 0 };

// iterate over all possible nibbles
for i in 0..16 {
// count how many successive elements have same next nibble
let len = match begin < input.len() {
true => input[begin..].iter()
.take_while(| pair | pair.0.as_ref()[pre_len] == i )
.count(),
false => 0
};
let len = input
.iter()
.skip(begin)
.take_while(|pair| pair.0.as_ref()[pre_len] == i)
.count();

// if at least 1 successive element has the same nibble
// append their suffixes
Expand All @@ -265,10 +253,11 @@ where
}

// if fist key len is equal prefix, append its value
match pre_len == key.len() {
true => { stream.append(&value); },
false => { stream.append_empty_data(); }
};
if pre_len == key.len() {
stream.append(&value);
} else {
stream.append_empty_data();
}
}

fn hash256aux<H, A, B>(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream)
Expand All @@ -288,10 +277,10 @@ where

#[cfg(test)]
mod tests {
extern crate ethereum_types;
use super::{trie_root, shared_prefix_len, hex_prefix_encode};
use keccak_hasher::KeccakHasher;
use self::ethereum_types::H256;
use ethereum_types::H256;
use hex_literal::hex;

#[test]
fn test_hex_prefix_encode() {
Expand Down Expand Up @@ -328,23 +317,28 @@ mod tests {

#[test]
fn simple_test() {
assert_eq!(trie_root::<KeccakHasher, _, _, _>(vec![
(b"A", b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" as &[u8])
]), H256::from(hex!("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")).as_ref());
assert_eq!(
trie_root::<KeccakHasher, _, _, _>(vec![
(b"A", b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" as &[u8])
]),
H256::from(hex!("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")).as_ref(),
);
}

#[test]
fn test_triehash_out_of_order() {
assert!(trie_root::<KeccakHasher, _, _, _>(vec![
(vec![0x01u8, 0x23], vec![0x01u8, 0x23]),
(vec![0x81u8, 0x23], vec![0x81u8, 0x23]),
(vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]),
]) ==
trie_root::<KeccakHasher, _, _, _>(vec![
(vec![0x01u8, 0x23], vec![0x01u8, 0x23]),
(vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), // last two tuples are swapped
(vec![0x81u8, 0x23], vec![0x81u8, 0x23]),
]));
assert_eq!(
trie_root::<KeccakHasher, _, _, _>(vec![
(vec![0x01u8, 0x23], vec![0x01u8, 0x23]),
(vec![0x81u8, 0x23], vec![0x81u8, 0x23]),
(vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]),
]),
trie_root::<KeccakHasher, _, _, _>(vec![
(vec![0x01u8, 0x23], vec![0x01u8, 0x23]),
(vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), // last two tuples are swapped
(vec![0x81u8, 0x23], vec![0x81u8, 0x23]),
]),
);
}

#[test]
Expand Down

0 comments on commit d272425

Please sign in to comment.