use core::iter;
use ff::PrimeField;
use incrementalmerkletree::{Hashable, Level};
use lazy_static::lazy_static;
use pasta_curves::Fp;
use crate::poseidon_hash;
pub const TREE_DEPTH: usize = 24;
pub(crate) const SHARD_HEIGHT: u8 = 4;
pub(crate) const MAX_CHECKPOINTS: usize = 1000;
lazy_static! {
pub(crate) static ref EMPTY_ROOTS: Vec<MerkleHashVote> = {
iter::empty()
.chain(Some(MerkleHashVote::empty_leaf()))
.chain(
(0..TREE_DEPTH).scan(MerkleHashVote::empty_leaf(), |state, l| {
let l = l as u8;
*state = MerkleHashVote::combine(l.into(), state, state);
Some(*state)
}),
)
.collect()
};
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct MerkleHashVote(pub(crate) Fp);
impl MerkleHashVote {
pub fn from_fp(value: Fp) -> Self {
MerkleHashVote(value)
}
pub fn inner(&self) -> Fp {
self.0
}
pub fn to_bytes(&self) -> [u8; 32] {
self.0.to_repr()
}
pub fn from_bytes(bytes: &[u8; 32]) -> Option<Self> {
Option::from(Fp::from_repr(*bytes).map(MerkleHashVote))
}
}
impl Hashable for MerkleHashVote {
fn empty_leaf() -> Self {
MerkleHashVote(poseidon_hash(Fp::zero(), Fp::zero()))
}
fn combine(_level: Level, left: &Self, right: &Self) -> Self {
MerkleHashVote(poseidon_hash(left.0, right.0))
}
fn empty_root(level: Level) -> Self {
EMPTY_ROOTS[usize::from(level)]
}
}