Remove GMiMC and Rescue hash functions (#450)

* Remove GMiMC and Rescue hash functions.

* rustfmt
This commit is contained in:
Hamish Ivey-Law 2022-01-28 09:08:27 +11:00 committed by GitHub
parent ab48cca1f3
commit a74ffdb898
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 6 additions and 1103 deletions

View File

@ -3,7 +3,6 @@
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use plonky2::field::goldilocks_field::GoldilocksField;
use plonky2::hash::gmimc::GMiMC;
use plonky2::hash::hash_types::{BytesHash, RichField};
use plonky2::hash::hashing::SPONGE_WIDTH;
use plonky2::hash::keccak::KeccakHash;
@ -11,16 +10,6 @@ use plonky2::hash::poseidon::Poseidon;
use plonky2::plonk::config::Hasher;
use tynm::type_name;
pub(crate) fn bench_gmimc<F: GMiMC<WIDTH>, const WIDTH: usize>(c: &mut Criterion) {
c.bench_function(&format!("gmimc<{}, {}>", type_name::<F>(), WIDTH), |b| {
b.iter_batched(
|| F::rand_arr::<WIDTH>(),
|state| F::gmimc_permute(state),
BatchSize::SmallInput,
)
});
}
pub(crate) fn bench_keccak<F: RichField>(c: &mut Criterion) {
c.bench_function("keccak256", |b| {
b.iter_batched(
@ -45,7 +34,6 @@ pub(crate) fn bench_poseidon<F: Poseidon>(c: &mut Criterion) {
}
fn criterion_benchmark(c: &mut Criterion) {
bench_gmimc::<GoldilocksField, 12>(c);
bench_poseidon::<GoldilocksField>(c);
bench_keccak::<GoldilocksField>(c);
}

View File

@ -11,7 +11,6 @@ use rand_chacha::ChaCha8Rng;
// range of GoldilocksField, then verify that each constant also fits in GoldilocksField.
const SAMPLE_RANGE_END: u64 = 0xffffffff70000001;
// const N: usize = 101; // For GMiMC
// const N: usize = 8 * 30; // For Posiedon-8
const N: usize = 12 * 30; // For Posiedon-12

View File

@ -228,9 +228,9 @@ mod tests {
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
use crate::gates::base_sum::BaseSumGate;
use crate::gates::constant::ConstantGate;
use crate::gates::gmimc::GMiMCGate;
use crate::gates::interpolation::HighDegreeInterpolationGate;
use crate::gates::noop::NoopGate;
use crate::gates::poseidon::PoseidonGate;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
#[test]
@ -245,7 +245,7 @@ mod tests {
GateRef::new(ConstantGate { num_consts: 4 }),
GateRef::new(ArithmeticExtensionGate { num_ops: 4 }),
GateRef::new(BaseSumGate::<4>::new(4)),
GateRef::new(GMiMCGate::<F, D, 12>::new()),
GateRef::new(PoseidonGate::<F, D>::new()),
GateRef::new(HighDegreeInterpolationGate::new(2)),
];
@ -276,7 +276,7 @@ mod tests {
assert!(
gates_with_prefix
.iter()
.all(|(g, p)| g.0.degree() + g.0.num_constants() + p.len() <= 8),
.all(|(g, p)| g.0.degree() + g.0.num_constants() + p.len() <= 9),
"Total degree is larger than 8."
);

View File

@ -1,433 +0,0 @@
use std::marker::PhantomData;
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_field::packed_field::PackedField;
use crate::gates::gate::Gate;
use crate::gates::packed_util::PackedEvaluableBase;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::gmimc;
use crate::hash::gmimc::GMiMC;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked,
};
/// Evaluates a full GMiMC permutation with 12 state elements.
///
/// This also has some extra features to make it suitable for efficiently verifying Merkle proofs.
/// It has a flag which can be used to swap the first four inputs with the next four, for ordering
/// sibling digests.
#[derive(Debug)]
pub struct GMiMCGate<
F: RichField + Extendable<D> + GMiMC<WIDTH>,
const D: usize,
const WIDTH: usize,
> {
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D> + GMiMC<WIDTH>, const D: usize, const WIDTH: usize>
GMiMCGate<F, D, WIDTH>
{
pub fn new() -> Self {
GMiMCGate {
_phantom: PhantomData,
}
}
/// The wire index for the `i`th input to the permutation.
pub fn wire_input(i: usize) -> usize {
i
}
/// The wire index for the `i`th output to the permutation.
pub fn wire_output(i: usize) -> usize {
WIDTH + i
}
/// If this is set to 1, the first four inputs will be swapped with the next four inputs. This
/// is useful for ordering hashes in Merkle proofs. Otherwise, this should be set to 0.
pub const WIRE_SWAP: usize = 2 * WIDTH;
/// A wire which stores the input to the `i`th cubing.
fn wire_cubing_input(i: usize) -> usize {
2 * WIDTH + 1 + i
}
/// End of wire indices, exclusive.
fn end() -> usize {
2 * WIDTH + 1 + gmimc::NUM_ROUNDS
}
}
impl<F: RichField + Extendable<D> + GMiMC<WIDTH>, const D: usize, const WIDTH: usize> Gate<F, D>
for GMiMCGate<F, D, WIDTH>
{
fn id(&self) -> String {
format!("<WIDTH={}> {:?}", WIDTH, self)
}
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
let mut constraints = Vec::with_capacity(self.num_constraints());
// Assert that `swap` is binary.
let swap = vars.local_wires[Self::WIRE_SWAP];
constraints.push(swap * (swap - F::Extension::ONE));
let mut state = Vec::with_capacity(12);
for i in 0..4 {
let a = vars.local_wires[i];
let b = vars.local_wires[i + 4];
state.push(a + swap * (b - a));
}
for i in 0..4 {
let a = vars.local_wires[i + 4];
let b = vars.local_wires[i];
state.push(a + swap * (b - a));
}
for i in 8..12 {
state.push(vars.local_wires[i]);
}
// Value that is implicitly added to each element.
// See https://affine.group/2020/02/starkware-challenge
let mut addition_buffer = F::Extension::ZERO;
for r in 0..gmimc::NUM_ROUNDS {
let active = r % WIDTH;
let constant = F::from_canonical_u64(<F as GMiMC<WIDTH>>::ROUND_CONSTANTS[r]);
let cubing_input = state[active] + addition_buffer + constant.into();
let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)];
constraints.push(cubing_input - cubing_input_wire);
let f = cubing_input_wire.cube();
addition_buffer += f;
state[active] -= f;
}
for i in 0..WIDTH {
state[i] += addition_buffer;
constraints.push(state[i] - vars.local_wires[Self::wire_output(i)]);
}
constraints
}
fn eval_unfiltered_base_one(
&self,
_vars: EvaluationVarsBase<F>,
_yield_constr: StridedConstraintConsumer<F>,
) {
panic!("use eval_unfiltered_base_packed instead");
}
fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch<F>) -> Vec<F> {
self.eval_unfiltered_base_batch_packed(vars_base)
}
fn eval_unfiltered_recursively(
&self,
builder: &mut CircuitBuilder<F, D>,
vars: EvaluationTargets<D>,
) -> Vec<ExtensionTarget<D>> {
let mut constraints = Vec::with_capacity(self.num_constraints());
let swap = vars.local_wires[Self::WIRE_SWAP];
constraints.push(builder.mul_sub_extension(swap, swap, swap));
let mut state = Vec::with_capacity(12);
for i in 0..4 {
let a = vars.local_wires[i];
let b = vars.local_wires[i + 4];
let delta = builder.sub_extension(b, a);
state.push(builder.mul_add_extension(swap, delta, a));
}
for i in 0..4 {
let a = vars.local_wires[i + 4];
let b = vars.local_wires[i];
let delta = builder.sub_extension(b, a);
state.push(builder.mul_add_extension(swap, delta, a));
}
for i in 8..12 {
state.push(vars.local_wires[i]);
}
// Value that is implicitly added to each element.
// See https://affine.group/2020/02/starkware-challenge
let mut addition_buffer = builder.zero_extension();
for r in 0..gmimc::NUM_ROUNDS {
let active = r % WIDTH;
let constant = F::from_canonical_u64(<F as GMiMC<WIDTH>>::ROUND_CONSTANTS[r]);
let constant = builder.constant_extension(constant.into());
let cubing_input =
builder.add_many_extension(&[state[active], addition_buffer, constant]);
let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)];
constraints.push(builder.sub_extension(cubing_input, cubing_input_wire));
let f = builder.cube_extension(cubing_input_wire);
addition_buffer = builder.add_extension(addition_buffer, f);
state[active] = builder.sub_extension(state[active], f);
}
for i in 0..WIDTH {
state[i] = builder.add_extension(state[i], addition_buffer);
constraints
.push(builder.sub_extension(state[i], vars.local_wires[Self::wire_output(i)]));
}
constraints
}
fn generators(
&self,
gate_index: usize,
_local_constants: &[F],
) -> Vec<Box<dyn WitnessGenerator<F>>> {
let gen = GMiMCGenerator::<F, D, WIDTH> {
gate_index,
_phantom: PhantomData,
};
vec![Box::new(gen.adapter())]
}
fn num_wires(&self) -> usize {
Self::end()
}
fn num_constants(&self) -> usize {
0
}
fn degree(&self) -> usize {
3
}
fn num_constraints(&self) -> usize {
gmimc::NUM_ROUNDS + WIDTH + 1
}
}
impl<F: RichField + Extendable<D> + GMiMC<WIDTH>, const D: usize, const WIDTH: usize>
PackedEvaluableBase<F, D> for GMiMCGate<F, D, WIDTH>
{
fn eval_unfiltered_base_packed<P: PackedField<Scalar = F>>(
&self,
vars: EvaluationVarsBasePacked<P>,
mut yield_constr: StridedConstraintConsumer<P>,
) {
// Assert that `swap` is binary.
let swap = vars.local_wires[Self::WIRE_SWAP];
yield_constr.one(swap * (swap - F::ONE));
let mut state = Vec::with_capacity(12);
for i in 0..4 {
let a = vars.local_wires[i];
let b = vars.local_wires[i + 4];
state.push(a + swap * (b - a));
}
for i in 0..4 {
let a = vars.local_wires[i + 4];
let b = vars.local_wires[i];
state.push(a + swap * (b - a));
}
for i in 8..12 {
state.push(vars.local_wires[i]);
}
// Value that is implicitly added to each element.
// See https://affine.group/2020/02/starkware-challenge
let mut addition_buffer = P::ZEROS;
for r in 0..gmimc::NUM_ROUNDS {
let active = r % WIDTH;
let constant = F::from_canonical_u64(<F as GMiMC<WIDTH>>::ROUND_CONSTANTS[r]);
let cubing_input = state[active] + addition_buffer + constant;
let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)];
yield_constr.one(cubing_input - cubing_input_wire);
let f = cubing_input_wire.square() * cubing_input_wire;
addition_buffer += f;
state[active] -= f;
}
for i in 0..WIDTH {
state[i] += addition_buffer;
yield_constr.one(state[i] - vars.local_wires[Self::wire_output(i)]);
}
}
}
#[derive(Debug)]
struct GMiMCGenerator<
F: RichField + Extendable<D> + GMiMC<WIDTH>,
const D: usize,
const WIDTH: usize,
> {
gate_index: usize,
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D> + GMiMC<WIDTH>, const D: usize, const WIDTH: usize>
SimpleGenerator<F> for GMiMCGenerator<F, D, WIDTH>
{
fn dependencies(&self) -> Vec<Target> {
let mut dep_input_indices = Vec::with_capacity(WIDTH + 1);
for i in 0..WIDTH {
dep_input_indices.push(GMiMCGate::<F, D, WIDTH>::wire_input(i));
}
dep_input_indices.push(GMiMCGate::<F, D, WIDTH>::WIRE_SWAP);
dep_input_indices
.into_iter()
.map(|input| {
Target::Wire(Wire {
gate: self.gate_index,
input,
})
})
.collect()
}
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let mut state = (0..WIDTH)
.map(|i| {
witness.get_wire(Wire {
gate: self.gate_index,
input: GMiMCGate::<F, D, WIDTH>::wire_input(i),
})
})
.collect::<Vec<_>>();
let swap_value = witness.get_wire(Wire {
gate: self.gate_index,
input: GMiMCGate::<F, D, WIDTH>::WIRE_SWAP,
});
debug_assert!(swap_value == F::ZERO || swap_value == F::ONE);
if swap_value == F::ONE {
for i in 0..4 {
state.swap(i, 4 + i);
}
}
// Value that is implicitly added to each element.
// See https://affine.group/2020/02/starkware-challenge
let mut addition_buffer = F::ZERO;
for r in 0..gmimc::NUM_ROUNDS {
let active = r % WIDTH;
let constant = F::from_canonical_u64(<F as GMiMC<WIDTH>>::ROUND_CONSTANTS[r]);
let cubing_input = state[active] + addition_buffer + constant;
out_buffer.set_wire(
Wire {
gate: self.gate_index,
input: GMiMCGate::<F, D, WIDTH>::wire_cubing_input(r),
},
cubing_input,
);
let f = cubing_input.cube();
addition_buffer += f;
state[active] -= f;
}
for i in 0..WIDTH {
state[i] += addition_buffer;
out_buffer.set_wire(
Wire {
gate: self.gate_index,
input: GMiMCGate::<F, D, WIDTH>::wire_output(i),
},
state[i],
);
}
}
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use plonky2_field::field_types::Field;
use plonky2_field::goldilocks_field::GoldilocksField;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::gates::gmimc::GMiMCGate;
use crate::hash::gmimc::GMiMC;
use crate::iop::generator::generate_partial_witness;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartialWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
#[test]
fn generated_output() {
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
const WIDTH: usize = 12;
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::new(config);
type Gate = GMiMCGate<F, D, WIDTH>;
let gate = Gate::new();
let gate_index = builder.add_gate(gate, vec![]);
let circuit = builder.build_prover::<C>();
let permutation_inputs = (0..WIDTH).map(F::from_canonical_usize).collect::<Vec<_>>();
let mut inputs = PartialWitness::new();
inputs.set_wire(
Wire {
gate: gate_index,
input: Gate::WIRE_SWAP,
},
F::ZERO,
);
for i in 0..WIDTH {
inputs.set_wire(
Wire {
gate: gate_index,
input: Gate::wire_input(i),
},
permutation_inputs[i],
);
}
let witness = generate_partial_witness(inputs, &circuit.prover_only, &circuit.common);
let expected_outputs: [F; WIDTH] =
F::gmimc_permute_naive(permutation_inputs.try_into().unwrap());
for i in 0..WIDTH {
let out = witness.get_wire(Wire {
gate: 0,
input: Gate::wire_output(i),
});
assert_eq!(out, expected_outputs[i]);
}
}
#[test]
fn low_degree() {
type F = GoldilocksField;
const WIDTH: usize = 12;
let gate = GMiMCGate::<F, 4, WIDTH>::new();
test_low_degree(gate)
}
#[test]
fn eval_fns() -> Result<()> {
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
const WIDTH: usize = 12;
let gate = GMiMCGate::<F, D, WIDTH>::new();
test_eval_fns::<F, C, _, D>(gate)
}
}

View File

@ -11,7 +11,6 @@ pub mod constant;
pub mod exponentiation;
pub mod gate;
pub mod gate_tree;
pub mod gmimc;
pub mod interpolation;
pub mod low_degree_interpolation;
pub mod multiplication_extension;

View File

@ -1,168 +0,0 @@
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_field::goldilocks_field::GoldilocksField;
use unroll::unroll_for_loops;
use crate::gates::gmimc::GMiMCGate;
use crate::hash::hash_types::{HashOut, RichField};
use crate::hash::hashing::{compress, hash_n_to_hash, PlonkyPermutation, SPONGE_WIDTH};
use crate::iop::target::{BoolTarget, Target};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::config::{AlgebraicHasher, Hasher};
pub(crate) const NUM_ROUNDS: usize = 101;
pub trait GMiMC<const WIDTH: usize>: Field
where
[u64; NUM_ROUNDS]: Sized,
{
const ROUND_CONSTANTS: [u64; NUM_ROUNDS];
#[unroll_for_loops]
fn gmimc_permute(mut xs: [Self; WIDTH]) -> [Self; WIDTH] {
// Value that is implicitly added to each element.
// See https://affine.group/2020/02/starkware-challenge
let mut addition_buffer = Self::ZERO;
for (r, &constant) in Self::ROUND_CONSTANTS.iter().enumerate() {
let active = r % WIDTH;
let f = (xs[active] + addition_buffer + Self::from_canonical_u64(constant)).cube();
addition_buffer += f;
xs[active] -= f;
}
for i in 0..WIDTH {
xs[i] += addition_buffer;
}
xs
}
#[unroll_for_loops]
fn gmimc_permute_naive(mut xs: [Self; WIDTH]) -> [Self; WIDTH] {
for (r, &constant) in Self::ROUND_CONSTANTS.iter().enumerate() {
let active = r % WIDTH;
let f = (xs[active] + Self::from_canonical_u64(constant)).cube();
for i in 0..WIDTH {
if i != active {
xs[i] += f;
}
}
}
xs
}
}
/// See `generate_constants` about how these were generated.
#[rustfmt::skip]
const GOLDILOCKS_ROUND_CONSTANTS: [u64; NUM_ROUNDS] = [
0xb585f767417ee042, 0x7746a55f77c10331, 0xb2fb0d321d356f7a, 0x0f6760a486f1621f,
0xe10d6666b36abcdf, 0x8cae14cb455cc50b, 0xd438539cf2cee334, 0xef781c7d4c1fd8b4,
0xcdc4a23a0aca4b1f, 0x277fa208d07b52e3, 0xe17653a300493d38, 0xc54302f27c287dc1,
0x8628782231d47d10, 0x59cd1a8a690b49f2, 0xc3b919ad9efec0b0, 0xa484c4c637641d97,
0x308bbd23f191398b, 0x6e4a40c1bf713cf1, 0x9a2eedb7510414fb, 0xe360c6e111c2c63b,
0xd5c771901d4d89aa, 0xc35eae076e7d6b2f, 0x849c2656d0a09cad, 0xc0572c8c5cf1df2b,
0xe9fa634a883b8bf3, 0xf56f6d4900fb1fdd, 0xf7d713e872a72a1b, 0x8297132b6ba47612,
0xad6805e12ee8af1c, 0xac51d9f6485c22b9, 0x502ad7dc3bd56bf8, 0x57a1550c3761c577,
0x66bbd30e99d311da, 0x0da2abef5e948f87, 0xf0612750443f8e94, 0x28b8ec3afb937d8c,
0x92a756e6be54ca18, 0x70e741ec304e925d, 0x019d5ee2b037c59f, 0x6f6f2ed7a30707d1,
0x7cf416d01e8c169c, 0x61df517bb17617df, 0x85dc499b4c67dbaa, 0x4b959b48dad27b23,
0xe8be3e5e0dd779a0, 0xf5c0bc1e525ed8e6, 0x40b12cbf263cf853, 0xa637093f13e2ea3c,
0x3cc3f89232e3b0c8, 0x2e479dc16bfe86c0, 0x6f49de07d6d39469, 0x213ce7beecc232de,
0x5b043134851fc00a, 0xa2de45784a861506, 0x7103aaf97bed8dd5, 0x5326fc0dbb88a147,
0xa9ceb750364cb77a, 0x27f8ec88cc9e991f, 0xfceb4fda8c93fb83, 0xfac6ff13b45b260e,
0x7131aa455813380b, 0x93510360d5d68119, 0xad535b24fb96e3db, 0x4627f5c6b7efc045,
0x645cf794e4da78a9, 0x241c70ed1ac2877f, 0xacb8e076b009e825, 0x3737e9db6477bd9d,
0xe7ea5e344cd688ed, 0x90dee4a009214640, 0xd1b1edf7c77e74af, 0x0b65481bab42158e,
0x99ad1aab4b4fe3e7, 0x438a7c91f1a360cd, 0xb60de3bd159088bf, 0xc99cab6b47a3e3bb,
0x69a5ed92d5677cef, 0x5e7b329c482a9396, 0x5fc0ac0829f893c9, 0x32db82924fb757ea,
0x0ade699c5cf24145, 0x7cc5583b46d7b5bb, 0x85df9ed31bf8abcb, 0x6604df501ad4de64,
0xeb84f60941611aec, 0xda60883523989bd4, 0x8f97fe40bf3470bf, 0xa93f485ce0ff2b32,
0x6704e8eebc2afb4b, 0xcee3e9ac788ad755, 0x510d0e66062a270d, 0xf6323f48d74634a0,
0x0b508cdf04990c90, 0xf241708a4ef7ddf9, 0x60e75c28bb368f82, 0xa6217d8c3f0f9989,
0x7159cd30f5435b53, 0x839b4e8fe97ec79f, 0x0d3f3e5e885db625, 0x8f7d83be1daea54b,
0x780f22441e8dbc04,
];
impl GMiMC<8> for GoldilocksField {
const ROUND_CONSTANTS: [u64; NUM_ROUNDS] = GOLDILOCKS_ROUND_CONSTANTS;
}
impl GMiMC<12> for GoldilocksField {
const ROUND_CONSTANTS: [u64; NUM_ROUNDS] = GOLDILOCKS_ROUND_CONSTANTS;
}
pub struct GMiMCPermutation;
impl<F: RichField> PlonkyPermutation<F> for GMiMCPermutation {
fn permute(input: [F; SPONGE_WIDTH]) -> [F; SPONGE_WIDTH] {
F::gmimc_permute(input)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct GMiMCHash;
impl<F: RichField> Hasher<F> for GMiMCHash {
const HASH_SIZE: usize = 4 * 8;
type Hash = HashOut<F>;
type Permutation = GMiMCPermutation;
fn hash(input: &[F], pad: bool) -> Self::Hash {
hash_n_to_hash::<F, Self::Permutation>(input, pad)
}
fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash {
compress::<F, Self::Permutation>(left, right)
}
}
impl<F: RichField> AlgebraicHasher<F> for GMiMCHash {
fn permute_swapped<const D: usize>(
inputs: [Target; SPONGE_WIDTH],
swap: BoolTarget,
builder: &mut CircuitBuilder<F, D>,
) -> [Target; SPONGE_WIDTH]
where
F: RichField + Extendable<D>,
{
let gate_type = GMiMCGate::<F, D, SPONGE_WIDTH>::new();
let gate = builder.add_gate(gate_type, vec![]);
let swap_wire = GMiMCGate::<F, D, SPONGE_WIDTH>::WIRE_SWAP;
let swap_wire = Target::wire(gate, swap_wire);
builder.connect(swap.target, swap_wire);
// Route input wires.
for i in 0..SPONGE_WIDTH {
let in_wire = GMiMCGate::<F, D, SPONGE_WIDTH>::wire_input(i);
let in_wire = Target::wire(gate, in_wire);
builder.connect(inputs[i], in_wire);
}
// Collect output wires.
(0..SPONGE_WIDTH)
.map(|i| Target::wire(gate, GMiMCGate::<F, D, SPONGE_WIDTH>::wire_output(i)))
.collect::<Vec<_>>()
.try_into()
.unwrap()
}
}
#[cfg(test)]
mod tests {
use plonky2_field::goldilocks_field::GoldilocksField;
use crate::hash::gmimc::GMiMC;
fn check_consistency<F: GMiMC<WIDTH>, const WIDTH: usize>() {
let xs = F::rand_arr::<WIDTH>();
let out = F::gmimc_permute(xs);
let out_naive = F::gmimc_permute_naive(xs);
assert_eq!(out, out_naive);
}
#[test]
fn consistency() {
check_consistency::<GoldilocksField, 12>();
}
}

View File

@ -3,13 +3,12 @@ use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::hash::gmimc::GMiMC;
use crate::hash::poseidon::Poseidon;
use crate::iop::target::Target;
use crate::plonk::config::GenericHashOut;
/// A prime order field with the features we need to use it as a base field in our argument system.
pub trait RichField: PrimeField + GMiMC<12> + Poseidon {}
pub trait RichField: PrimeField + Poseidon {}
impl RichField for GoldilocksField {}

View File

@ -1,5 +1,4 @@
mod arch;
pub mod gmimc;
pub mod hash_types;
pub mod hashing;
pub mod keccak;
@ -8,4 +7,3 @@ pub mod merkle_tree;
pub mod path_compression;
pub mod poseidon;
pub mod poseidon_goldilocks;
pub mod rescue;

View File

@ -1,457 +0,0 @@
//! Implements Rescue Prime.
use plonky2_field::field_types::Field;
use unroll::unroll_for_loops;
const ROUNDS: usize = 8;
const W: usize = 12;
const MDS: [[u64; W]; W] = [
[
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
16140901062381928449,
2635249153041947502,
3074457345215605419,
11068046442776179508,
13835058053470224385,
6148914690431210838,
9223372035646816257,
1,
],
[
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
16140901062381928449,
2635249153041947502,
3074457345215605419,
11068046442776179508,
13835058053470224385,
6148914690431210838,
9223372035646816257,
],
[
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
16140901062381928449,
2635249153041947502,
3074457345215605419,
11068046442776179508,
13835058053470224385,
6148914690431210838,
],
[
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
16140901062381928449,
2635249153041947502,
3074457345215605419,
11068046442776179508,
13835058053470224385,
],
[
17293822566837780481,
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
16140901062381928449,
2635249153041947502,
3074457345215605419,
11068046442776179508,
],
[
3255307777287111620,
17293822566837780481,
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
16140901062381928449,
2635249153041947502,
3074457345215605419,
],
[
1024819115071868473,
3255307777287111620,
17293822566837780481,
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
16140901062381928449,
2635249153041947502,
],
[
9708812669101911849,
1024819115071868473,
3255307777287111620,
17293822566837780481,
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
16140901062381928449,
],
[
2767011610694044877,
9708812669101911849,
1024819115071868473,
3255307777287111620,
17293822566837780481,
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
2049638230143736946,
],
[
878416384347315834,
2767011610694044877,
9708812669101911849,
1024819115071868473,
3255307777287111620,
17293822566837780481,
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
5534023221388089754,
],
[
17608255704416649217,
878416384347315834,
2767011610694044877,
9708812669101911849,
1024819115071868473,
3255307777287111620,
17293822566837780481,
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
16769767337539665921,
],
[
15238614667590392076,
17608255704416649217,
878416384347315834,
2767011610694044877,
9708812669101911849,
1024819115071868473,
3255307777287111620,
17293822566837780481,
15987178195121148178,
1317624576520973751,
5675921252705733081,
10760600708254618966,
],
];
const RESCUE_CONSTANTS: [[u64; W]; ROUNDS * 2] = [
[
12050887499329086906,
1748247961703512657,
315780861775001585,
2827656358919812970,
13335864861236723579,
3010729529365640897,
8463534053828271146,
2528500966106598845,
8969871077123422281,
1002624930202741107,
599979829006456404,
4386170815218774254,
],
[
5771413917591851532,
11946802620311685142,
4759792267858670262,
6879094914431255667,
3985911073214909073,
1542850118294175816,
5393560436452023029,
8331250756632997735,
3395511836281190608,
17601255793194446503,
12848459944475727152,
11995465655754698601,
],
[
14063960046551560130,
14790209580166185143,
5509023472758717841,
1274395897760495573,
16719545989415697758,
17865948122414223407,
3919263713959798649,
5633741078654387163,
15665612362287352054,
3418834727998553015,
5324019631954832682,
17962066557010997431,
],
[
3282193104189649752,
18423507935939999211,
9035104445528866459,
30842260240043277,
3896337933354935129,
6615548113269323045,
6625827707190475694,
6677757329269550670,
11419013193186889337,
17111888851716383760,
12075517898615128691,
8139844272075088233,
],
[
8872892112814161072,
17529364346566228604,
7526576514327158912,
850359069964902700,
9679332912197531902,
10591229741059812071,
12759208863825924546,
14552519355635838750,
16066249893409806278,
11283035366525176262,
1047378652379935387,
17032498397644511356,
],
[
2938626421478254042,
10375267398354586672,
13728514869380643947,
16707318479225743731,
9785828188762698567,
8610686976269299752,
5478372191917042178,
12716344455538470365,
9968276048553747246,
14746805727771473956,
4822070620124107028,
9901161649549513416,
],
[
13458162407040644078,
4045792126424269312,
9709263167782315020,
2163173014916005515,
17079206331095671215,
2556388076102629669,
6582772486087242347,
1239959540200663058,
18268236910639895687,
12499012548657350745,
17213068585339946119,
7641451088868756688,
],
[
14674555473338434116,
14624532976317185113,
13625541984298615970,
7612892294159054770,
12294028208969561574,
6067206081581804358,
5778082506883496792,
7389487446513884800,
12929525660730020877,
18244350162788654296,
15285920877034454694,
3640669683987215349,
],
[
6737585134029996281,
1826890539455248546,
289376081355380231,
10782622161517803787,
12978425540147835172,
9828233103297278473,
16384075371934678711,
3187492301890791304,
12985433735185968457,
9470935291631377473,
16328323199113140151,
16218490552434224203,
],
[
6188809977565251499,
18437718710937437067,
4530469469895539008,
9596355277372723349,
13602518824447658705,
8759976068576854281,
10504320064094929535,
3980760429843656150,
14609448298151012462,
5839843841558860609,
10283805260656050418,
7239168159249274821,
],
[
3604243611640027441,
5237321927316578323,
5071861664926666316,
13025405632646149705,
3285281651566464074,
12121596060272825779,
1900602777802961569,
8122527981264852045,
6731303887159752901,
9197659817406857040,
844741616904786364,
14249777686667858094,
],
[
8602844218963499297,
10133401373828451640,
11618292280328565166,
8828272598402499582,
4252246265076774689,
9760449011955070998,
10233981507028897480,
10427510555228840014,
1007817664531124790,
4465396600980659145,
7727267420665314215,
7904022788946844554,
],
[
11418297156527169222,
15865399053509010196,
1727198235391450850,
16557095577717348672,
1524052121709169653,
14531367160053894310,
4071756280138432327,
10333204220115446291,
16584144375833061215,
12237566480526488368,
11090440024401607208,
18281335018830792766,
],
[
16152169547074248135,
18338155611216027761,
15842640128213925612,
14687926435880145351,
13259626900273707210,
6187877366876303234,
10312881470701795438,
1924945292721719446,
2278209355262975917,
3250749056007953206,
11589006946114672195,
241829012299953928,
],
[
11244459446597052449,
7319043416418482137,
8148526814449636806,
9054933038587901070,
550333919248348827,
5513167392062632770,
12644459803778263764,
9903621375535446226,
16390581784506871871,
14586524717888286021,
6975796306584548762,
5200407948555191573,
],
[
2855794043288846965,
1259443213892506318,
6145351706926586935,
3853784494234324998,
5871277378086513850,
9414363368707862566,
11946957446931890832,
308083693687568600,
12712587722369770461,
6792392698104204991,
16465224002344550280,
10282380383506806095,
],
];
pub fn rescue<F: Field>(mut xs: [F; W]) -> [F; W] {
for r in 0..8 {
xs = sbox_layer_a(xs);
xs = mds_layer(xs);
xs = constant_layer(xs, &RESCUE_CONSTANTS[r * 2]);
xs = sbox_layer_b(xs);
xs = mds_layer(xs);
xs = constant_layer(xs, &RESCUE_CONSTANTS[r * 2 + 1]);
}
xs
}
#[unroll_for_loops]
fn sbox_layer_a<F: Field>(x: [F; W]) -> [F; W] {
let mut result = [F::ZERO; W];
for i in 0..W {
result[i] = x[i].cube();
}
result
}
#[unroll_for_loops]
fn sbox_layer_b<F: Field>(x: [F; W]) -> [F; W] {
let mut result = [F::ZERO; W];
for i in 0..W {
result[i] = x[i].cube_root();
}
result
}
#[unroll_for_loops]
fn mds_layer<F: Field>(x: [F; W]) -> [F; W] {
let mut result = [F::ZERO; W];
for r in 0..W {
for c in 0..W {
result[r] += F::from_canonical_u64(MDS[r][c]) * x[c];
}
}
result
}
#[unroll_for_loops]
fn constant_layer<F: Field>(xs: [F; W], con: &[u64; W]) -> [F; W] {
let mut result = [F::ZERO; W];
for i in 0..W {
result[i] = xs[i] + F::from_canonical_u64(con[i]);
}
result
}

View File

@ -5,7 +5,6 @@ use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::goldilocks_field::GoldilocksField;
use serde::{de::DeserializeOwned, Serialize};
use crate::hash::gmimc::GMiMCHash;
use crate::hash::hash_types::HashOut;
use crate::hash::hash_types::RichField;
use crate::hash::hashing::{PlonkyPermutation, SPONGE_WIDTH};
@ -76,16 +75,6 @@ impl GenericConfig<2> for PoseidonGoldilocksConfig {
type InnerHasher = PoseidonHash;
}
/// Configuration using GMiMC over the Goldilocks field.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct GMiMCGoldilocksConfig;
impl GenericConfig<2> for GMiMCGoldilocksConfig {
type F = GoldilocksField;
type FE = QuadraticExtension<Self::F>;
type Hasher = GMiMCHash;
type InnerHasher = GMiMCHash;
}
/// Configuration using truncated Keccak over the Goldilocks field.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct KeccakGoldilocksConfig;

View File

@ -212,9 +212,7 @@ mod tests {
use crate::gates::noop::NoopGate;
use crate::iop::witness::{PartialWitness, Witness};
use crate::plonk::circuit_data::VerifierOnlyCircuitData;
use crate::plonk::config::{
GMiMCGoldilocksConfig, GenericConfig, KeccakGoldilocksConfig, PoseidonGoldilocksConfig,
};
use crate::plonk::config::{GenericConfig, KeccakGoldilocksConfig, PoseidonGoldilocksConfig};
use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs};
use crate::plonk::prover::prove;
use crate::util::timing::TimingTree;
@ -352,7 +350,6 @@ mod tests {
init_logger();
const D: usize = 2;
type PC = PoseidonGoldilocksConfig;
type GC = GMiMCGoldilocksConfig;
type KC = KeccakGoldilocksConfig;
type F = <PC as GenericConfig<D>>::F;
@ -363,16 +360,8 @@ mod tests {
recursive_proof::<F, PC, PC, D>(proof, vd, cd, &config, &config, None, false, false)?;
test_serialization(&proof, &cd)?;
let (proof, vd, cd) =
recursive_proof::<F, GC, PC, D>(proof, vd, cd, &config, &config, None, false, false)?;
test_serialization(&proof, &cd)?;
let (proof, vd, cd) =
recursive_proof::<F, GC, GC, D>(proof, vd, cd, &config, &config, None, false, false)?;
test_serialization(&proof, &cd)?;
let (proof, _vd, cd) =
recursive_proof::<F, KC, GC, D>(proof, vd, cd, &config, &config, None, false, false)?;
recursive_proof::<F, KC, PC, D>(proof, vd, cd, &config, &config, None, false, false)?;
test_serialization(&proof, &cd)?;
Ok(())