-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #242 from dusk-network/mocello/240_hades
Move hades permutation into poseidon lib
- Loading branch information
Showing
18 changed files
with
819 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
<!-- This Source Code Form is subject to the terms of the Mozilla Public --> | ||
<!-- License, v. 2.0. If a copy of the MPL was not distributed with this --> | ||
<!-- file, You can obtain one at http://mozilla.org/MPL/2.0/. --> | ||
|
||
<!-- Copyright (c) DUSK NETWORK. All rights reserved. --> | ||
|
||
# How to generate the assets | ||
|
||
The `ark.bin` and `mds.bin` files in this folder are generated using the snippets below: | ||
|
||
## Filename: ark.bin | ||
|
||
```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; | ||
|
||
fn constants() -> [BlsScalar; CONSTANTS] { | ||
let mut cnst = [BlsScalar::zero(); CONSTANTS]; | ||
let mut p = BlsScalar::one(); | ||
let mut bytes = b"poseidon-for-plonk".to_vec(); | ||
|
||
cnst.iter_mut().for_each(|c| { | ||
let mut hasher = Sha512::new(); | ||
hasher.update(bytes.as_slice()); | ||
bytes = hasher.finalize().to_vec(); | ||
|
||
let mut v = [0x00u8; 64]; | ||
v.copy_from_slice(&bytes[0..64]); | ||
|
||
*c = BlsScalar::from_bytes_wide(&v) + p; | ||
p = *c; | ||
}); | ||
|
||
cnst | ||
} | ||
|
||
fn write_constants() -> std::io::Result<()> { | ||
let filename = "ark.bin"; | ||
let mut buf: Vec<u8> = vec![]; | ||
|
||
constants().iter().for_each(|c| { | ||
c.internal_repr() | ||
.iter() | ||
.for_each(|r| buf.extend_from_slice(&(*r).to_le_bytes())); | ||
}); | ||
|
||
let mut file = fs::File::create(filename)?; | ||
file.write_all(&buf)?; | ||
Ok(()) | ||
} | ||
``` | ||
|
||
## Filename: mds.bin | ||
|
||
```rust | ||
use dusk_bls12_381::BlsScalar; | ||
use std::fs; | ||
use std::io::Write; | ||
|
||
// The width of the permutation container, this needs to be the same number as | ||
// in `dusk_poseidon::hades::WIDTH`. | ||
const WIDTH: usize = 5; | ||
|
||
fn mds() -> [[BlsScalar; WIDTH]; WIDTH] { | ||
let mut matrix = [[BlsScalar::zero(); WIDTH]; WIDTH]; | ||
let mut xs = [BlsScalar::zero(); WIDTH]; | ||
let mut ys = [BlsScalar::zero(); WIDTH]; | ||
|
||
// Generate x and y values deterministically for the cauchy matrix, where | ||
// `x[i] != y[i]` to allow the values to be inverted and there are no | ||
// duplicates in the x vector or y vector, so that the determinant is always | ||
// non-zero. | ||
// [a b] | ||
// [c d] | ||
// det(M) = (ad - bc) ; if a == b and c == d => det(M) = 0 | ||
// For an MDS matrix, every possible mxm submatrix, must have det(M) != 0 | ||
(0..WIDTH).for_each(|i| { | ||
xs[i] = BlsScalar::from(i as u64); | ||
ys[i] = BlsScalar::from((i + WIDTH) as u64); | ||
}); | ||
|
||
let mut m = 0; | ||
(0..WIDTH).for_each(|i| { | ||
(0..WIDTH).for_each(|j| { | ||
matrix[m][j] = (xs[i] + ys[j]).invert().unwrap(); | ||
}); | ||
m += 1; | ||
}); | ||
|
||
matrix | ||
} | ||
|
||
fn write_mds() -> std::io::Result<()> { | ||
let filename = "mds.bin"; | ||
let mut buf: Vec<u8> = vec![]; | ||
|
||
mds().iter().for_each(|row| { | ||
row.iter().for_each(|c| { | ||
c.internal_repr() | ||
.iter() | ||
.for_each(|r| buf.extend_from_slice(&(*r).to_le_bytes())); | ||
}); | ||
}); | ||
|
||
let mut file = fs::File::create(filename)?; | ||
file.write_all(&buf)?; | ||
Ok(()) | ||
} | ||
``` |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) DUSK NETWORK. All rights reserved. | ||
|
||
//! Implementation of [Hades252](https://eprint.iacr.org/2019/458.pdf) | ||
//! permutation algorithm over the Bls12-381 Scalar field. | ||
//! | ||
//! ## Parameters | ||
//! | ||
//! - `p = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001` | ||
//! - Permutation `WIDTH` is 5 field elements | ||
//! - 8 full rounds: 4 full rounds at the beginning and 4 full rounds at the | ||
//! end, and each full round has `WIDTH` quintic S-Boxes. | ||
//! - 59 partial rounds: each partial round has a quintic S-Box and `WIDTH - 1` | ||
//! identity functions. | ||
//! - 960 round constants | ||
//! - Round constants for the full rounds 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" | ||
mod mds_matrix; | ||
mod round_constants; | ||
mod strategies; | ||
|
||
use mds_matrix::MDS_MATRIX; | ||
use round_constants::ROUND_CONSTANTS; | ||
|
||
const TOTAL_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; | ||
|
||
#[cfg(feature = "zk")] | ||
pub use strategies::GadgetStrategy; | ||
pub use strategies::{ScalarStrategy, Strategy}; | ||
|
||
const fn u64_from_buffer<const N: usize>(buf: &[u8; N], i: usize) -> u64 { | ||
u64::from_le_bytes([ | ||
buf[i], | ||
buf[i + 1], | ||
buf[i + 2], | ||
buf[i + 3], | ||
buf[i + 4], | ||
buf[i + 5], | ||
buf[i + 6], | ||
buf[i + 7], | ||
]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) DUSK NETWORK. All rights reserved. | ||
|
||
use dusk_bls12_381::BlsScalar; | ||
|
||
use crate::hades::WIDTH; | ||
|
||
/// Represents a `static reference` to the | ||
/// `Maximum Distance Separable Matrix -> MDS_MATRIX` | ||
/// of `(WIDTH x WIDTH)`. | ||
/// | ||
/// This matrix is loaded from the `mds.bin` file where | ||
/// is pre-computed and represented in bytes. | ||
pub const MDS_MATRIX: [[BlsScalar; WIDTH]; WIDTH] = { | ||
let bytes = include_bytes!("../../assets/mds.bin"); | ||
let mut mds = [[BlsScalar::zero(); WIDTH]; WIDTH]; | ||
let mut k = 0; | ||
let mut i = 0; | ||
|
||
while i < WIDTH { | ||
let mut j = 0; | ||
while j < WIDTH { | ||
let a = super::u64_from_buffer(bytes, k); | ||
let b = super::u64_from_buffer(bytes, k + 8); | ||
let c = super::u64_from_buffer(bytes, k + 16); | ||
let d = super::u64_from_buffer(bytes, k + 24); | ||
k += 32; | ||
|
||
mds[i][j] = BlsScalar::from_raw([a, b, c, d]); | ||
j += 1; | ||
} | ||
i += 1; | ||
} | ||
|
||
mds | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) DUSK NETWORK. All rights reserved. | ||
|
||
//! This module is designed to load the 960 constants used as `round_constants` | ||
//! from `ark.bin`. | ||
//! | ||
//! The constants were originally computed using: | ||
//! https://extgit.iaik.tugraz.at/krypto/hadesmimc/blob/master/code/calc_round_numbers.py | ||
//! and then mapped onto `BlsScalar` in the Bls12_381 scalar field. | ||
use dusk_bls12_381::BlsScalar; | ||
|
||
use crate::hades::CONSTANTS; | ||
|
||
/// `ROUND_CONSTANTS` constists on a static reference | ||
/// that points to the pre-loaded 960 Fq constants. | ||
/// | ||
/// This 960 `BlsScalar` constants are loaded from `ark.bin` | ||
/// where all of the `BlsScalar`s are represented in buf. | ||
/// | ||
/// This round constants have been taken from: | ||
/// https://extgit.iaik.tugraz.at/krypto/hadesmimc/blob/master/code/calc_round_numbers.py | ||
/// and then mapped onto `Fq` in the Ristretto scalar field. | ||
pub const ROUND_CONSTANTS: [BlsScalar; CONSTANTS] = { | ||
let bytes = include_bytes!("../../assets/ark.bin"); | ||
let mut cnst = [BlsScalar::zero(); CONSTANTS]; | ||
|
||
let mut i = 0; | ||
let mut j = 0; | ||
while i < bytes.len() { | ||
let a = super::u64_from_buffer(bytes, i); | ||
let b = super::u64_from_buffer(bytes, i + 8); | ||
let c = super::u64_from_buffer(bytes, i + 16); | ||
let d = super::u64_from_buffer(bytes, i + 24); | ||
|
||
cnst[j] = BlsScalar::from_raw([a, b, c, d]); | ||
j += 1; | ||
|
||
i += 32; | ||
} | ||
|
||
cnst | ||
}; | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_round_constants() { | ||
// Check each element is non-zero | ||
let zero = BlsScalar::zero(); | ||
let has_zero = ROUND_CONSTANTS.iter().any(|&x| x == zero); | ||
for ctant in ROUND_CONSTANTS.iter() { | ||
let bytes = ctant.to_bytes(); | ||
assert!(&BlsScalar::from_bytes(&bytes).unwrap() == ctant); | ||
} | ||
assert!(!has_zero); | ||
} | ||
} |
Oops, something went wrong.