combined tree
This commit is contained in:
parent
e80228fb18
commit
48507454f3
214
src/lib.rs
214
src/lib.rs
|
@ -25,12 +25,221 @@
|
||||||
//! roll back to any previous checkpoint.
|
//! roll back to any previous checkpoint.
|
||||||
|
|
||||||
pub trait TreeHasher {
|
pub trait TreeHasher {
|
||||||
type Digest: Clone + PartialEq;
|
type Digest: Clone + PartialEq + std::fmt::Debug;
|
||||||
|
|
||||||
fn empty_leaf() -> Self::Digest;
|
fn empty_leaf() -> Self::Digest;
|
||||||
fn combine(a: &Self::Digest, b: &Self::Digest) -> Self::Digest;
|
fn combine(a: &Self::Digest, b: &Self::Digest) -> Self::Digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct EfficientTree<H: TreeHasher> {
|
||||||
|
something: H::Digest
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: TreeHasher> EfficientTree<H> {
|
||||||
|
pub fn new(depth: usize) -> Self {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(&mut self, value: &H::Digest) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtains the current root of this Merkle tree.
|
||||||
|
pub fn root(&self) -> H::Digest {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marks the current tree state leaf as a value that we're interested in
|
||||||
|
/// witnessing. Returns true if successful and false if the tree is empty.
|
||||||
|
pub fn witness(&mut self) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtains an authentication path to the value specified in the tree.
|
||||||
|
/// Returns `None` if there is no available authentication path to the
|
||||||
|
/// specified value.
|
||||||
|
pub fn authentication_path(&self, value: &H::Digest) -> Option<(usize, Vec<H::Digest>)> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marks the specified tree state value as a value we're no longer
|
||||||
|
/// interested in maintaining a witness for. Returns true if successful and
|
||||||
|
/// false if the value is not a known witness.
|
||||||
|
pub fn remove_witness(&mut self, value: &H::Digest) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marks the current tree state as a checkpoint if it is not already a
|
||||||
|
/// checkpoint.
|
||||||
|
pub fn checkpoint(&mut self) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rewinds the tree state to the previous checkpoint. This function will
|
||||||
|
/// fail and return false if there is no previous checkpoint or in the event
|
||||||
|
/// witness data would be destroyed in the process.
|
||||||
|
pub fn rewind(&mut self) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the oldest checkpoint. Returns true if successful and false if
|
||||||
|
/// there are no checkpoints.
|
||||||
|
pub fn pop_checkpoint(&mut self) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start a recording of append operations performed on a tree.
|
||||||
|
pub fn recording(&self) -> EfficientRecording<H> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Plays a recording of append operations back. Returns true if successful
|
||||||
|
/// and false if the recording is incompatible with the current tree state.
|
||||||
|
pub fn play(&mut self, recording: &EfficientRecording<H>) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct EfficientRecording<H: TreeHasher> {
|
||||||
|
something: H::Digest
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: TreeHasher> EfficientRecording<H> {
|
||||||
|
pub fn append(&mut self, value: &H::Digest) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn play(&mut self, recording: &Self) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CombinedTree<H: TreeHasher> {
|
||||||
|
inefficient: Tree<H>,
|
||||||
|
efficient: EfficientTree<H>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: TreeHasher> CombinedTree<H> {
|
||||||
|
pub fn new(depth: usize) -> Self {
|
||||||
|
CombinedTree {
|
||||||
|
inefficient: Tree::new(depth),
|
||||||
|
efficient: EfficientTree::new(depth),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(&mut self, value: &H::Digest) -> bool {
|
||||||
|
let a = self.inefficient.append(value);
|
||||||
|
let b = self.efficient.append(value);
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtains the current root of this Merkle tree.
|
||||||
|
pub fn root(&self) -> H::Digest {
|
||||||
|
let a = self.inefficient.root();
|
||||||
|
let b = self.efficient.root();
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marks the current tree state leaf as a value that we're interested in
|
||||||
|
/// witnessing. Returns true if successful and false if the tree is empty.
|
||||||
|
pub fn witness(&mut self) -> bool {
|
||||||
|
let a = self.inefficient.witness();
|
||||||
|
let b = self.efficient.witness();
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtains an authentication path to the value specified in the tree.
|
||||||
|
/// Returns `None` if there is no available authentication path to the
|
||||||
|
/// specified value.
|
||||||
|
pub fn authentication_path(&self, value: &H::Digest) -> Option<(usize, Vec<H::Digest>)> {
|
||||||
|
let a = self.inefficient.authentication_path(value);
|
||||||
|
let b = self.efficient.authentication_path(value);
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marks the specified tree state value as a value we're no longer
|
||||||
|
/// interested in maintaining a witness for. Returns true if successful and
|
||||||
|
/// false if the value is not a known witness.
|
||||||
|
pub fn remove_witness(&mut self, value: &H::Digest) -> bool {
|
||||||
|
let a = self.inefficient.remove_witness(value);
|
||||||
|
let b = self.efficient.remove_witness(value);
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marks the current tree state as a checkpoint if it is not already a
|
||||||
|
/// checkpoint.
|
||||||
|
pub fn checkpoint(&mut self) {
|
||||||
|
self.inefficient.checkpoint();
|
||||||
|
self.efficient.checkpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rewinds the tree state to the previous checkpoint. This function will
|
||||||
|
/// fail and return false if there is no previous checkpoint or in the event
|
||||||
|
/// witness data would be destroyed in the process.
|
||||||
|
pub fn rewind(&mut self) -> bool {
|
||||||
|
let a = self.inefficient.rewind();
|
||||||
|
let b = self.efficient.rewind();
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the oldest checkpoint. Returns true if successful and false if
|
||||||
|
/// there are no checkpoints.
|
||||||
|
pub fn pop_checkpoint(&mut self) -> bool {
|
||||||
|
let a = self.inefficient.pop_checkpoint();
|
||||||
|
let b = self.efficient.pop_checkpoint();
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start a recording of append operations performed on a tree.
|
||||||
|
pub fn recording(&self) -> CombinedRecording<H> {
|
||||||
|
CombinedRecording {
|
||||||
|
inefficient: self.inefficient.recording(),
|
||||||
|
efficient: self.efficient.recording()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Plays a recording of append operations back. Returns true if successful
|
||||||
|
/// and false if the recording is incompatible with the current tree state.
|
||||||
|
pub fn play(&mut self, recording: &CombinedRecording<H>) -> bool {
|
||||||
|
let a = self.inefficient.play(&recording.inefficient);
|
||||||
|
let b = self.efficient.play(&recording.efficient);
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CombinedRecording<H: TreeHasher> {
|
||||||
|
inefficient: Recording<H>,
|
||||||
|
efficient: EfficientRecording<H>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: TreeHasher> CombinedRecording<H> {
|
||||||
|
pub fn append(&mut self, value: &H::Digest) -> bool {
|
||||||
|
let a = self.inefficient.append(value);
|
||||||
|
let b = self.efficient.append(value);
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn play(&mut self, recording: &Self) -> bool {
|
||||||
|
let a = self.inefficient.play(&recording.inefficient);
|
||||||
|
let b = self.efficient.play(&recording.efficient);
|
||||||
|
assert_eq!(a, b);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Tree<H: TreeHasher> {
|
pub struct Tree<H: TreeHasher> {
|
||||||
leaves: Vec<H::Digest>,
|
leaves: Vec<H::Digest>,
|
||||||
|
@ -190,6 +399,7 @@ impl<H: TreeHasher> Tree<H> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Recording<H: TreeHasher> {
|
pub struct Recording<H: TreeHasher> {
|
||||||
start_position: usize,
|
start_position: usize,
|
||||||
current_position: usize,
|
current_position: usize,
|
||||||
|
@ -421,7 +631,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn do_stuff(ops in proptest::collection::vec(arb_operation(), 1..100)) {
|
fn do_stuff(ops in proptest::collection::vec(arb_operation(), 1..100)) {
|
||||||
const DEPTH: usize = 4;
|
const DEPTH: usize = 4;
|
||||||
let mut tree = Tree::<Hash>::new(DEPTH);
|
let mut tree = CombinedTree::<Hash>::new(DEPTH);
|
||||||
|
|
||||||
let mut prevtrees = vec![];
|
let mut prevtrees = vec![];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue