use std::marker::PhantomData;
use std::fmt;
use crypto::{Hash, CryptoHash, HashStream};
use super::{BaseIndex, BaseIndexIter, Fork, Snapshot, StorageValue};
use super::indexes_metadata::IndexType;
use self::key::{BitsRange, ChildKind, LEAF_KEY_PREFIX};
use self::node::{BranchNode, Node};
pub use self::key::{KEY_SIZE as PROOF_MAP_KEY_SIZE, ProofMapKey, ProofPath};
pub use self::proof::{BranchProofNode, MapProof, ProofNode};
#[cfg(test)]
mod tests;
mod key;
mod node;
mod proof;
pub struct ProofMapIndex<T, K, V> {
base: BaseIndex<T>,
_k: PhantomData<K>,
_v: PhantomData<V>,
}
#[derive(Debug)]
pub struct ProofMapIndexIter<'a, K, V> {
base_iter: BaseIndexIter<'a, ProofPath, V>,
_k: PhantomData<K>,
}
#[derive(Debug)]
pub struct ProofMapIndexKeys<'a, K> {
base_iter: BaseIndexIter<'a, ProofPath, ()>,
_k: PhantomData<K>,
}
#[derive(Debug)]
pub struct ProofMapIndexValues<'a, V> {
base_iter: BaseIndexIter<'a, ProofPath, V>,
}
enum RemoveResult {
KeyNotFound,
Leaf,
Branch((ProofPath, Hash)),
UpdateHash(Hash),
}
impl<T, K, V> ProofMapIndex<T, K, V>
where
T: AsRef<Snapshot>,
K: ProofMapKey,
V: StorageValue,
{
pub fn new<S: AsRef<str>>(name: S, view: T) -> Self {
ProofMapIndex {
base: BaseIndex::new(name, IndexType::ProofMap, view),
_k: PhantomData,
_v: PhantomData,
}
}
pub fn with_prefix<S: AsRef<str>>(name: S, prefix: Vec<u8>, view: T) -> Self {
ProofMapIndex {
base: BaseIndex::with_prefix(name, prefix, IndexType::ProofMap, view),
_k: PhantomData,
_v: PhantomData,
}
}
fn get_root_key(&self) -> Option<ProofPath> {
self.base.iter::<_, ProofPath, _>(&()).next().map(
|(k, _): (ProofPath, ())| k,
)
}
fn get_root_node(&self) -> Option<(ProofPath, Node<V>)> {
match self.get_root_key() {
Some(key) => {
let node = self.get_node_unchecked(&key);
Some((key, node))
}
None => None,
}
}
fn get_node_unchecked(&self, key: &ProofPath) -> Node<V> {
if key.is_leaf() {
Node::Leaf(self.base.get(key).unwrap())
} else {
Node::Branch(self.base.get(key).unwrap())
}
}
fn construct_proof(
&self,
current_branch: &BranchNode,
searched_path: &ProofPath,
) -> Option<ProofNode<V>> {
let child_path = current_branch.child_path(searched_path.bit(0)).start_from(
searched_path
.start(),
);
let c_pr_l = child_path.common_prefix_len(searched_path);
debug_assert!(c_pr_l > 0);
if c_pr_l < child_path.len() {
return None;
}
let res: ProofNode<V> = match self.get_node_unchecked(&child_path) {
Node::Leaf(child_value) => ProofNode::Leaf(child_value),
Node::Branch(child_branch) => {
let l_s = child_branch.child_path(ChildKind::Left);
let r_s = child_branch.child_path(ChildKind::Right);
let suf_searched_path = searched_path.suffix(c_pr_l);
let proof_from_level_below: Option<ProofNode<V>> =
self.construct_proof(&child_branch, &suf_searched_path);
if let Some(child_proof) = proof_from_level_below {
let child_proof_pos = suf_searched_path.bit(0);
let neighbor_child_hash = *child_branch.child_hash(!child_proof_pos);
match child_proof_pos {
ChildKind::Left => ProofNode::Branch(BranchProofNode::LeftBranch {
left_node: Box::new(child_proof),
right_hash: neighbor_child_hash,
left_key: l_s.suffix(searched_path.start() + c_pr_l),
right_key: r_s.suffix(searched_path.start() + c_pr_l),
}),
ChildKind::Right => ProofNode::Branch(BranchProofNode::RightBranch {
left_hash: neighbor_child_hash,
right_node: Box::new(child_proof),
left_key: l_s.suffix(searched_path.start() + c_pr_l),
right_key: r_s.suffix(searched_path.start() + c_pr_l),
}),
}
} else {
let l_h = *child_branch.child_hash(ChildKind::Left); let r_h = *child_branch.child_hash(ChildKind::Right); ProofNode::Branch(BranchProofNode::BranchKeyNotFound {
left_hash: l_h,
right_hash: r_h,
left_key: l_s.suffix(searched_path.start() + c_pr_l),
right_key: r_s.suffix(searched_path.start() + c_pr_l),
})
}
}
};
Some(res)
}
pub fn root_hash(&self) -> Hash {
match self.get_root_node() {
Some((k, Node::Leaf(v))) => {
HashStream::new()
.update(k.as_bytes())
.update(v.hash().as_ref())
.hash()
}
Some((_, Node::Branch(branch))) => branch.hash(),
None => Hash::zero(),
}
}
pub fn get(&self, key: &K) -> Option<V> {
self.base.get(&ProofPath::new(key))
}
pub fn contains(&self, key: &K) -> bool {
self.base.contains(&ProofPath::new(key))
}
pub fn get_proof(&self, key: &K) -> MapProof<V> {
let searched_path = ProofPath::new(key);
match self.get_root_node() {
Some((root_db_key, Node::Leaf(root_value))) => {
if searched_path == root_db_key {
MapProof::LeafRootInclusive(root_db_key, root_value)
} else {
MapProof::LeafRootExclusive(root_db_key, root_value.hash())
}
}
Some((root_db_key, Node::Branch(branch))) => {
let root_path = root_db_key;
let l_s = branch.child_path(ChildKind::Left);
let r_s = branch.child_path(ChildKind::Right);
let c_pr_l = root_path.common_prefix_len(&searched_path);
if c_pr_l == root_path.len() {
let suf_searched_path = searched_path.suffix(c_pr_l);
let proof_from_level_below: Option<ProofNode<V>> =
self.construct_proof(&branch, &suf_searched_path);
if let Some(child_proof) = proof_from_level_below {
let child_proof_pos = suf_searched_path.bit(0);
let neighbor_child_hash = *branch.child_hash(!child_proof_pos);
match child_proof_pos {
ChildKind::Left => MapProof::Branch(BranchProofNode::LeftBranch {
left_node: Box::new(child_proof),
right_hash: neighbor_child_hash,
left_key: l_s,
right_key: r_s,
}),
ChildKind::Right => MapProof::Branch(BranchProofNode::RightBranch {
left_hash: neighbor_child_hash,
right_node: Box::new(child_proof),
left_key: l_s,
right_key: r_s,
}),
}
} else {
let l_h = *branch.child_hash(ChildKind::Left); let r_h = *branch.child_hash(ChildKind::Right); MapProof::Branch(BranchProofNode::BranchKeyNotFound {
left_hash: l_h,
right_hash: r_h,
left_key: l_s,
right_key: r_s,
})
}
} else {
let l_h = *branch.child_hash(ChildKind::Left); let r_h = *branch.child_hash(ChildKind::Right); MapProof::Branch(BranchProofNode::BranchKeyNotFound {
left_hash: l_h,
right_hash: r_h,
left_key: l_s,
right_key: r_s,
})
}
}
None => MapProof::Empty,
}
}
pub fn iter(&self) -> ProofMapIndexIter<K, V> {
ProofMapIndexIter {
base_iter: self.base.iter(&LEAF_KEY_PREFIX),
_k: PhantomData,
}
}
pub fn keys(&self) -> ProofMapIndexKeys<K> {
ProofMapIndexKeys {
base_iter: self.base.iter(&LEAF_KEY_PREFIX),
_k: PhantomData,
}
}
pub fn values(&self) -> ProofMapIndexValues<V> {
ProofMapIndexValues { base_iter: self.base.iter(&LEAF_KEY_PREFIX) }
}
pub fn iter_from(&self, from: &K) -> ProofMapIndexIter<K, V> {
ProofMapIndexIter {
base_iter: self.base.iter_from(&LEAF_KEY_PREFIX, &ProofPath::new(from)),
_k: PhantomData,
}
}
pub fn keys_from(&self, from: &K) -> ProofMapIndexKeys<K> {
ProofMapIndexKeys {
base_iter: self.base.iter_from(&LEAF_KEY_PREFIX, &ProofPath::new(from)),
_k: PhantomData,
}
}
pub fn values_from(&self, from: &K) -> ProofMapIndexValues<V> {
ProofMapIndexValues {
base_iter: self.base.iter_from(&LEAF_KEY_PREFIX, &ProofPath::new(from)),
}
}
}
impl<'a, K, V> ProofMapIndex<&'a mut Fork, K, V>
where
K: ProofMapKey,
V: StorageValue,
{
fn insert_leaf(&mut self, key: &ProofPath, value: V) -> Hash {
debug_assert!(key.is_leaf());
let hash = value.hash();
self.base.put(key, value);
hash
}
fn insert_branch(
&mut self,
parent: &BranchNode,
proof_path: &ProofPath,
value: V,
) -> (Option<u16>, Hash) {
let child_path = parent.child_path(proof_path.bit(0)).start_from(
proof_path.start(),
);
let i = child_path.common_prefix_len(proof_path);
if child_path.len() == i {
if child_path.is_leaf() {
let hash = self.insert_leaf(proof_path, value);
(None, hash)
} else {
match self.get_node_unchecked(&child_path) {
Node::Leaf(_) => {
unreachable!("Something went wrong!");
}
Node::Branch(mut branch) => {
let (j, h) = self.insert_branch(&branch, &proof_path.suffix(i), value);
match j {
Some(j) => {
branch.set_child(
proof_path.bit(i),
&proof_path.suffix(i).prefix(j),
&h,
);
}
None => branch.set_child_hash(proof_path.bit(i), &h),
};
let hash = branch.hash();
self.base.put(&child_path, branch);
(None, hash)
}
}
}
} else {
let suffix_path = proof_path.suffix(i);
let mut new_branch = BranchNode::empty();
let hash = self.insert_leaf(&suffix_path, value);
new_branch.set_child(suffix_path.bit(0), &suffix_path, &hash);
new_branch.set_child(
child_path.bit(i),
&child_path.suffix(i),
parent.child_hash(proof_path.bit(0)),
);
let hash = new_branch.hash();
self.base.put(&proof_path.prefix(i), new_branch);
(Some(i), hash)
}
}
pub fn put(&mut self, key: &K, value: V) {
let proof_path = ProofPath::new(key);
match self.get_root_node() {
Some((prefix, Node::Leaf(prefix_data))) => {
let prefix_path = prefix;
let i = prefix_path.common_prefix_len(&proof_path);
let leaf_hash = self.insert_leaf(&proof_path, value);
if i < proof_path.len() {
let mut branch = BranchNode::empty();
branch.set_child(proof_path.bit(i), &proof_path.suffix(i), &leaf_hash);
branch.set_child(
prefix_path.bit(i),
&prefix_path.suffix(i),
&prefix_data.hash(),
);
let new_prefix = proof_path.prefix(i);
self.base.put(&new_prefix, branch);
}
}
Some((prefix, Node::Branch(mut branch))) => {
let prefix_path = prefix;
let i = prefix_path.common_prefix_len(&proof_path);
if i == prefix_path.len() {
let suffix_path = proof_path.suffix(i);
let (j, h) = self.insert_branch(&branch, &suffix_path, value);
match j {
Some(j) => branch.set_child(suffix_path.bit(0), &suffix_path.prefix(j), &h),
None => branch.set_child_hash(suffix_path.bit(0), &h),
};
self.base.put(&prefix_path, branch);
} else {
let hash = self.insert_leaf(&proof_path, value);
let mut new_branch = BranchNode::empty();
new_branch.set_child(
prefix_path.bit(i),
&prefix_path.suffix(i),
&branch.hash(),
);
new_branch.set_child(proof_path.bit(i), &proof_path.suffix(i), &hash);
let new_prefix = prefix_path.prefix(i);
self.base.put(&new_prefix, new_branch);
}
}
None => {
self.insert_leaf(&proof_path, value);
}
}
}
fn remove_node(&mut self, parent: &BranchNode, proof_path: &ProofPath) -> RemoveResult {
let child_path = parent.child_path(proof_path.bit(0)).start_from(
proof_path.start(),
);
let i = child_path.common_prefix_len(proof_path);
if i == child_path.len() {
match self.get_node_unchecked(&child_path) {
Node::Leaf(_) => {
self.base.remove(proof_path);
return RemoveResult::Leaf;
}
Node::Branch(mut branch) => {
let suffix_path = proof_path.suffix(i);
match self.remove_node(&branch, &suffix_path) {
RemoveResult::Leaf => {
let child = !suffix_path.bit(0);
let key = branch.child_path(child);
let hash = branch.child_hash(child);
self.base.remove(&child_path);
return RemoveResult::Branch((key, *hash));
}
RemoveResult::Branch((key, hash)) => {
let new_child_path = key.start_from(suffix_path.start());
branch.set_child(suffix_path.bit(0), &new_child_path, &hash);
let h = branch.hash();
self.base.put(&child_path, branch);
return RemoveResult::UpdateHash(h);
}
RemoveResult::UpdateHash(hash) => {
branch.set_child_hash(suffix_path.bit(0), &hash);
let h = branch.hash();
self.base.put(&child_path, branch);
return RemoveResult::UpdateHash(h);
}
RemoveResult::KeyNotFound => return RemoveResult::KeyNotFound,
}
}
}
}
RemoveResult::KeyNotFound
}
pub fn remove(&mut self, key: &K) {
let proof_path = ProofPath::new(key);
match self.get_root_node() {
Some((prefix, Node::Leaf(_))) => {
let key = proof_path;
if key == prefix {
self.base.remove(&key);
}
}
Some((prefix, Node::Branch(mut branch))) => {
let i = prefix.common_prefix_len(&proof_path);
if i == prefix.len() {
let suffix_path = proof_path.suffix(i);
match self.remove_node(&branch, &suffix_path) {
RemoveResult::Leaf => self.base.remove(&prefix),
RemoveResult::Branch((key, hash)) => {
let new_child_path = key.start_from(suffix_path.start());
branch.set_child(suffix_path.bit(0), &new_child_path, &hash);
self.base.put(&prefix, branch);
}
RemoveResult::UpdateHash(hash) => {
branch.set_child_hash(suffix_path.bit(0), &hash);
self.base.put(&prefix, branch);
}
RemoveResult::KeyNotFound => return,
}
}
}
None => (),
}
}
pub fn clear(&mut self) {
self.base.clear()
}
}
impl<'a, T, K, V> ::std::iter::IntoIterator for &'a ProofMapIndex<T, K, V>
where
T: AsRef<Snapshot>,
K: ProofMapKey,
V: StorageValue,
{
type Item = (K::Owned, V);
type IntoIter = ProofMapIndexIter<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K, V> Iterator for ProofMapIndexIter<'a, K, V>
where
K: ProofMapKey,
V: StorageValue,
{
type Item = (K::Owned, V);
fn next(&mut self) -> Option<Self::Item> {
self.base_iter.next().map(
|(k, v)| (K::read(k.raw_key()), v),
)
}
}
impl<'a, K> Iterator for ProofMapIndexKeys<'a, K>
where
K: ProofMapKey,
{
type Item = K::Owned;
fn next(&mut self) -> Option<Self::Item> {
self.base_iter.next().map(|(k, _)| K::read(k.raw_key()))
}
}
impl<'a, V> Iterator for ProofMapIndexValues<'a, V>
where
V: StorageValue,
{
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
self.base_iter.next().map(|(_, v)| v)
}
}
#[derive(Debug)]
enum ProofMapIndexEntry<V: StorageValue + fmt::Debug> {
Branch {
hash: Hash,
prefix: ProofPath,
left: Box<ProofMapIndexEntry<V>>,
right: Box<ProofMapIndexEntry<V>>,
},
Leaf {
key: ProofPath,
hash: Hash,
value: V,
},
}
impl<V: StorageValue + fmt::Debug> ProofMapIndexEntry<V> {
fn dump<T, K>(
index: &ProofMapIndex<T, K, V>,
root_prefix: ProofPath,
root_node: Node<V>,
) -> ProofMapIndexEntry<V>
where
T: AsRef<Snapshot>,
K: ProofMapKey,
{
let root_hash = index.root_hash();
match root_node {
Node::Leaf(value) => ProofMapIndexEntry::Leaf {
key: root_prefix,
hash: root_hash,
value,
},
Node::Branch(branch) => {
let left = Box::new(Self::child_node(index, &branch, ChildKind::Left));
let right = Box::new(Self::child_node(index, &branch, ChildKind::Right));
ProofMapIndexEntry::Branch {
hash: root_hash,
prefix: root_prefix,
left,
right,
}
}
}
}
fn child_node<T, K>(
index: &ProofMapIndex<T, K, V>,
parent: &BranchNode,
kind: ChildKind,
) -> ProofMapIndexEntry<V>
where
T: AsRef<Snapshot>,
K: ProofMapKey,
{
let key = parent.child_path(kind);
let hash = *parent.child_hash(kind);
let node = index.get_node_unchecked(&key);
match node {
Node::Leaf(value) => ProofMapIndexEntry::Leaf { key, hash, value },
Node::Branch(branch) => {
let left = Box::new(Self::child_node(index, &branch, ChildKind::Left));
let right = Box::new(Self::child_node(index, &branch, ChildKind::Right));
ProofMapIndexEntry::Branch {
hash,
prefix: key,
left,
right,
}
}
}
}
}
impl<T, K, V> ::std::fmt::Debug for ProofMapIndex<T, K, V>
where
T: AsRef<Snapshot>,
K: ProofMapKey,
V: StorageValue + fmt::Debug,
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
if let Some((prefix, node)) = self.get_root_node() {
let root_entry = ProofMapIndexEntry::dump(self, prefix, node);
f.debug_struct("ProofMapIndex")
.field("entries", &root_entry)
.finish()
} else {
f.debug_struct("ProofMapIndex").finish()
}
}
}