Skip to content
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license.workspace = true
repository.workspace = true

[dependencies]
ark-bn254 = { workspace = true, features = ["curve", "r1cs"] }
ark-crypto-primitives = { workspace = true, features = ["constraints", "sponge", "crh"] }
ark-ec = { workspace = true }
ark-ff = { workspace = true, features = ["asm"] }
Expand All @@ -23,7 +24,7 @@ sha3 = { workspace = true }
thiserror = { workspace = true }

[dev-dependencies]
ark-bn254 = { workspace = true, features = ["curve", "r1cs"] }
ark-grumpkin = { workspace = true, features = ["r1cs"] }
ark-pallas = { workspace = true, features = ["curve", "r1cs"] }

[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
Expand Down
17 changes: 10 additions & 7 deletions crates/primitives/src/transcripts/poseidon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ fn find_fd_round_numbers<F: PrimeField>(
}
}

assert_ne!(min_cost, usize::MAX);

(r_f, r_p)
}

Expand All @@ -106,13 +108,14 @@ pub fn poseidon_paper_config<F: PrimeField, const SECURITY_BITS: usize>(
alpha: u64,
rate: usize,
) -> PoseidonConfig<F> {
assert_ne!(alpha, 1);
assert_eq!(
BigUint::from(alpha).gcd(&(-F::one()).into()),
BigUint::one()
);
let (full_rounds, partial_rounds) =
find_fd_round_numbers::<F>(rate, alpha, SECURITY_BITS, get_sbox_cost, true);
let (ark, mds) = find_poseidon_ark_and_mds::<F>(
find_fd_round_numbers::<F>(rate + 1, alpha, SECURITY_BITS, get_sbox_cost, true);
let (ark, mds) = find_poseidon_ark_and_mds(
F::MODULUS_BIT_SIZE as u64,
rate,
full_rounds,
Expand All @@ -131,9 +134,9 @@ pub fn poseidon_paper_config<F: PrimeField, const SECURITY_BITS: usize>(
)
}

/// [`poseidon_circom_config`] produces a Poseidon configuration which agrees
/// with Circom's Poseidon(4) when `F` is the scalar field of BN254.
pub fn poseidon_circom_config<F: PrimeField>() -> PoseidonConfig<F> {
/// [`poseidon_circom_config`] produces a Poseidon configuration for BN254's
/// scalar field that agrees with Circom's Poseidon(4).
pub fn poseidon_circom_config() -> PoseidonConfig<ark_bn254::Fr> {
// 120 bit security target as in
// https://eprint.iacr.org/2019/458.pdf
// t = rate + 1
Expand All @@ -143,8 +146,8 @@ pub fn poseidon_circom_config<F: PrimeField>() -> PoseidonConfig<F> {
let alpha = 5;
let rate = 4;

let (ark, mds) = find_poseidon_ark_and_mds::<F>(
F::MODULUS_BIT_SIZE as u64,
let (ark, mds) = find_poseidon_ark_and_mds(
ark_bn254::Fr::MODULUS_BIT_SIZE as u64,
rate,
full_rounds as u64,
partial_rounds as u64,
Expand Down
47 changes: 24 additions & 23 deletions crates/primitives/src/transcripts/poseidon/sponge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ impl<F: PrimeField> TranscriptGadget<F> for PoseidonSpongeVar<F> {

#[cfg(test)]
mod tests {
use ark_bn254::{Fq, Fr, G1Projective as G1, g1::Config};
use ark_bn254::{Fr, G1Projective as G1};
use ark_crypto_primitives::sponge::poseidon::{PoseidonSponge, constraints::PoseidonSpongeVar};
use ark_ff::UniformRand;
use ark_grumpkin::Projective as G2;
use ark_r1cs_std::{
GR1CSVar, alloc::AllocVar, fields::fp::FpVar,
groups::curves::short_weierstrass::ProjectiveVar,
Expand All @@ -104,7 +105,7 @@ mod tests {
// Test with value taken from https://github.com/iden3/circomlibjs/blob/43cc582b100fc3459cf78d903a6f538e5d7f38ee/test/poseidon.js#L32
#[test]
fn check_against_circom_poseidon() -> Result<(), Box<dyn Error>> {
let config = poseidon_circom_config::<Fr>();
let config = poseidon_circom_config();
let mut poseidon_sponge = PoseidonSponge::new(config);
let v = vec![1, 2, 3, 4]
.into_iter()
Expand All @@ -125,15 +126,15 @@ mod tests {
#[test]
fn test_challenge_field_element() -> Result<(), Box<dyn Error>> {
// Create a transcript outside of the circuit
let config = poseidon_circom_config::<Fr>();
let mut tr = PoseidonSponge::<Fr>::new(config.clone());
let config = poseidon_circom_config();
let mut tr = PoseidonSponge::new(config.clone());
tr.add(&Fr::from(42_u32));
let c = tr.challenge_field_element();

// Create a transcript inside of the circuit
let cs = ConstraintSystem::<Fr>::new_ref();
let mut tr_var = PoseidonSpongeVar::<Fr>::new(config);
let v = FpVar::<Fr>::new_witness(cs.clone(), || Ok(Fr::from(42_u32)))?;
let cs = ConstraintSystem::new_ref();
let mut tr_var = PoseidonSpongeVar::new(config);
let v = FpVar::new_witness(cs.clone(), || Ok(Fr::from(42_u32)))?;
tr_var.add(&v)?;
let c_var = tr_var.challenge_field_element()?;

Expand All @@ -148,15 +149,15 @@ mod tests {
let nbits = 128;

// Create a transcript outside of the circuit
let config = poseidon_circom_config::<Fq>();
let mut tr = PoseidonSponge::<Fq>::new(config.clone());
tr.add(&Fq::from(42_u32));
let config = poseidon_circom_config();
let mut tr = PoseidonSponge::new(config.clone());
tr.add(&Fr::from(42_u32));
let c = tr.challenge_bits(nbits);

// Create a transcript inside of the circuit
let cs = ConstraintSystem::<Fq>::new_ref();
let mut tr_var = PoseidonSpongeVar::<Fq>::new(config);
let v = FpVar::<Fq>::new_witness(cs.clone(), || Ok(Fq::from(42_u32)))?;
let cs = ConstraintSystem::new_ref();
let mut tr_var = PoseidonSpongeVar::new(config);
let v = FpVar::new_witness(cs.clone(), || Ok(Fr::from(42_u32)))?;
tr_var.add(&v)?;
let c_var = tr_var.challenge_bits(nbits)?;

Expand All @@ -169,18 +170,18 @@ mod tests {
#[test]
fn test_absorb_canonical_point() -> Result<(), Box<dyn Error>> {
// Create a transcript outside of the circuit
let config = poseidon_circom_config::<Fq>();
let mut tr = PoseidonSponge::<Fq>::new(config.clone());
let config = poseidon_circom_config();
let mut tr = PoseidonSponge::new(config.clone());
let rng = &mut thread_rng();

let p = G1::rand(rng);
let p = G2::rand(rng);
tr.add(&p);
let c = tr.challenge_field_element();

// Create a transcript inside of the circuit
let cs = ConstraintSystem::<Fq>::new_ref();
let mut tr_var = PoseidonSpongeVar::<Fq>::new(config);
let p_var = ProjectiveVar::<Config, FpVar<Fq>>::new_witness(cs, || Ok(p))?;
let cs = ConstraintSystem::new_ref();
let mut tr_var = PoseidonSpongeVar::new(config);
let p_var = ProjectiveVar::new_witness(cs, || Ok(p))?;
tr_var.add(&p_var)?;
let c_var = tr_var.challenge_field_element()?;

Expand All @@ -193,17 +194,17 @@ mod tests {
#[test]
fn test_absorb_emulated_point() -> Result<(), Box<dyn Error>> {
// Create a transcript outside of the circuit
let config = poseidon_circom_config::<Fr>();
let mut tr = PoseidonSponge::<Fr>::new(config.clone());
let config = poseidon_circom_config();
let mut tr = PoseidonSponge::new(config.clone());
let rng = &mut thread_rng();

let p = G1::rand(rng);
tr.add(&p);
let c = tr.challenge_field_element();

// Create a transcript inside of the circuit
let cs = ConstraintSystem::<Fr>::new_ref();
let mut tr_var = PoseidonSpongeVar::<Fr>::new(config);
let cs = ConstraintSystem::new_ref();
let mut tr_var = PoseidonSpongeVar::new(config);
let p_var = EmulatedAffineVar::new_witness(cs, || Ok(p))?;
tr_var.add(&p_var)?;
let c_var = tr_var.challenge_field_element()?;
Expand Down
Loading