Skip to content

refactor: implement append-only tree #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@ default = ["std"]
std = []
# SMT implemented in C
smtc = []
# A storage optimized SMT implemented in trie (https://ouvrard-pierre-alain.medium.com/sparse-merkle-tree-86e6e2fc26da)
trie = []

[dependencies]
cfg-if = "1"
blake2b-rs = "0.2"

[dev-dependencies]
proptest = "0.9"
criterion = "0.2"
criterion = "0.4"
rand = "0.8"
hex = "0.4.3"
serde = { version = "1.0", features = ["derive"] }
Expand Down
11 changes: 1 addition & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
default: fmt clippy clippy-trie test test-trie bench-test bench-test-trie check test-c-impl test-cxx-build
default: fmt clippy test bench-test check test-c-impl test-cxx-build

test:
cargo test --all --features std,smtc

test-trie:
cargo test --all --all-features

bench-test:
cargo bench -- --test

bench-test-trie:
cargo bench --features trie -- --test

clippy:
cargo clippy --all --features std,smtc --all-targets

clippy-trie:
cargo clippy --all --all-features --all-targets

fmt:
cargo fmt --all -- --check

Expand Down
57 changes: 30 additions & 27 deletions benches/smt_benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[macro_use]
extern crate criterion;

use criterion::Criterion;
use criterion::{BenchmarkId, Criterion};
use rand::{thread_rng, Rng};
use sparse_merkle_tree::{
blake2b::Blake2bHasher, default_store::DefaultStore, SparseMerkleTree, H256,
Expand Down Expand Up @@ -30,6 +30,7 @@ fn random_smt(update_count: usize, rng: &mut impl Rng) -> (SMT, Vec<H256>) {
(smt, keys)
}

#[allow(deprecated)]
fn random_smt_update_all(update_count: usize, rng: &mut impl Rng) {
let mut smt = SMT::default();
let mut kvs = Vec::with_capacity(update_count);
Expand All @@ -42,40 +43,42 @@ fn random_smt_update_all(update_count: usize, rng: &mut impl Rng) {
}

fn bench(c: &mut Criterion) {
c.bench_function_over_inputs(
"SMT update",
|b, &&size| {
b.iter(|| {
let mut rng = thread_rng();
random_smt(size, &mut rng)
});
},
&[100, 10_000],
);
for input in [100usize, 10000] {
c.bench_with_input(
BenchmarkId::new("SMT update_all", input),
&input,
|b, &size| {
b.iter(|| {
let mut rng = thread_rng();
random_smt(size, &mut rng)
});
},
);
}

c.bench_function_over_inputs(
"SMT update_all",
|b, &&size| {
b.iter(|| {
let mut rng = thread_rng();
random_smt_update_all(size, &mut rng)
});
},
&[100, 10_000],
);
for input in [100usize, 10000] {
c.bench_with_input(
BenchmarkId::new("SMT update_all", input),
&input,
|b, &size| {
b.iter(|| {
let mut rng = thread_rng();
random_smt_update_all(size, &mut rng)
});
},
);
}

c.bench_function_over_inputs(
"SMT get",
|b, &&size| {
for input in [5000usize, 10000] {
c.bench_with_input(BenchmarkId::new("SMT get", input), &input, |b, &size| {
let mut rng = thread_rng();
let (smt, _keys) = random_smt(size, &mut rng);
b.iter(|| {
let key = random_h256(&mut rng);
smt.get(&key).unwrap();
});
},
&[5_000, 10_000],
);
});
}

c.bench_function("SMT generate merkle proof", |b| {
let mut rng = thread_rng();
Expand Down
9 changes: 5 additions & 4 deletions benches/store_counter_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use sparse_merkle_tree::{
default_store::DefaultStore,
error::Error,
traits::{StoreReadOps, StoreWriteOps},
BranchKey, BranchNode, SparseMerkleTree, H256,
BranchNode, SparseMerkleTree, H256,
};

#[derive(Debug, Default)]
Expand All @@ -29,7 +29,7 @@ struct Counters {
}

impl<V: Clone> StoreReadOps<V> for DefaultStoreWithCounters<V> {
fn get_branch(&self, branch_key: &BranchKey) -> Result<Option<BranchNode>, Error> {
fn get_branch(&self, branch_key: &H256) -> Result<Option<BranchNode>, Error> {
self.counters
.get_branch_counter
.fetch_add(1, Ordering::SeqCst);
Expand All @@ -44,7 +44,7 @@ impl<V: Clone> StoreReadOps<V> for DefaultStoreWithCounters<V> {
}

impl<V> StoreWriteOps<V> for DefaultStoreWithCounters<V> {
fn insert_branch(&mut self, branch_key: BranchKey, branch: BranchNode) -> Result<(), Error> {
fn insert_branch(&mut self, branch_key: H256, branch: BranchNode) -> Result<(), Error> {
self.counters
.insert_branch_counter
.fetch_add(1, Ordering::SeqCst);
Expand All @@ -56,7 +56,7 @@ impl<V> StoreWriteOps<V> for DefaultStoreWithCounters<V> {
.fetch_add(1, Ordering::SeqCst);
self.store.insert_leaf(leaf_key, leaf)
}
fn remove_branch(&mut self, branch_key: &BranchKey) -> Result<(), Error> {
fn remove_branch(&mut self, branch_key: &H256) -> Result<(), Error> {
self.counters
.remove_branch_counter
.fetch_add(1, Ordering::SeqCst);
Expand Down Expand Up @@ -95,6 +95,7 @@ fn random_smt(update_count: usize, rng: &mut impl Rng) {
);
}

#[allow(deprecated)]
fn random_smt_update_all(update_count: usize, rng: &mut impl Rng) {
let mut smt = SMT::default();
let mut kvs = Vec::with_capacity(update_count);
Expand Down
8 changes: 0 additions & 8 deletions proptest-regressions/tests.txt

This file was deleted.

13 changes: 0 additions & 13 deletions proptest-regressions/tests/tree.txt

This file was deleted.

2 changes: 1 addition & 1 deletion src/ckb_smt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl SMTBuilder {
len: 0,
capacity: 0,
}),
_buffer: Vec::with_capacity(capacity as usize),
_buffer: Vec::with_capacity(capacity),
};
unsafe {
smt_state_init(smt.state.as_mut(), smt._buffer.as_ptr(), capacity as u32);
Expand Down
40 changes: 20 additions & 20 deletions src/default_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,53 @@ use crate::{
collections,
error::Error,
traits::{StoreReadOps, StoreWriteOps},
tree::{BranchKey, BranchNode},
tree::BranchNode,
H256,
};

#[derive(Debug, Clone, Default)]
pub struct DefaultStore<V> {
branches_map: Map<BranchKey, BranchNode>,
leaves_map: Map<H256, V>,
nodes: Map<H256, BranchNode>,
leaves: Map<H256, V>,
}

impl<V> DefaultStore<V> {
pub fn branches_map(&self) -> &Map<BranchKey, BranchNode> {
&self.branches_map
pub fn branches_map(&self) -> &Map<H256, BranchNode> {
&self.nodes
}
pub fn leaves_map(&self) -> &Map<H256, V> {
&self.leaves_map
&self.leaves
}
pub fn clear(&mut self) {
self.branches_map.clear();
self.leaves_map.clear();
self.nodes.clear();
self.leaves.clear();
}
}

impl<V: Clone> StoreReadOps<V> for DefaultStore<V> {
fn get_branch(&self, branch_key: &BranchKey) -> Result<Option<BranchNode>, Error> {
Ok(self.branches_map.get(branch_key).map(Clone::clone))
fn get_branch(&self, key: &H256) -> Result<Option<BranchNode>, Error> {
Ok(self.nodes.get(key).map(Clone::clone))
}
fn get_leaf(&self, leaf_key: &H256) -> Result<Option<V>, Error> {
Ok(self.leaves_map.get(leaf_key).map(Clone::clone))
fn get_leaf(&self, key: &H256) -> Result<Option<V>, Error> {
Ok(self.leaves.get(key).map(Clone::clone))
}
}

impl<V> StoreWriteOps<V> for DefaultStore<V> {
fn insert_branch(&mut self, branch_key: BranchKey, branch: BranchNode) -> Result<(), Error> {
self.branches_map.insert(branch_key, branch);
fn insert_branch(&mut self, key: H256, branch: BranchNode) -> Result<(), Error> {
self.nodes.insert(key, branch);
Ok(())
}
fn insert_leaf(&mut self, leaf_key: H256, leaf: V) -> Result<(), Error> {
self.leaves_map.insert(leaf_key, leaf);
fn insert_leaf(&mut self, key: H256, leaf: V) -> Result<(), Error> {
self.leaves.insert(key, leaf);
Ok(())
}
fn remove_branch(&mut self, branch_key: &BranchKey) -> Result<(), Error> {
self.branches_map.remove(branch_key);
fn remove_branch(&mut self, key: &H256) -> Result<(), Error> {
self.nodes.remove(key);
Ok(())
}
fn remove_leaf(&mut self, leaf_key: &H256) -> Result<(), Error> {
self.leaves_map.remove(leaf_key);
fn remove_leaf(&mut self, key: &H256) -> Result<(), Error> {
self.leaves.remove(key);
Ok(())
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/h256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl H256 {
pub fn set_bit(&mut self, i: u8) {
let byte_pos = i / BYTE_SIZE;
let bit_pos = i % BYTE_SIZE;
self.0[byte_pos as usize] |= 1 << bit_pos as u8;
self.0[byte_pos as usize] |= 1 << bit_pos;
}

#[inline]
Expand Down
7 changes: 1 addition & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,13 @@ pub mod merkle_proof;
mod tests;
pub mod traits;
mod tree;
#[cfg(feature = "trie")]
mod trie_tree;

#[cfg(feature = "smtc")]
pub use ckb_smt::{SMTBuilder, SMT};
pub use h256::H256;
pub use merkle_proof::{CompiledMerkleProof, MerkleProof};
#[cfg(not(feature = "trie"))]
pub use tree::BranchNode;
pub use tree::SparseMerkleTree;
pub use tree::{BranchKey, BranchNode};
#[cfg(feature = "trie")]
pub use trie_tree::SparseMerkleTree;

/// Expected path size: log2(256) * 2, used for hint vector capacity
pub const EXPECTED_PATH_SIZE: usize = 16;
Expand Down
Loading