use crate::consts::INITIAL_STATE;
use alloc::vec::Vec;
#[derive(Debug)]
pub struct SecsParam {
pub(crate) n: u8,
}
impl SecsParam {
#[inline(always)]
pub const fn new(n: u8) -> Self {
assert!(n >= 16 && n < 48, "n must be between 16 and 48");
SecsParam { n }
}
}
#[derive(Debug)]
pub struct DataRange(
usize,
)
usize,
);
impl DataRange {
#[inline(always)]
pub const fn new(start: usize, end: usize) -> Self {
assert!(start < end, "start must be less than end");
DataRange(start, end)
}
#[inline(always)]
pub const fn length(&self) -> usize {
self.1 - self.0
}
#[inline(always)]
pub const fn start(&self) -> usize {
self.0
}
#[inline(always)]
pub const fn end(&self) -> usize {
self.1
}
}
#[derive(Debug)]
pub struct ToBeHashed {
pub data: Vec<u8>,
pub confidentials: Vec<DataRange>,
}
impl ToBeHashed {
pub fn check_datarange(&self) -> Result<(), &'static str> {
let mut last_end = 0;
for range in &self.confidentials {
if range.start() < last_end {
return Err("Invalid range: ranges must not overlap and must be ascending");
}
if range.end() > self.data.len() {
return Err("Invalid range: end exceeds data length");
}
last_end = range.end();
}
Ok(())
}
#[inline(always)]
pub fn is_in_confidentials(&self, start: usize, end: usize) -> bool {
self.confidentials.iter().any(|range| {
(range.start() < end && range.end() > start)
|| (range.start() >= start && range.start() < end)
})
}
}
#[cfg_attr(test, derive(Debug, PartialEq))]
pub enum PenisBlock {
Private(PrivateBlock),
Public(RawBlock),
}
impl PenisBlock {
#[inline(always)]
pub(crate) const fn type_flag(&self) -> u8 {
match self {
PenisBlock::Private(_) => 1,
PenisBlock::Public(_) => 0,
}
}
#[inline(always)]
pub(crate) const fn encoded_size(&self) -> usize {
match self {
PenisBlock::Private(_) => 0x60,
PenisBlock::Public(_) => 0x40,
}
}
}
pub(crate) type SchedVariable = u32;
pub(crate) type SchedArray = [SchedVariable; 64];
pub(crate) type PartialSchedArray = [SchedVariable; 16];
pub(crate) type RawBlock = [u8; 64];
pub(crate) type RawBlockRef<'a> = &'a [u8];
pub(crate) type NRound = usize;
#[derive(PartialEq, Debug)]
pub struct PrivateBlock {
pub psa: PartialSchedArray,
pub state: State,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct State {
pub a: u32,
pub b: u32,
pub c: u32,
pub d: u32,
pub e: u32,
pub f: u32,
pub g: u32,
pub h: u32,
}
impl State {
#[inline(always)]
pub fn finalize(&self) -> [u8; 32] {
let mut final_hash = [0u8; 32];
final_hash[0..4].clone_from_slice(&self.a.to_be_bytes());
final_hash[4..8].clone_from_slice(&self.b.to_be_bytes());
final_hash[8..12].clone_from_slice(&self.c.to_be_bytes());
final_hash[12..16].clone_from_slice(&self.d.to_be_bytes());
final_hash[16..20].clone_from_slice(&self.e.to_be_bytes());
final_hash[20..24].clone_from_slice(&self.f.to_be_bytes());
final_hash[24..28].clone_from_slice(&self.g.to_be_bytes());
final_hash[28..32].clone_from_slice(&self.h.to_be_bytes());
final_hash
}
#[inline(always)]
pub fn finalize_u32(&self) -> [u32; 8] {
[
self.a, self.b, self.c, self.d, self.e, self.f, self.g, self.h,
]
}
pub fn from_bytes(bytes: &[u8]) -> Self {
assert_eq!(bytes.len(), 32);
State {
a: u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
b: u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
c: u32::from_be_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]),
d: u32::from_be_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]),
e: u32::from_be_bytes([bytes[16], bytes[17], bytes[18], bytes[19]]),
f: u32::from_be_bytes([bytes[20], bytes[21], bytes[22], bytes[23]]),
g: u32::from_be_bytes([bytes[24], bytes[25], bytes[26], bytes[27]]),
h: u32::from_be_bytes([bytes[28], bytes[29], bytes[30], bytes[31]]),
}
}
}
impl Default for State {
#[inline(always)]
fn default() -> Self {
INITIAL_STATE
}
}
#[cfg(test)]
mod tests {
use alloc::vec;
use super::*;
#[test]
fn test_is_in_confidentials() {
let to_be_hashed_1 = ToBeHashed {
data: vec![],
confidentials: vec![
DataRange::new(0, 10),
DataRange::new(20, 30),
DataRange::new(40, 50),
],
};
assert!(to_be_hashed_1.is_in_confidentials(5, 15)); assert!(!to_be_hashed_1.is_in_confidentials(10, 20)); assert!(to_be_hashed_1.is_in_confidentials(0, 10)); assert!(to_be_hashed_1.is_in_confidentials(9, 20));
let to_be_hashed_2 = ToBeHashed {
data: vec![],
confidentials: vec![
DataRange::new(5, 15),
DataRange::new(25, 35),
DataRange::new(45, 55),
],
};
assert!(to_be_hashed_2.is_in_confidentials(10, 20)); assert!(!to_be_hashed_2.is_in_confidentials(20, 25)); assert!(to_be_hashed_2.is_in_confidentials(5, 15)); assert!(to_be_hashed_2.is_in_confidentials(14, 25));
let to_be_hashed_3 = ToBeHashed {
data: vec![],
confidentials: vec![
DataRange::new(0, 5),
DataRange::new(10, 15),
DataRange::new(20, 25),
],
};
assert!(to_be_hashed_3.is_in_confidentials(3, 12)); assert!(!to_be_hashed_3.is_in_confidentials(5, 10)); assert!(to_be_hashed_3.is_in_confidentials(0, 5)); assert!(to_be_hashed_3.is_in_confidentials(4, 10)); }
}