mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 11:31:08 +03:00
189 lines
7.1 KiB
Rust
189 lines
7.1 KiB
Rust
|
// Copyright 2019 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.
|
||
|
|
||
|
use self::chain::txhashset::BitmapAccumulator;
|
||
|
use self::core::core::hash::Hash;
|
||
|
use self::core::ser::PMMRIndexHashable;
|
||
|
use bit_vec::BitVec;
|
||
|
use grin_chain as chain;
|
||
|
use grin_core as core;
|
||
|
use grin_util as util;
|
||
|
|
||
|
#[test]
|
||
|
fn test_bitmap_accumulator() {
|
||
|
util::init_test_logger();
|
||
|
|
||
|
let mut accumulator = BitmapAccumulator::new();
|
||
|
assert_eq!(accumulator.root(), Hash::default());
|
||
|
|
||
|
// 1000... (rebuild from 0, setting [0] true)
|
||
|
accumulator.apply(vec![0], vec![0], 1).unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(0, true);
|
||
|
bit_vec.to_bytes().hash_with_index(0)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// 1100... (rebuild from 0, setting [0, 1] true)
|
||
|
accumulator.apply(vec![0], vec![0, 1], 2).unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(0, true);
|
||
|
bit_vec.set(1, true);
|
||
|
bit_vec.to_bytes().hash_with_index(0)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// 0100... (rebuild from 0, setting [1] true, which will reset [0] false)
|
||
|
accumulator.apply(vec![0], vec![1], 2).unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(1, true);
|
||
|
let expected_bytes = bit_vec.to_bytes();
|
||
|
expected_bytes.hash_with_index(0)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// 0100... (rebuild from 1, setting [1] true)
|
||
|
accumulator.apply(vec![1], vec![1], 2).unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(1, true);
|
||
|
let expected_bytes = bit_vec.to_bytes();
|
||
|
expected_bytes.hash_with_index(0)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// 0100...0001 (rebuild from 0, setting [1, 1023] true)
|
||
|
accumulator.apply(vec![0], vec![1, 1023], 1024).unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(1, true);
|
||
|
bit_vec.set(1023, true);
|
||
|
let expected_bytes = bit_vec.to_bytes();
|
||
|
expected_bytes.hash_with_index(0)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// Now set bits such that we extend the bitmap accumulator across multiple 1024 bit chunks.
|
||
|
// We need a second bit_vec here to reflect the additional chunk.
|
||
|
// 0100...0001, 1000...0000 (rebuild from 0, setting [1, 1023, 1024] true)
|
||
|
accumulator
|
||
|
.apply(vec![0], vec![1, 1023, 1024], 1025)
|
||
|
.unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(1, true);
|
||
|
bit_vec.set(1023, true);
|
||
|
let mut bit_vec2 = BitVec::from_elem(1024, false);
|
||
|
bit_vec2.set(0, true);
|
||
|
let expected_bytes_0 = bit_vec.to_bytes();
|
||
|
let expected_bytes_1 = bit_vec2.to_bytes();
|
||
|
let expected_hash_0 = expected_bytes_0.hash_with_index(0);
|
||
|
let expected_hash_1 = expected_bytes_1.hash_with_index(1);
|
||
|
(expected_hash_0, expected_hash_1).hash_with_index(2)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// Just rebuild the second bitmap chunk.
|
||
|
// 0100...0001, 0100...0000 (rebuild from 1025, setting [1025] true)
|
||
|
accumulator.apply(vec![1025], vec![1025], 1026).unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(1, true);
|
||
|
bit_vec.set(1023, true);
|
||
|
let mut bit_vec2 = BitVec::from_elem(1024, false);
|
||
|
bit_vec2.set(1, true);
|
||
|
let expected_bytes_0 = bit_vec.to_bytes();
|
||
|
let expected_bytes_1 = bit_vec2.to_bytes();
|
||
|
let expected_hash_0 = expected_bytes_0.hash_with_index(0);
|
||
|
let expected_hash_1 = expected_bytes_1.hash_with_index(1);
|
||
|
(expected_hash_0, expected_hash_1).hash_with_index(2)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// Rebuild the first bitmap chunk and all chunks after it.
|
||
|
// 0100...0000, 0100...0000 (rebuild from 1, setting [1, 1025] true)
|
||
|
accumulator.apply(vec![1], vec![1, 1025], 1026).unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(1, true);
|
||
|
let mut bit_vec2 = BitVec::from_elem(1024, false);
|
||
|
bit_vec2.set(1, true);
|
||
|
let expected_bytes_0 = bit_vec.to_bytes();
|
||
|
let expected_bytes_1 = bit_vec2.to_bytes();
|
||
|
let expected_hash_0 = expected_bytes_0.hash_with_index(0);
|
||
|
let expected_hash_1 = expected_bytes_1.hash_with_index(1);
|
||
|
(expected_hash_0, expected_hash_1).hash_with_index(2)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// Make sure we handle the case where the first chunk is all 0s
|
||
|
// 0000...0000, 0100...0000 (rebuild from 1, setting [1025] true)
|
||
|
accumulator.apply(vec![1], vec![1025], 1026).unwrap();
|
||
|
let expected_hash = {
|
||
|
let bit_vec = BitVec::from_elem(1024, false);
|
||
|
let mut bit_vec2 = BitVec::from_elem(1024, false);
|
||
|
bit_vec2.set(1, true);
|
||
|
let expected_bytes_0 = bit_vec.to_bytes();
|
||
|
let expected_bytes_1 = bit_vec2.to_bytes();
|
||
|
let expected_hash_0 = expected_bytes_0.hash_with_index(0);
|
||
|
let expected_hash_1 = expected_bytes_1.hash_with_index(1);
|
||
|
(expected_hash_0, expected_hash_1).hash_with_index(2)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// Check that removing the last bit in a chunk removes the now empty chunk
|
||
|
// if it is the rightmost chunk.
|
||
|
// 0000...0001 (rebuild from 1023, setting [1023] true)
|
||
|
accumulator.apply(vec![1023], vec![1023], 1024).unwrap();
|
||
|
let expected_hash = {
|
||
|
let mut bit_vec = BitVec::from_elem(1024, false);
|
||
|
bit_vec.set(1023, true);
|
||
|
let expected_bytes = bit_vec.to_bytes();
|
||
|
expected_bytes.hash_with_index(0)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
|
||
|
// Make sure we pad appropriately with 0s if we set a distant bit to 1.
|
||
|
// Start with an empty accumulator.
|
||
|
// 0000...0000, 0000...0000, 0000...0000, 0000...0001 (rebuild from 4095, setting [4095] true)
|
||
|
let mut accumulator = BitmapAccumulator::new();
|
||
|
accumulator.apply(vec![4095], vec![4095], 4096).unwrap();
|
||
|
let expected_hash = {
|
||
|
let bit_vec0 = BitVec::from_elem(1024, false);
|
||
|
let bit_vec1 = BitVec::from_elem(1024, false);
|
||
|
let bit_vec2 = BitVec::from_elem(1024, false);
|
||
|
let mut bit_vec3 = BitVec::from_elem(1024, false);
|
||
|
bit_vec3.set(1023, true);
|
||
|
|
||
|
let expected_bytes_0 = bit_vec0.to_bytes();
|
||
|
let expected_bytes_1 = bit_vec1.to_bytes();
|
||
|
let expected_bytes_2 = bit_vec2.to_bytes();
|
||
|
let expected_bytes_3 = bit_vec3.to_bytes();
|
||
|
|
||
|
let expected_hash_0 = expected_bytes_0.hash_with_index(0);
|
||
|
let expected_hash_1 = expected_bytes_1.hash_with_index(1);
|
||
|
let expected_hash_2 = (expected_hash_0, expected_hash_1).hash_with_index(2);
|
||
|
|
||
|
let expected_hash_3 = expected_bytes_2.hash_with_index(3);
|
||
|
let expected_hash_4 = expected_bytes_3.hash_with_index(4);
|
||
|
let expected_hash_5 = (expected_hash_3, expected_hash_4).hash_with_index(5);
|
||
|
|
||
|
(expected_hash_2, expected_hash_5).hash_with_index(6)
|
||
|
};
|
||
|
assert_eq!(accumulator.root(), expected_hash);
|
||
|
}
|