poseidon: s/arity/width

To match the paper more closely (arity specifically refers to Merkle
tree instantiations).
This commit is contained in:
Jack Grigg 2021-03-16 09:45:19 +13:00
parent 2beb6c3e82
commit 4c3e20535d
3 changed files with 24 additions and 24 deletions

View File

@ -15,7 +15,7 @@ use grain::SboxType;
pub trait Spec<F: FieldExt> {
/// The type used to hold permutation state, or equivalent-length constant values.
///
/// This must be an array of length [`Spec::arity`], that defaults to all-zeroes.
/// This must be an array of length [`Spec::width`], that defaults to all-zeroes.
type State: Default + AsRef<[F]> + AsMut<[F]>;
/// The type used to hold duplex sponge state.
@ -25,8 +25,8 @@ pub trait Spec<F: FieldExt> {
/// to `[None; RATE]`.
type Rate: Default + AsRef<[Option<F>]> + AsMut<[Option<F>]>;
/// The arity of this specification.
fn arity() -> usize;
/// The width of this specification.
fn width() -> usize;
/// The number of full rounds for this specification.
fn full_rounds() -> usize;
@ -46,7 +46,7 @@ pub trait Spec<F: FieldExt> {
/// Generates `(round_constants, mds, mds^-1)` corresponding to this specification.
fn constants(&self) -> (Vec<Self::State>, Vec<Self::State>, Vec<Self::State>) {
let t = Self::arity();
let t = Self::width();
let r_f = Self::full_rounds();
let r_p = Self::partial_rounds();
@ -107,8 +107,8 @@ fn permute<F: FieldExt, S: Spec<F>>(
let mut new_state = S::State::default();
// Matrix multiplication
#[allow(clippy::needless_range_loop)]
for i in 0..S::arity() {
for j in 0..S::arity() {
for i in 0..S::width() {
for j in 0..S::width() {
new_state.as_mut()[i] += mds[i].as_ref()[j] * state.as_ref()[j];
}
}

View File

@ -4,13 +4,13 @@ use super::grain::Grain;
pub(super) fn generate_mds<F: FieldExt>(
grain: &mut Grain<F>,
arity: usize,
width: usize,
mut select: usize,
) -> (Vec<Vec<F>>, Vec<Vec<F>>) {
let (xs, ys, mds) = loop {
// Generate two [F; arity] arrays of unique field elements.
// Generate two [F; width] arrays of unique field elements.
let (xs, ys) = loop {
let mut vals: Vec<_> = (0..2 * arity)
let mut vals: Vec<_> = (0..2 * width)
.map(|_| grain.next_field_element_without_rejection())
.collect();
@ -19,7 +19,7 @@ pub(super) fn generate_mds<F: FieldExt>(
unique.sort_unstable();
unique.dedup();
if vals.len() == unique.len() {
let rhs = vals.split_off(arity);
let rhs = vals.split_off(width);
break (vals, rhs);
}
};
@ -49,10 +49,10 @@ pub(super) fn generate_mds<F: FieldExt>(
// However, the Poseidon paper and reference impl use the positive formulation,
// and we want to rely on the reference impl for MDS security, so we use the same
// formulation.
let mut mds = vec![vec![F::zero(); arity]; arity];
let mut mds = vec![vec![F::zero(); width]; width];
#[allow(clippy::needless_range_loop)]
for i in 0..arity {
for j in 0..arity {
for i in 0..width {
for j in 0..width {
let sum = xs[i] + ys[j];
// We leverage the secure MDS selection counter to also check this.
assert!(!sum.is_zero());
@ -75,7 +75,7 @@ pub(super) fn generate_mds<F: FieldExt>(
// where A_i(x) and B_i(x) are the Lagrange polynomials for xs and ys respectively.
//
// We adapt this to the positive Cauchy formulation by negating ys.
let mut mds_inv = vec![vec![F::zero(); arity]; arity];
let mut mds_inv = vec![vec![F::zero(); width]; width];
let l = |xs: &[F], j, x: F| {
let x_j = xs[j];
xs.iter().enumerate().fold(F::one(), |acc, (m, x_m)| {
@ -88,8 +88,8 @@ pub(super) fn generate_mds<F: FieldExt>(
})
};
let neg_ys: Vec<_> = ys.iter().map(|y| -*y).collect();
for i in 0..arity {
for j in 0..arity {
for i in 0..width {
for j in 0..width {
mds_inv[i][j] = (xs[j] - neg_ys[i]) * l(&xs, j, neg_ys[i]) * l(&neg_ys, i, xs[j]);
}
}
@ -105,17 +105,17 @@ mod tests {
#[test]
fn poseidon_mds() {
let arity = 3;
let mut grain = Grain::new(super::super::grain::SboxType::Pow, arity as u16, 8, 56);
let (mds, mds_inv) = generate_mds::<Fp>(&mut grain, arity, 0);
let width = 3;
let mut grain = Grain::new(super::super::grain::SboxType::Pow, width as u16, 8, 56);
let (mds, mds_inv) = generate_mds::<Fp>(&mut grain, width, 0);
// Verify that MDS * MDS^-1 = I.
#[allow(clippy::needless_range_loop)]
for i in 0..arity {
for j in 0..arity {
for i in 0..width {
for j in 0..width {
let expected = if i == j { Fp::one() } else { Fp::zero() };
assert_eq!(
(0..arity).fold(Fp::zero(), |acc, k| acc + (mds[i][k] * mds_inv[k][j])),
(0..width).fold(Fp::zero(), |acc, k| acc + (mds[i][k] * mds_inv[k][j])),
expected
);
}

View File

@ -15,7 +15,7 @@ impl Spec<pallas::Base> for OrchardNullifier {
type State = [pallas::Base; 3];
type Rate = [Option<pallas::Base>; 2];
fn arity() -> usize {
fn width() -> usize {
3
}
@ -1540,7 +1540,7 @@ mod tests {
type State = [F; 3];
type Rate = [Option<F>; 2];
fn arity() -> usize {
fn width() -> usize {
3
}