use dusk_bls12_381::BlsScalar;
use dusk_safe::{Call, Error, Safe, Sponge};
const W: usize = 7;
#[derive(Default, Debug, Clone, Copy, PartialEq)]
struct Rotate();
impl Safe<BlsScalar, W> for Rotate {
fn permute(&mut self, state: &mut [BlsScalar; W]) {
let tmp = state[0];
for i in 1..W {
state[i - 1] = state[i];
}
state[W - 1] = tmp;
}
fn tag(&mut self, _input: &[u8]) -> BlsScalar {
BlsScalar::zero()
}
fn add(&mut self, right: &BlsScalar, left: &BlsScalar) -> BlsScalar {
right + left
}
}
impl Rotate {
pub fn new() -> Self {
Self()
}
}
#[test]
fn sponge() -> Result<(), Error> {
let domain_sep = 0;
let iopattern = vec![
Call::Absorb(6),
Call::Squeeze(1),
Call::Absorb(4),
Call::Absorb(4),
Call::Squeeze(3),
Call::Squeeze(4),
];
let mut sponge = Sponge::start(Rotate::new(), iopattern, domain_sep)?;
sponge.absorb(
6,
&[
BlsScalar::from(1),
BlsScalar::from(2),
BlsScalar::from(3),
BlsScalar::from(8),
BlsScalar::from(5),
BlsScalar::from(6),
BlsScalar::from(7),
],
)?;
sponge.squeeze(1)?;
let input = [BlsScalar::from(6); 4];
sponge.absorb(4, &input)?;
sponge.absorb(4, &input)?;
sponge.squeeze(3)?;
sponge.squeeze(4)?;
let output = sponge.finish()?;
assert_eq!(
output,
vec![
BlsScalar::from(2),
BlsScalar::from(20),
BlsScalar::from(11),
BlsScalar::from(12),
BlsScalar::from(6),
BlsScalar::from(1),
BlsScalar::from(8),
BlsScalar::from(11),
]
);
Ok(())
}
#[test]
fn absorb_fails() -> Result<(), Error> {
let domain_sep = 0;
let iopattern = vec![Call::Absorb(6), Call::Squeeze(1)];
let input = [BlsScalar::one(); 10];
let mut sponge = Sponge::start(Rotate::new(), iopattern, domain_sep)?;
let error = sponge.clone().absorb(6, &input[..4]).unwrap_err();
assert_eq!(error, Error::TooFewInputElements);
let error = sponge.clone().absorb(4, &input[..4]).unwrap_err();
assert_eq!(error, Error::IOPatternViolation);
let error = sponge.squeeze(1).unwrap_err();
assert_eq!(error, Error::IOPatternViolation);
Ok(())
}
#[test]
fn squeeze_fails() -> Result<(), Error> {
let domain_sep = 0;
let iopattern = vec![Call::Absorb(6), Call::Squeeze(1)];
let input = [BlsScalar::one(); 10];
let mut sponge = Sponge::start(Rotate::new(), iopattern, domain_sep)?;
sponge.absorb(6, &input[..6])?;
let error = sponge.clone().squeeze(4).unwrap_err();
assert_eq!(error, Error::IOPatternViolation);
let error = sponge.absorb(1, &input).unwrap_err();
assert_eq!(error, Error::IOPatternViolation);
Ok(())
}
#[test]
fn finish_fails() -> Result<(), Error> {
let domain_sep = 0;
let iopattern = vec![
Call::Absorb(6),
Call::Squeeze(1),
Call::Absorb(1),
Call::Squeeze(1),
];
let input = [BlsScalar::one(); 10];
let mut sponge = Sponge::start(Rotate::new(), iopattern, domain_sep)?;
sponge.absorb(6, &input[..6])?;
sponge.squeeze(1)?;
let error = sponge.clone().finish().unwrap_err();
assert_eq!(error, Error::IOPatternViolation);
sponge.absorb(1, &input)?;
sponge.squeeze(1)?;
let error = sponge.absorb(1, &input).unwrap_err();
assert_eq!(error, Error::IOPatternViolation);
Ok(())
}