#![allow(unexpected_cfgs)]
use crate::HASH_LEN;
#[inline]
pub(crate) fn keccak256v(parts: &[&[u8]]) -> [u8; HASH_LEN] {
#[cfg(all(
test,
feature = "std",
not(feature = "parallel"),
not(any(feature = "profile-128s-q18", feature = "profile-128s-q20"))
))]
metrics::record(parts);
#[cfg(any(target_os = "solana", feature = "solana"))]
{
solana_program::keccak::hashv(parts).to_bytes()
}
#[cfg(not(any(target_os = "solana", feature = "solana")))]
{
use sha3::{Digest, Keccak256};
let mut hasher = Keccak256::new();
for part in parts {
hasher.update(part);
}
let mut out = [0u8; HASH_LEN];
out.copy_from_slice(&hasher.finalize());
out
}
}
#[inline]
#[cfg_attr(not(test), allow(dead_code))]
pub(crate) fn keccak256(data: &[u8]) -> [u8; HASH_LEN] {
keccak256v(&[data])
}
#[inline]
#[cfg_attr(not(shrincs_hash_suite_sha2), allow(dead_code))]
pub(crate) fn sha256v(parts: &[&[u8]]) -> [u8; HASH_LEN] {
#[cfg(all(
test,
feature = "std",
not(feature = "parallel"),
not(any(feature = "profile-128s-q18", feature = "profile-128s-q20"))
))]
metrics::record(parts);
#[cfg(any(target_os = "solana", feature = "solana"))]
{
solana_program::hash::hashv(parts).to_bytes()
}
#[cfg(not(any(target_os = "solana", feature = "solana")))]
{
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
for part in parts {
hasher.update(part);
}
let mut out = [0u8; HASH_LEN];
out.copy_from_slice(&hasher.finalize());
out
}
}
#[cfg(all(
test,
feature = "std",
not(feature = "parallel"),
not(any(feature = "profile-128s-q18", feature = "profile-128s-q20"))
))]
pub(crate) mod metrics {
use core::cell::Cell;
const MEM_OP_BASE_COST: u64 = 10;
const HASH_BASE_COST: u64 = 85;
thread_local! {
static CALLS: Cell<u64> = const { Cell::new(0) };
static BYTES: Cell<u64> = const { Cell::new(0) };
static SLICE_COST: Cell<u64> = const { Cell::new(0) };
}
pub(super) fn record(parts: &[&[u8]]) {
CALLS.with(|calls| calls.set(calls.get() + 1));
for part in parts {
let len = part.len() as u64;
BYTES.with(|bytes| bytes.set(bytes.get() + len));
SLICE_COST.with(|cost| cost.set(cost.get() + MEM_OP_BASE_COST.max(len / 2)));
}
}
pub(crate) fn snapshot() -> (u64, u64, u64) {
(
CALLS.with(Cell::get),
BYTES.with(Cell::get),
SLICE_COST.with(Cell::get),
)
}
pub(crate) fn reset() {
CALLS.with(|calls| calls.set(0));
BYTES.with(|bytes| bytes.set(0));
SLICE_COST.with(|cost| cost.set(0));
}
pub(crate) fn estimated_syscall_cu(calls: u64, slice_cost: u64) -> u64 {
calls * HASH_BASE_COST + slice_cost
}
}