Implement efficient incremental merkle tree.
This commit is contained in:
parent
1267c8ec07
commit
c1fcd83329
|
@ -4,9 +4,8 @@ version = "0.1.0"
|
|||
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# [dependencies]
|
||||
# rand = "0.8"
|
||||
# typenum = "1.12"
|
||||
[dependencies]
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
proptest = "0.10"
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# Seeds for failure cases proptest has generated in the past. It is
|
||||
# automatically read and these particular cases re-run before any
|
||||
# novel cases are generated.
|
||||
#
|
||||
# It is recommended to check this file in to source control so that
|
||||
# everyone who runs the test benefits from these saved cases.
|
||||
cc 03d2e6d3f1b4481ff13703db7ae68090186d46f53b32b120ea7c8fd074d989bf # shrinks to ops = [Append(0)]
|
||||
cc a5db6c7b12d4e62269748d5de35ec6c1d9ecad60d40648e4b13e70e62fb9d4c6 # shrinks to ops = [Checkpoint, Rewind, Append(0)]
|
||||
cc 7db76fac780991d1809e66ea8313881b40942655d8acecd70a3764741aef061b # shrinks to ops = [Append(25), Witness, Authpath(25)]
|
||||
cc 25abc8160aaeb3e31332e11b939fee7fc8df15e84c75c115b2b9b0e301a01c35 # shrinks to ops = [Append("a"), Append("a"), Checkpoint, Append("a"), Witness, Rewind]
|
||||
cc 3aeb3f6da0d628f572f2c8eb0a96880f19ab6eabda0f755a2b7aa488857c5d05 # shrinks to ops = [Append("n"), Witness, Checkpoint, Append("n"), Witness, Rewind]
|
||||
cc 05d84777b24be0fec28e8863e270a8394c1c1ada96d09653fe863e6f1fe22cd5 # shrinks to ops = [Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("l"), Witness, Append("a"), Authpath("l")]
|
||||
cc 630bea6389a30231ca8a7bfbd52ff855ccb313e966683ad15e0e27c97fdb5812 # shrinks to ops = [Append("i"), Witness, Witness, Unwitness("i"), Unwitness("i")]
|
||||
cc e235eeed24a308c7bd63636148fba5f70b2b764147d97f7ad742ae0aab246f3e # shrinks to ops = [Append("k"), Witness, Checkpoint, Rewind, Append("a"), Append("a"), Append("a"), Append("a"), Witness, Append("a"), Append("a"), Append("a"), Authpath("k")]
|
||||
cc b2e8571f71e494c3a8f3eda094360ef35945b9761d2ec43eb1661abbc959b2d4 # shrinks to ops = [Append("a"), Checkpoint, Witness, Rewind]
|
||||
cc f363fe92d0b7071b8e1a72098c169b5a2ae62ebb99ff8d8b7d1fffd6907901d1 # shrinks to ops = [Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("a"), Append("p"), Witness, Append("u"), Witness, Append("x"), Append("h"), Authpath("p")]
|
1130
src/bridgetree.rs
1130
src/bridgetree.rs
File diff suppressed because it is too large
Load Diff
35
src/lib.rs
35
src/lib.rs
|
@ -24,13 +24,14 @@
|
|||
//! checkpoints that we're no longer interested in. It should be possible to
|
||||
//! roll back to any previous checkpoint.
|
||||
|
||||
pub mod sample;
|
||||
pub mod bridgetree;
|
||||
pub mod sample;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Add;
|
||||
use std::ops::Sub;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[repr(transparent)]
|
||||
pub struct Level(u32);
|
||||
|
||||
|
@ -150,21 +151,21 @@ pub(crate) mod tests {
|
|||
use std::hash::Hasher;
|
||||
use std::hash::SipHasher;
|
||||
|
||||
use super::bridgetree::{EfficientRecording, EfficientTree};
|
||||
use super::bridgetree::{BridgeRecording, BridgeTree};
|
||||
use super::sample::{lazy_root, CompleteRecording, CompleteTree};
|
||||
use super::{Hashable, Level, Recording, Tree};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CombinedTree<H: Hashable + Hash + Eq> {
|
||||
inefficient: CompleteTree<H>,
|
||||
bridgetree: EfficientTree<H>,
|
||||
efficient: BridgeTree<H>,
|
||||
}
|
||||
|
||||
impl<H: Hashable + Hash + Eq + Clone> CombinedTree<H> {
|
||||
pub fn new(depth: usize) -> Self {
|
||||
CombinedTree {
|
||||
inefficient: CompleteTree::new(depth, 100),
|
||||
bridgetree: EfficientTree::new(depth),
|
||||
efficient: BridgeTree::new(depth, 100),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +175,7 @@ pub(crate) mod tests {
|
|||
|
||||
fn append(&mut self, value: &H) -> bool {
|
||||
let a = self.inefficient.append(value);
|
||||
let b = self.bridgetree.append(value);
|
||||
let b = self.efficient.append(value);
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
@ -182,7 +183,7 @@ pub(crate) mod tests {
|
|||
/// Obtains the current root of this Merkle tree.
|
||||
fn root(&self) -> H {
|
||||
let a = self.inefficient.root();
|
||||
let b = self.bridgetree.root();
|
||||
let b = self.efficient.root();
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
@ -191,7 +192,7 @@ pub(crate) mod tests {
|
|||
/// witnessing. Returns true if successful and false if the tree is empty.
|
||||
fn witness(&mut self) -> bool {
|
||||
let a = self.inefficient.witness();
|
||||
let b = self.bridgetree.witness();
|
||||
let b = self.efficient.witness();
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
@ -201,7 +202,7 @@ pub(crate) mod tests {
|
|||
/// specified value.
|
||||
fn authentication_path(&self, value: &H) -> Option<(usize, Vec<H>)> {
|
||||
let a = self.inefficient.authentication_path(value);
|
||||
let b = self.bridgetree.authentication_path(value);
|
||||
let b = self.efficient.authentication_path(value);
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
@ -211,7 +212,7 @@ pub(crate) mod tests {
|
|||
/// false if the value is not a known witness.
|
||||
fn remove_witness(&mut self, value: &H) -> bool {
|
||||
let a = self.inefficient.remove_witness(value);
|
||||
let b = self.bridgetree.remove_witness(value);
|
||||
let b = self.efficient.remove_witness(value);
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
@ -220,7 +221,7 @@ pub(crate) mod tests {
|
|||
/// checkpoint.
|
||||
fn checkpoint(&mut self) {
|
||||
self.inefficient.checkpoint();
|
||||
self.bridgetree.checkpoint();
|
||||
self.efficient.checkpoint();
|
||||
}
|
||||
|
||||
/// Rewinds the tree state to the previous checkpoint. This function will
|
||||
|
@ -228,7 +229,7 @@ pub(crate) mod tests {
|
|||
/// witness data would be destroyed in the process.
|
||||
fn rewind(&mut self) -> bool {
|
||||
let a = self.inefficient.rewind();
|
||||
let b = self.bridgetree.rewind();
|
||||
let b = self.efficient.rewind();
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
@ -237,7 +238,7 @@ pub(crate) mod tests {
|
|||
fn recording(&self) -> CombinedRecording<H> {
|
||||
CombinedRecording {
|
||||
inefficient: self.inefficient.recording(),
|
||||
bridgetree: self.bridgetree.recording(),
|
||||
efficient: self.efficient.recording(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +246,7 @@ pub(crate) mod tests {
|
|||
/// and false if the recording is incompatible with the current tree state.
|
||||
fn play(&mut self, recording: &CombinedRecording<H>) -> bool {
|
||||
let a = self.inefficient.play(&recording.inefficient);
|
||||
let b = self.bridgetree.play(&recording.bridgetree);
|
||||
let b = self.efficient.play(&recording.efficient);
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
@ -254,20 +255,20 @@ pub(crate) mod tests {
|
|||
#[derive(Clone)]
|
||||
pub struct CombinedRecording<H: Hashable> {
|
||||
inefficient: CompleteRecording<H>,
|
||||
bridgetree: EfficientRecording<H>,
|
||||
efficient: BridgeRecording<H>,
|
||||
}
|
||||
|
||||
impl<H: Hashable + Clone + PartialEq> Recording<H> for CombinedRecording<H> {
|
||||
fn append(&mut self, value: &H) -> bool {
|
||||
let a = self.inefficient.append(value);
|
||||
let b = self.bridgetree.append(value);
|
||||
let b = self.efficient.append(value);
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
||||
fn play(&mut self, recording: &Self) -> bool {
|
||||
let a = self.inefficient.play(&recording.inefficient);
|
||||
let b = self.bridgetree.play(&recording.bridgetree);
|
||||
let b = self.efficient.play(&recording.efficient);
|
||||
assert_eq!(a, b);
|
||||
a
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue