mirror of https://github.com/zcash/orchard.git
poseidon: s/arity/width
To match the paper more closely (arity specifically refers to Merkle tree instantiations).
This commit is contained in:
parent
2beb6c3e82
commit
4c3e20535d
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue