use crate::*;
use serde::{Deserialize, Serialize};
use thiserror::Error;
pub struct OneshotMerkleTree {
hash_list: Vec<Hash256>,
}
impl OneshotMerkleTree {
pub const EMPTY_HASH: Hash256 = Hash256::zero();
pub fn create(data: Vec<Hash256>) -> Self {
OneshotMerkleTree { hash_list: data }
}
pub fn create_merkle_proof(&self, key: Hash256) -> Option<MerkleProof> {
if !self.hash_list.contains(&key) {
return None;
}
let mut merkle_proof: MerkleProof = MerkleProof { proof: Vec::new() };
let mut merkle_tree: Vec<Vec<Hash256>> = Self::merkle_tree(&self.hash_list);
let mut target_hash: Hash256 = key;
merkle_tree.pop();
for level in merkle_tree {
for pair in level.chunks(2) {
if pair.contains(&target_hash) {
if pair.len() == 2 {
let is_right_node: bool = pair[0] == target_hash;
if is_right_node {
merkle_proof
.proof
.push(MerkleProofEntry::RightChild(pair[is_right_node as usize]))
} else {
merkle_proof
.proof
.push(MerkleProofEntry::LeftChild(pair[is_right_node as usize]))
}
target_hash = Hash256::aggregate(&pair[0], &pair[1]);
} else {
merkle_proof.proof.push(MerkleProofEntry::OnlyChild);
target_hash = Hash256::hash(pair[0]);
};
}
}
}
Some(merkle_proof)
}
fn merkle_tree(hash_list: &[Hash256]) -> Vec<Vec<Hash256>> {
let mut merkle_tree: Vec<Vec<Hash256>> = vec![hash_list.to_vec()];
while !Self::is_fully_created(&merkle_tree) {
let mut upper_level_hash_list: Vec<Hash256> = Vec::new();
for pair in merkle_tree.last().unwrap().chunks(2) {
if pair.len() == 2 {
upper_level_hash_list.push(Hash256::aggregate(&pair[0], &pair[1]));
} else {
upper_level_hash_list.push(Hash256::hash(pair[0]));
}
}
merkle_tree.push(upper_level_hash_list);
}
merkle_tree
}
fn is_fully_created(merkle_tree: &[Vec<Hash256>]) -> bool {
merkle_tree.last().unwrap().len() == 1
}
pub fn root(&self) -> Hash256 {
if self.hash_list.is_empty() {
Self::EMPTY_HASH
} else {
Self::merkle_tree(&self.hash_list)
.last()
.unwrap()
.last()
.unwrap()
.to_owned()
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct MerkleProof {
pub proof: Vec<MerkleProofEntry>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub enum MerkleProofEntry {
LeftChild(Hash256),
RightChild(Hash256),
OnlyChild,
}
#[derive(Error, Debug, Serialize, Deserialize, Clone)]
pub enum MerkleProofError {
#[error("malformed proof: {0}")]
MalformedProof(String),
#[error("unmatched string: expected {0} but found {1}")]
UnmatchedRoot(String, String),
}
impl MerkleProof {
pub fn verify(&self, root: Hash256, data: &[u8]) -> Result<(), MerkleProofError> {
let mut calculated_root: Hash256 = Hash256::hash(data);
for node in &self.proof {
calculated_root = match node {
MerkleProofEntry::LeftChild(pair_hash) => {
Hash256::aggregate(pair_hash, &calculated_root)
}
MerkleProofEntry::RightChild(pair_hash) => {
Hash256::aggregate(&calculated_root, pair_hash)
}
MerkleProofEntry::OnlyChild => Hash256::hash(calculated_root),
};
}
if root == calculated_root {
Ok(())
} else {
Err(MerkleProofError::UnmatchedRoot(
root.to_string(),
calculated_root.to_string(),
))
}
}
}
#[cfg(test)]
mod test {
use super::*;
fn create_hash_list(number: u8) -> Vec<Hash256> {
let mut hash_list: Vec<Hash256> = Vec::new();
for n in 0..number {
hash_list.push(Hash256::hash([n]));
}
hash_list
}
#[test]
fn create_merkle_proof_for_data_not_in_the_tree() {
let hash_list: Vec<Hash256> = create_hash_list(16);
let merkle_tree: OneshotMerkleTree = OneshotMerkleTree::create(hash_list);
let key: Hash256 = Hash256::hash([42]);
assert!(OneshotMerkleTree::create_merkle_proof(&merkle_tree, key).is_none());
}
#[test]
fn root_of_empty_tree() {
let merkle_tree: OneshotMerkleTree = OneshotMerkleTree::create(Vec::new());
assert_eq!(
OneshotMerkleTree::root(&merkle_tree),
OneshotMerkleTree::EMPTY_HASH
);
}
#[test]
fn verification_failure() {
let hash_list: Vec<Hash256> = create_hash_list(16);
let merkle_tree: OneshotMerkleTree = OneshotMerkleTree::create(hash_list);
let key: Hash256 = Hash256::hash([2]);
let merkle_proof: Option<MerkleProof> =
OneshotMerkleTree::create_merkle_proof(&merkle_tree, key);
let root_hash: Hash256 = OneshotMerkleTree::root(&merkle_tree);
assert!(merkle_proof.is_some());
assert!(root_hash != OneshotMerkleTree::EMPTY_HASH);
assert!(MerkleProof::verify(&merkle_proof.unwrap(), root_hash, &[42]).is_err());
}
#[test]
fn even_number_of_leaves_pow_of_two() {
let hash_list: Vec<Hash256> = create_hash_list(16);
let merkle_tree: OneshotMerkleTree = OneshotMerkleTree::create(hash_list);
let data: [u8; 1] = [2];
let key: Hash256 = Hash256::hash(data);
let merkle_proof: Option<MerkleProof> =
OneshotMerkleTree::create_merkle_proof(&merkle_tree, key);
let root_hash: Hash256 = OneshotMerkleTree::root(&merkle_tree);
assert!(merkle_proof.is_some());
assert!(root_hash != OneshotMerkleTree::EMPTY_HASH);
assert!(MerkleProof::verify(&merkle_proof.unwrap(), root_hash, &data).is_ok());
}
#[test]
fn even_number_of_leaves_not_pow_of_two() {
let hash_list: Vec<Hash256> = create_hash_list(10);
let merkle_tree: OneshotMerkleTree = OneshotMerkleTree::create(hash_list);
let key: Hash256 = Hash256::hash([9]);
let merkle_proof: Option<MerkleProof> =
OneshotMerkleTree::create_merkle_proof(&merkle_tree, key);
let root_hash: Hash256 = OneshotMerkleTree::root(&merkle_tree);
assert!(merkle_proof.is_some());
assert!(root_hash != OneshotMerkleTree::EMPTY_HASH);
assert!(MerkleProof::verify(&merkle_proof.unwrap(), root_hash, &[9]).is_ok());
}
#[test]
fn odd_number_of_leaves() {
let hash_list: Vec<Hash256> = create_hash_list(11);
let merkle_tree: OneshotMerkleTree = OneshotMerkleTree::create(hash_list);
let key: Hash256 = Hash256::hash([10]);
let merkle_proof: Option<MerkleProof> =
OneshotMerkleTree::create_merkle_proof(&merkle_tree, key);
let root_hash: Hash256 = OneshotMerkleTree::root(&merkle_tree);
assert!(merkle_proof.is_some());
assert!(root_hash != OneshotMerkleTree::EMPTY_HASH);
assert!(MerkleProof::verify(&merkle_proof.unwrap(), root_hash, &[10]).is_ok());
}
}