use borsh::BorshSerialize;
use light_compressed_account::hash_to_bn254_field_size_be;
use light_hasher::{errors::HasherError, sha256::Sha256BE, Hasher, Poseidon};
use light_program_profiler::profile;
use super::TokenData;
use crate::{state::compressed_token::CompressedTokenAccountState, NATIVE_MINT};
impl TokenData {
pub fn is_native(&self) -> bool {
self.mint == NATIVE_MINT
}
pub fn hash_with_hashed_values(
hashed_mint: &[u8; 32],
hashed_owner: &[u8; 32],
amount_bytes: &[u8; 32],
hashed_delegate: &Option<&[u8; 32]>,
) -> Result<[u8; 32], HasherError> {
Self::hash_inputs_with_hashed_values::<false>(
hashed_mint,
hashed_owner,
amount_bytes,
hashed_delegate,
)
}
pub fn hash_frozen_with_hashed_values(
hashed_mint: &[u8; 32],
hashed_owner: &[u8; 32],
amount_bytes: &[u8; 32],
hashed_delegate: &Option<&[u8; 32]>,
) -> Result<[u8; 32], HasherError> {
Self::hash_inputs_with_hashed_values::<true>(
hashed_mint,
hashed_owner,
amount_bytes,
hashed_delegate,
)
}
pub fn hash_inputs_with_hashed_values<const FROZEN_INPUTS: bool>(
mint: &[u8; 32],
owner: &[u8; 32],
amount_bytes: &[u8],
hashed_delegate: &Option<&[u8; 32]>,
) -> Result<[u8; 32], HasherError> {
let mut hash_inputs = vec![mint.as_slice(), owner.as_slice(), amount_bytes];
if let Some(hashed_delegate) = hashed_delegate {
hash_inputs.push(hashed_delegate.as_slice());
}
let mut state_bytes = [0u8; 32];
if FROZEN_INPUTS {
state_bytes[31] = CompressedTokenAccountState::Frozen as u8;
hash_inputs.push(&state_bytes[..]);
}
Poseidon::hashv(hash_inputs.as_slice())
}
}
impl TokenData {
#[profile]
#[inline(always)]
pub fn hash_sha_flat(&self) -> Result<[u8; 32], HasherError> {
let bytes = self.try_to_vec().map_err(|_| HasherError::BorshError)?;
Sha256BE::hash(bytes.as_slice())
}
pub fn hash_v2(&self) -> Result<[u8; 32], HasherError> {
self._hash::<true>()
}
pub fn hash_v1(&self) -> Result<[u8; 32], HasherError> {
self._hash::<false>()
}
fn _hash<const BATCHED: bool>(&self) -> Result<[u8; 32], HasherError> {
let hashed_mint = hash_to_bn254_field_size_be(self.mint.to_bytes().as_slice());
let hashed_owner = hash_to_bn254_field_size_be(self.owner.to_bytes().as_slice());
let mut amount_bytes = [0u8; 32];
if BATCHED {
amount_bytes[24..].copy_from_slice(self.amount.to_be_bytes().as_slice());
} else {
amount_bytes[24..].copy_from_slice(self.amount.to_le_bytes().as_slice());
}
let hashed_delegate;
let hashed_delegate_option = if let Some(delegate) = self.delegate {
hashed_delegate = hash_to_bn254_field_size_be(delegate.to_bytes().as_slice());
Some(&hashed_delegate)
} else {
None
};
if self.state != CompressedTokenAccountState::Initialized as u8 {
Self::hash_inputs_with_hashed_values::<true>(
&hashed_mint,
&hashed_owner,
&amount_bytes,
&hashed_delegate_option,
)
} else {
Self::hash_inputs_with_hashed_values::<false>(
&hashed_mint,
&hashed_owner,
&amount_bytes,
&hashed_delegate_option,
)
}
}
}