use ethereum_types::H256;
use ethrex_crypto::Crypto;
use ethrex_rlp::{decode::RLPDecode, encode::RLPEncode, error::RLPDecodeError, structs::Encoder};
use crate::rkyv_utils::H256Wrapper;
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Hash,
PartialOrd,
Ord,
Eq,
serde::Serialize,
serde::Deserialize,
rkyv::Serialize,
rkyv::Deserialize,
rkyv::Archive,
)]
pub enum NodeHash {
Hashed(#[rkyv(with=H256Wrapper)] H256),
Inline(([u8; 31], u8)),
}
impl AsRef<[u8]> for NodeHash {
fn as_ref(&self) -> &[u8] {
match self {
NodeHash::Inline((slice, len)) => &slice[0..(*len as usize)],
NodeHash::Hashed(x) => x.as_bytes(),
}
}
}
impl NodeHash {
pub fn from_encoded(encoded: &[u8], crypto: &dyn Crypto) -> NodeHash {
if encoded.len() >= 32 {
let hash = crypto.keccak256(encoded);
NodeHash::Hashed(H256::from_slice(&hash))
} else {
NodeHash::from_slice(encoded)
}
}
pub(crate) fn from_slice(slice: &[u8]) -> NodeHash {
match slice.len() {
0..32 => {
let mut buffer = [0; 31];
buffer[0..slice.len()].copy_from_slice(slice);
NodeHash::Inline((buffer, slice.len() as u8))
}
_ => NodeHash::Hashed(H256::from_slice(slice)),
}
}
pub fn finalize(self, crypto: &dyn Crypto) -> H256 {
match self {
NodeHash::Inline(_) => H256(crypto.keccak256(self.as_ref())),
NodeHash::Hashed(x) => x,
}
}
pub fn is_valid(&self) -> bool {
!matches!(self, NodeHash::Inline(v) if v.1 == 0)
}
pub fn encode<'a>(&self, mut encoder: Encoder<'a>) -> Encoder<'a> {
match self {
NodeHash::Inline(_) => {
encoder = encoder.encode_raw(self.as_ref());
}
NodeHash::Hashed(_) => {
encoder = encoder.encode_bytes(self.as_ref());
}
}
encoder
}
pub fn len(&self) -> usize {
match self {
NodeHash::Hashed(h256) => h256.as_bytes().len(),
NodeHash::Inline(value) => value.1 as usize,
}
}
pub fn is_empty(&self) -> bool {
match self {
NodeHash::Hashed(h256) => h256.as_bytes().is_empty(),
NodeHash::Inline(value) => value.1 == 0,
}
}
}
impl From<H256> for NodeHash {
fn from(value: H256) -> Self {
NodeHash::Hashed(value)
}
}
impl From<NodeHash> for Vec<u8> {
fn from(val: NodeHash) -> Self {
val.as_ref().to_vec()
}
}
impl From<&NodeHash> for Vec<u8> {
fn from(val: &NodeHash) -> Self {
val.as_ref().to_vec()
}
}
impl Default for NodeHash {
fn default() -> Self {
NodeHash::Inline(([0; 31], 0))
}
}
impl RLPEncode for NodeHash {
fn encode(&self, buf: &mut dyn bytes::BufMut) {
RLPEncode::encode(&Into::<Vec<u8>>::into(self), buf)
}
fn length(&self) -> usize {
match self {
NodeHash::Hashed(_) => 33, NodeHash::Inline((_, 0)) => 1, NodeHash::Inline((_, len)) => *len as usize, }
}
}
impl RLPDecode for NodeHash {
fn decode_unfinished(rlp: &[u8]) -> Result<(Self, &[u8]), ethrex_rlp::error::RLPDecodeError> {
let (hash, rest): (Vec<u8>, &[u8]);
(hash, rest) = RLPDecode::decode_unfinished(rlp)?;
if hash.len() > 32 {
return Err(RLPDecodeError::InvalidLength);
}
let hash = NodeHash::from_slice(&hash);
Ok((hash, rest))
}
}