Skip to content

Commit

Permalink
Bump arkworks
Browse files Browse the repository at this point in the history
  • Loading branch information
winderica committed Dec 19, 2024
1 parent a97402a commit 5cf5e5c
Show file tree
Hide file tree
Showing 10 changed files with 416 additions and 338 deletions.
395 changes: 110 additions & 285 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,16 @@ bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" }
acvm_cli = { path = "tooling/acvm_cli" }

# Arkworks
ark-bn254 = { version = "^0.4.0", default-features = false, features = [
ark-bn254 = { version = "^0.5.0", default-features = false, features = [
"curve",
] }
ark-bls12-381 = { version = "^0.4.0", default-features = false, features = [
ark-bls12-381 = { version = "^0.5.0", default-features = false, features = [
"curve",
] }
grumpkin = { version = "0.1.0", package = "noir_grumpkin", features = ["std"] }
ark-ec = { version = "^0.4.0", default-features = false }
ark-ff = { version = "^0.4.0", default-features = false }
ark-std = { version = "^0.4.0", default-features = false }
ark-grumpkin = { version = "^0.5.0", default-features = false }
ark-ec = { version = "^0.5.0", default-features = false }
ark-ff = { version = "^0.5.0", default-features = false }
ark-std = { version = "^0.5.0", default-features = false }

# Misc utils crates
iter-extended = { path = "utils/iter-extended" }
Expand Down
4 changes: 2 additions & 2 deletions acvm-repo/acvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ bls12_381 = [
]

[dev-dependencies]
ark-bls12-381 = { version = "^0.4.0", default-features = false, features = [
ark-bls12-381 = { version = "^0.5.0", default-features = false, features = [
"curve",
] }
ark-ff.workspace = true
ark-bn254.workspace = true
bn254_blackbox_solver.workspace = true
proptest.workspace = true
zkhash = { version = "^0.2.0", default-features = false }
num-bigint.workspace = true
278 changes: 267 additions & 11 deletions acvm-repo/acvm/tests/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use proptest::arbitrary::any;
use proptest::prelude::*;
use proptest::result::maybe_ok;
use proptest::sample::select;
use zkhash::poseidon2::poseidon2_params::Poseidon2Params;

#[test]
fn bls12_381_circuit() {
Expand Down Expand Up @@ -1210,6 +1209,264 @@ where
fields.into_iter().map(|field| into_repr_vec(field)).collect()
}

// From https://docs.rs/crate/zkhash/0.2.0/source/ .
// The original code depends on `ark_ff` v0.4.0, but here we use v0.5.0.
mod zkhash {
use ark_ff::PrimeField;
use std::sync::Arc;

#[derive(Clone, Debug)]
pub struct Poseidon2Params<F: PrimeField> {
pub(crate) t: usize, // statesize
pub(crate) d: usize, // sbox degree
pub(crate) rounds_f_beginning: usize,
pub(crate) rounds_p: usize,
#[allow(dead_code)]
pub(crate) rounds_f_end: usize,
pub(crate) rounds: usize,
pub(crate) mat_internal_diag_m_1: Vec<F>,
pub(crate) _mat_internal: Vec<Vec<F>>,
pub(crate) round_constants: Vec<Vec<F>>,
}

impl<F: PrimeField> Poseidon2Params<F> {
#[allow(clippy::too_many_arguments)]
pub fn new(
t: usize,
d: usize,
rounds_f: usize,
rounds_p: usize,
mat_internal_diag_m_1: &[F],
mat_internal: &[Vec<F>],
round_constants: &[Vec<F>],
) -> Self {
assert!(d == 3 || d == 5 || d == 7 || d == 11);
assert_eq!(rounds_f % 2, 0);
let r = rounds_f / 2;
let rounds = rounds_f + rounds_p;

Poseidon2Params {
t,
d,
rounds_f_beginning: r,
rounds_p,
rounds_f_end: r,
rounds,
mat_internal_diag_m_1: mat_internal_diag_m_1.to_owned(),
_mat_internal: mat_internal.to_owned(),
round_constants: round_constants.to_owned(),
}
}
}

#[derive(Clone, Debug)]
pub struct Poseidon2<F: PrimeField> {
pub(crate) params: Arc<Poseidon2Params<F>>,
}

impl<F: PrimeField> Poseidon2<F> {
pub fn new(params: &Arc<Poseidon2Params<F>>) -> Self {
Poseidon2 { params: Arc::clone(params) }
}

pub fn permutation(&self, input: &[F]) -> Vec<F> {
let t = self.params.t;
assert_eq!(input.len(), t);

let mut current_state = input.to_owned();

// Linear layer at beginning
self.matmul_external(&mut current_state);

for r in 0..self.params.rounds_f_beginning {
current_state = self.add_rc(&current_state, &self.params.round_constants[r]);
current_state = self.sbox(&current_state);
self.matmul_external(&mut current_state);
}

let p_end = self.params.rounds_f_beginning + self.params.rounds_p;
for r in self.params.rounds_f_beginning..p_end {
current_state[0].add_assign(&self.params.round_constants[r][0]);
current_state[0] = self.sbox_p(&current_state[0]);
self.matmul_internal(&mut current_state, &self.params.mat_internal_diag_m_1);
}

for r in p_end..self.params.rounds {
current_state = self.add_rc(&current_state, &self.params.round_constants[r]);
current_state = self.sbox(&current_state);
self.matmul_external(&mut current_state);
}
current_state
}

fn sbox(&self, input: &[F]) -> Vec<F> {
input.iter().map(|el| self.sbox_p(el)).collect()
}

fn sbox_p(&self, input: &F) -> F {
let mut input2 = *input;
input2.square_in_place();

match self.params.d {
3 => {
let mut out = input2;
out.mul_assign(input);
out
}
5 => {
let mut out = input2;
out.square_in_place();
out.mul_assign(input);
out
}
7 => {
let mut out = input2;
out.square_in_place();
out.mul_assign(&input2);
out.mul_assign(input);
out
}
_ => {
panic!()
}
}
}

fn matmul_m4(&self, input: &mut [F]) {
let t = self.params.t;
let t4 = t / 4;
for i in 0..t4 {
let start_index = i * 4;
let mut t_0 = input[start_index];
t_0.add_assign(&input[start_index + 1]);
let mut t_1 = input[start_index + 2];
t_1.add_assign(&input[start_index + 3]);
let mut t_2 = input[start_index + 1];
t_2.double_in_place();
t_2.add_assign(&t_1);
let mut t_3 = input[start_index + 3];
t_3.double_in_place();
t_3.add_assign(&t_0);
let mut t_4 = t_1;
t_4.double_in_place();
t_4.double_in_place();
t_4.add_assign(&t_3);
let mut t_5 = t_0;
t_5.double_in_place();
t_5.double_in_place();
t_5.add_assign(&t_2);
let mut t_6 = t_3;
t_6.add_assign(&t_5);
let mut t_7 = t_2;
t_7.add_assign(&t_4);
input[start_index] = t_6;
input[start_index + 1] = t_5;
input[start_index + 2] = t_7;
input[start_index + 3] = t_4;
}
}

fn matmul_external(&self, input: &mut [F]) {
let t = self.params.t;
match t {
2 => {
// Matrix circ(2, 1)
let mut sum = input[0];
sum.add_assign(&input[1]);
input[0].add_assign(&sum);
input[1].add_assign(&sum);
}
3 => {
// Matrix circ(2, 1, 1)
let mut sum = input[0];
sum.add_assign(&input[1]);
sum.add_assign(&input[2]);
input[0].add_assign(&sum);
input[1].add_assign(&sum);
input[2].add_assign(&sum);
}
4 => {
// Applying cheap 4x4 MDS matrix to each 4-element part of the state
self.matmul_m4(input);
}
8 | 12 | 16 | 20 | 24 => {
// Applying cheap 4x4 MDS matrix to each 4-element part of the state
self.matmul_m4(input);

// Applying second cheap matrix for t > 4
let t4 = t / 4;
let mut stored = [F::zero(); 4];
for l in 0..4 {
stored[l] = input[l];
for j in 1..t4 {
stored[l].add_assign(&input[4 * j + l]);
}
}
for i in 0..input.len() {
input[i].add_assign(&stored[i % 4]);
}
}
_ => {
panic!()
}
}
}

fn matmul_internal(&self, input: &mut [F], mat_internal_diag_m_1: &[F]) {
let t = self.params.t;

match t {
2 => {
// [2, 1]
// [1, 3]
let mut sum = input[0];
sum.add_assign(&input[1]);
input[0].add_assign(&sum);
input[1].double_in_place();
input[1].add_assign(&sum);
}
3 => {
// [2, 1, 1]
// [1, 2, 1]
// [1, 1, 3]
let mut sum = input[0];
sum.add_assign(&input[1]);
sum.add_assign(&input[2]);
input[0].add_assign(&sum);
input[1].add_assign(&sum);
input[2].double_in_place();
input[2].add_assign(&sum);
}
4 | 8 | 12 | 16 | 20 | 24 => {
// Compute input sum
let mut sum = input[0];
input.iter().skip(1).take(t - 1).for_each(|el| sum.add_assign(el));
// Add sum + diag entry * element to each element
for i in 0..input.len() {
input[i].mul_assign(&mat_internal_diag_m_1[i]);
input[i].add_assign(&sum);
}
}
_ => {
panic!()
}
}
}

fn add_rc(&self, input: &[F], rc: &[F]) -> Vec<F> {
input
.iter()
.zip(rc.iter())
.map(|(a, b)| {
let mut r = *a;
r.add_assign(b);
r
})
.collect()
}
}
}

fn run_both_poseidon2_permutations(
inputs: Vec<ConstantOrWitness>,
) -> Result<(Vec<ark_bn254::Fr>, Vec<ark_bn254::Fr>), OpcodeResolutionError<FieldElement>> {
Expand All @@ -1228,16 +1485,15 @@ fn run_both_poseidon2_permutations(
let mat_internal = vec![];
let round_constants = into_repr_mat(POSEIDON2_CONFIG.round_constant);

let external_poseidon2 =
zkhash::poseidon2::poseidon2::Poseidon2::new(&Arc::new(Poseidon2Params::new(
poseidon2_t,
poseidon2_d,
rounds_f,
rounds_p,
&mat_internal_diag_m_1,
&mat_internal,
&round_constants,
)));
let external_poseidon2 = zkhash::Poseidon2::new(&Arc::new(zkhash::Poseidon2Params::new(
poseidon2_t,
poseidon2_d,
rounds_f,
rounds_p,
&mat_internal_diag_m_1,
&mat_internal,
&round_constants,
)));

let expected_result =
external_poseidon2.permutation(&into_repr_vec(drop_use_constant(&inputs)));
Expand Down
2 changes: 1 addition & 1 deletion acvm-repo/bn254_blackbox_solver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ hex.workspace = true
lazy_static.workspace = true

ark-bn254.workspace = true
grumpkin.workspace = true
ark-grumpkin.workspace = true
ark-ec.workspace = true
ark-ff.workspace = true
num-bigint.workspace = true
Expand Down
Loading

0 comments on commit 5cf5e5c

Please sign in to comment.