use serde::{Serialize, Serializer};
use serde::ser::SerializeMap;
use std::fmt;
use crypto::{Hash, HashStream};
use super::super::{Error, StorageValue};
use super::key::{BitsRange, ChildKind, ProofMapKey, ProofPath, KEY_SIZE};
impl Serialize for ProofPath {
fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut repr = String::with_capacity(KEY_SIZE * 8);
let bpath = self;
for ind in 0..self.len() {
match bpath.bit(ind) {
ChildKind::Left => {
repr.push('0');
}
ChildKind::Right => {
repr.push('1');
}
}
}
ser.serialize_str(&repr)
}
}
pub enum MapProof<V> {
LeafRootInclusive(ProofPath, V),
LeafRootExclusive(ProofPath, Hash),
Empty,
Branch(BranchProofNode<V>),
}
pub enum ProofNode<V> {
Branch(BranchProofNode<V>),
Leaf(V),
}
pub enum BranchProofNode<V> {
BranchKeyNotFound {
left_hash: Hash,
right_hash: Hash,
left_key: ProofPath,
right_key: ProofPath,
},
LeftBranch {
left_node: Box<ProofNode<V>>,
right_hash: Hash,
left_key: ProofPath,
right_key: ProofPath,
},
RightBranch {
left_hash: Hash,
right_node: Box<ProofNode<V>>,
left_key: ProofPath,
right_key: ProofPath,
},
}
impl<V: StorageValue> MapProof<V> {
pub fn root_hash(&self) -> Hash {
use self::MapProof::*;
match *self {
Empty => Hash::zero(),
LeafRootInclusive(ref root_key, ref root_val) => {
HashStream::new()
.update(root_key.as_bytes())
.update(root_val.hash().as_ref())
.hash()
}
LeafRootExclusive(ref root_key, ref root_val_hash) => {
HashStream::new()
.update(root_key.as_bytes())
.update(root_val_hash.as_ref())
.hash()
}
Branch(ref branch) => branch.root_hash(),
}
}
}
impl<V: StorageValue> ProofNode<V> {
fn root_hash(&self) -> Hash {
use self::ProofNode::*;
match *self {
Leaf(ref val) => val.hash(),
Branch(ref branch) => branch.root_hash(),
}
}
}
impl<V: StorageValue> BranchProofNode<V> {
fn root_hash(&self) -> Hash {
use self::BranchProofNode::*;
match *self {
BranchKeyNotFound {
ref left_hash,
ref right_hash,
ref left_key,
ref right_key,
} => {
HashStream::new()
.update(left_hash.as_ref())
.update(right_hash.as_ref())
.update(left_key.as_bytes())
.update(right_key.as_bytes())
.hash()
}
LeftBranch {
ref left_node,
ref right_hash,
ref left_key,
ref right_key,
} => {
HashStream::new()
.update(left_node.root_hash().as_ref())
.update(right_hash.as_ref())
.update(left_key.as_bytes())
.update(right_key.as_bytes())
.hash()
}
RightBranch {
ref left_hash,
ref right_node,
ref left_key,
ref right_key,
} => {
HashStream::new()
.update(left_hash.as_ref())
.update(right_node.root_hash().as_ref())
.update(left_key.as_bytes())
.update(right_key.as_bytes())
.hash()
}
}
}
}
impl<V: Serialize> Serialize for MapProof<V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use self::MapProof::*;
match *self {
Empty => {
let state = serializer.serialize_map(Some(0))?;
state.end()
}
LeafRootInclusive(ref key, ref value) => {
#[derive(Serialize)]
struct SerializeHelper<'a, V: Serialize + 'a> {
val: &'a V,
}
let helper = SerializeHelper { val: value };
let mut state = serializer.serialize_map(Some(1))?;
state.serialize_entry(key, &helper)?;
state.end()
}
LeafRootExclusive(ref key, ref hash) => {
let mut state = serializer.serialize_map(Some(1))?;
state.serialize_entry(key, hash)?;
state.end()
}
Branch(ref branch) => branch.serialize(serializer),
}
}
}
impl<V: Serialize> Serialize for BranchProofNode<V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use self::BranchProofNode::*;
let mut state = serializer.serialize_map(Some(2))?;
match *self {
BranchKeyNotFound {
left_hash: ref lhash,
right_hash: ref rhash,
left_key: ref lkey,
right_key: ref rkey,
} => {
state.serialize_entry(lkey, lhash)?;
state.serialize_entry(rkey, rhash)?;
}
LeftBranch {
left_node: ref proof,
right_hash: ref rhash,
left_key: ref lkey,
right_key: ref rkey,
} => {
state.serialize_entry(lkey, proof)?;
state.serialize_entry(rkey, rhash)?;
}
RightBranch {
left_hash: ref lhash,
right_node: ref proof,
left_key: ref lkey,
right_key: ref rkey,
} => {
state.serialize_entry(lkey, lhash)?;
state.serialize_entry(rkey, proof)?;
}
}
state.end()
}
}
impl<V: Serialize> Serialize for ProofNode<V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use self::ProofNode::*;
match *self {
Leaf(ref value) => {
#[derive(Serialize)]
struct SerializeHelper<'a, V: Serialize + 'a> {
val: &'a V,
}
let helper = SerializeHelper { val: value };
helper.serialize(serializer)
}
Branch(ref branch) => branch.serialize(serializer),
}
}
}
impl<V: fmt::Debug + StorageValue> MapProof<V> {
pub fn validate<K: ProofMapKey>(&self, key: &K, root_hash: Hash) -> Result<Option<&V>, Error> {
let searched_key = ProofPath::new(key);
use self::MapProof::*;
let res: Option<&V> = match *self {
Empty => None,
LeafRootInclusive(ref root_path, ref val) => {
let root_key = root_path;
if root_key != &searched_key {
return Err(Error::new(format!(
"Proof is inconsistent with searched key: \
{:?}. Proof: {:?}. ",
searched_key,
self
)));
}
Some(val)
}
LeafRootExclusive(ref root_path, _) => {
let root_key = root_path;
if root_key == &searched_key {
return Err(Error::new(format!(
"Proof is inconsistent with searched key: \
{:?}. Proof: {:?} ",
searched_key,
self
)));
}
None
}
Branch(ref branch) => branch.validate(&searched_key)?,
};
let proof_hash = self.root_hash();
if proof_hash != root_hash {
return Err(Error::new(format!(
"The proof doesn't match the expected hash! \
Expected: {:?} , from proof: {:?}",
root_hash,
proof_hash
)));
}
Ok(res)
}
}
impl<V: fmt::Debug> BranchProofNode<V> {
fn validate(&self, searched_key: &ProofPath) -> Result<Option<&V>, Error> {
use self::BranchProofNode::*;
let res: Option<&V> = match *self {
LeftBranch {
left_node: ref proof,
left_key: ref left_path_key,
..
} => {
let left_path = left_path_key;
if !searched_key.starts_with(left_path) {
return Err(Error::new(format!(
"Proof is inconsistent with searched_key: \
{:?}. Proof: {:?}",
searched_key,
self
)));
}
proof.validate_consistency(left_path, searched_key)?
}
RightBranch {
right_node: ref proof,
right_key: ref right_path_key,
..
} => {
let right_path = right_path_key;
if !searched_key.starts_with(right_path) {
return Err(Error::new(format!(
"Proof is inconsistent with searched_key: \
{:?}. Proof: {:?}",
searched_key,
self
)));
}
proof.validate_consistency(right_path, searched_key)?
}
BranchKeyNotFound {
left_key: ref left_path_key,
right_key: ref right_path_key,
..
} => {
let left_path = left_path_key;
let right_path = right_path_key;
if searched_key.starts_with(left_path) || searched_key.starts_with(right_path) {
return Err(Error::new(format!(
"Proof is inconsistent with searched_key: \
{:?}. Proof: {:?}",
searched_key,
self
)));
}
None
}
};
Ok(res)
}
fn validate_consistency<'a>(
&'a self,
parent_path: &ProofPath,
searched_key: &ProofPath,
) -> Result<Option<&'a V>, Error> {
use self::BranchProofNode::*;
let res: Option<&V> = match *self {
LeftBranch {
left_node: ref proof,
left_key: ref left_path_key,
right_key: ref right_path_key,
..
} => {
let left_path = left_path_key.start_from(0);
let right_path = right_path_key.start_from(0);
if !left_path.starts_with(parent_path) || !right_path.starts_with(parent_path) {
return Err(Error::new(format!(
"Proof is inconsistent with itself: Proof: \
{:?} . Parent path: {:?}",
self,
parent_path
)));
}
if !searched_key.starts_with(&left_path) {
return Err(Error::new(format!(
"Proof is inconsistent with searched_key: \
{:?}. Proof: {:?}",
searched_key,
self
)));
}
proof.validate_consistency(&left_path, searched_key)?
}
RightBranch {
right_node: ref proof,
left_key: ref left_path_key,
right_key: ref right_path_key,
..
} => {
let left_path = left_path_key.start_from(0);
let right_path = right_path_key.start_from(0);
if !left_path.starts_with(parent_path) || !right_path.starts_with(parent_path) {
return Err(Error::new(format!(
"Proof is inconsistent with itself: Proof: \
{:?} . Parent path: {:?}",
self,
parent_path
)));
}
if !searched_key.starts_with(&right_path) {
return Err(Error::new(format!(
"Proof is inconsistent with searched_key: \
{:?}. Proof: {:?}",
searched_key,
self
)));
}
proof.validate_consistency(&right_path, searched_key)?
}
BranchKeyNotFound {
left_key: ref left_path_key,
right_key: ref right_path_key,
..
} => {
let left_path = left_path_key.start_from(0);
let right_path = right_path_key.start_from(0);
if !left_path.starts_with(parent_path) || !right_path.starts_with(parent_path) {
return Err(Error::new(format!(
"Proof is inconsistent with itself: Proof: \
{:?} . Parent path: {:?}",
self,
parent_path
)));
}
if searched_key.starts_with(&left_path) || searched_key.starts_with(&right_path) {
return Err(Error::new(format!(
"Proof is inconsistent with searched_key: \
{:?}. Proof: {:?}",
searched_key,
self
)));
}
None
}
};
Ok(res)
}
}
impl<V: fmt::Debug> ProofNode<V> {
fn validate_consistency<'a>(
&'a self,
parent_key: &ProofPath,
searched_key: &ProofPath,
) -> Result<Option<&'a V>, Error> {
use self::ProofNode::*;
let res: Option<&V> = match *self {
Leaf(ref val) => {
if searched_key != parent_key {
return Err(Error::new(format!(
"Proof is inconsistent with searched_key: \
{:?}. Parent path: {:?} ",
searched_key,
parent_key
)));
}
Some(val)
}
Branch(ref branch) => branch.validate_consistency(parent_key, searched_key)?,
};
Ok(res)
}
}
impl<V: fmt::Debug> fmt::Debug for MapProof<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::MapProof::*;
match *self {
LeafRootInclusive(ref db_key, ref val) => {
write!(f, "{{\"path\":{:?},{:?}}}", db_key, val)
}
LeafRootExclusive(ref db_key, ref val_hash) => {
write!(f, "{{\"path\":{:?},\"val_hash\":{:?}}}", db_key, val_hash)
}
Empty => write!(f, "{{}}"),
Branch(ref branch) => write!(f, "{:?}", branch),
}
}
}
impl<V: fmt::Debug> fmt::Debug for ProofNode<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ProofNode::*;
match *self {
Branch(ref branch) => write!(f, "{:?}", branch),
Leaf(ref val) => write!(f, "{{\"val\":{:?}}}", val),
}
}
}
impl<V: fmt::Debug> fmt::Debug for BranchProofNode<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::BranchProofNode::*;
match *self {
LeftBranch {
ref left_node,
ref right_hash,
ref left_key,
ref right_key,
} => {
write!(
f,
"{{\"left\":{:?},\"right\":{:?},\"left_path\":{:?},\"right_path\":{:?}}}",
left_node,
right_hash,
left_key,
right_key
)
}
RightBranch {
ref left_hash,
ref right_node,
ref left_key,
ref right_key,
} => {
write!(
f,
"{{\"left\":{:?},\"right\":{:?},\"left_path\":{:?},\"right_path\":{:?}}}",
left_hash,
right_node,
left_key,
right_key
)
}
BranchKeyNotFound {
ref left_hash,
ref right_hash,
ref left_key,
ref right_key,
} => {
write!(
f,
"{{\"left\":{:?},\"right\":{:?},\"left_path\":{:?},\"right_path\":{:?}}}",
left_hash,
right_hash,
left_key,
right_key
)
}
}
}
}