mirror of
https://github.com/pezkuwichain/merkle-mountain-range.git
synced 2026-06-18 02:21:03 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fb7605c6da | |||
| 92f32c6751 | |||
| 0e3b02c38f | |||
| d6cfbe6454 | |||
| c8ae8dad9d | |||
| 7796272361 | |||
| bb196e8b96 | |||
| bf24bf0b93 | |||
| 8b8adae74c | |||
| be20646ac8 | |||
| a037309912 | |||
| 0b37e46871 | |||
| 09092d0039 | |||
| caa2a4fdce | |||
| f0925ef6bd | |||
| 13d50d12d9 | |||
| b16216f90e | |||
| 9f9a95c73e |
+6
-6
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ckb-merkle-mountain-range"
|
name = "ckb-merkle-mountain-range"
|
||||||
version = "0.3.1"
|
version = "0.5.0"
|
||||||
authors = ["Nervos Core Dev <dev@nervos.org>"]
|
authors = ["Nervos Core Dev <dev@nervos.org>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
@@ -12,15 +12,15 @@ default = ["std"]
|
|||||||
std = []
|
std = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cfg-if = "0.1"
|
cfg-if = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
faster-hex = "0.3"
|
faster-hex = "0.6.1"
|
||||||
criterion = "0.3"
|
criterion = "0.3"
|
||||||
rand = "0.6"
|
rand = "0.8.5"
|
||||||
proptest = "0.9.4"
|
proptest = "1.0.0"
|
||||||
lazy_static = "1.3.0"
|
lazy_static = "1.3.0"
|
||||||
bytes = "0.4"
|
bytes = "1.2.0"
|
||||||
blake2b-rs = "0.1.4"
|
blake2b-rs = "0.1.4"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
A generalized merkle mountain range implementation.
|
A generalized merkle mountain range implementation.
|
||||||
|
|
||||||
**Notice** this library is not stable yet, API and proof format may changes. Make sure you know what you do before using this library.
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Leaves accumulation
|
* Leaves accumulation
|
||||||
@@ -38,7 +36,7 @@ For example, we insert a leaf to the example MMR:
|
|||||||
3. insert parent node to position `20`.
|
3. insert parent node to position `20`.
|
||||||
4. the node `20` also has a left sibling `17`, calculate parent node: `merge(mmr[17], mmr[20])`.
|
4. the node `20` also has a left sibling `17`, calculate parent node: `merge(mmr[17], mmr[20])`.
|
||||||
5. insert new node to next position `21`.
|
5. insert new node to next position `21`.
|
||||||
6. the node `20` have no left sibling, complete the insertion.
|
6. the node `21` have no left sibling, complete the insertion.
|
||||||
|
|
||||||
Example MMR after insertion of a new leaf:
|
Example MMR after insertion of a new leaf:
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ fn bench(c: &mut Criterion) {
|
|||||||
c.bench_function("left_index_to_pos", |b| {
|
c.bench_function("left_index_to_pos", |b| {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let leaf_index = rng.gen_range(50_000_000_000, 70_000_000_000);
|
let leaf_index = rng.gen_range(50_000_000_000..70_000_000_000);
|
||||||
leaf_index_to_pos(leaf_index);
|
leaf_index_to_pos(leaf_index);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -18,7 +18,7 @@ fn bench(c: &mut Criterion) {
|
|||||||
c.bench_function("left_index_to_mmr_size", |b| {
|
c.bench_function("left_index_to_mmr_size", |b| {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let leaf_index = rng.gen_range(50_000_000_000, 70_000_000_000);
|
let leaf_index = rng.gen_range(50_000_000_000..70_000_000_000);
|
||||||
leaf_index_to_mmr_size(leaf_index);
|
leaf_index_to_mmr_size(leaf_index);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+12
-10
@@ -1,7 +1,7 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate criterion;
|
extern crate criterion;
|
||||||
|
|
||||||
use criterion::Criterion;
|
use criterion::{BenchmarkId, Criterion};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use ckb_merkle_mountain_range::{util::MemStore, Error, MMRStore, Merge, Result, MMR};
|
use ckb_merkle_mountain_range::{util::MemStore, Error, MMRStore, Merge, Result, MMR};
|
||||||
@@ -31,13 +31,13 @@ struct MergeNumberHash;
|
|||||||
|
|
||||||
impl Merge for MergeNumberHash {
|
impl Merge for MergeNumberHash {
|
||||||
type Item = NumberHash;
|
type Item = NumberHash;
|
||||||
fn merge(lhs: &Self::Item, rhs: &Self::Item) -> Self::Item {
|
fn merge(lhs: &Self::Item, rhs: &Self::Item) -> Result<Self::Item> {
|
||||||
let mut hasher = new_blake2b();
|
let mut hasher = new_blake2b();
|
||||||
let mut hash = [0u8; 32];
|
let mut hash = [0u8; 32];
|
||||||
hasher.update(&lhs.0);
|
hasher.update(&lhs.0);
|
||||||
hasher.update(&rhs.0);
|
hasher.update(&rhs.0);
|
||||||
hasher.finalize(&mut hash);
|
hasher.finalize(&mut hash);
|
||||||
NumberHash(hash.to_vec().into())
|
Ok(NumberHash(hash.to_vec().into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,13 +53,15 @@ fn prepare_mmr(count: u32) -> (u64, MemStore<NumberHash>, Vec<u64>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn bench(c: &mut Criterion) {
|
fn bench(c: &mut Criterion) {
|
||||||
c.bench_function_over_inputs(
|
{
|
||||||
"MMR insert",
|
let mut group = c.benchmark_group("MMR insertion");
|
||||||
|b, &&size| {
|
let inputs = [10_000, 100_000, 100_0000];
|
||||||
b.iter(|| prepare_mmr(size));
|
for input in inputs.iter() {
|
||||||
},
|
group.bench_with_input(BenchmarkId::new("times", input), &input, |b, &&size| {
|
||||||
&[10_000, 100_000, 100_0000],
|
b.iter(|| prepare_mmr(size));
|
||||||
);
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.bench_function("MMR gen proof", |b| {
|
c.bench_function("MMR gen proof", |b| {
|
||||||
let (mmr_size, store, positions) = prepare_mmr(100_0000);
|
let (mmr_size, store, positions) = prepare_mmr(100_0000);
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ pub enum Error {
|
|||||||
CorruptedProof,
|
CorruptedProof,
|
||||||
/// The leaves is an empty list, or beyond the mmr range
|
/// The leaves is an empty list, or beyond the mmr range
|
||||||
GenProofForInvalidLeaves,
|
GenProofForInvalidLeaves,
|
||||||
|
|
||||||
|
/// The two nodes couldn't merge into one.
|
||||||
|
MergeError(crate::string::String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Display for Error {
|
impl core::fmt::Display for Error {
|
||||||
@@ -20,6 +23,7 @@ impl core::fmt::Display for Error {
|
|||||||
StoreError(msg) => write!(f, "Store error {}", msg)?,
|
StoreError(msg) => write!(f, "Store error {}", msg)?,
|
||||||
CorruptedProof => write!(f, "Corrupted proof")?,
|
CorruptedProof => write!(f, "Corrupted proof")?,
|
||||||
GenProofForInvalidLeaves => write!(f, "Generate proof ofr invalid leaves")?,
|
GenProofForInvalidLeaves => write!(f, "Generate proof ofr invalid leaves")?,
|
||||||
|
MergeError(msg) => write!(f, "Merge error {}", msg)?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod helper;
|
pub mod helper;
|
||||||
mod merge;
|
mod merge;
|
||||||
mod mmr;
|
mod mmr;
|
||||||
mod mmr_store;
|
mod mmr_store;
|
||||||
|
|||||||
+8
-1
@@ -1,4 +1,11 @@
|
|||||||
|
use crate::Result;
|
||||||
|
|
||||||
pub trait Merge {
|
pub trait Merge {
|
||||||
type Item;
|
type Item;
|
||||||
fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item;
|
|
||||||
|
fn merge(left: &Self::Item, right: &Self::Item) -> Result<Self::Item>;
|
||||||
|
|
||||||
|
fn merge_peaks(peak1: &Self::Item, peak2: &Self::Item) -> Result<Self::Item> {
|
||||||
|
Self::merge(peak1, peak2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -14,7 +14,8 @@ use crate::{Error, Merge, Result};
|
|||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
pub struct MMR<T, M, S: MMRStore<T>> {
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
pub struct MMR<T, M, S> {
|
||||||
mmr_size: u64,
|
mmr_size: u64,
|
||||||
batch: MMRBatch<T, S>,
|
batch: MMRBatch<T, S>,
|
||||||
merge: PhantomData<M>,
|
merge: PhantomData<M>,
|
||||||
@@ -62,7 +63,7 @@ impl<'a, T: Clone + PartialEq + Debug, M: Merge<Item = T>, S: MMRStore<T>> MMR<T
|
|||||||
let right_pos = left_pos + sibling_offset(height);
|
let right_pos = left_pos + sibling_offset(height);
|
||||||
let left_elem = self.find_elem(left_pos, &elems)?;
|
let left_elem = self.find_elem(left_pos, &elems)?;
|
||||||
let right_elem = self.find_elem(right_pos, &elems)?;
|
let right_elem = self.find_elem(right_pos, &elems)?;
|
||||||
let parent_elem = M::merge(&left_elem, &right_elem);
|
let parent_elem = M::merge(&left_elem, &right_elem)?;
|
||||||
elems.push(parent_elem);
|
elems.push(parent_elem);
|
||||||
height += 1
|
height += 1
|
||||||
}
|
}
|
||||||
@@ -95,7 +96,7 @@ impl<'a, T: Clone + PartialEq + Debug, M: Merge<Item = T>, S: MMRStore<T>> MMR<T
|
|||||||
while rhs_peaks.len() > 1 {
|
while rhs_peaks.len() > 1 {
|
||||||
let right_peak = rhs_peaks.pop().expect("pop");
|
let right_peak = rhs_peaks.pop().expect("pop");
|
||||||
let left_peak = rhs_peaks.pop().expect("pop");
|
let left_peak = rhs_peaks.pop().expect("pop");
|
||||||
rhs_peaks.push(M::merge(&right_peak, &left_peak));
|
rhs_peaks.push(M::merge_peaks(&right_peak, &left_peak)?);
|
||||||
}
|
}
|
||||||
Ok(rhs_peaks.pop())
|
Ok(rhs_peaks.pop())
|
||||||
}
|
}
|
||||||
@@ -319,7 +320,7 @@ fn calculate_peak_root<
|
|||||||
M::merge(&sibling_item, &item)
|
M::merge(&sibling_item, &item)
|
||||||
} else {
|
} else {
|
||||||
M::merge(&item, &sibling_item)
|
M::merge(&item, &sibling_item)
|
||||||
};
|
}?;
|
||||||
|
|
||||||
if parent_pos < peak_pos {
|
if parent_pos < peak_pos {
|
||||||
queue.push_back((parent_pos, parent_item, height + 1));
|
queue.push_back((parent_pos, parent_item, height + 1));
|
||||||
@@ -393,7 +394,7 @@ fn bagging_peaks_hashes<'a, T: 'a + PartialEq + Debug + Clone, M: Merge<Item = T
|
|||||||
while peaks_hashes.len() > 1 {
|
while peaks_hashes.len() > 1 {
|
||||||
let right_peak = peaks_hashes.pop().expect("pop");
|
let right_peak = peaks_hashes.pop().expect("pop");
|
||||||
let left_peak = peaks_hashes.pop().expect("pop");
|
let left_peak = peaks_hashes.pop().expect("pop");
|
||||||
peaks_hashes.push(M::merge(&right_peak, &left_peak));
|
peaks_hashes.push(M::merge_peaks(&right_peak, &left_peak)?);
|
||||||
}
|
}
|
||||||
peaks_hashes.pop().ok_or(Error::CorruptedProof)
|
peaks_hashes.pop().ok_or(Error::CorruptedProof)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
use crate::{vec::Vec, Result};
|
use crate::{vec::Vec, Result};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct MMRBatch<Elem, Store: MMRStore<Elem>> {
|
pub struct MMRBatch<Elem, Store> {
|
||||||
memory_batch: Vec<(u64, Vec<Elem>)>,
|
memory_batch: Vec<(u64, Vec<Elem>)>,
|
||||||
store: Store,
|
store: Store,
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1,8 +1,9 @@
|
|||||||
mod test_accumulate_headers;
|
mod test_accumulate_headers;
|
||||||
mod test_helper;
|
mod test_helper;
|
||||||
mod test_mmr;
|
mod test_mmr;
|
||||||
|
mod test_sequence;
|
||||||
|
|
||||||
use crate::Merge;
|
use crate::{Merge, Result};
|
||||||
use blake2b_rs::{Blake2b, Blake2bBuilder};
|
use blake2b_rs::{Blake2b, Blake2bBuilder};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
@@ -26,12 +27,12 @@ struct MergeNumberHash;
|
|||||||
|
|
||||||
impl Merge for MergeNumberHash {
|
impl Merge for MergeNumberHash {
|
||||||
type Item = NumberHash;
|
type Item = NumberHash;
|
||||||
fn merge(lhs: &Self::Item, rhs: &Self::Item) -> Self::Item {
|
fn merge(lhs: &Self::Item, rhs: &Self::Item) -> Result<Self::Item> {
|
||||||
let mut hasher = new_blake2b();
|
let mut hasher = new_blake2b();
|
||||||
let mut hash = [0u8; 32];
|
let mut hash = [0u8; 32];
|
||||||
hasher.update(&lhs.0);
|
hasher.update(&lhs.0);
|
||||||
hasher.update(&rhs.0);
|
hasher.update(&rhs.0);
|
||||||
hasher.finalize(&mut hash);
|
hasher.finalize(&mut hash);
|
||||||
NumberHash(hash.to_vec().into())
|
Ok(NumberHash(hash.to_vec().into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use super::new_blake2b;
|
use super::new_blake2b;
|
||||||
use crate::{leaf_index_to_pos, util::MemStore, MMRStore, Merge, MerkleProof, Result, MMR};
|
use crate::{leaf_index_to_pos, util::MemStore, MMRStore, Merge, MerkleProof, Result, MMR};
|
||||||
use bytes::Bytes;
|
use bytes::{Bytes, BytesMut};
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Header {
|
struct Header {
|
||||||
@@ -42,9 +42,9 @@ struct HashWithTD {
|
|||||||
|
|
||||||
impl HashWithTD {
|
impl HashWithTD {
|
||||||
fn serialize(&self) -> Bytes {
|
fn serialize(&self) -> Bytes {
|
||||||
let mut data = self.hash.clone();
|
let mut data = BytesMut::from(self.hash.as_ref());
|
||||||
data.extend(&self.td.to_le_bytes());
|
data.extend(&self.td.to_le_bytes());
|
||||||
data
|
data.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize(mut data: Bytes) -> Self {
|
fn deserialize(mut data: Bytes) -> Self {
|
||||||
@@ -57,12 +57,12 @@ impl HashWithTD {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for HashWithTD {
|
impl fmt::Debug for HashWithTD {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"HashWithTD {{ hash: {}, td: {} }}",
|
"HashWithTD {{ hash: {}, td: {} }}",
|
||||||
faster_hex::hex_string(&self.hash).unwrap(),
|
faster_hex::hex_string(&self.hash),
|
||||||
self.td
|
self.td
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -72,17 +72,17 @@ struct MergeHashWithTD;
|
|||||||
|
|
||||||
impl Merge for MergeHashWithTD {
|
impl Merge for MergeHashWithTD {
|
||||||
type Item = HashWithTD;
|
type Item = HashWithTD;
|
||||||
fn merge(lhs: &Self::Item, rhs: &Self::Item) -> Self::Item {
|
fn merge(lhs: &Self::Item, rhs: &Self::Item) -> Result<Self::Item> {
|
||||||
let mut hasher = new_blake2b();
|
let mut hasher = new_blake2b();
|
||||||
let mut hash = [0u8; 32];
|
let mut hash = [0u8; 32];
|
||||||
hasher.update(&lhs.serialize());
|
hasher.update(&lhs.serialize());
|
||||||
hasher.update(&rhs.serialize());
|
hasher.update(&rhs.serialize());
|
||||||
hasher.finalize(&mut hash);
|
hasher.finalize(&mut hash);
|
||||||
let td = lhs.td + rhs.td;
|
let td = lhs.td + rhs.td;
|
||||||
HashWithTD {
|
Ok(HashWithTD {
|
||||||
hash: hash.to_vec().into(),
|
hash: hash.to_vec().into(),
|
||||||
td,
|
td,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ fn test_mmr_root() {
|
|||||||
mmr.push(NumberHash::from(i)).unwrap();
|
mmr.push(NumberHash::from(i)).unwrap();
|
||||||
});
|
});
|
||||||
let root = mmr.get_root().expect("get root");
|
let root = mmr.get_root().expect("get root");
|
||||||
let hex_root = hex_string(&root.0).unwrap();
|
let hex_root = hex_string(&root.0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"f6794677f37a57df6a5ec36ce61036e43a36c1a009d05c81c9aa685dde1fd6e3",
|
"f6794677f37a57df6a5ec36ce61036e43a36c1a009d05c81c9aa685dde1fd6e3",
|
||||||
hex_root
|
hex_root
|
||||||
@@ -154,7 +154,7 @@ proptest! {
|
|||||||
let mut leaves: Vec<u32> = (0..count).collect();
|
let mut leaves: Vec<u32> = (0..count).collect();
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
leaves.shuffle(&mut rng);
|
leaves.shuffle(&mut rng);
|
||||||
let leaves_count = rng.gen_range(1, count - 1);
|
let leaves_count = rng.gen_range(1..count - 1);
|
||||||
leaves.truncate(leaves_count as usize);
|
leaves.truncate(leaves_count as usize);
|
||||||
test_mmr(count, leaves);
|
test_mmr(count, leaves);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use proptest::proptest;
|
||||||
|
use rand::{prelude::*, thread_rng};
|
||||||
|
|
||||||
|
use crate::{util::MemStore, Merge, Result, MMR};
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Default)]
|
||||||
|
struct NumberRange {
|
||||||
|
start: u32,
|
||||||
|
end: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MergeNumberRange;
|
||||||
|
|
||||||
|
impl fmt::Debug for NumberRange {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "NumberRange({}, {})", self.start, self.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for MergeNumberRange {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "MergeNumberRange")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for NumberRange {
|
||||||
|
fn from(num: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
start: num,
|
||||||
|
end: num,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NumberRange {
|
||||||
|
fn is_normalized(&self) -> bool {
|
||||||
|
self.start <= self.end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Merge for MergeNumberRange {
|
||||||
|
type Item = NumberRange;
|
||||||
|
fn merge(lhs: &Self::Item, rhs: &Self::Item) -> Result<Self::Item> {
|
||||||
|
Ok(Self::Item {
|
||||||
|
start: lhs.start,
|
||||||
|
end: rhs.end,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn merge_peaks(lhs: &Self::Item, rhs: &Self::Item) -> Result<Self::Item> {
|
||||||
|
Self::merge(rhs, lhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_sequence_sub_func(count: u32, proof_elem: Vec<u32>) {
|
||||||
|
let store = MemStore::default();
|
||||||
|
let mut mmr = MMR::<_, MergeNumberRange, _>::new(0, &store);
|
||||||
|
let positions = (0..count)
|
||||||
|
.map(|i| mmr.push(NumberRange::from(i)).expect("push"))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let root = mmr.get_root().expect("get_root");
|
||||||
|
assert!(root.is_normalized());
|
||||||
|
let proof = mmr
|
||||||
|
.gen_proof(
|
||||||
|
proof_elem
|
||||||
|
.iter()
|
||||||
|
.map(|elem| positions[*elem as usize])
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.expect("gen_proof");
|
||||||
|
for item in proof.proof_items() {
|
||||||
|
assert!(item.is_normalized())
|
||||||
|
}
|
||||||
|
mmr.commit().expect("commit");
|
||||||
|
let result = proof
|
||||||
|
.verify(
|
||||||
|
root,
|
||||||
|
proof_elem
|
||||||
|
.iter()
|
||||||
|
.map(|elem| (positions[*elem as usize], NumberRange::from(*elem)))
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.expect("verify");
|
||||||
|
assert!(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test]
|
||||||
|
fn test_sequence(count in 10u32..500u32) {
|
||||||
|
let mut leaves: Vec<u32> = (0..count).collect();
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
leaves.shuffle(&mut rng);
|
||||||
|
let leaves_count = rng.gen_range(1..count - 1);
|
||||||
|
leaves.truncate(leaves_count as usize);
|
||||||
|
test_sequence_sub_func(count, leaves);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user