#![no_std]
#![deny(missing_docs)]
mod error;
mod pubkey;
mod signature;
#[cfg(not(any(target_arch = "bpf", target_os = "solana")))]
mod privkey;
#[cfg(not(any(target_arch = "bpf", target_os = "solana")))]
mod keypair;
pub use error::WinternitzError;
pub use pubkey::{WinternitzPubkey, WinternitzRoot};
pub use signature::WinternitzSignature;
#[cfg(not(any(target_arch = "bpf", target_os = "solana")))]
pub use privkey::WinternitzPrivkey;
#[cfg(not(any(target_arch = "bpf", target_os = "solana")))]
pub use keypair::WinternitzKeypair;
pub(crate) const fn assert_n<const N: usize>() {
assert!(
N >= 16 && N <= 32 && N.is_multiple_of(2),
"N must be even and in 16..=32",
);
}
#[inline(always)]
pub(crate) fn chain(seed: &[u8; 32], iters: u8) -> [u8; 32] {
let mut current = *seed;
for _ in 0..iters {
current = solana_sha256_hasher::hash(¤t).to_bytes();
}
current
}
#[inline(always)]
pub(crate) fn hash<const N: usize>(message: &[&[u8]]) -> [u8; N] {
const { assert_n::<N>() };
let digest = solana_sha256_hasher::hashv(message).to_bytes();
let mut out = [0u8; N];
out.copy_from_slice(&digest[..N]);
out
}