mirror of
https://github.com/pseXperiments/icicle.git
synced 2026-01-09 13:07:59 -05:00
Feat/roman/poseidon2 (#507)
This PR adds support for poseidon2 permutation function as described in https://eprint.iacr.org/2023/323.pdf Reference implementations used (and compared against): https://github.com/HorizenLabs/poseidon2/tree/main https://github.com/Plonky3/Plonky3/tree/main Tasks: - [x] Remove commented code and prints - [ ] Add doc-comments to functions and structs - [x] Fix possible issue with Plonky3 imports - [x] Update NTT/Plonky3 test - [x] Add Plonky3-bn254 test (impossible)
This commit is contained in:
@@ -11,14 +11,13 @@ repository.workspace = true
|
||||
[dependencies]
|
||||
|
||||
icicle-cuda-runtime = { workspace = true }
|
||||
|
||||
ark-ff = { version = "0.4.0", optional = true }
|
||||
ark-ec = { version = "0.4.0", optional = true, features = ["parallel"] }
|
||||
ark-poly = { version = "0.4.0", optional = true }
|
||||
ark-std = { version = "0.4.0", optional = true }
|
||||
|
||||
rayon = "1.8.1"
|
||||
|
||||
hex = "0.4"
|
||||
criterion = "0.3"
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::traits::ArkConvertible;
|
||||
use crate::traits::{FieldConfig, FieldImpl, MontgomeryConvertible};
|
||||
#[cfg(feature = "arkworks")]
|
||||
use ark_ff::{BigInteger, Field as ArkField, PrimeField};
|
||||
use hex::FromHex;
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::DeviceSlice;
|
||||
@@ -82,6 +83,12 @@ impl<const NUM_LIMBS: usize, F: FieldConfig> FieldImpl for Field<NUM_LIMBS, F> {
|
||||
Self::from(limbs)
|
||||
}
|
||||
|
||||
fn from_hex(s: &str) -> Self {
|
||||
let mut bytes = Vec::from_hex(if s.starts_with("0x") { &s[2..] } else { s }).expect("Invalid hex string");
|
||||
bytes.reverse();
|
||||
Self::from_bytes_le(&bytes)
|
||||
}
|
||||
|
||||
fn zero() -> Self {
|
||||
FieldImpl::from_u32(0)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ pub mod msm;
|
||||
pub mod ntt;
|
||||
pub mod polynomials;
|
||||
pub mod poseidon;
|
||||
pub mod poseidon2;
|
||||
#[doc(hidden)]
|
||||
pub mod tests;
|
||||
pub mod traits;
|
||||
|
||||
@@ -56,10 +56,11 @@ pub fn check_poseidon_hash_many<F: FieldImpl>()
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon<F>,
|
||||
{
|
||||
let arity = 2u32;
|
||||
let constants = init_poseidon::<F>(arity as u32);
|
||||
for arity in [2, 4] {
|
||||
let constants = init_poseidon::<F>(arity as u32);
|
||||
|
||||
_check_poseidon_hash_many(constants);
|
||||
_check_poseidon_hash_many(constants);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_poseidon_custom_config<F: FieldImpl>(field_bytes: usize, field_prefix: &str, partial_rounds: u32)
|
||||
|
||||
384
wrappers/rust/icicle-core/src/poseidon2/mod.rs
Normal file
384
wrappers/rust/icicle-core/src/poseidon2/mod.rs
Normal file
@@ -0,0 +1,384 @@
|
||||
#[doc(hidden)]
|
||||
pub mod tests;
|
||||
|
||||
use icicle_cuda_runtime::{
|
||||
device::check_device,
|
||||
device_context::{DeviceContext, DEFAULT_DEVICE_ID},
|
||||
memory::{DeviceSlice, HostOrDeviceSlice},
|
||||
};
|
||||
|
||||
use crate::{error::IcicleResult, traits::FieldImpl};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DiffusionStrategy {
|
||||
Default,
|
||||
Montgomery,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MdsType {
|
||||
Default,
|
||||
Plonky,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PoseidonMode {
|
||||
Compression,
|
||||
Permutation,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Poseidon2Constants<'a, F: FieldImpl> {
|
||||
width: u32,
|
||||
|
||||
alpha: u32,
|
||||
|
||||
internal_rounds: u32,
|
||||
|
||||
external_rounds: u32,
|
||||
|
||||
round_constants: &'a DeviceSlice<F>,
|
||||
|
||||
inernal_matrix_diag: &'a DeviceSlice<F>,
|
||||
|
||||
pub mds_type: MdsType,
|
||||
|
||||
pub diffusion: DiffusionStrategy,
|
||||
}
|
||||
|
||||
impl<F: FieldImpl> std::fmt::Debug for Poseidon2Constants<'_, F> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}, {}, {}, {}",
|
||||
self.width, self.alpha, self.internal_rounds, self.external_rounds
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Struct that encodes Poseidon parameters to be passed into the [poseidon_hash_many](poseidon_hash_many) function.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Poseidon2Config<'a> {
|
||||
/// Details related to the device such as its id and stream id. See [DeviceContext](@ref device_context::DeviceContext).
|
||||
pub ctx: DeviceContext<'a>,
|
||||
|
||||
are_states_on_device: bool,
|
||||
|
||||
are_outputs_on_device: bool,
|
||||
|
||||
pub mode: PoseidonMode,
|
||||
|
||||
pub output_index: u32,
|
||||
|
||||
/// If true, hash results will also be copied in the input pointer in aligned format
|
||||
pub loop_state: bool,
|
||||
|
||||
/// Whether to run Poseidon asynchronously. If set to `true`, Poseidon will be non-blocking
|
||||
/// and you'd need to synchronize it explicitly by running `cudaStreamSynchronize` or `cudaDeviceSynchronize`.
|
||||
/// If set to `false`, Poseidon will block the current CPU thread.
|
||||
pub is_async: bool,
|
||||
}
|
||||
|
||||
impl<'a> Default for Poseidon2Config<'a> {
|
||||
fn default() -> Self {
|
||||
Self::default_for_device(DEFAULT_DEVICE_ID)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Poseidon2Config<'a> {
|
||||
pub fn default_for_device(device_id: usize) -> Self {
|
||||
Self {
|
||||
ctx: DeviceContext::default_for_device(device_id),
|
||||
are_states_on_device: false,
|
||||
are_outputs_on_device: false,
|
||||
mode: PoseidonMode::Compression,
|
||||
output_index: 1,
|
||||
loop_state: false,
|
||||
is_async: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Poseidon2<F: FieldImpl> {
|
||||
fn create_optimized_constants<'a>(
|
||||
width: u32,
|
||||
alpha: u32,
|
||||
internal_rounds: u32,
|
||||
external_rounds: u32,
|
||||
round_constants: &mut [F],
|
||||
internal_matrix_diag: &mut [F],
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<Poseidon2Constants<'a, F>>;
|
||||
fn load_optimized_constants<'a>(
|
||||
width: u32,
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<Poseidon2Constants<'a, F>>;
|
||||
fn poseidon_unchecked(
|
||||
states: &mut (impl HostOrDeviceSlice<F> + ?Sized),
|
||||
output: &mut (impl HostOrDeviceSlice<F> + ?Sized),
|
||||
number_of_states: u32,
|
||||
width: u32,
|
||||
constants: &Poseidon2Constants<F>,
|
||||
config: &Poseidon2Config,
|
||||
) -> IcicleResult<()>;
|
||||
}
|
||||
|
||||
/// Loads pre-calculated poseidon constants on the GPU.
|
||||
pub fn load_optimized_poseidon2_constants<'a, F>(
|
||||
width: u32,
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<Poseidon2Constants<'a, F>>
|
||||
where
|
||||
F: FieldImpl,
|
||||
<F as FieldImpl>::Config: Poseidon2<F>,
|
||||
{
|
||||
<<F as FieldImpl>::Config as Poseidon2<F>>::load_optimized_constants(width, mds_type, diffusion, ctx)
|
||||
}
|
||||
|
||||
/// Creates new instance of poseidon constants on the GPU.
|
||||
pub fn create_optimized_poseidon2_constants<'a, F>(
|
||||
width: u32,
|
||||
alpha: u32,
|
||||
ctx: &DeviceContext,
|
||||
internal_rounds: u32,
|
||||
external_rounds: u32,
|
||||
round_constants: &mut [F],
|
||||
internal_matrix_diag: &mut [F],
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
) -> IcicleResult<Poseidon2Constants<'a, F>>
|
||||
where
|
||||
F: FieldImpl,
|
||||
<F as FieldImpl>::Config: Poseidon2<F>,
|
||||
{
|
||||
<<F as FieldImpl>::Config as Poseidon2<F>>::create_optimized_constants(
|
||||
width,
|
||||
alpha,
|
||||
internal_rounds,
|
||||
external_rounds,
|
||||
round_constants,
|
||||
internal_matrix_diag,
|
||||
mds_type,
|
||||
diffusion,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
/// Computes the poseidon hashes for multiple preimages.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `input` - a pointer to the input data. May point to a vector of preimages or a vector of states filled with preimages.
|
||||
///
|
||||
/// * `output` - a pointer to the output data. Must be at least of size [number_of_states](number_of_states)
|
||||
///
|
||||
/// * `number_of_states` - number of input blocks of size `arity`
|
||||
///
|
||||
/// * `arity` - the arity of the hash function (the size of 1 preimage)
|
||||
///
|
||||
/// * `constants` - Poseidon constants.
|
||||
///
|
||||
/// * `config` - config used to specify extra arguments of the Poseidon.
|
||||
pub fn poseidon_hash_many<F>(
|
||||
states: &mut (impl HostOrDeviceSlice<F> + ?Sized),
|
||||
output: &mut (impl HostOrDeviceSlice<F> + ?Sized),
|
||||
number_of_states: u32,
|
||||
width: u32,
|
||||
constants: &Poseidon2Constants<F>,
|
||||
config: &Poseidon2Config,
|
||||
) -> IcicleResult<()>
|
||||
where
|
||||
F: FieldImpl,
|
||||
<F as FieldImpl>::Config: Poseidon2<F>,
|
||||
{
|
||||
if states.len() < (number_of_states * width) as usize {
|
||||
panic!(
|
||||
"input len is {}; but needs to be at least {}",
|
||||
states.len(),
|
||||
number_of_states * width
|
||||
);
|
||||
}
|
||||
|
||||
if output.len() < number_of_states as usize {
|
||||
panic!(
|
||||
"output len is {}; but needs to be at least {}",
|
||||
output.len(),
|
||||
number_of_states
|
||||
);
|
||||
}
|
||||
|
||||
let ctx_device_id = config
|
||||
.ctx
|
||||
.device_id;
|
||||
if let Some(device_id) = states.device_id() {
|
||||
assert_eq!(
|
||||
device_id, ctx_device_id,
|
||||
"Device ids in input and context are different"
|
||||
);
|
||||
}
|
||||
if let Some(device_id) = output.device_id() {
|
||||
assert_eq!(
|
||||
device_id, ctx_device_id,
|
||||
"Device ids in output and context are different"
|
||||
);
|
||||
}
|
||||
check_device(ctx_device_id);
|
||||
let mut local_cfg = config.clone();
|
||||
local_cfg.are_states_on_device = states.is_on_device();
|
||||
local_cfg.are_outputs_on_device = output.is_on_device();
|
||||
|
||||
<<F as FieldImpl>::Config as Poseidon2<F>>::poseidon_unchecked(
|
||||
states,
|
||||
output,
|
||||
number_of_states,
|
||||
width,
|
||||
constants,
|
||||
&local_cfg,
|
||||
)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_poseidon2 {
|
||||
(
|
||||
$field_prefix:literal,
|
||||
$field_prefix_ident:ident,
|
||||
$field:ident,
|
||||
$field_config:ident
|
||||
) => {
|
||||
mod $field_prefix_ident {
|
||||
use crate::poseidon2::{
|
||||
$field, $field_config, CudaError, DeviceContext, DiffusionStrategy, MdsType, Poseidon2Config,
|
||||
Poseidon2Constants,
|
||||
};
|
||||
extern "C" {
|
||||
#[link_name = concat!($field_prefix, "_create_optimized_poseidon2_constants_cuda")]
|
||||
pub(crate) fn _create_optimized_constants(
|
||||
width: u32,
|
||||
alpha: u32,
|
||||
internal_rounds: u32,
|
||||
external_rounds: u32,
|
||||
constants: *mut $field,
|
||||
internal_matrix_diag: *mut $field,
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
ctx: &DeviceContext,
|
||||
poseidon_constants: *mut Poseidon2Constants<$field>,
|
||||
) -> CudaError;
|
||||
|
||||
#[link_name = concat!($field_prefix, "_init_optimized_poseidon2_constants_cuda")]
|
||||
pub(crate) fn _load_optimized_constants(
|
||||
width: u32,
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
ctx: &DeviceContext,
|
||||
constants: *mut Poseidon2Constants<$field>,
|
||||
) -> CudaError;
|
||||
|
||||
#[link_name = concat!($field_prefix, "_poseidon2_hash_cuda")]
|
||||
pub(crate) fn hash_many(
|
||||
states: *mut $field,
|
||||
output: *mut $field,
|
||||
number_of_states: u32,
|
||||
width: u32,
|
||||
constants: &Poseidon2Constants<$field>,
|
||||
config: &Poseidon2Config,
|
||||
) -> CudaError;
|
||||
}
|
||||
}
|
||||
|
||||
impl Poseidon2<$field> for $field_config {
|
||||
fn create_optimized_constants<'a>(
|
||||
width: u32,
|
||||
alpha: u32,
|
||||
internal_rounds: u32,
|
||||
external_rounds: u32,
|
||||
round_constants: &mut [$field],
|
||||
internal_matrix_diag: &mut [$field],
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<Poseidon2Constants<'a, $field>> {
|
||||
unsafe {
|
||||
let mut poseidon_constants = MaybeUninit::<Poseidon2Constants<'a, $field>>::uninit();
|
||||
let err = $field_prefix_ident::_create_optimized_constants(
|
||||
width,
|
||||
alpha,
|
||||
internal_rounds,
|
||||
external_rounds,
|
||||
round_constants as *mut _ as *mut $field,
|
||||
internal_matrix_diag as *mut _ as *mut $field,
|
||||
mds_type,
|
||||
diffusion,
|
||||
ctx,
|
||||
poseidon_constants.as_mut_ptr(),
|
||||
)
|
||||
.wrap();
|
||||
err.and(Ok(poseidon_constants.assume_init()))
|
||||
}
|
||||
}
|
||||
|
||||
fn load_optimized_constants<'a>(
|
||||
width: u32,
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<Poseidon2Constants<'a, $field>> {
|
||||
unsafe {
|
||||
let mut constants = MaybeUninit::<Poseidon2Constants<'a, $field>>::uninit();
|
||||
let err = $field_prefix_ident::_load_optimized_constants(
|
||||
width,
|
||||
mds_type,
|
||||
diffusion,
|
||||
ctx,
|
||||
constants.as_mut_ptr(),
|
||||
)
|
||||
.wrap();
|
||||
err.and(Ok(constants.assume_init()))
|
||||
}
|
||||
}
|
||||
|
||||
fn poseidon_unchecked(
|
||||
states: &mut (impl HostOrDeviceSlice<$field> + ?Sized),
|
||||
output: &mut (impl HostOrDeviceSlice<$field> + ?Sized),
|
||||
number_of_states: u32,
|
||||
width: u32,
|
||||
constants: &Poseidon2Constants<$field>,
|
||||
config: &Poseidon2Config,
|
||||
) -> IcicleResult<()> {
|
||||
unsafe {
|
||||
$field_prefix_ident::hash_many(
|
||||
states.as_mut_ptr(),
|
||||
output.as_mut_ptr(),
|
||||
number_of_states,
|
||||
width,
|
||||
constants,
|
||||
config,
|
||||
)
|
||||
.wrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_poseidon2_tests {
|
||||
(
|
||||
$field:ident
|
||||
) => {
|
||||
#[test]
|
||||
fn test_poseidon2_hash_many() {
|
||||
check_poseidon_hash_many::<$field>()
|
||||
}
|
||||
};
|
||||
}
|
||||
105
wrappers/rust/icicle-core/src/poseidon2/tests.rs
Normal file
105
wrappers/rust/icicle-core/src/poseidon2/tests.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
use crate::poseidon2::{MdsType, PoseidonMode};
|
||||
use crate::traits::FieldImpl;
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::memory::{HostOrDeviceSlice, HostSlice};
|
||||
|
||||
use super::{
|
||||
load_optimized_poseidon2_constants, poseidon_hash_many, DiffusionStrategy, Poseidon2, Poseidon2Config,
|
||||
Poseidon2Constants,
|
||||
};
|
||||
|
||||
pub fn init_poseidon<'a, F: FieldImpl>(
|
||||
width: u32,
|
||||
mds_type: MdsType,
|
||||
diffusion: DiffusionStrategy,
|
||||
) -> Poseidon2Constants<'a, F>
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon2<F>,
|
||||
{
|
||||
let ctx = DeviceContext::default();
|
||||
load_optimized_poseidon2_constants::<F>(width, mds_type, diffusion, &ctx).unwrap()
|
||||
}
|
||||
|
||||
fn _check_poseidon_hash_many<F: FieldImpl>(width: u32, constants: Poseidon2Constants<F>) -> (F, F)
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon2<F>,
|
||||
{
|
||||
let test_size = 1 << 10;
|
||||
let mut inputs = vec![F::one(); test_size * width as usize];
|
||||
let mut outputs = vec![F::zero(); test_size];
|
||||
|
||||
let input_slice = HostSlice::from_mut_slice(&mut inputs);
|
||||
let output_slice = HostSlice::from_mut_slice(&mut outputs);
|
||||
|
||||
let config = Poseidon2Config::default();
|
||||
poseidon_hash_many::<F>(
|
||||
input_slice,
|
||||
output_slice,
|
||||
test_size as u32,
|
||||
width as u32,
|
||||
&constants,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a1 = output_slice[0];
|
||||
let a2 = output_slice[output_slice.len() - 2];
|
||||
|
||||
assert_eq!(a1, a2);
|
||||
|
||||
(a1, a2)
|
||||
}
|
||||
|
||||
pub fn check_poseidon_hash_many<'a, F: FieldImpl + 'a>()
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon2<F>,
|
||||
{
|
||||
let widths = [2, 3, 4, 8, 12, 16, 20, 24];
|
||||
for width in widths {
|
||||
let constants = init_poseidon::<'a, F>(width as u32, MdsType::Default, DiffusionStrategy::Default);
|
||||
|
||||
_check_poseidon_hash_many(width, constants);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_poseidon_kats<'a, F: FieldImpl>(width: usize, kats: &[F], constants: &Poseidon2Constants<'a, F>)
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon2<F>,
|
||||
{
|
||||
assert_eq!(width, kats.len());
|
||||
|
||||
let batch_size = 1024;
|
||||
let mut input = vec![F::one(); width];
|
||||
let mut outputs = vec![F::zero(); width * batch_size];
|
||||
|
||||
for i in 0..width {
|
||||
input[i] = F::from_u32(i as u32);
|
||||
}
|
||||
|
||||
let mut inputs: Vec<F> = std::iter::repeat(input.clone())
|
||||
.take(batch_size)
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
let input_slice = HostSlice::from_mut_slice(&mut inputs);
|
||||
let output_slice = HostSlice::from_mut_slice(&mut outputs);
|
||||
|
||||
let mut config = Poseidon2Config::default();
|
||||
config.mode = PoseidonMode::Permutation;
|
||||
poseidon_hash_many::<F>(
|
||||
input_slice,
|
||||
output_slice,
|
||||
batch_size as u32,
|
||||
width as u32,
|
||||
&constants,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
for (i, val) in output_slice
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
assert_eq!(*val, kats[i % width]);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ pub trait FieldImpl:
|
||||
|
||||
fn to_bytes_le(&self) -> Vec<u8>;
|
||||
fn from_bytes_le(bytes: &[u8]) -> Self;
|
||||
fn from_hex(s: &str) -> Self;
|
||||
fn zero() -> Self;
|
||||
fn one() -> Self;
|
||||
fn from_u32(val: u32) -> Self;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
pub mod curve;
|
||||
pub mod ecntt;
|
||||
|
||||
pub mod msm;
|
||||
pub mod ntt;
|
||||
pub mod polynomials;
|
||||
pub mod poseidon;
|
||||
pub mod poseidon2;
|
||||
pub mod tree;
|
||||
pub mod vec_ops;
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
use crate::curve::{ScalarCfg, ScalarField};
|
||||
|
||||
use icicle_core::error::IcicleResult;
|
||||
use icicle_core::impl_poseidon2;
|
||||
use icicle_core::poseidon2::{DiffusionStrategy, MdsType, Poseidon2, Poseidon2Config, Poseidon2Constants};
|
||||
use icicle_core::traits::IcicleResultWrap;
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
impl_poseidon2!("bn254", bn254, ScalarField, ScalarCfg);
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_poseidon2_tests;
|
||||
use icicle_core::ntt::FieldImpl;
|
||||
use icicle_core::poseidon2::{tests::*, DiffusionStrategy, MdsType};
|
||||
|
||||
impl_poseidon2_tests!(ScalarField);
|
||||
|
||||
#[test]
|
||||
fn test_poseidon2_kats() {
|
||||
let kats = [
|
||||
ScalarField::from_hex("0x0bb61d24daca55eebcb1929a82650f328134334da98ea4f847f760054f4a3033"),
|
||||
ScalarField::from_hex("0x303b6f7c86d043bfcbcc80214f26a30277a15d3f74ca654992defe7ff8d03570"),
|
||||
ScalarField::from_hex("0x1ed25194542b12eef8617361c3ba7c52e660b145994427cc86296242cf766ec8"),
|
||||
];
|
||||
|
||||
let constants = init_poseidon::<ScalarField>(3, MdsType::Default, DiffusionStrategy::Default);
|
||||
check_poseidon_kats(3, &kats, &constants);
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,13 @@ cmake = "0.1.50"
|
||||
[dev-dependencies]
|
||||
risc0-core = "0.21.0"
|
||||
risc0-zkp = "0.21.0"
|
||||
p3-baby-bear = { git = "https://github.com/Plonky3/Plonky3", rev = "83590121c8c28011cffa7e73cb71cf9bf94b8477" }
|
||||
p3-field = { git = "https://github.com/Plonky3/Plonky3", rev = "83590121c8c28011cffa7e73cb71cf9bf94b8477" }
|
||||
p3-dft = { git = "https://github.com/Plonky3/Plonky3", rev = "83590121c8c28011cffa7e73cb71cf9bf94b8477" }
|
||||
p3-matrix = { git = "https://github.com/Plonky3/Plonky3", rev = "83590121c8c28011cffa7e73cb71cf9bf94b8477" }
|
||||
p3-baby-bear = { git = "https://github.com/Plonky3/Plonky3", rev = "1e87146ebfaedc2150b635b10a096b733795fdce" }
|
||||
p3-symmetric = { git = "https://github.com/Plonky3/Plonky3", rev = "1e87146ebfaedc2150b635b10a096b733795fdce" }
|
||||
p3-mds = { git = "https://github.com/Plonky3/Plonky3", rev = "1e87146ebfaedc2150b635b10a096b733795fdce" }
|
||||
p3-poseidon2 = { git = "https://github.com/Plonky3/Plonky3", rev = "1e87146ebfaedc2150b635b10a096b733795fdce" }
|
||||
p3-field = { git = "https://github.com/Plonky3/Plonky3", rev = "1e87146ebfaedc2150b635b10a096b733795fdce" }
|
||||
p3-dft = { git = "https://github.com/Plonky3/Plonky3", rev = "1e87146ebfaedc2150b635b10a096b733795fdce" }
|
||||
p3-matrix = { git = "https://github.com/Plonky3/Plonky3", rev = "1e87146ebfaedc2150b635b10a096b733795fdce" }
|
||||
serial_test = "3.0.0"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod field;
|
||||
pub mod ntt;
|
||||
pub mod polynomials;
|
||||
pub mod poseidon2;
|
||||
pub mod vec_ops;
|
||||
|
||||
@@ -120,7 +120,7 @@ pub(crate) mod tests {
|
||||
ntt_cfg.columns_batch = true;
|
||||
ntt_inplace(HostSlice::from_mut_slice(&mut scalars[..]), NTTDir::kForward, &ntt_cfg).unwrap();
|
||||
|
||||
let result_p3 = Radix2Dit.dft_batch(matrix_p3);
|
||||
let result_p3 = Radix2Dit::default().dft_batch(matrix_p3);
|
||||
|
||||
for i in 0..nrows {
|
||||
for j in 0..ntt_size {
|
||||
@@ -156,7 +156,7 @@ pub(crate) mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let ext_result_p3 = Radix2Dit.dft_batch(ext_matrix_p3);
|
||||
let ext_result_p3 = Radix2Dit::default().dft_batch(ext_matrix_p3);
|
||||
|
||||
for i in 0..nrows {
|
||||
for j in 0..ntt_size {
|
||||
|
||||
633
wrappers/rust/icicle-fields/icicle-babybear/src/poseidon2/mod.rs
Normal file
633
wrappers/rust/icicle-fields/icicle-babybear/src/poseidon2/mod.rs
Normal file
@@ -0,0 +1,633 @@
|
||||
use crate::field::{ScalarCfg, ScalarField};
|
||||
|
||||
use icicle_core::error::IcicleResult;
|
||||
use icicle_core::impl_poseidon2;
|
||||
use icicle_core::poseidon2::{DiffusionStrategy, MdsType, Poseidon2, Poseidon2Config, Poseidon2Constants};
|
||||
use icicle_core::traits::IcicleResultWrap;
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
impl_poseidon2!("babybear", babybear, ScalarField, ScalarCfg);
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::field::ScalarField;
|
||||
use icicle_core::impl_poseidon2_tests;
|
||||
use icicle_core::poseidon2::{create_optimized_poseidon2_constants, tests::*, DiffusionStrategy, MdsType};
|
||||
use icicle_core::traits::FieldImpl;
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
|
||||
use p3_baby_bear::BabyBear;
|
||||
use p3_baby_bear::DiffusionMatrixBabyBear;
|
||||
use p3_field::{AbstractField, PrimeField32};
|
||||
use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral};
|
||||
use p3_symmetric::Permutation;
|
||||
|
||||
impl_poseidon2_tests!(ScalarField);
|
||||
|
||||
#[test]
|
||||
fn test_poseidon2_kats() {
|
||||
let kats = [
|
||||
ScalarField::from_hex("0x2ed3e23d"),
|
||||
ScalarField::from_hex("0x12921fb0"),
|
||||
ScalarField::from_hex("0x0e659e79"),
|
||||
ScalarField::from_hex("0x61d81dc9"),
|
||||
ScalarField::from_hex("0x32bae33b"),
|
||||
ScalarField::from_hex("0x62486ae3"),
|
||||
ScalarField::from_hex("0x1e681b60"),
|
||||
ScalarField::from_hex("0x24b91325"),
|
||||
ScalarField::from_hex("0x2a2ef5b9"),
|
||||
ScalarField::from_hex("0x50e8593e"),
|
||||
ScalarField::from_hex("0x5bc818ec"),
|
||||
ScalarField::from_hex("0x10691997"),
|
||||
ScalarField::from_hex("0x35a14520"),
|
||||
ScalarField::from_hex("0x2ba6a3c5"),
|
||||
ScalarField::from_hex("0x279d47ec"),
|
||||
ScalarField::from_hex("0x55014e81"),
|
||||
ScalarField::from_hex("0x5953a67f"),
|
||||
ScalarField::from_hex("0x2f403111"),
|
||||
ScalarField::from_hex("0x6b8828ff"),
|
||||
ScalarField::from_hex("0x1801301f"),
|
||||
ScalarField::from_hex("0x2749207a"),
|
||||
ScalarField::from_hex("0x3dc9cf21"),
|
||||
ScalarField::from_hex("0x3c985ba2"),
|
||||
ScalarField::from_hex("0x57a99864"),
|
||||
];
|
||||
|
||||
let constants = init_poseidon::<ScalarField>(24, MdsType::Default, DiffusionStrategy::Default);
|
||||
check_poseidon_kats(24, &kats, &constants);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poseidon2_plonky3_t16() {
|
||||
let rounds_p = 13;
|
||||
let rounds_f = 8;
|
||||
const ALPHA: u64 = 7;
|
||||
const WIDTH: usize = 16;
|
||||
|
||||
let cnv = BabyBear::from_canonical_u32;
|
||||
let external_constants: Vec<[BabyBear; 16]> = vec![
|
||||
[
|
||||
cnv(1774958255),
|
||||
cnv(1185780729),
|
||||
cnv(1621102414),
|
||||
cnv(1796380621),
|
||||
cnv(588815102),
|
||||
cnv(1932426223),
|
||||
cnv(1925334750),
|
||||
cnv(747903232),
|
||||
cnv(89648862),
|
||||
cnv(360728943),
|
||||
cnv(977184635),
|
||||
cnv(1425273457),
|
||||
cnv(256487465),
|
||||
cnv(1200041953),
|
||||
cnv(572403254),
|
||||
cnv(448208942),
|
||||
],
|
||||
[
|
||||
cnv(1215789478),
|
||||
cnv(944884184),
|
||||
cnv(953948096),
|
||||
cnv(547326025),
|
||||
cnv(646827752),
|
||||
cnv(889997530),
|
||||
cnv(1536873262),
|
||||
cnv(86189867),
|
||||
cnv(1065944411),
|
||||
cnv(32019634),
|
||||
cnv(333311454),
|
||||
cnv(456061748),
|
||||
cnv(1963448500),
|
||||
cnv(1827584334),
|
||||
cnv(1391160226),
|
||||
cnv(1348741381),
|
||||
],
|
||||
[
|
||||
cnv(88424255),
|
||||
cnv(104111868),
|
||||
cnv(1763866748),
|
||||
cnv(79691676),
|
||||
cnv(1988915530),
|
||||
cnv(1050669594),
|
||||
cnv(359890076),
|
||||
cnv(573163527),
|
||||
cnv(222820492),
|
||||
cnv(159256268),
|
||||
cnv(669703072),
|
||||
cnv(763177444),
|
||||
cnv(889367200),
|
||||
cnv(256335831),
|
||||
cnv(704371273),
|
||||
cnv(25886717),
|
||||
],
|
||||
[
|
||||
cnv(51754520),
|
||||
cnv(1833211857),
|
||||
cnv(454499742),
|
||||
cnv(1384520381),
|
||||
cnv(777848065),
|
||||
cnv(1053320300),
|
||||
cnv(1851729162),
|
||||
cnv(344647910),
|
||||
cnv(401996362),
|
||||
cnv(1046925956),
|
||||
cnv(5351995),
|
||||
cnv(1212119315),
|
||||
cnv(754867989),
|
||||
cnv(36972490),
|
||||
cnv(751272725),
|
||||
cnv(506915399),
|
||||
],
|
||||
[
|
||||
cnv(1922082829),
|
||||
cnv(1870549801),
|
||||
cnv(1502529704),
|
||||
cnv(1990744480),
|
||||
cnv(1700391016),
|
||||
cnv(1702593455),
|
||||
cnv(321330495),
|
||||
cnv(528965731),
|
||||
cnv(183414327),
|
||||
cnv(1886297254),
|
||||
cnv(1178602734),
|
||||
cnv(1923111974),
|
||||
cnv(744004766),
|
||||
cnv(549271463),
|
||||
cnv(1781349648),
|
||||
cnv(542259047),
|
||||
],
|
||||
[
|
||||
cnv(1536158148),
|
||||
cnv(715456982),
|
||||
cnv(503426110),
|
||||
cnv(340311124),
|
||||
cnv(1558555932),
|
||||
cnv(1226350925),
|
||||
cnv(742828095),
|
||||
cnv(1338992758),
|
||||
cnv(1641600456),
|
||||
cnv(1843351545),
|
||||
cnv(301835475),
|
||||
cnv(43203215),
|
||||
cnv(386838401),
|
||||
cnv(1520185679),
|
||||
cnv(1235297680),
|
||||
cnv(904680097),
|
||||
],
|
||||
[
|
||||
cnv(1491801617),
|
||||
cnv(1581784677),
|
||||
cnv(913384905),
|
||||
cnv(247083962),
|
||||
cnv(532844013),
|
||||
cnv(107190701),
|
||||
cnv(213827818),
|
||||
cnv(1979521776),
|
||||
cnv(1358282574),
|
||||
cnv(1681743681),
|
||||
cnv(1867507480),
|
||||
cnv(1530706910),
|
||||
cnv(507181886),
|
||||
cnv(695185447),
|
||||
cnv(1172395131),
|
||||
cnv(1250800299),
|
||||
],
|
||||
[
|
||||
cnv(1503161625),
|
||||
cnv(817684387),
|
||||
cnv(498481458),
|
||||
cnv(494676004),
|
||||
cnv(1404253825),
|
||||
cnv(108246855),
|
||||
cnv(59414691),
|
||||
cnv(744214112),
|
||||
cnv(890862029),
|
||||
cnv(1342765939),
|
||||
cnv(1417398904),
|
||||
cnv(1897591937),
|
||||
cnv(1066647396),
|
||||
cnv(1682806907),
|
||||
cnv(1015795079),
|
||||
cnv(1619482808),
|
||||
],
|
||||
];
|
||||
|
||||
let internal_constants: Vec<BabyBear> = vec![
|
||||
cnv(1518359488),
|
||||
cnv(1765533241),
|
||||
cnv(945325693),
|
||||
cnv(422793067),
|
||||
cnv(311365592),
|
||||
cnv(1311448267),
|
||||
cnv(1629555936),
|
||||
cnv(1009879353),
|
||||
cnv(190525218),
|
||||
cnv(786108885),
|
||||
cnv(557776863),
|
||||
cnv(212616710),
|
||||
cnv(605745517),
|
||||
];
|
||||
|
||||
let poseidon2: Poseidon2<BabyBear, Poseidon2ExternalMatrixGeneral, DiffusionMatrixBabyBear, WIDTH, ALPHA> =
|
||||
Poseidon2::new(
|
||||
rounds_f,
|
||||
external_constants.clone(),
|
||||
Poseidon2ExternalMatrixGeneral::default(),
|
||||
rounds_p,
|
||||
internal_constants.clone(),
|
||||
DiffusionMatrixBabyBear::default(),
|
||||
);
|
||||
|
||||
let mut input: [BabyBear; WIDTH] = [BabyBear::zero(); WIDTH];
|
||||
for i in 0..WIDTH {
|
||||
input[i] = BabyBear::from_canonical_u32(i as u32);
|
||||
}
|
||||
|
||||
let output = poseidon2.permute(input);
|
||||
|
||||
let mut kats: [ScalarField; WIDTH] = [ScalarField::zero(); WIDTH];
|
||||
for i in 0..WIDTH {
|
||||
kats[i] = ScalarField::from_u32(output[i].as_canonical_u32());
|
||||
}
|
||||
|
||||
let ctx = DeviceContext::default();
|
||||
let mut round_constants = vec![ScalarField::zero(); rounds_f * WIDTH + rounds_p];
|
||||
let external_constants_flattened: Vec<ScalarField> = external_constants
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|c| ScalarField::from_u32(c.as_canonical_u32()))
|
||||
.collect();
|
||||
let internal_constants_icicle: Vec<ScalarField> = internal_constants
|
||||
.iter()
|
||||
.map(|&c| ScalarField::from_u32(c.as_canonical_u32()))
|
||||
.collect();
|
||||
|
||||
(&mut round_constants[..rounds_f / 2 * WIDTH])
|
||||
.copy_from_slice(&external_constants_flattened[..rounds_f / 2 * WIDTH]);
|
||||
(&mut round_constants[rounds_f / 2 * WIDTH..rounds_f / 2 * WIDTH + rounds_p])
|
||||
.copy_from_slice(&internal_constants_icicle[..]);
|
||||
(&mut round_constants[rounds_p + rounds_f / 2 * WIDTH..])
|
||||
.copy_from_slice(&external_constants_flattened[rounds_f / 2 * WIDTH..]);
|
||||
|
||||
let mut internal_matrix_diag = vec![
|
||||
ScalarField::from_u32(0x78000001 - 2),
|
||||
ScalarField::from_u32(1),
|
||||
ScalarField::from_u32(1 << 1),
|
||||
ScalarField::from_u32(1 << 2),
|
||||
ScalarField::from_u32(1 << 3),
|
||||
ScalarField::from_u32(1 << 4),
|
||||
ScalarField::from_u32(1 << 5),
|
||||
ScalarField::from_u32(1 << 6),
|
||||
ScalarField::from_u32(1 << 7),
|
||||
ScalarField::from_u32(1 << 8),
|
||||
ScalarField::from_u32(1 << 9),
|
||||
ScalarField::from_u32(1 << 10),
|
||||
ScalarField::from_u32(1 << 11),
|
||||
ScalarField::from_u32(1 << 12),
|
||||
ScalarField::from_u32(1 << 13),
|
||||
ScalarField::from_u32(1 << 15),
|
||||
];
|
||||
let mut constants = create_optimized_poseidon2_constants(
|
||||
WIDTH as u32,
|
||||
ALPHA as u32,
|
||||
&ctx,
|
||||
rounds_p as u32,
|
||||
rounds_f as u32,
|
||||
&mut round_constants,
|
||||
&mut internal_matrix_diag,
|
||||
MdsType::Plonky,
|
||||
DiffusionStrategy::Montgomery,
|
||||
)
|
||||
.unwrap();
|
||||
check_poseidon_kats(WIDTH, &kats, &constants);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poseidon2_plonky3_t24() {
|
||||
let rounds_p = 21;
|
||||
let rounds_f = 8;
|
||||
const ALPHA: u64 = 7;
|
||||
const WIDTH: usize = 24;
|
||||
|
||||
let cnv = BabyBear::from_canonical_u32;
|
||||
let external_constants: Vec<[BabyBear; 24]> = vec![
|
||||
[
|
||||
cnv(262278199),
|
||||
cnv(127253399),
|
||||
cnv(314968988),
|
||||
cnv(246143118),
|
||||
cnv(157582794),
|
||||
cnv(118043943),
|
||||
cnv(454905424),
|
||||
cnv(815798990),
|
||||
cnv(1004040026),
|
||||
cnv(1773108264),
|
||||
cnv(1066694495),
|
||||
cnv(1930780904),
|
||||
cnv(1180307149),
|
||||
cnv(1464793095),
|
||||
cnv(1660766320),
|
||||
cnv(1389166148),
|
||||
cnv(343354132),
|
||||
cnv(1307439985),
|
||||
cnv(638242172),
|
||||
cnv(525458520),
|
||||
cnv(1964135730),
|
||||
cnv(1751797115),
|
||||
cnv(1421525369),
|
||||
cnv(831813382),
|
||||
],
|
||||
[
|
||||
cnv(695835963),
|
||||
cnv(1845603984),
|
||||
cnv(540703332),
|
||||
cnv(1333667262),
|
||||
cnv(1917861751),
|
||||
cnv(1170029417),
|
||||
cnv(1989924532),
|
||||
cnv(1518763784),
|
||||
cnv(1339793538),
|
||||
cnv(622609176),
|
||||
cnv(686842369),
|
||||
cnv(1737016378),
|
||||
cnv(1282239129),
|
||||
cnv(897025192),
|
||||
cnv(716894289),
|
||||
cnv(1997503974),
|
||||
cnv(395622276),
|
||||
cnv(1201063290),
|
||||
cnv(1917549072),
|
||||
cnv(1150912935),
|
||||
cnv(1687379185),
|
||||
cnv(1507936940),
|
||||
cnv(241306552),
|
||||
cnv(989176635),
|
||||
],
|
||||
[
|
||||
cnv(1147522062),
|
||||
cnv(27129487),
|
||||
cnv(1257820264),
|
||||
cnv(142102402),
|
||||
cnv(217046702),
|
||||
cnv(1664590951),
|
||||
cnv(855276054),
|
||||
cnv(1215259350),
|
||||
cnv(946500736),
|
||||
cnv(552696906),
|
||||
cnv(1424297384),
|
||||
cnv(538103555),
|
||||
cnv(1608853840),
|
||||
cnv(162510541),
|
||||
cnv(623051854),
|
||||
cnv(1549062383),
|
||||
cnv(1908416316),
|
||||
cnv(1622328571),
|
||||
cnv(1079030649),
|
||||
cnv(1584033957),
|
||||
cnv(1099252725),
|
||||
cnv(1910423126),
|
||||
cnv(447555988),
|
||||
cnv(862495875),
|
||||
],
|
||||
[
|
||||
cnv(128479034),
|
||||
cnv(1587822577),
|
||||
cnv(608401422),
|
||||
cnv(1290028279),
|
||||
cnv(342857858),
|
||||
cnv(825405577),
|
||||
cnv(427731030),
|
||||
cnv(1718628547),
|
||||
cnv(588764636),
|
||||
cnv(204228775),
|
||||
cnv(1454563174),
|
||||
cnv(1740472809),
|
||||
cnv(1338899225),
|
||||
cnv(1269493554),
|
||||
cnv(53007114),
|
||||
cnv(1647670797),
|
||||
cnv(306391314),
|
||||
cnv(172614232),
|
||||
cnv(51256176),
|
||||
cnv(1221257987),
|
||||
cnv(1239734761),
|
||||
cnv(273790406),
|
||||
cnv(1781980094),
|
||||
cnv(1291790245),
|
||||
],
|
||||
[
|
||||
cnv(53041581),
|
||||
cnv(723038058),
|
||||
cnv(1439947916),
|
||||
cnv(1136469704),
|
||||
cnv(205609311),
|
||||
cnv(1883820770),
|
||||
cnv(14387587),
|
||||
cnv(720724951),
|
||||
cnv(1854174607),
|
||||
cnv(1629316321),
|
||||
cnv(530151394),
|
||||
cnv(1679178250),
|
||||
cnv(1549779579),
|
||||
cnv(48375137),
|
||||
cnv(976057819),
|
||||
cnv(463976218),
|
||||
cnv(875839332),
|
||||
cnv(1946596189),
|
||||
cnv(434078361),
|
||||
cnv(1878280202),
|
||||
cnv(1363837384),
|
||||
cnv(1470845646),
|
||||
cnv(1792450386),
|
||||
cnv(1040977421),
|
||||
],
|
||||
[
|
||||
cnv(1209164052),
|
||||
cnv(714957516),
|
||||
cnv(390340387),
|
||||
cnv(1213686459),
|
||||
cnv(790726260),
|
||||
cnv(117294666),
|
||||
cnv(140621810),
|
||||
cnv(993455846),
|
||||
cnv(1889603648),
|
||||
cnv(78845751),
|
||||
cnv(925018226),
|
||||
cnv(708123747),
|
||||
cnv(1647665372),
|
||||
cnv(1649953458),
|
||||
cnv(942439428),
|
||||
cnv(1006235079),
|
||||
cnv(238616145),
|
||||
cnv(930036496),
|
||||
cnv(1401020792),
|
||||
cnv(989618631),
|
||||
cnv(1545325389),
|
||||
cnv(1715719711),
|
||||
cnv(755691969),
|
||||
cnv(150307788),
|
||||
],
|
||||
[
|
||||
cnv(1567618575),
|
||||
cnv(1663353317),
|
||||
cnv(1950429111),
|
||||
cnv(1891637550),
|
||||
cnv(192082241),
|
||||
cnv(1080533265),
|
||||
cnv(1463323727),
|
||||
cnv(890243564),
|
||||
cnv(158646617),
|
||||
cnv(1402624179),
|
||||
cnv(59510015),
|
||||
cnv(1198261138),
|
||||
cnv(1065075039),
|
||||
cnv(1150410028),
|
||||
cnv(1293938517),
|
||||
cnv(76770019),
|
||||
cnv(1478577620),
|
||||
cnv(1748789933),
|
||||
cnv(457372011),
|
||||
cnv(1841795381),
|
||||
cnv(760115692),
|
||||
cnv(1042892522),
|
||||
cnv(1507649755),
|
||||
cnv(1827572010),
|
||||
],
|
||||
[
|
||||
cnv(1206940496),
|
||||
cnv(1896271507),
|
||||
cnv(1003792297),
|
||||
cnv(738091882),
|
||||
cnv(1124078057),
|
||||
cnv(1889898),
|
||||
cnv(813674331),
|
||||
cnv(228520958),
|
||||
cnv(1832911930),
|
||||
cnv(781141772),
|
||||
cnv(459826664),
|
||||
cnv(202271745),
|
||||
cnv(1296144415),
|
||||
cnv(1111203133),
|
||||
cnv(1090783436),
|
||||
cnv(641665156),
|
||||
cnv(1393671120),
|
||||
cnv(1303271640),
|
||||
cnv(809508074),
|
||||
cnv(162506101),
|
||||
cnv(1262312258),
|
||||
cnv(1672219447),
|
||||
cnv(1608891156),
|
||||
cnv(1380248020),
|
||||
],
|
||||
];
|
||||
|
||||
let internal_constants: Vec<BabyBear> = vec![
|
||||
cnv(497520322),
|
||||
cnv(1930103076),
|
||||
cnv(1052077299),
|
||||
cnv(1540960371),
|
||||
cnv(924863639),
|
||||
cnv(1365519753),
|
||||
cnv(1726563304),
|
||||
cnv(440300254),
|
||||
cnv(1891545577),
|
||||
cnv(822033215),
|
||||
cnv(1111544260),
|
||||
cnv(308575117),
|
||||
cnv(1708681573),
|
||||
cnv(1240419708),
|
||||
cnv(1199068823),
|
||||
cnv(1186174623),
|
||||
cnv(1551596046),
|
||||
cnv(1886977120),
|
||||
cnv(1327682690),
|
||||
cnv(1210751726),
|
||||
cnv(1810596765),
|
||||
];
|
||||
|
||||
let poseidon2: Poseidon2<BabyBear, Poseidon2ExternalMatrixGeneral, DiffusionMatrixBabyBear, WIDTH, ALPHA> =
|
||||
Poseidon2::new(
|
||||
rounds_f,
|
||||
external_constants.clone(),
|
||||
Poseidon2ExternalMatrixGeneral::default(),
|
||||
rounds_p,
|
||||
internal_constants.clone(),
|
||||
DiffusionMatrixBabyBear::default(),
|
||||
);
|
||||
|
||||
let mut input: [BabyBear; WIDTH] = [BabyBear::zero(); WIDTH];
|
||||
for i in 0..WIDTH {
|
||||
input[i] = BabyBear::from_canonical_u32(i as u32);
|
||||
}
|
||||
|
||||
let output = poseidon2.permute(input);
|
||||
|
||||
let mut kats: [ScalarField; WIDTH] = [ScalarField::zero(); WIDTH];
|
||||
for i in 0..WIDTH {
|
||||
kats[i] = ScalarField::from_u32(output[i].as_canonical_u32());
|
||||
}
|
||||
|
||||
let ctx = DeviceContext::default();
|
||||
let mut round_constants = vec![ScalarField::zero(); rounds_f * WIDTH + rounds_p];
|
||||
let external_constants_flattened: Vec<ScalarField> = external_constants
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|c| ScalarField::from_u32(c.as_canonical_u32()))
|
||||
.collect();
|
||||
let internal_constants_icicle: Vec<ScalarField> = internal_constants
|
||||
.iter()
|
||||
.map(|&c| ScalarField::from_u32(c.as_canonical_u32()))
|
||||
.collect();
|
||||
|
||||
(&mut round_constants[..rounds_f / 2 * WIDTH])
|
||||
.copy_from_slice(&external_constants_flattened[..rounds_f / 2 * WIDTH]);
|
||||
(&mut round_constants[rounds_f / 2 * WIDTH..rounds_f / 2 * WIDTH + rounds_p])
|
||||
.copy_from_slice(&internal_constants_icicle[..]);
|
||||
(&mut round_constants[rounds_p + rounds_f / 2 * WIDTH..])
|
||||
.copy_from_slice(&external_constants_flattened[rounds_f / 2 * WIDTH..]);
|
||||
|
||||
let mut internal_matrix_diag = vec![
|
||||
ScalarField::from_u32(0x78000001 - 2),
|
||||
ScalarField::from_u32(1),
|
||||
ScalarField::from_u32(1 << 1),
|
||||
ScalarField::from_u32(1 << 2),
|
||||
ScalarField::from_u32(1 << 3),
|
||||
ScalarField::from_u32(1 << 4),
|
||||
ScalarField::from_u32(1 << 5),
|
||||
ScalarField::from_u32(1 << 6),
|
||||
ScalarField::from_u32(1 << 7),
|
||||
ScalarField::from_u32(1 << 8),
|
||||
ScalarField::from_u32(1 << 9),
|
||||
ScalarField::from_u32(1 << 10),
|
||||
ScalarField::from_u32(1 << 11),
|
||||
ScalarField::from_u32(1 << 12),
|
||||
ScalarField::from_u32(1 << 13),
|
||||
ScalarField::from_u32(1 << 14),
|
||||
ScalarField::from_u32(1 << 15),
|
||||
ScalarField::from_u32(1 << 16),
|
||||
ScalarField::from_u32(1 << 18),
|
||||
ScalarField::from_u32(1 << 19),
|
||||
ScalarField::from_u32(1 << 20),
|
||||
ScalarField::from_u32(1 << 21),
|
||||
ScalarField::from_u32(1 << 22),
|
||||
ScalarField::from_u32(1 << 23),
|
||||
];
|
||||
let mut constants = create_optimized_poseidon2_constants(
|
||||
WIDTH as u32,
|
||||
ALPHA as u32,
|
||||
&ctx,
|
||||
rounds_p as u32,
|
||||
rounds_f as u32,
|
||||
&mut round_constants,
|
||||
&mut internal_matrix_diag,
|
||||
MdsType::Plonky,
|
||||
DiffusionStrategy::Montgomery,
|
||||
)
|
||||
.unwrap();
|
||||
check_poseidon_kats(WIDTH, &kats, &constants);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user