use std::fmt::Write;
use proptest::prelude::*;
use super::{
curve::{Point, SCALAR_BYTES, Scalar},
field::{Fp, Fp5},
schnorr::SIG_BYTES,
};
#[must_use]
pub(crate) fn hex_to_bytes(hex: &str) -> Vec<u8> {
assert!(hex.len().is_multiple_of(2), "hex must have even length");
(0..hex.len())
.step_by(2)
.map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap())
.collect()
}
#[must_use]
pub(crate) fn bytes_to_hex(bytes: &[u8]) -> String {
let mut s = String::with_capacity(bytes.len() * 2);
for b in bytes {
write!(&mut s, "{b:02x}").expect("writing into String never fails");
}
s
}
#[must_use]
pub(crate) fn hex_to_array<const N: usize>(hex: &str) -> [u8; N] {
let bytes = hex_to_bytes(hex);
assert_eq!(bytes.len(), N, "expected {N} bytes, was {}", bytes.len(),);
let mut out = [0u8; N];
out.copy_from_slice(&bytes);
out
}
#[must_use]
pub(crate) fn decode_scalar_bytes(hex: &str) -> [u8; SCALAR_BYTES] {
hex_to_array::<SCALAR_BYTES>(hex)
}
#[must_use]
pub(crate) fn decode_fp5_bytes(hex: &str) -> Fp5 {
Fp5::try_from_le_bytes(hex_to_array::<40>(hex)).expect("non-canonical Fp5 fixture")
}
#[must_use]
pub(crate) fn decode_sig_bytes(hex: &str) -> [u8; SIG_BYTES] {
hex_to_array::<SIG_BYTES>(hex)
}
pub(crate) fn arb_fp() -> impl Strategy<Value = Fp> {
any::<u64>().prop_map(Fp::from_u64_reduce)
}
pub(crate) fn arb_fp_nonzero() -> impl Strategy<Value = Fp> {
arb_fp().prop_filter("non-zero", |x| !x.is_zero())
}
pub(crate) fn arb_fp5() -> impl Strategy<Value = Fp5> {
any::<[u64; 5]>().prop_map(Fp5::from_u64s_reduce)
}
pub(crate) fn arb_fp5_nonzero() -> impl Strategy<Value = Fp5> {
arb_fp5().prop_filter("non-zero", |x| !x.is_zero())
}
pub(crate) fn arb_scalar() -> impl Strategy<Value = Scalar> {
any::<[u64; 5]>().prop_map(|limbs| {
let mut bytes = [0u8; SCALAR_BYTES];
for (i, limb) in limbs.iter().enumerate() {
bytes[i * 8..(i + 1) * 8].copy_from_slice(&limb.to_le_bytes());
}
Scalar::from_le_bytes_reduce(bytes)
})
}
pub(crate) fn arb_scalar_nonzero() -> impl Strategy<Value = Scalar> {
arb_scalar().prop_filter("non-zero", |s| !s.is_zero())
}
pub(crate) fn arb_point() -> impl Strategy<Value = Point> {
arb_scalar().prop_map(|seed| Point::GENERATOR.scalar_mul(seed))
}