mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
26b411e79e
We have a pattern in the code - return Vec, turn it into an iterator, filter and collect to another Vec. The idea was to return iterator where possible to avoid allocating intermediate vecs.
560 lines
16 KiB
Rust
560 lines
16 KiB
Rust
// Copyright 2020 The Grin Developers
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
mod common;
|
|
|
|
use self::core::core::hash::Hash;
|
|
use self::core::core::pmmr::{self, VecBackend, PMMR};
|
|
use self::core::ser::PMMRIndexHashable;
|
|
use crate::common::TestElem;
|
|
use chrono::prelude::Utc;
|
|
use grin_core as core;
|
|
use std::u64;
|
|
|
|
#[test]
|
|
fn some_peak_map() {
|
|
assert_eq!(pmmr::peak_map_height(0), (0b0, 0));
|
|
assert_eq!(pmmr::peak_map_height(1), (0b1, 0));
|
|
assert_eq!(pmmr::peak_map_height(2), (0b1, 1));
|
|
assert_eq!(pmmr::peak_map_height(3), (0b10, 0));
|
|
assert_eq!(pmmr::peak_map_height(4), (0b11, 0));
|
|
assert_eq!(pmmr::peak_map_height(5), (0b11, 1));
|
|
assert_eq!(pmmr::peak_map_height(6), (0b11, 2));
|
|
assert_eq!(pmmr::peak_map_height(7), (0b100, 0));
|
|
assert_eq!(pmmr::peak_map_height(u64::MAX), ((u64::MAX >> 1) + 1, 0));
|
|
assert_eq!(pmmr::peak_map_height(u64::MAX - 1), (u64::MAX >> 1, 63));
|
|
}
|
|
|
|
#[ignore]
|
|
#[test]
|
|
fn bench_peak_map() {
|
|
let nano_to_millis = 1.0 / 1_000_000.0;
|
|
|
|
let increments = vec![1_000_000u64, 10_000_000u64, 100_000_000u64];
|
|
|
|
for v in increments {
|
|
let start = Utc::now().timestamp_nanos();
|
|
for i in 0..v {
|
|
let _ = pmmr::peak_map_height(i);
|
|
}
|
|
let fin = Utc::now().timestamp_nanos();
|
|
let dur_ms = (fin - start) as f64 * nano_to_millis;
|
|
println!("{:9?} peak_map_height() in {:9.3?}ms", v, dur_ms);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn some_peak_size() {
|
|
assert_eq!(pmmr::peak_sizes_height(0), (vec![], 0));
|
|
assert_eq!(pmmr::peak_sizes_height(1), (vec![1], 0));
|
|
assert_eq!(pmmr::peak_sizes_height(2), (vec![1], 1));
|
|
assert_eq!(pmmr::peak_sizes_height(3), (vec![3], 0));
|
|
assert_eq!(pmmr::peak_sizes_height(4), (vec![3, 1], 0));
|
|
assert_eq!(pmmr::peak_sizes_height(5), (vec![3, 1], 1));
|
|
assert_eq!(pmmr::peak_sizes_height(6), (vec![3, 1], 2));
|
|
assert_eq!(pmmr::peak_sizes_height(7), (vec![7], 0));
|
|
assert_eq!(pmmr::peak_sizes_height(u64::MAX), (vec![u64::MAX], 0));
|
|
|
|
let size_of_peaks = (1..64).map(|i| u64::MAX >> i).collect::<Vec<u64>>();
|
|
assert_eq!(pmmr::peak_sizes_height(u64::MAX - 1), (size_of_peaks, 63));
|
|
}
|
|
|
|
#[test]
|
|
#[allow(unused_variables)]
|
|
fn first_100_mmr_heights() {
|
|
let first_100_str = "0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 4 \
|
|
0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 4 5 \
|
|
0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 4 0 0 1 0 0";
|
|
let first_100 = first_100_str.split(' ').map(|n| n.parse::<u64>().unwrap());
|
|
let mut count = 1;
|
|
for n in first_100 {
|
|
assert_eq!(
|
|
n,
|
|
pmmr::bintree_postorder_height(count),
|
|
"expected {}, got {}",
|
|
n,
|
|
pmmr::bintree_postorder_height(count)
|
|
);
|
|
count += 1;
|
|
}
|
|
}
|
|
|
|
// The pos of the rightmost leaf for the provided MMR size (last leaf in subtree).
|
|
#[test]
|
|
fn test_bintree_rightmost() {
|
|
assert_eq!(pmmr::bintree_rightmost(0), 0);
|
|
assert_eq!(pmmr::bintree_rightmost(1), 1);
|
|
assert_eq!(pmmr::bintree_rightmost(2), 2);
|
|
assert_eq!(pmmr::bintree_rightmost(3), 2);
|
|
assert_eq!(pmmr::bintree_rightmost(4), 4);
|
|
assert_eq!(pmmr::bintree_rightmost(5), 5);
|
|
assert_eq!(pmmr::bintree_rightmost(6), 5);
|
|
assert_eq!(pmmr::bintree_rightmost(7), 5);
|
|
}
|
|
|
|
// The pos of the leftmost leaf for the provided MMR size (first leaf in subtree).
|
|
#[test]
|
|
fn test_bintree_leftmost() {
|
|
assert_eq!(pmmr::bintree_leftmost(0), 0);
|
|
assert_eq!(pmmr::bintree_leftmost(1), 1);
|
|
assert_eq!(pmmr::bintree_leftmost(2), 2);
|
|
assert_eq!(pmmr::bintree_leftmost(3), 1);
|
|
assert_eq!(pmmr::bintree_leftmost(4), 4);
|
|
assert_eq!(pmmr::bintree_leftmost(5), 5);
|
|
assert_eq!(pmmr::bintree_leftmost(6), 4);
|
|
assert_eq!(pmmr::bintree_leftmost(7), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_n_leaves() {
|
|
// make sure we handle an empty MMR correctly
|
|
assert_eq!(pmmr::n_leaves(0), 0);
|
|
|
|
// and various sizes on non-empty MMRs
|
|
assert_eq!(pmmr::n_leaves(1), 1);
|
|
assert_eq!(pmmr::n_leaves(2), 2);
|
|
assert_eq!(pmmr::n_leaves(3), 2);
|
|
assert_eq!(pmmr::n_leaves(4), 3);
|
|
assert_eq!(pmmr::n_leaves(5), 4);
|
|
assert_eq!(pmmr::n_leaves(6), 4);
|
|
assert_eq!(pmmr::n_leaves(7), 4);
|
|
assert_eq!(pmmr::n_leaves(8), 5);
|
|
assert_eq!(pmmr::n_leaves(9), 6);
|
|
assert_eq!(pmmr::n_leaves(10), 6);
|
|
}
|
|
|
|
/// Find parent and sibling positions for various node positions.
|
|
#[test]
|
|
fn various_families() {
|
|
// 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3
|
|
assert_eq!(pmmr::family(1), (3, 2));
|
|
assert_eq!(pmmr::family(2), (3, 1));
|
|
assert_eq!(pmmr::family(3), (7, 6));
|
|
assert_eq!(pmmr::family(4), (6, 5));
|
|
assert_eq!(pmmr::family(5), (6, 4));
|
|
assert_eq!(pmmr::family(6), (7, 3));
|
|
assert_eq!(pmmr::family(7), (15, 14));
|
|
assert_eq!(pmmr::family(1_000), (1_001, 997));
|
|
}
|
|
|
|
#[test]
|
|
fn test_paths() {
|
|
assert_eq!(pmmr::path(1, 3).collect::<Vec<_>>(), [1, 3]);
|
|
assert_eq!(pmmr::path(2, 3).collect::<Vec<_>>(), [2, 3]);
|
|
assert_eq!(pmmr::path(4, 16).collect::<Vec<_>>(), [4, 6, 7, 15]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_left_sibling() {
|
|
assert_eq!(pmmr::is_left_sibling(1), true);
|
|
assert_eq!(pmmr::is_left_sibling(2), false);
|
|
assert_eq!(pmmr::is_left_sibling(3), true);
|
|
}
|
|
|
|
#[test]
|
|
fn various_branches() {
|
|
// the two leaf nodes in a 3 node tree (height 1)
|
|
assert_eq!(pmmr::family_branch(1, 3), [(3, 2)]);
|
|
assert_eq!(pmmr::family_branch(2, 3), [(3, 1)]);
|
|
|
|
// the root node in a 3 node tree
|
|
assert_eq!(pmmr::family_branch(3, 3), []);
|
|
|
|
// leaf node in a larger tree of 7 nodes (height 2)
|
|
assert_eq!(pmmr::family_branch(1, 7), [(3, 2), (7, 6)]);
|
|
|
|
// note these only go as far up as the local peak, not necessarily the single
|
|
// root
|
|
assert_eq!(pmmr::family_branch(1, 4), [(3, 2)]);
|
|
// pos 4 in a tree of size 4 is a local peak
|
|
assert_eq!(pmmr::family_branch(4, 4), []);
|
|
// pos 4 in a tree of size 5 is also still a local peak
|
|
assert_eq!(pmmr::family_branch(4, 5), []);
|
|
// pos 4 in a tree of size 6 has a parent and a sibling
|
|
assert_eq!(pmmr::family_branch(4, 6), [(6, 5)]);
|
|
// a tree of size 7 is all under a single root
|
|
assert_eq!(pmmr::family_branch(4, 7), [(6, 5), (7, 3)]);
|
|
|
|
// ok now for a more realistic one, a tree with over a million nodes in it
|
|
// find the "family path" back up the tree from a leaf node at 0
|
|
// Note: the first two entries in the branch are consistent with a small 7 node
|
|
// tree Note: each sibling is on the left branch, this is an example of the
|
|
// largest possible list of peaks before we start combining them into larger
|
|
// peaks.
|
|
assert_eq!(
|
|
pmmr::family_branch(1, 1_049_000),
|
|
[
|
|
(3, 2),
|
|
(7, 6),
|
|
(15, 14),
|
|
(31, 30),
|
|
(63, 62),
|
|
(127, 126),
|
|
(255, 254),
|
|
(511, 510),
|
|
(1023, 1022),
|
|
(2047, 2046),
|
|
(4095, 4094),
|
|
(8191, 8190),
|
|
(16383, 16382),
|
|
(32767, 32766),
|
|
(65535, 65534),
|
|
(131071, 131070),
|
|
(262143, 262142),
|
|
(524287, 524286),
|
|
(1048575, 1048574),
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn some_peaks() {
|
|
// 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3
|
|
|
|
let empty: Vec<u64> = vec![];
|
|
|
|
// make sure we handle an empty MMR correctly
|
|
assert_eq!(pmmr::peaks(0), empty);
|
|
|
|
// and various non-empty MMRs
|
|
assert_eq!(pmmr::peaks(1), [1]);
|
|
assert_eq!(pmmr::peaks(2), empty);
|
|
assert_eq!(pmmr::peaks(3), [3]);
|
|
assert_eq!(pmmr::peaks(4), [3, 4]);
|
|
assert_eq!(pmmr::peaks(5), empty);
|
|
assert_eq!(pmmr::peaks(6), empty);
|
|
assert_eq!(pmmr::peaks(7), [7]);
|
|
assert_eq!(pmmr::peaks(8), [7, 8]);
|
|
assert_eq!(pmmr::peaks(9), empty);
|
|
assert_eq!(pmmr::peaks(10), [7, 10]);
|
|
assert_eq!(pmmr::peaks(11), [7, 10, 11]);
|
|
assert_eq!(pmmr::peaks(22), [15, 22]);
|
|
assert_eq!(pmmr::peaks(32), [31, 32]);
|
|
assert_eq!(pmmr::peaks(35), [31, 34, 35]);
|
|
assert_eq!(pmmr::peaks(42), [31, 38, 41, 42]);
|
|
|
|
// large realistic example with almost 1.5 million nodes
|
|
// note the distance between peaks decreases toward the right (trees get
|
|
// smaller)
|
|
assert_eq!(
|
|
pmmr::peaks(1048555),
|
|
[
|
|
524287, 786430, 917501, 983036, 1015803, 1032186, 1040377, 1044472, 1046519, 1047542,
|
|
1048053, 1048308, 1048435, 1048498, 1048529, 1048544, 1048551, 1048554, 1048555,
|
|
],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[allow(unused_variables)]
|
|
fn pmmr_push_root() {
|
|
let elems = [
|
|
TestElem([0, 0, 0, 1]),
|
|
TestElem([0, 0, 0, 2]),
|
|
TestElem([0, 0, 0, 3]),
|
|
TestElem([0, 0, 0, 4]),
|
|
TestElem([0, 0, 0, 5]),
|
|
TestElem([0, 0, 0, 6]),
|
|
TestElem([0, 0, 0, 7]),
|
|
TestElem([0, 0, 0, 8]),
|
|
TestElem([1, 0, 0, 0]),
|
|
];
|
|
|
|
let mut ba = VecBackend::new();
|
|
let mut pmmr = PMMR::new(&mut ba);
|
|
|
|
// one element
|
|
pmmr.push(&elems[0]).unwrap();
|
|
pmmr.dump(false);
|
|
let pos_0 = elems[0].hash_with_index(0);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_0]);
|
|
assert_eq!(pmmr.root().unwrap(), pos_0);
|
|
assert_eq!(pmmr.unpruned_size(), 1);
|
|
|
|
// two elements
|
|
pmmr.push(&elems[1]).unwrap();
|
|
pmmr.dump(false);
|
|
let pos_1 = elems[1].hash_with_index(1);
|
|
let pos_2 = (pos_0, pos_1).hash_with_index(2);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_2]);
|
|
assert_eq!(pmmr.root().unwrap(), pos_2);
|
|
assert_eq!(pmmr.unpruned_size(), 3);
|
|
|
|
// three elements
|
|
pmmr.push(&elems[2]).unwrap();
|
|
pmmr.dump(false);
|
|
let pos_3 = elems[2].hash_with_index(3);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_2, pos_3]);
|
|
assert_eq!(pmmr.root().unwrap(), (pos_2, pos_3).hash_with_index(4));
|
|
assert_eq!(pmmr.unpruned_size(), 4);
|
|
|
|
// four elements
|
|
pmmr.push(&elems[3]).unwrap();
|
|
pmmr.dump(false);
|
|
let pos_4 = elems[3].hash_with_index(4);
|
|
let pos_5 = (pos_3, pos_4).hash_with_index(5);
|
|
let pos_6 = (pos_2, pos_5).hash_with_index(6);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_6]);
|
|
assert_eq!(pmmr.root().unwrap(), pos_6);
|
|
assert_eq!(pmmr.unpruned_size(), 7);
|
|
|
|
// five elements
|
|
pmmr.push(&elems[4]).unwrap();
|
|
pmmr.dump(false);
|
|
let pos_7 = elems[4].hash_with_index(7);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_6, pos_7]);
|
|
assert_eq!(pmmr.root().unwrap(), (pos_6, pos_7).hash_with_index(8));
|
|
assert_eq!(pmmr.unpruned_size(), 8);
|
|
|
|
// six elements
|
|
pmmr.push(&elems[5]).unwrap();
|
|
let pos_8 = elems[5].hash_with_index(8);
|
|
let pos_9 = (pos_7, pos_8).hash_with_index(9);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_6, pos_9]);
|
|
assert_eq!(pmmr.root().unwrap(), (pos_6, pos_9).hash_with_index(10));
|
|
assert_eq!(pmmr.unpruned_size(), 10);
|
|
|
|
// seven elements
|
|
pmmr.push(&elems[6]).unwrap();
|
|
let pos_10 = elems[6].hash_with_index(10);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_6, pos_9, pos_10]);
|
|
assert_eq!(
|
|
pmmr.root().unwrap(),
|
|
(pos_6, (pos_9, pos_10).hash_with_index(11)).hash_with_index(11)
|
|
);
|
|
assert_eq!(pmmr.unpruned_size(), 11);
|
|
|
|
// 001001200100123
|
|
// eight elements
|
|
pmmr.push(&elems[7]).unwrap();
|
|
let pos_11 = elems[7].hash_with_index(11);
|
|
let pos_12 = (pos_10, pos_11).hash_with_index(12);
|
|
let pos_13 = (pos_9, pos_12).hash_with_index(13);
|
|
let pos_14 = (pos_6, pos_13).hash_with_index(14);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_14]);
|
|
assert_eq!(pmmr.root().unwrap(), pos_14);
|
|
assert_eq!(pmmr.unpruned_size(), 15);
|
|
|
|
// nine elements
|
|
pmmr.push(&elems[8]).unwrap();
|
|
let pos_15 = elems[8].hash_with_index(15);
|
|
assert_eq!(pmmr.peaks().collect::<Vec<_>>(), vec![pos_14, pos_15]);
|
|
assert_eq!(pmmr.root().unwrap(), (pos_14, pos_15).hash_with_index(16));
|
|
assert_eq!(pmmr.unpruned_size(), 16);
|
|
}
|
|
|
|
#[test]
|
|
fn pmmr_get_last_n_insertions() {
|
|
let elems = [
|
|
TestElem([0, 0, 0, 1]),
|
|
TestElem([0, 0, 0, 2]),
|
|
TestElem([0, 0, 0, 3]),
|
|
TestElem([0, 0, 0, 4]),
|
|
TestElem([0, 0, 0, 5]),
|
|
TestElem([0, 0, 0, 6]),
|
|
TestElem([0, 0, 0, 7]),
|
|
TestElem([0, 0, 0, 8]),
|
|
TestElem([1, 0, 0, 0]),
|
|
];
|
|
|
|
let mut ba = VecBackend::new();
|
|
let mut pmmr = PMMR::new(&mut ba);
|
|
|
|
// test when empty
|
|
let res = pmmr.readonly_pmmr().get_last_n_insertions(19);
|
|
assert!(res.is_empty());
|
|
|
|
pmmr.push(&elems[0]).unwrap();
|
|
let res = pmmr.readonly_pmmr().get_last_n_insertions(19);
|
|
assert!(res.len() == 1);
|
|
|
|
pmmr.push(&elems[1]).unwrap();
|
|
|
|
let res = pmmr.readonly_pmmr().get_last_n_insertions(12);
|
|
assert!(res.len() == 2);
|
|
|
|
pmmr.push(&elems[2]).unwrap();
|
|
|
|
let res = pmmr.readonly_pmmr().get_last_n_insertions(2);
|
|
assert!(res.len() == 2);
|
|
|
|
pmmr.push(&elems[3]).unwrap();
|
|
|
|
let res = pmmr.readonly_pmmr().get_last_n_insertions(19);
|
|
assert!(res.len() == 4);
|
|
|
|
pmmr.push(&elems[5]).unwrap();
|
|
pmmr.push(&elems[6]).unwrap();
|
|
pmmr.push(&elems[7]).unwrap();
|
|
pmmr.push(&elems[8]).unwrap();
|
|
|
|
let res = pmmr.readonly_pmmr().get_last_n_insertions(7);
|
|
assert!(res.len() == 7);
|
|
}
|
|
|
|
#[test]
|
|
#[allow(unused_variables)]
|
|
fn pmmr_prune() {
|
|
let elems = [
|
|
TestElem([0, 0, 0, 1]),
|
|
TestElem([0, 0, 0, 2]),
|
|
TestElem([0, 0, 0, 3]),
|
|
TestElem([0, 0, 0, 4]),
|
|
TestElem([0, 0, 0, 5]),
|
|
TestElem([0, 0, 0, 6]),
|
|
TestElem([0, 0, 0, 7]),
|
|
TestElem([0, 0, 0, 8]),
|
|
TestElem([1, 0, 0, 0]),
|
|
];
|
|
|
|
let orig_root: Hash;
|
|
let sz: u64;
|
|
let mut ba = VecBackend::new();
|
|
{
|
|
let mut pmmr = PMMR::new(&mut ba);
|
|
for elem in &elems[..] {
|
|
pmmr.push(elem).unwrap();
|
|
}
|
|
orig_root = pmmr.root().unwrap();
|
|
sz = pmmr.unpruned_size();
|
|
}
|
|
|
|
// First check the initial numbers of elements.
|
|
assert_eq!(ba.hashes.len(), 16);
|
|
assert_eq!(ba.removed.len(), 0);
|
|
|
|
// pruning a leaf with no parent should do nothing
|
|
{
|
|
let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz);
|
|
pmmr.prune(16).unwrap();
|
|
assert_eq!(orig_root, pmmr.root().unwrap());
|
|
}
|
|
assert_eq!(ba.hashes.len(), 16);
|
|
assert_eq!(ba.removed.len(), 1);
|
|
|
|
// pruning leaves with no shared parent just removes 1 element
|
|
{
|
|
let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz);
|
|
pmmr.prune(2).unwrap();
|
|
assert_eq!(orig_root, pmmr.root().unwrap());
|
|
}
|
|
assert_eq!(ba.hashes.len(), 16);
|
|
assert_eq!(ba.removed.len(), 2);
|
|
|
|
{
|
|
let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz);
|
|
pmmr.prune(4).unwrap();
|
|
assert_eq!(orig_root, pmmr.root().unwrap());
|
|
}
|
|
assert_eq!(ba.hashes.len(), 16);
|
|
assert_eq!(ba.removed.len(), 3);
|
|
|
|
// pruning a non-leaf node has no effect
|
|
{
|
|
let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz);
|
|
pmmr.prune(3).unwrap_err();
|
|
assert_eq!(orig_root, pmmr.root().unwrap());
|
|
}
|
|
assert_eq!(ba.hashes.len(), 16);
|
|
assert_eq!(ba.removed.len(), 3);
|
|
|
|
// TODO - no longer true (leaves only now) - pruning sibling removes subtree
|
|
{
|
|
let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz);
|
|
pmmr.prune(5).unwrap();
|
|
assert_eq!(orig_root, pmmr.root().unwrap());
|
|
}
|
|
assert_eq!(ba.hashes.len(), 16);
|
|
assert_eq!(ba.removed.len(), 4);
|
|
|
|
// TODO - no longer true (leaves only now) - pruning all leaves under level >1
|
|
// removes all subtree
|
|
{
|
|
let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz);
|
|
pmmr.prune(1).unwrap();
|
|
assert_eq!(orig_root, pmmr.root().unwrap());
|
|
}
|
|
assert_eq!(ba.hashes.len(), 16);
|
|
assert_eq!(ba.removed.len(), 5);
|
|
|
|
// pruning everything should only leave us with a single peak
|
|
{
|
|
let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz);
|
|
for n in 1..16 {
|
|
let _ = pmmr.prune(n);
|
|
}
|
|
assert_eq!(orig_root, pmmr.root().unwrap());
|
|
}
|
|
assert_eq!(ba.hashes.len(), 16);
|
|
assert_eq!(ba.removed.len(), 9);
|
|
}
|
|
|
|
#[test]
|
|
fn check_insertion_to_pmmr_index() {
|
|
assert_eq!(pmmr::insertion_to_pmmr_index(1), 1);
|
|
assert_eq!(pmmr::insertion_to_pmmr_index(2), 2);
|
|
assert_eq!(pmmr::insertion_to_pmmr_index(3), 4);
|
|
assert_eq!(pmmr::insertion_to_pmmr_index(4), 5);
|
|
assert_eq!(pmmr::insertion_to_pmmr_index(5), 8);
|
|
assert_eq!(pmmr::insertion_to_pmmr_index(6), 9);
|
|
assert_eq!(pmmr::insertion_to_pmmr_index(7), 11);
|
|
assert_eq!(pmmr::insertion_to_pmmr_index(8), 12);
|
|
}
|
|
|
|
#[test]
|
|
fn check_elements_from_pmmr_index() {
|
|
let mut ba = VecBackend::new();
|
|
let mut pmmr = PMMR::new(&mut ba);
|
|
// 20 elements should give max index 38
|
|
for x in 1..21 {
|
|
pmmr.push(&TestElem([0, 0, 0, x])).unwrap();
|
|
}
|
|
|
|
// Normal case
|
|
let res = pmmr.readonly_pmmr().elements_from_pmmr_index(1, 1000, None);
|
|
assert_eq!(res.0, 38);
|
|
assert_eq!(res.1.len(), 20);
|
|
assert_eq!(res.1[0].0[3], 1);
|
|
assert_eq!(res.1[19].0[3], 20);
|
|
|
|
// middle of pack
|
|
let res = pmmr
|
|
.readonly_pmmr()
|
|
.elements_from_pmmr_index(8, 1000, Some(34));
|
|
assert_eq!(res.0, 34);
|
|
assert_eq!(res.1.len(), 14);
|
|
assert_eq!(res.1[0].0[3], 5);
|
|
assert_eq!(res.1[13].0[3], 18);
|
|
|
|
// bounded
|
|
let res = pmmr
|
|
.readonly_pmmr()
|
|
.elements_from_pmmr_index(8, 7, Some(34));
|
|
assert_eq!(res.0, 19);
|
|
assert_eq!(res.1.len(), 7);
|
|
assert_eq!(res.1[0].0[3], 5);
|
|
assert_eq!(res.1[6].0[3], 11);
|
|
|
|
// pruning a few nodes should get consistent results
|
|
pmmr.prune(pmmr::insertion_to_pmmr_index(5)).unwrap();
|
|
pmmr.prune(pmmr::insertion_to_pmmr_index(20)).unwrap();
|
|
|
|
let res = pmmr
|
|
.readonly_pmmr()
|
|
.elements_from_pmmr_index(8, 7, Some(34));
|
|
assert_eq!(res.0, 20);
|
|
assert_eq!(res.1.len(), 7);
|
|
assert_eq!(res.1[0].0[3], 6);
|
|
assert_eq!(res.1[6].0[3], 12);
|
|
}
|