mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 06:43:07 +00:00
Arithmetic & permutation gadgets
This commit is contained in:
parent
aea4eeaaae
commit
4086b2b447
@ -10,11 +10,11 @@ use crate::gates::gate::{GateInstance, GateRef};
|
||||
use crate::gates::noop::NoopGate;
|
||||
use crate::generator::{CopyGenerator, WitnessGenerator};
|
||||
use crate::hash::merkle_root_bit_rev_order;
|
||||
use crate::partition::get_subgroup_shift;
|
||||
use crate::polynomial::polynomial::PolynomialValues;
|
||||
use crate::target::Target;
|
||||
use crate::util::{log2_strict, transpose, transpose_poly_values};
|
||||
use crate::wire::Wire;
|
||||
use crate::partition::get_subgroup_shift;
|
||||
|
||||
pub struct CircuitBuilder<F: Field> {
|
||||
pub(crate) config: CircuitConfig,
|
||||
@ -51,12 +51,18 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
}
|
||||
|
||||
let index = self.gate_instances.len();
|
||||
|
||||
// TODO: Not passing next constants for now. Not sure if it's really useful...
|
||||
self.add_generators(gate_type.0.generators(index, &constants, &[]));
|
||||
|
||||
self.gate_instances.push(GateInstance { gate_type, constants });
|
||||
index
|
||||
}
|
||||
|
||||
fn check_gate_compatibility(&self, gate: &GateRef<F>) {
|
||||
assert!(gate.0.num_wires() <= self.config.num_wires);
|
||||
assert!(gate.0.num_wires() <= self.config.num_wires,
|
||||
"{:?} requires {} wires, but our GateConfig has only {}",
|
||||
gate.0.id(), gate.0.num_wires(), self.config.num_wires);
|
||||
}
|
||||
|
||||
/// Shorthand for `generate_copy` and `assert_equal`.
|
||||
@ -74,11 +80,15 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
/// Uses Plonk's permutation argument to require that two elements be equal.
|
||||
/// Both elements must be routable, otherwise this method will panic.
|
||||
pub fn assert_equal(&mut self, x: Target, y: Target) {
|
||||
assert!(x.is_routable(self.config));
|
||||
assert!(y.is_routable(self.config));
|
||||
assert!(x.is_routable(self.config), "Tried to route a wire that isn't routable");
|
||||
assert!(y.is_routable(self.config), "Tried to route a wire that isn't routable");
|
||||
// TODO: Add to copy_constraints.
|
||||
}
|
||||
|
||||
pub fn add_generators(&mut self, generators: Vec<Box<dyn WitnessGenerator<F>>>) {
|
||||
self.generators.extend(generators);
|
||||
}
|
||||
|
||||
pub fn add_generator<G: WitnessGenerator<F>>(&mut self, generator: G) {
|
||||
self.generators.push(Box::new(generator));
|
||||
}
|
||||
@ -113,10 +123,6 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
constants.iter().map(|&c| self.constant(c)).collect()
|
||||
}
|
||||
|
||||
pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn blind_and_pad(&mut self) {
|
||||
// TODO: Blind.
|
||||
|
||||
@ -125,16 +131,6 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_generators(&self) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
self.gate_instances.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(gate_index, gate_inst)| gate_inst.gate_type.0.generators(
|
||||
gate_index,
|
||||
&gate_inst.constants,
|
||||
&[])) // TODO: Not supporting next_const for now.
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn constant_polys(&self) -> Vec<PolynomialValues<F>> {
|
||||
let num_constants = self.gate_instances.iter()
|
||||
.map(|gate_inst| gate_inst.constants.len())
|
||||
@ -178,7 +174,7 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
let sigma_ldes_t = transpose_poly_values(sigma_ldes);
|
||||
let sigmas_root = merkle_root_bit_rev_order(sigma_ldes_t.clone());
|
||||
|
||||
let generators = self.get_generators();
|
||||
let generators = self.generators;
|
||||
let prover_only = ProverOnlyCircuitData { generators, constant_ldes_t, sigma_ldes_t };
|
||||
let verifier_only = VerifierOnlyCircuitData {};
|
||||
|
||||
@ -215,14 +211,14 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
}
|
||||
|
||||
/// Builds a "prover circuit", with data needed to generate proofs but not verify them.
|
||||
pub fn build_prover(mut self) -> ProverCircuitData<F> {
|
||||
pub fn build_prover(self) -> ProverCircuitData<F> {
|
||||
// TODO: Can skip parts of this.
|
||||
let CircuitData { prover_only, common, .. } = self.build();
|
||||
ProverCircuitData { prover_only, common }
|
||||
}
|
||||
|
||||
/// Builds a "verifier circuit", with data needed to verify proofs but not generate them.
|
||||
pub fn build_verifier(mut self) -> VerifierCircuitData<F> {
|
||||
pub fn build_verifier(self) -> VerifierCircuitData<F> {
|
||||
// TODO: Can skip parts of this.
|
||||
let CircuitData { verifier_only, common, .. } = self.build();
|
||||
VerifierCircuitData { verifier_only, common }
|
||||
|
||||
@ -21,8 +21,8 @@ pub struct CircuitConfig {
|
||||
impl Default for CircuitConfig {
|
||||
fn default() -> Self {
|
||||
CircuitConfig {
|
||||
num_wires: 3,
|
||||
num_routed_wires: 3,
|
||||
num_wires: 4,
|
||||
num_routed_wires: 4,
|
||||
security_bits: 128,
|
||||
rate_bits: 3,
|
||||
num_checks: 3,
|
||||
|
||||
@ -80,18 +80,22 @@ impl Field for CrandallField {
|
||||
while u != 1 && v != 1 {
|
||||
while u.is_even() {
|
||||
u >>= 1;
|
||||
if b.is_odd() {
|
||||
b += Self::ORDER;
|
||||
}
|
||||
if b.is_even() {
|
||||
b >>= 1;
|
||||
} else {
|
||||
// b = (b + p)/2, avoiding overflow
|
||||
b = (b >> 1) + (Self::ORDER >> 1) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
while v.is_even() {
|
||||
v >>= 1;
|
||||
if c.is_odd() {
|
||||
c += Self::ORDER;
|
||||
}
|
||||
if c.is_even() {
|
||||
c >>= 1;
|
||||
} else {
|
||||
// c = (c + p)/2, avoiding overflow
|
||||
c = (c >> 1) + (Self::ORDER >> 1) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if u < v {
|
||||
|
||||
@ -1,21 +1,75 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::field::field::Field;
|
||||
use crate::target::Target;
|
||||
use crate::gates::arithmetic::ArithmeticGate;
|
||||
use crate::wire::Wire;
|
||||
|
||||
impl<F: Field> CircuitBuilder<F> {
|
||||
pub fn neg(&mut self, x: Target) -> Target {
|
||||
let neg_one = self.neg_one();
|
||||
self.mul(x, neg_one)
|
||||
}
|
||||
|
||||
pub fn add(&mut self, x: Target, y: Target) -> Target {
|
||||
todo!()
|
||||
let zero = self.zero();
|
||||
let one = self.one();
|
||||
if x == zero {
|
||||
return y;
|
||||
}
|
||||
if y == zero {
|
||||
return x;
|
||||
}
|
||||
|
||||
let gate = self.add_gate(ArithmeticGate::new(), vec![F::ONE, F::ONE]);
|
||||
|
||||
let wire_multiplicand_0 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_0 };
|
||||
let wire_multiplicand_1 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_1 };
|
||||
let wire_addend = Wire { gate, input: ArithmeticGate::WIRE_ADDEND };
|
||||
let wire_output = Wire { gate, input: ArithmeticGate::WIRE_OUTPUT };
|
||||
|
||||
self.route(x, Target::Wire(wire_multiplicand_0));
|
||||
self.route(one, Target::Wire(wire_multiplicand_1));
|
||||
self.route(y, Target::Wire(wire_addend));
|
||||
Target::Wire(wire_output)
|
||||
}
|
||||
|
||||
pub fn add_many(&mut self, terms: &[Target]) -> Target {
|
||||
let mut sum = self.zero();
|
||||
for term in terms {
|
||||
sum = self.add(sum, *term);
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
pub fn sub(&mut self, x: Target, y: Target) -> Target {
|
||||
todo!()
|
||||
let zero = self.zero();
|
||||
if x == zero {
|
||||
return y;
|
||||
}
|
||||
if y == zero {
|
||||
return x;
|
||||
}
|
||||
|
||||
// TODO: Inefficient impl for now.
|
||||
let neg_y = self.neg(y);
|
||||
self.add(x, neg_y)
|
||||
}
|
||||
|
||||
pub fn mul(&mut self, x: Target, y: Target) -> Target {
|
||||
// TODO: Check if one operand is 0 or 1.
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn mul_many(&mut self, terms: &[Target]) -> Target {
|
||||
let mut product = self.one();
|
||||
for term in terms {
|
||||
product = self.mul(product, *term);
|
||||
}
|
||||
product
|
||||
}
|
||||
|
||||
pub fn div(&mut self, x: Target, y: Target) -> Target {
|
||||
// TODO: Check if one operand is 0 or 1.
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
41
src/gadgets/hash.rs
Normal file
41
src/gadgets/hash.rs
Normal file
@ -0,0 +1,41 @@
|
||||
use std::convert::TryInto;
|
||||
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gmimc::GMiMCGate;
|
||||
use crate::gates::noop::NoopGate;
|
||||
use crate::hash::GMIMC_ROUNDS;
|
||||
use crate::target::Target;
|
||||
use crate::wire::Wire;
|
||||
|
||||
impl<F: Field> CircuitBuilder<F> {
|
||||
pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] {
|
||||
let zero = self.zero();
|
||||
self.permute_switched(inputs, zero)
|
||||
}
|
||||
|
||||
pub(crate) fn permute_switched(&mut self, inputs: [Target; 12], switch: Target) -> [Target; 12] {
|
||||
let gate = self.add_gate_no_constants(
|
||||
GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants());
|
||||
|
||||
let switch_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_SWITCH;
|
||||
let switch_wire = Target::Wire(Wire { gate, input: switch_wire });
|
||||
self.route(switch, switch_wire);
|
||||
|
||||
for i in 0..12 {
|
||||
let in_wire = GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i);
|
||||
let in_wire = Target::Wire(Wire { gate, input: in_wire });
|
||||
self.route(inputs[i], in_wire);
|
||||
}
|
||||
|
||||
// Add a NoopGate just to receive the outputs.
|
||||
let next_gate = self.add_gate_no_constants(NoopGate::get());
|
||||
|
||||
(0..12)
|
||||
.map(|i| Target::Wire(
|
||||
Wire { gate: next_gate, input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i) }))
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
pub(crate) mod arithmetic;
|
||||
pub(crate) mod split_join;
|
||||
pub(crate) mod hash;
|
||||
|
||||
156
src/gates/arithmetic.rs
Normal file
156
src/gates/arithmetic.rs
Normal file
@ -0,0 +1,156 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::constraint_polynomial::{EvaluationTargets, EvaluationVars};
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::{Gate, GateRef};
|
||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||
use crate::target::Target;
|
||||
use crate::wire::Wire;
|
||||
use crate::witness::PartialWitness;
|
||||
|
||||
/// A gate which can be configured to perform various arithmetic. In particular, it computes
|
||||
///
|
||||
/// ```text
|
||||
/// output := const_0 * multiplicand_0 * multiplicand_1 + const_1 * addend
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct ArithmeticGate;
|
||||
|
||||
impl ArithmeticGate {
|
||||
pub fn new<F: Field>() -> GateRef<F> {
|
||||
GateRef::new(ArithmeticGate)
|
||||
}
|
||||
|
||||
pub const WIRE_MULTIPLICAND_0: usize = 0;
|
||||
pub const WIRE_MULTIPLICAND_1: usize = 1;
|
||||
pub const WIRE_ADDEND: usize = 2;
|
||||
pub const WIRE_OUTPUT: usize = 3;
|
||||
}
|
||||
|
||||
impl<F: Field> Gate<F> for ArithmeticGate {
|
||||
fn id(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F>) -> Vec<F> {
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
let multiplicand_0 = vars.local_wires[Self::WIRE_MULTIPLICAND_0];
|
||||
let multiplicand_1 = vars.local_wires[Self::WIRE_MULTIPLICAND_1];
|
||||
let addend = vars.local_wires[Self::WIRE_ADDEND];
|
||||
let output = vars.local_wires[Self::WIRE_OUTPUT];
|
||||
let computed_output = const_0 * multiplicand_0 * multiplicand_1 + const_1 * addend;
|
||||
vec![computed_output - output]
|
||||
}
|
||||
|
||||
fn eval_unfiltered_recursively(
|
||||
&self,
|
||||
builder: &mut CircuitBuilder<F>,
|
||||
vars: EvaluationTargets,
|
||||
) -> Vec<Target> {
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
let multiplicand_0 = vars.local_wires[Self::WIRE_MULTIPLICAND_0];
|
||||
let multiplicand_1 = vars.local_wires[Self::WIRE_MULTIPLICAND_1];
|
||||
let addend = vars.local_wires[Self::WIRE_ADDEND];
|
||||
let output = vars.local_wires[Self::WIRE_OUTPUT];
|
||||
|
||||
let product_term = builder.mul_many(&[const_0, multiplicand_0, multiplicand_1]);
|
||||
let addend_term = builder.mul(const_1, addend);
|
||||
let computed_output = builder.add_many(&[product_term, addend_term]);
|
||||
vec![builder.sub(computed_output, output)]
|
||||
}
|
||||
|
||||
fn generators(
|
||||
&self,
|
||||
gate_index: usize,
|
||||
local_constants: &[F],
|
||||
_next_constants: &[F],
|
||||
) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
let gen = ArithmeticGenerator {
|
||||
gate_index,
|
||||
const_0: local_constants[0],
|
||||
const_1: local_constants[1],
|
||||
};
|
||||
vec![Box::new(gen)]
|
||||
}
|
||||
|
||||
fn num_wires(&self) -> usize {
|
||||
4
|
||||
}
|
||||
|
||||
fn num_constants(&self) -> usize {
|
||||
2
|
||||
}
|
||||
|
||||
fn degree(&self) -> usize {
|
||||
3
|
||||
}
|
||||
|
||||
fn num_constraints(&self) -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
struct ArithmeticGenerator<F: Field> {
|
||||
gate_index: usize,
|
||||
const_0: F,
|
||||
const_1: F,
|
||||
}
|
||||
|
||||
impl<F: Field> SimpleGenerator<F> for ArithmeticGenerator<F> {
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![
|
||||
Target::Wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_0,
|
||||
}),
|
||||
Target::Wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_1,
|
||||
}),
|
||||
Target::Wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_ADDEND,
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
fn run_once(&self, witness: &PartialWitness<F>) -> PartialWitness<F> {
|
||||
let multiplicand_0_target = Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_0,
|
||||
};
|
||||
let multiplicand_1_target = Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_1,
|
||||
};
|
||||
let addend_target = Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_ADDEND,
|
||||
};
|
||||
let output_target = Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_OUTPUT,
|
||||
};
|
||||
|
||||
let multiplicand_0 = witness.get_wire(multiplicand_0_target);
|
||||
let multiplicand_1 = witness.get_wire(multiplicand_1_target);
|
||||
let addend = witness.get_wire(addend_target);
|
||||
|
||||
let output = self.const_0 * multiplicand_0 * multiplicand_1
|
||||
+ self.const_1 * addend;
|
||||
|
||||
PartialWitness::singleton_wire(output_target, output)
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::{test_gate_low_degree, ArithmeticGate, Tweedledum};
|
||||
//
|
||||
// test_gate_low_degree!(
|
||||
// low_degree_ArithmeticGate,
|
||||
// Tweedledum,
|
||||
// ArithmeticGate<Tweedledum>
|
||||
// );
|
||||
// }
|
||||
@ -84,6 +84,6 @@ impl<F: Field> SimpleGenerator<F> for ConstantGenerator<F> {
|
||||
|
||||
fn run_once(&self, _witness: &PartialWitness<F>) -> PartialWitness<F> {
|
||||
let wire = Wire { gate: self.gate_index, input: ConstantGate::WIRE_OUTPUT };
|
||||
PartialWitness::singleton(Target::Wire(wire), self.constant)
|
||||
PartialWitness::singleton_target(Target::Wire(wire), self.constant)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ use crate::constraint_polynomial::{EvaluationTargets, EvaluationVars};
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::{Gate, GateRef};
|
||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||
use crate::gmimc::gmimc_automatic_constants;
|
||||
use crate::target::Target;
|
||||
use crate::wire::Wire;
|
||||
use crate::witness::PartialWitness;
|
||||
@ -26,7 +27,8 @@ impl<F: Field, const R: usize> GMiMCGate<F, R> {
|
||||
}
|
||||
|
||||
pub fn with_automatic_constants() -> GateRef<F> {
|
||||
todo!()
|
||||
let constants = Arc::new(gmimc_automatic_constants::<F, R>());
|
||||
Self::with_constants(constants)
|
||||
}
|
||||
|
||||
/// If this is set to 1, the first four inputs will be swapped with the next four inputs. This
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
pub(crate) mod arithmetic;
|
||||
pub(crate) mod constant;
|
||||
pub(crate) mod fri_consistency_gate;
|
||||
pub(crate) mod gate;
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Debug;
|
||||
use std::time::Instant;
|
||||
|
||||
use log::trace;
|
||||
|
||||
use crate::field::field::Field;
|
||||
use crate::target::Target;
|
||||
@ -12,10 +9,10 @@ use crate::witness::PartialWitness;
|
||||
/// given set of generators.
|
||||
pub(crate) fn generate_partial_witness<F: Field>(
|
||||
witness: &mut PartialWitness<F>,
|
||||
mut generators: &[Box<dyn WitnessGenerator<F>>],
|
||||
generators: &[Box<dyn WitnessGenerator<F>>],
|
||||
) {
|
||||
// Index generator indices by their watched targets.
|
||||
let mut generator_indices_by_watches: HashMap<Target, Vec<usize>> = HashMap::new();
|
||||
let mut generator_indices_by_watches = HashMap::new();
|
||||
for (i, generator) in generators.iter().enumerate() {
|
||||
for watch in generator.watch_list() {
|
||||
generator_indices_by_watches
|
||||
@ -40,9 +37,7 @@ pub(crate) fn generate_partial_witness<F: Field>(
|
||||
let mut next_pending_generator_indices = HashSet::new();
|
||||
|
||||
for &generator_idx in &pending_generator_indices {
|
||||
let start = Instant::now();
|
||||
let (result, finished) = generators[generator_idx].run(&witness);
|
||||
trace!("run {:?} took {}", generators[generator_idx], start.elapsed().as_secs_f32());
|
||||
if finished {
|
||||
expired_generator_indices.insert(generator_idx);
|
||||
}
|
||||
@ -66,7 +61,7 @@ pub(crate) fn generate_partial_witness<F: Field>(
|
||||
}
|
||||
|
||||
/// A generator participates in the generation of the witness.
|
||||
pub trait WitnessGenerator<F: Field>: 'static + Debug + Send + Sync {
|
||||
pub trait WitnessGenerator<F: Field>: 'static + Send + Sync {
|
||||
/// Targets to be "watched" by this generator. Whenever a target in the watch list is populated,
|
||||
/// the generator will be queued to run.
|
||||
fn watch_list(&self) -> Vec<Target>;
|
||||
@ -80,7 +75,7 @@ pub trait WitnessGenerator<F: Field>: 'static + Debug + Send + Sync {
|
||||
|
||||
/// A generator which runs once after a list of dependencies is present in the witness.
|
||||
// TODO: Remove Debug. Here temporarily to debug generator issues.
|
||||
pub trait SimpleGenerator<F: Field>: 'static + Debug + Send + Sync {
|
||||
pub trait SimpleGenerator<F: Field>: 'static + Send + Sync {
|
||||
fn dependencies(&self) -> Vec<Target>;
|
||||
|
||||
fn run_once(&self, witness: &PartialWitness<F>) -> PartialWitness<F>;
|
||||
@ -114,6 +109,6 @@ impl<F: Field> SimpleGenerator<F> for CopyGenerator {
|
||||
|
||||
fn run_once(&self, witness: &PartialWitness<F>) -> PartialWitness<F> {
|
||||
let value = witness.get_target(self.src);
|
||||
PartialWitness::singleton(self.dst, value)
|
||||
PartialWitness::singleton_target(self.dst, value)
|
||||
}
|
||||
}
|
||||
|
||||
11
src/gmimc.rs
11
src/gmimc.rs
@ -1,9 +1,20 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
use unroll::unroll_for_loops;
|
||||
|
||||
use crate::field::field::Field;
|
||||
|
||||
pub(crate) fn gmimc_automatic_constants<F: Field, const R: usize>() -> [F; R] {
|
||||
let mut rng = ChaCha8Rng::seed_from_u64(0);
|
||||
let mut constants = [F::ZERO; R];
|
||||
for i in 0..R {
|
||||
constants[i] = F::rand_from_rng(&mut rng);
|
||||
}
|
||||
constants
|
||||
}
|
||||
|
||||
pub fn gmimc_compress<F: Field, const R: usize>(a: [F; 4], b: [F; 4], constants: Arc<[F; R]>) -> [F; 4] {
|
||||
// Sponge with r=8, c=4.
|
||||
let state_0 = [a[0], a[1], a[2], a[3], b[0],
|
||||
|
||||
@ -13,8 +13,9 @@ pub(crate) const SPONGE_RATE: usize = 8;
|
||||
pub(crate) const SPONGE_CAPACITY: usize = 4;
|
||||
pub(crate) const SPONGE_WIDTH: usize = SPONGE_RATE + SPONGE_CAPACITY;
|
||||
|
||||
const GMIMC_ROUNDS: usize = 101;
|
||||
const GMIMC_CONSTANTS: [u64; GMIMC_ROUNDS] = [11875528958976719239, 6107683892976199900, 7756999550758271958, 14819109722912164804, 9716579428412441110, 13627117528901194436, 16260683900833506663, 5942251937084147420, 3340009544523273897, 5103423085715007461, 17051583366444092101, 11122892258227244197, 16564300648907092407, 978667924592675864, 17676416205210517593, 1938246372790494499, 8857737698008340728, 1616088456497468086, 15961521580811621978, 17427220057097673602, 14693961562064090188, 694121596646283736, 554241305747273747, 5783347729647881086, 14933083198980931734, 2600898787591841337, 9178797321043036456, 18068112389665928586, 14493389459750307626, 1650694762687203587, 12538946551586403559, 10144328970401184255, 4215161528137084719, 17559540991336287827, 1632269449854444901, 986434918028205468, 14921385763379308253, 4345141219277982730, 2645897826751167170, 9815223670029373528, 7687983869685434132, 13956100321958014639, 519639453142393369, 15617837024229225911, 1557446238053329052, 8130006133842942201, 864716631341688017, 2860289738131495304, 16723700803638270299, 8363528906277648001, 13196016034228493087, 2514677332206134618, 15626342185220554936, 466271571343554681, 17490024028988898434, 6454235936129380878, 15187752952940298536, 18043495619660620405, 17118101079533798167, 13420382916440963101, 535472393366793763, 1071152303676936161, 6351382326603870931, 12029593435043638097, 9983185196487342247, 414304527840226604, 1578977347398530191, 13594880016528059526, 13219707576179925776, 6596253305527634647, 17708788597914990288, 7005038999589109658, 10171979740390484633, 1791376803510914239, 2405996319967739434, 12383033218117026776, 17648019043455213923, 6600216741450137683, 5359884112225925883, 1501497388400572107, 11860887439428904719, 64080876483307031, 11909038931518362287, 14166132102057826906, 14172584203466994499, 593515702472765471, 3423583343794830614, 10041710997716717966, 13434212189787960052, 9943803922749087030, 3216887087479209126, 17385898166602921353, 617799950397934255, 9245115057096506938, 13290383521064450731, 10193883853810413351, 14648839921475785656, 14635698366607946133, 9134302981480720532, 10045888297267997632, 10752096344939765738];
|
||||
pub(crate) const GMIMC_ROUNDS: usize = 101;
|
||||
/// This is the result of `gmimc_automatic_constants`; i.e. it's from ChaCha20 seeded with 0.
|
||||
pub(crate) const GMIMC_CONSTANTS: [u64; GMIMC_ROUNDS] = [13080132715619999810, 8594738768332784433, 12896916466795114362, 1109962092924985887, 16216730424513838303, 10137062674532189451, 15292064468290167604, 17255573296743700660, 14827154243383347999, 2846171648262623971, 16246264665335217464, 14214208089399786945, 9667108688411000080, 6470857421371427314, 14103331941574951088, 11854816474757864855, 3498097497657653643, 7947235693333396721, 11110078702363612411, 16384314114341783099, 15404405914224921002, 14077880832148466479, 9555554663682579629, 13859595359622389547, 16859897326779206643, 17685474422023725021, 17858764736437889563, 9410011023624402450, 12495243630852222748, 12416945299436348089, 5776666812952701944, 6314421663507268983, 7402742472177291738, 982536713292517255, 17321168867539521172, 2934354895304883596, 10567510599683852824, 8135543734546633309, 116353493093565855, 8029688164312877009, 9003846638141970076, 7052445133185619935, 9645665433271393194, 5446430061585660707, 16770910636054378912, 17708360573237778662, 4661556288797079635, 11977051900536351292, 4378616569536950472, 3334807503157233344, 8019184736760206441, 2395043909056213726, 6558421058999795722, 11735894061922784518, 8143540539718733269, 5991753490174091591, 12235918792748480378, 2880312033996085535, 18224748117164817283, 18070411014966027790, 8156487614951798795, 10615269511128318233, 12489426406026437595, 5055279340584943685, 7231927320516917417, 2602078848371820415, 12445944370602567717, 3978905924297801117, 16711272946032085229, 10439032362290464320, 15110119873264383151, 821141790739535246, 11073536381779174375, 4866839313593360589, 13118391690850240703, 14527674975242150843, 7612751960041028847, 6808090908507673494, 6899703780195472329, 3664666286710282218, 783179505504239941, 8990689242729919931, 9646603556395461579, 7351246026916028004, 16970959815450893036, 15735726859844361172, 10347018222946250943, 12195545879691602738, 7423314197870213963, 14908016118492485461, 5840340123122280205, 17740311464247702688, 815306422036794512, 17456357369997417977, 6982651077270605698, 11970987325834369417, 8167785009370061651, 9483259820363401119, 954550221761525285, 10339565172077536587, 8651171085167737860];
|
||||
|
||||
/// Controls the granularity of parallelization when building Merkle trees. I.e., we will try to
|
||||
/// split up the task into units of work, such that each unit involves hashing roughly this many
|
||||
|
||||
12
src/main.rs
12
src/main.rs
@ -1,4 +1,3 @@
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Instant;
|
||||
|
||||
@ -13,6 +12,7 @@ use crate::circuit_data::CircuitConfig;
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::constant::ConstantGate;
|
||||
use crate::gates::gmimc::GMiMCGate;
|
||||
use crate::hash::{GMIMC_CONSTANTS, GMIMC_ROUNDS};
|
||||
use crate::polynomial::polynomial::PolynomialCoeffs;
|
||||
use crate::witness::PartialWitness;
|
||||
|
||||
@ -76,12 +76,7 @@ fn bench_field_mul<F: Field>() {
|
||||
}
|
||||
|
||||
fn bench_prove<F: Field>() {
|
||||
let mut gmimc_constants = [F::ZERO; GMIMC_ROUNDS];
|
||||
for i in 0..GMIMC_ROUNDS {
|
||||
gmimc_constants[i] = F::from_canonical_u64(GMIMC_CONSTANTS[i]);
|
||||
}
|
||||
let gmimc_gate = GMiMCGate::<F, GMIMC_ROUNDS>::with_constants(
|
||||
Arc::new(gmimc_constants));
|
||||
let gmimc_gate = GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants();
|
||||
|
||||
let config = CircuitConfig {
|
||||
num_wires: 120,
|
||||
@ -110,9 +105,6 @@ fn bench_prove<F: Field>() {
|
||||
prover.prove(inputs);
|
||||
}
|
||||
|
||||
const GMIMC_ROUNDS: usize = 101;
|
||||
const GMIMC_CONSTANTS: [u64; GMIMC_ROUNDS] = [11875528958976719239, 6107683892976199900, 7756999550758271958, 14819109722912164804, 9716579428412441110, 13627117528901194436, 16260683900833506663, 5942251937084147420, 3340009544523273897, 5103423085715007461, 17051583366444092101, 11122892258227244197, 16564300648907092407, 978667924592675864, 17676416205210517593, 1938246372790494499, 8857737698008340728, 1616088456497468086, 15961521580811621978, 17427220057097673602, 14693961562064090188, 694121596646283736, 554241305747273747, 5783347729647881086, 14933083198980931734, 2600898787591841337, 9178797321043036456, 18068112389665928586, 14493389459750307626, 1650694762687203587, 12538946551586403559, 10144328970401184255, 4215161528137084719, 17559540991336287827, 1632269449854444901, 986434918028205468, 14921385763379308253, 4345141219277982730, 2645897826751167170, 9815223670029373528, 7687983869685434132, 13956100321958014639, 519639453142393369, 15617837024229225911, 1557446238053329052, 8130006133842942201, 864716631341688017, 2860289738131495304, 16723700803638270299, 8363528906277648001, 13196016034228493087, 2514677332206134618, 15626342185220554936, 466271571343554681, 17490024028988898434, 6454235936129380878, 15187752952940298536, 18043495619660620405, 17118101079533798167, 13420382916440963101, 535472393366793763, 1071152303676936161, 6351382326603870931, 12029593435043638097, 9983185196487342247, 414304527840226604, 1578977347398530191, 13594880016528059526, 13219707576179925776, 6596253305527634647, 17708788597914990288, 7005038999589109658, 10171979740390484633, 1791376803510914239, 2405996319967739434, 12383033218117026776, 17648019043455213923, 6600216741450137683, 5359884112225925883, 1501497388400572107, 11860887439428904719, 64080876483307031, 11909038931518362287, 14166132102057826906, 14172584203466994499, 593515702472765471, 3423583343794830614, 10041710997716717966, 13434212189787960052, 9943803922749087030, 3216887087479209126, 17385898166602921353, 617799950397934255, 9245115057096506938, 13290383521064450731, 10193883853810413351, 14648839921475785656, 14635698366607946133, 9134302981480720532, 10045888297267997632, 10752096344939765738];
|
||||
|
||||
fn bench_gmimc<F: Field>() {
|
||||
const THREADS: usize = 12;
|
||||
const LDE_BITS: i32 = 3;
|
||||
|
||||
@ -226,7 +226,11 @@ mod tests {
|
||||
outputs_per_round.push(challenger.get_n_challenges(num_outputs_per_round[r]));
|
||||
}
|
||||
|
||||
let config = CircuitConfig::default();
|
||||
let config = CircuitConfig {
|
||||
num_wires: 114,
|
||||
num_routed_wires: 13,
|
||||
..CircuitConfig::default()
|
||||
};
|
||||
let mut builder = CircuitBuilder::<F>::new(config);
|
||||
let mut recursive_challenger = RecursiveChallenger::new(&mut builder);
|
||||
let mut recursive_outputs_per_round: Vec<Vec<Target>> =
|
||||
|
||||
@ -16,7 +16,11 @@ impl<F: Field> PartialWitness<F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn singleton(target: Target, value: F) -> Self {
|
||||
pub fn singleton_wire(wire: Wire, value: F) -> Self {
|
||||
Self::singleton_target(Target::Wire(wire), value)
|
||||
}
|
||||
|
||||
pub fn singleton_target(target: Target, value: F) -> Self {
|
||||
let mut witness = PartialWitness::new();
|
||||
witness.set_target(target, value);
|
||||
witness
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user