Conversation
Implementing FS hashing using the PoseidonSponge, temporarily with the same default initialization as used in the tests for crypto-primitives. |
| rayon = { version = "1", optional = true } | ||
| digest = { version = "0.9" } | ||
| derivative = { version = "2", features = ["use_core"] } | ||
| itertools = "0.11.0" |
There was a problem hiding this comment.
I will probably have to remove this to pass the no-std test.
| #[derive(Clone)] | ||
| pub struct SimplePoseidonRng<F: PrimeField>(PoseidonSponge<F>); | ||
|
|
||
| impl<F: PrimeField> RngCore for SimplePoseidonRng<F> { |
There was a problem hiding this comment.
RngCore is required for backwards compatibility with generation of random field elements in ark-ff and ark-poly. Changing these is a much larger piece of work than exposing the sponge construction through RngCore and beyond the scope of this PR imo.
| /// Instantiate Poseidon sponge with default parameters | ||
| impl<F: PrimeField> Default for SimplePoseidonRng<F> { | ||
| fn default() -> Self { | ||
| // let default = | ||
| // Self(PoseidonSponge::new(&poseidon_parameters_for_test())) | ||
| let (alpha, rate, full_rounds, partial_rounds) = (17, 2, 8, 29); | ||
| let (ark, mds) = find_poseidon_ark_and_mds( | ||
| F::MODULUS_BIT_SIZE as u64, | ||
| rate, | ||
| full_rounds, | ||
| partial_rounds, | ||
| 0, | ||
| ); | ||
| let config = PoseidonConfig { | ||
| full_rounds: full_rounds as usize, | ||
| partial_rounds: partial_rounds as usize, | ||
| alpha: alpha as u64, | ||
| ark, | ||
| mds, | ||
| rate, | ||
| capacity: 1, | ||
| }; | ||
| SimplePoseidonRng(PoseidonSponge::new(&config)) |
There was a problem hiding this comment.
I hope these are good defaults.
src/lib.rs
Outdated
| impl<F: PrimeField, PC: PolynomialCommitment<F, DensePolynomial<F>>, FS: FiatShamirRng> | ||
| Marlin<F, PC, FS> | ||
| impl< | ||
| F: PrimeField + Absorb, |
There was a problem hiding this comment.
The addition of the Absorb trait bound is very problematic. Although it will improve efficiency of absorption, it makes the implementation far less generic. I am not certain how to improve this, considering that specialization of traits is an unstable feature.
There was a problem hiding this comment.
I resolved this by implementing the fast_prove and fast_verify methods that may be invoked when the PrimeField also satisfies the Absorb trait bound. I think this is a good trade off, since Absorb is not nearly as well implemented as Canonical(De)Serialize and it may be a pain for people to upgrade to the new implementation. Over time, I think the old method can be deprecated in favor of the new, but I think a prerequisite is implementing a derive Absorb macro.
Obviously there is a lot of code duplication, this can be refactored if @Pratyush approves the design philosophy here.
|
Any updates on this? I am ready to take any necessary steps to make it ready to merge. @Pratyush @mmagician |
| let (eta_a, eta_b, eta_c) = rng | ||
| .squeeze_field_elements(3) | ||
| .iter() | ||
| .map(|x: &F| x.to_owned()) | ||
| .collect_tuple() | ||
| .unwrap(); |
There was a problem hiding this comment.
| let (eta_a, eta_b, eta_c) = rng | |
| .squeeze_field_elements(3) | |
| .iter() | |
| .map(|x: &F| x.to_owned()) | |
| .collect_tuple() | |
| .unwrap(); | |
| let [eta_a, eta_b, eta_c] = rng | |
| .squeeze_field_elements(3)[..3] | |
| else { unreachable!("should have three elements") }; |
| let (f1, f2, f3) = rng | ||
| .squeeze_field_elements(3) | ||
| .iter() | ||
| .map(|x: &F| x.to_owned()) | ||
| .collect_tuple() | ||
| .unwrap(); |
There was a problem hiding this comment.
This is not secure; we cannot use the sponge for randomness for zero knowledge. The old version should work fine.
| let (eta_a, eta_b, eta_c) = rng | ||
| .squeeze_field_elements(3) | ||
| .iter() | ||
| .map(|x: &F| x.to_owned()) | ||
| .collect_tuple() | ||
| .unwrap(); |
There was a problem hiding this comment.
| let (eta_a, eta_b, eta_c) = rng | |
| .squeeze_field_elements(3) | |
| .iter() | |
| .map(|x: &F| x.to_owned()) | |
| .collect_tuple() | |
| .unwrap(); | |
| let [eta_a, eta_b, eta_c, ..] = rng | |
| .squeeze_field_elements(3)[..3] | |
| else { unreachable!("should be of size 3) }; |
| let fcinput = first_comms | ||
| .iter() | ||
| .map(|p| p.commitment().clone()) | ||
| .collect::<Vec<_>>(); | ||
|
|
||
| fs_rng.absorb(&to_bytes![first_comms, prover_first_msg].unwrap()); | ||
| match prover_first_msg { | ||
| ProverMsg::FieldElements(ref elems) => { | ||
| absorb!(&mut fs_rng, &to_bytes(&fcinput), &to_bytes(elems)); | ||
| } | ||
| ProverMsg::EmptyMessage => fs_rng.absorb(&to_bytes(&fcinput)), | ||
| } |
There was a problem hiding this comment.
Let's wrap this into a helper function.
| let scinput = second_comms | ||
| .iter() | ||
| .map(|p| p.commitment().clone()) | ||
| .collect::<Vec<_>>(); | ||
| match prover_second_msg { | ||
| ProverMsg::FieldElements(ref elems) => { | ||
| absorb!(&mut fs_rng, &to_bytes(&scinput), &to_bytes(elems)); | ||
| } | ||
| ProverMsg::EmptyMessage => fs_rng.absorb(&to_bytes(&scinput)), | ||
| } |
| let tcinput = third_comms | ||
| .iter() | ||
| .map(|p| p.commitment().clone()) | ||
| .collect::<Vec<_>>(); | ||
| match prover_third_msg { | ||
| ProverMsg::FieldElements(ref elems) => { | ||
| absorb!(&mut fs_rng, &to_bytes(&tcinput), &to_bytes(elems)); | ||
| } | ||
| ProverMsg::EmptyMessage => fs_rng.absorb(&to_bytes(&tcinput)), | ||
| } |
| match &proof.prover_messages[0] { | ||
| ProverMsg::FieldElements(ref elems) => { | ||
| absorb!(&mut fs_rng, &to_bytes(first_comms), &to_bytes(elems)); | ||
| } | ||
| ProverMsg::EmptyMessage => fs_rng.absorb(&to_bytes(first_comms)), | ||
| } | ||
| let (_, verifier_state) = | ||
| AHPForR1CS::verifier_first_round(index_vk.index_info, &mut fs_rng)?; |
There was a problem hiding this comment.
Let's use the helper function here also.
| { | ||
| /// Create a zkSNARK asserting that the constraint system is satisfied. | ||
| /// Uses fast absorption of field elements into sponge | ||
| pub fn fast_prove<C: ConstraintSynthesizer<F>, R: RngCore + CryptographicSponge>( |
| let (a, b) = rng | ||
| .squeeze_field_elements(2) | ||
| .iter() | ||
| .map(|x: &Fr| x.to_owned()) | ||
| .collect_tuple() | ||
| .unwrap(); |
There was a problem hiding this comment.
Let's create a helper squeeze macro.
Go right ahead! I guess you can make a new pull request and I will close this one? |
Description
Updated arkworks-rs dependencies to v0.4.0.
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
Pendingsection inCHANGELOG.mdFiles changedin the Github PR explorer