use std::marker::PhantomData;
use digest::{Digest, FixedOutput};
use serde::{Deserialize, Serialize};
use crate::StmResult;
use crate::codec;
use super::MerkleTreeError;
#[cfg(feature = "future_snark")]
#[allow(dead_code)]
#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct MerklePath<D: Digest> {
pub(crate) values: Vec<Vec<u8>>,
pub(crate) index: usize,
hasher: PhantomData<D>,
}
#[cfg(feature = "future_snark")]
#[allow(dead_code)]
impl<D: Digest + FixedOutput> MerklePath<D> {
pub(crate) fn new(values: Vec<Vec<u8>>, index: usize) -> Self {
Self {
values,
index,
hasher: Default::default(),
}
}
pub fn to_bytes(&self) -> StmResult<Vec<u8>> {
codec::to_cbor_bytes(self)
}
pub fn from_bytes(bytes: &[u8]) -> StmResult<MerklePath<D>> {
codec::from_versioned_bytes(bytes, Self::from_bytes_legacy)
}
fn from_bytes_legacy(bytes: &[u8]) -> StmResult<MerklePath<D>> {
let mut u64_bytes = [0u8; 8];
u64_bytes.copy_from_slice(bytes.get(..8).ok_or(MerkleTreeError::SerializationError)?);
let index = usize::try_from(u64::from_be_bytes(u64_bytes))
.map_err(|_| MerkleTreeError::SerializationError)?;
u64_bytes.copy_from_slice(bytes.get(8..16).ok_or(MerkleTreeError::SerializationError)?);
let len = usize::try_from(u64::from_be_bytes(u64_bytes))
.map_err(|_| MerkleTreeError::SerializationError)?;
let mut values = Vec::with_capacity(len);
for i in 0..len {
values.push(
bytes
.get(
16 + i * <D as Digest>::output_size()
..16 + (i + 1) * <D as Digest>::output_size(),
)
.ok_or(MerkleTreeError::SerializationError)?
.to_vec(),
);
}
Ok(MerklePath {
values,
index,
hasher: PhantomData,
})
}
}
#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct MerkleBatchPath<D: Digest + FixedOutput> {
pub(crate) values: Vec<Vec<u8>>,
pub(crate) indices: Vec<usize>,
pub(crate) hasher: PhantomData<D>,
}
impl<D: Digest + FixedOutput> MerkleBatchPath<D> {
pub(crate) fn new(values: Vec<Vec<u8>>, indices: Vec<usize>) -> MerkleBatchPath<D> {
Self {
values,
indices,
hasher: Default::default(),
}
}
pub fn to_bytes(&self) -> StmResult<Vec<u8>> {
codec::to_cbor_bytes(self)
}
pub fn from_bytes(bytes: &[u8]) -> StmResult<Self> {
codec::from_versioned_bytes(bytes, Self::from_bytes_legacy)
}
fn from_bytes_legacy(bytes: &[u8]) -> StmResult<Self> {
let mut u64_bytes = [0u8; 8];
u64_bytes.copy_from_slice(&bytes[..8]);
let len_v = usize::try_from(u64::from_be_bytes(u64_bytes))
.map_err(|_| MerkleTreeError::SerializationError)?;
u64_bytes.copy_from_slice(&bytes[8..16]);
let len_i = usize::try_from(u64::from_be_bytes(u64_bytes))
.map_err(|_| MerkleTreeError::SerializationError)?;
let mut values = Vec::with_capacity(len_v);
for i in 0..len_v {
values.push(
bytes[16 + i * <D as Digest>::output_size()
..16 + (i + 1) * <D as Digest>::output_size()]
.to_vec(),
);
}
let offset = 16 + len_v * <D as Digest>::output_size();
let mut indices = Vec::with_capacity(len_v);
for i in 0..len_i {
u64_bytes.copy_from_slice(&bytes[offset + i * 8..offset + (i + 1) * 8]);
indices.push(
usize::try_from(u64::from_be_bytes(u64_bytes))
.map_err(|_| MerkleTreeError::SerializationError)?,
);
}
Ok(MerkleBatchPath {
values,
indices,
hasher: PhantomData,
})
}
}
#[cfg(test)]
mod tests {
use crate::{
MembershipDigest, MithrilMembershipDigest, VerificationKeyForConcatenation,
membership_commitment::MerkleTreeConcatenationLeaf,
membership_commitment::merkle_tree::tree::MerkleTree,
};
use super::*;
type ConcatenationHash = <MithrilMembershipDigest as MembershipDigest>::ConcatenationHash;
mod golden_cbor_batch_path {
use super::*;
const GOLDEN_CBOR_BYTES: &[u8; 155] = &[
1, 163, 102, 118, 97, 108, 117, 101, 115, 130, 152, 32, 24, 57, 20, 24, 139, 24, 83,
24, 194, 24, 218, 24, 202, 24, 66, 24, 139, 24, 49, 24, 144, 24, 148, 24, 132, 6, 2,
24, 97, 24, 112, 24, 38, 24, 29, 24, 60, 24, 139, 24, 233, 24, 189, 24, 95, 24, 168,
24, 204, 24, 84, 24, 33, 24, 201, 24, 140, 23, 22, 152, 32, 24, 128, 24, 78, 24, 52,
24, 132, 24, 35, 24, 118, 24, 64, 24, 83, 24, 60, 24, 38, 24, 181, 24, 197, 24, 144,
24, 188, 24, 235, 24, 225, 2, 24, 223, 24, 135, 24, 104, 24, 193, 24, 226, 24, 148, 24,
170, 24, 114, 24, 26, 24, 173, 24, 161, 24, 34, 24, 70, 24, 241, 24, 90, 103, 105, 110,
100, 105, 99, 101, 115, 130, 0, 2, 102, 104, 97, 115, 104, 101, 114, 246,
];
fn golden_value() -> MerkleBatchPath<ConcatenationHash> {
let nr = 4;
let pks = vec![VerificationKeyForConcatenation::default(); nr];
let leaves = pks
.into_iter()
.enumerate()
.map(|(i, k)| MerkleTreeConcatenationLeaf(k, i as u64))
.collect::<Vec<_>>();
let tree = MerkleTree::<ConcatenationHash, MerkleTreeConcatenationLeaf>::new(&leaves);
tree.compute_merkle_tree_batch_path(vec![0, 2])
}
#[test]
fn cbor_golden_bytes_can_be_decoded() {
let decoded = MerkleBatchPath::<ConcatenationHash>::from_bytes(GOLDEN_CBOR_BYTES)
.expect("CBOR golden bytes deserialization should not fail");
let expected = golden_value();
assert_eq!(expected.values, decoded.values);
assert_eq!(expected.indices, decoded.indices);
}
#[test]
fn cbor_encoding_is_stable() {
let bytes = MerkleBatchPath::to_bytes(&golden_value())
.expect("CBOR serialization should not fail");
assert_eq!(GOLDEN_CBOR_BYTES.as_slice(), bytes.as_slice());
}
}
#[cfg(feature = "future_snark")]
mod golden_cbor_path {
use super::*;
fn golden_value() -> MerklePath<ConcatenationHash> {
let nr = 4;
let pks = vec![VerificationKeyForConcatenation::default(); nr];
let leaves = pks
.into_iter()
.enumerate()
.map(|(i, k)| MerkleTreeConcatenationLeaf(k, i as u64))
.collect::<Vec<_>>();
let tree = MerkleTree::<ConcatenationHash, MerkleTreeConcatenationLeaf>::new(&leaves);
tree.compute_merkle_tree_path(0)
}
const GOLDEN_CBOR_BYTES: &[u8; 149] = &[
1, 163, 102, 118, 97, 108, 117, 101, 115, 130, 152, 32, 24, 57, 20, 24, 139, 24, 83,
24, 194, 24, 218, 24, 202, 24, 66, 24, 139, 24, 49, 24, 144, 24, 148, 24, 132, 6, 2,
24, 97, 24, 112, 24, 38, 24, 29, 24, 60, 24, 139, 24, 233, 24, 189, 24, 95, 24, 168,
24, 204, 24, 84, 24, 33, 24, 201, 24, 140, 23, 22, 152, 32, 24, 75, 24, 152, 24, 193,
24, 39, 24, 81, 24, 31, 24, 79, 24, 34, 24, 232, 24, 192, 24, 38, 24, 94, 24, 109, 24,
160, 24, 171, 24, 148, 24, 173, 24, 203, 24, 85, 24, 33, 24, 116, 20, 24, 62, 24, 51,
1, 24, 112, 24, 227, 4, 24, 226, 24, 56, 24, 30, 24, 27, 101, 105, 110, 100, 101, 120,
0, 102, 104, 97, 115, 104, 101, 114, 246,
];
#[test]
fn cbor_golden_bytes_can_be_decoded() {
let decoded = MerklePath::<ConcatenationHash>::from_bytes(GOLDEN_CBOR_BYTES)
.expect("CBOR golden bytes deserialization should not fail");
assert_eq!(
golden_value().to_bytes().expect("serialization should not fail"),
decoded.to_bytes().expect("serialization should not fail"),
);
}
#[test]
fn cbor_encoding_is_stable() {
let bytes = golden_value().to_bytes().expect("CBOR serialization should not fail");
assert_eq!(GOLDEN_CBOR_BYTES.as_slice(), bytes.as_slice());
}
}
}