Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the hades-constants iterator and reduce the amount of constants to 335 #247

Merged
merged 1 commit into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.34.0] - 2024-01-24

### Changed

- Restructure crate features [#184]
- Rename trait `hades::Strategy` to `hades::Permutation` [#243]
- Rename struct `hades::ScalarStrategy` to `hades::ScalarPermutation` [#243]
- Rename struct `hades::GadgetStrategy` to `hades::GadgetPermutaiton` [#243]
- Reduce the number of `ROUND_CONSTANTS` from 960 to 335 [#246]
- Remove the constants iterator in favor of indexing the constants array directly [#246]
- Change `ROUND_CONSTANTS` into a two-dimensional array [#246]
- Rename `TOTAL_FULL_ROUNDS` to `FULL_ROUNDS` [#246]

### Removed

- Remove `default` and `alloc` features [#184]
- Remove `hades::Strategy`, `hades::ScalarStrategy` and `hades::GadgetStrategy` from public API [#243]
- Remove `dusk-hades` dependency [#240]

### Added

- Add `zk` and `cipher` features [#184]
- Add the code for the hades permutation to crate [#240]
- Add internal `permute` and `permute_gadget` functions to `hades` module [#243]

## [0.34.0] - 2024-01-24

### Changed

- Restructure crate features [#184]

### Removed

- Remove `default` and `alloc` features [#184]

### Added

- Add `zk` and `cipher` features [#184]

## [0.33.0] - 2024-01-03

### Changed
Expand Down Expand Up @@ -436,6 +449,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Variants of sponge for `Scalar` & `Gadget(Variable/LC)`.

<!-- ISSUES -->
[#246]: https://github.com/dusk-network/poseidon252/issues/246
[#243]: https://github.com/dusk-network/poseidon252/issues/243
[#240]: https://github.com/dusk-network/poseidon252/issues/240
[#215]: https://github.com/dusk-network/poseidon252/issues/215
Expand Down
14 changes: 7 additions & 7 deletions assets/HOWTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@

# How to generate the assets

The `ark.bin` and `mds.bin` files in this folder are generated using the snippets below:
The `arc.bin` and `mds.bin` files in this folder are generated using the snippets below:

## Filename: ark.bin
## Generate round constants

```rust
use dusk_bls12_381::BlsScalar;
use sha2::{Digest, Sha512};
use std::fs;
use std::io::Write;

// The amount of constants generated, this needs to be the same number as in
// `dusk_poseidon::hades::CONSTANTS`.
const CONSTANTS: usize = 960;
// The amount of constants generated, this needs to be at least the total number
// of rounds (= 59 + 8) multiplied by the width of the permutaiton array (= 5).
const CONSTANTS: usize = (59 + 8) * 5;

fn constants() -> [BlsScalar; CONSTANTS] {
let mut cnst = [BlsScalar::zero(); CONSTANTS];
Expand All @@ -41,7 +41,7 @@ fn constants() -> [BlsScalar; CONSTANTS] {
}

fn write_constants() -> std::io::Result<()> {
let filename = "ark.bin";
let filename = "arc.bin";
let mut buf: Vec<u8> = vec![];

constants().iter().for_each(|c| {
Expand All @@ -56,7 +56,7 @@ fn write_constants() -> std::io::Result<()> {
}
```

## Filename: mds.bin
## Generate mds matrix

```rust
use dusk_bls12_381::BlsScalar;
Expand Down
Binary file added assets/arc.bin
Binary file not shown.
Binary file removed assets/ark.bin
Binary file not shown.
7 changes: 2 additions & 5 deletions src/hades.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
//! end, and each full round has `WIDTH` quintic S-Boxes.
//! - 59 partial rounds: each partial round has `WIDTH - 1` identity function
//! and one quintic S-Box.
//! - 960 round constants
//! - Round constants are generated using [this algorithm](https://extgit.iaik.tugraz.at/krypto/hadesmimc/blob/master/code/calc_round_numbers.py)
//! - 335 round constants which are generated using [this algorithm](https://extgit.iaik.tugraz.at/krypto/hadesmimc/blob/master/code/calc_round_numbers.py)
//! - The MDS matrix is a cauchy matrix, the method used to generate it, is
//! noted in section "Concrete Instantiations Poseidon and Starkad"

Expand All @@ -28,12 +27,10 @@ use mds_matrix::MDS_MATRIX;
use permutation::Permutation;
use round_constants::ROUND_CONSTANTS;

const TOTAL_FULL_ROUNDS: usize = 8;
const FULL_ROUNDS: usize = 8;

const PARTIAL_ROUNDS: usize = 59;

const CONSTANTS: usize = 960;

/// The amount of field elements that fit into the hades permutation container
pub const WIDTH: usize = 5;

Expand Down
109 changes: 44 additions & 65 deletions src/hades/permutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use dusk_bls12_381::BlsScalar;
#[cfg(feature = "zk")]
use dusk_plonk::prelude::{Composer, Witness};

use crate::hades::{PARTIAL_ROUNDS, ROUND_CONSTANTS, TOTAL_FULL_ROUNDS, WIDTH};
use crate::hades::{FULL_ROUNDS, PARTIAL_ROUNDS, WIDTH};

/// State for zero-knowledge plonk circuits
#[cfg(feature = "zk")]
Expand All @@ -35,11 +35,11 @@ use scalar::ScalarPermutation;
///
/// This permutation is a 3-step process that:
/// - Applies half of the `FULL_ROUNDS` (which can be understood as linear ops).
/// - Applies the `PARTIAL_ROUDS` (which can be understood as non-linear ops).
/// - Applies the `PARTIAL_ROUNDS` (which can be understood as non-linear ops).
/// - Applies the other half of the `FULL_ROUNDS`.
///
/// This structure allows to minimize the number of non-linear ops while
/// mantaining the security.
/// maintaining the security.
pub(crate) fn permute(state: &mut [BlsScalar; WIDTH]) {
let mut hades = ScalarPermutation::new();

Expand All @@ -50,11 +50,11 @@ pub(crate) fn permute(state: &mut [BlsScalar; WIDTH]) {
///
/// This permutation is a 3-step process that:
/// - Applies half of the `FULL_ROUNDS` (which can be understood as linear ops).
/// - Applies the `PARTIAL_ROUDS` (which can be understood as non-linear ops).
/// - Applies the `PARTIAL_ROUNDS` (which can be understood as non-linear ops).
/// - Applies the other half of the `FULL_ROUNDS`.
///
/// This structure allows to minimize the number of non-linear ops while
/// mantaining the security.
/// maintaining the security.
#[cfg(feature = "zk")]
pub(crate) fn permute_gadget(
composer: &mut Composer,
Expand All @@ -67,30 +67,19 @@ pub(crate) fn permute_gadget(

/// Defines the Hades252 permutation algorithm.
pub(crate) trait Permutation<T> {
/// Fetch the next round constant from an iterator
fn next_c<'b, I>(constants: &mut I) -> BlsScalar
where
I: Iterator<Item = &'b BlsScalar>,
{
constants
.next()
.copied()
.expect("Hades252 shouldn't be out of ARK constants")
}
/// Increment the inner rounds counter.
///
/// This counter is needed to index the `ROUND_CONSTANTS`.
fn increment_round(&mut self);

/// Add round keys to the state.
/// Add round constants to the state.
///
/// This round key addition, also known as `ARK`, is used to reach
/// This constants addition, also known as `ARC`, is used to reach
/// `Confusion and Diffusion` properties for the algorithm.
///
/// Basically it allows to destroy any connection between the inputs and the
/// outputs of the function.
fn add_round_key<'b, I>(
&mut self,
constants: &mut I,
state: &mut [T; WIDTH],
) where
I: Iterator<Item = &'b BlsScalar>;
fn add_round_constants(&mut self, state: &mut [T; WIDTH]);

/// Computes `input ^ 5 (mod p)`
///
Expand All @@ -100,94 +89,84 @@ pub(crate) trait Permutation<T> {
fn quintic_s_box(&mut self, value: &mut T);

/// Multiply the MDS matrix with the state.
fn mul_matrix<'b, I>(&mut self, constants: &mut I, state: &mut [T; WIDTH])
where
I: Iterator<Item = &'b BlsScalar>;
fn mul_matrix(&mut self, state: &mut [T; WIDTH]);

/// Applies a `Partial Round` also known as a `Partial S-Box layer` to a set
/// of inputs.
///
/// One partial round consists of 3 steps:
/// - ARK: Add round keys constants to each state element.
/// - Sub State: Apply `quintic S-Box` just to **the last element of the
/// - ARC: Add round constants to the elements of the state.
/// - Sub Words: Apply `quintic S-Box` just to **the last element of the
/// state** generated from the first step.
/// - Mix Layer: Multiplies the output state from the second step by the
/// `MDS_MATRIX`.
fn apply_partial_round<'b, I>(
&mut self,
constants: &mut I,
state: &mut [T; WIDTH],
) where
I: Iterator<Item = &'b BlsScalar>,
{
// Add round keys to each state element
self.add_round_key(constants, state);

// Then apply quintic s-box
fn apply_partial_round(&mut self, state: &mut [T; WIDTH]) {
// Increment the inner rounds counter
self.increment_round();

// Add round constants to each state element
self.add_round_constants(state);

// Then apply quintic s-box to the last element of the state
self.quintic_s_box(&mut state[WIDTH - 1]);

// Multiply this result by the MDS matrix
self.mul_matrix(constants, state);
self.mul_matrix(state);
}

/// Applies a `Full Round` also known as a `Full S-Box layer` to a set of
/// inputs.
///
/// One full round constists of 3 steps:
/// - ARK: Add round keys to each state element.
/// - Sub State: Apply `quintic S-Box` to **all of the state-elements**
/// One full round consists of 3 steps:
/// - ARC: Add round constants to the elements of the state.
/// - Sub Words: Apply `quintic S-Box` to **all of the state-elements**
/// generated from the first step.
/// - Mix Layer: Multiplies the output state from the second step by the
/// `MDS_MATRIX`.
fn apply_full_round<'a, I>(
&mut self,
constants: &mut I,
state: &mut [T; WIDTH],
) where
I: Iterator<Item = &'a BlsScalar>,
{
// Add round keys to each state element
self.add_round_key(constants, state);

// Then apply quintic s-box
fn apply_full_round(&mut self, state: &mut [T; WIDTH]) {
// Increment the inner rounds counter
self.increment_round();

// Add round constants to each state element
self.add_round_constants(state);

// Then apply quintic s-box to each element of the state
state.iter_mut().for_each(|w| self.quintic_s_box(w));

// Multiply this result by the MDS matrix
self.mul_matrix(constants, state);
self.mul_matrix(state);
}

/// Applies one Hades permutation.
///
/// This permutation is a 3-step process that:
/// - Applies half of the `FULL_ROUNDS` (which can be understood as linear
/// ops).
/// - Applies the `PARTIAL_ROUDS` (which can be understood as non-linear
/// - Applies the `PARTIAL_ROUNDS` (which can be understood as non-linear
/// ops).
/// - Applies the other half of the `FULL_ROUNDS`.
///
/// This structure allows to minimize the number of non-linear ops while
/// mantaining the security.
/// maintaining the security.
fn perm(&mut self, state: &mut [T; WIDTH]) {
let mut constants = ROUND_CONSTANTS.iter();

// Apply R_f full rounds
for _ in 0..TOTAL_FULL_ROUNDS / 2 {
self.apply_full_round(&mut constants, state);
for _ in 0..FULL_ROUNDS / 2 {
self.apply_full_round(state);
}

// Apply R_P partial rounds
for _ in 0..PARTIAL_ROUNDS {
self.apply_partial_round(&mut constants, state);
self.apply_partial_round(state);
}

// Apply R_f full rounds
for _ in 0..TOTAL_FULL_ROUNDS / 2 {
self.apply_full_round(&mut constants, state);
for _ in 0..FULL_ROUNDS / 2 {
self.apply_full_round(state);
}
}

/// Return the total rounds count
fn rounds() -> usize {
TOTAL_FULL_ROUNDS + PARTIAL_ROUNDS
FULL_ROUNDS + PARTIAL_ROUNDS
}
}
Loading