mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 06:43:07 +00:00
Merge pull request #13 from mir-protocol/hash_instance
Seed Challenger with a hash of the instance
This commit is contained in:
commit
a9e7ff800e
@ -1,16 +1,19 @@
|
|||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, VerifierCircuitData, VerifierOnlyCircuitData};
|
use crate::circuit_data::{
|
||||||
|
CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData,
|
||||||
|
VerifierCircuitData, VerifierOnlyCircuitData,
|
||||||
|
};
|
||||||
|
use crate::field::cosets::get_unique_coset_shifts;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gates::constant::ConstantGate;
|
use crate::gates::constant::ConstantGate;
|
||||||
use crate::gates::gate::{GateInstance, GateRef};
|
use crate::gates::gate::{GateInstance, GateRef};
|
||||||
use crate::gates::noop::NoopGate;
|
use crate::gates::noop::NoopGate;
|
||||||
use crate::generator::{CopyGenerator, WitnessGenerator};
|
use crate::generator::{CopyGenerator, WitnessGenerator};
|
||||||
use crate::hash::merkle_root_bit_rev_order;
|
use crate::hash::{hash_n_to_hash, merkle_root_bit_rev_order};
|
||||||
use crate::field::cosets::get_unique_coset_shifts;
|
|
||||||
use crate::polynomial::polynomial::PolynomialValues;
|
use crate::polynomial::polynomial::PolynomialValues;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::util::{log2_strict, transpose, transpose_poly_values};
|
use crate::util::{log2_strict, transpose, transpose_poly_values};
|
||||||
@ -84,14 +87,21 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
// TODO: Not passing next constants for now. Not sure if it's really useful...
|
// TODO: Not passing next constants for now. Not sure if it's really useful...
|
||||||
self.add_generators(gate_type.0.generators(index, &constants, &[]));
|
self.add_generators(gate_type.0.generators(index, &constants, &[]));
|
||||||
|
|
||||||
self.gate_instances.push(GateInstance { gate_type, constants });
|
self.gate_instances.push(GateInstance {
|
||||||
|
gate_type,
|
||||||
|
constants,
|
||||||
|
});
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_gate_compatibility(&self, gate: &GateRef<F>) {
|
fn check_gate_compatibility(&self, gate: &GateRef<F>) {
|
||||||
assert!(gate.0.num_wires() <= self.config.num_wires,
|
assert!(
|
||||||
"{:?} requires {} wires, but our GateConfig has only {}",
|
gate.0.num_wires() <= self.config.num_wires,
|
||||||
gate.0.id(), 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`.
|
/// Shorthand for `generate_copy` and `assert_equal`.
|
||||||
@ -109,8 +119,14 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
/// Uses Plonk's permutation argument to require that two elements be equal.
|
/// Uses Plonk's permutation argument to require that two elements be equal.
|
||||||
/// Both elements must be routable, otherwise this method will panic.
|
/// Both elements must be routable, otherwise this method will panic.
|
||||||
pub fn assert_equal(&mut self, x: Target, y: Target) {
|
pub fn assert_equal(&mut self, x: Target, y: Target) {
|
||||||
assert!(x.is_routable(self.config), "Tried to route a wire that isn't routable");
|
assert!(
|
||||||
assert!(y.is_routable(self.config), "Tried to route a wire that isn't routable");
|
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.
|
// TODO: Add to copy_constraints.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +166,10 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let gate = self.add_gate(ConstantGate::get(), vec![c]);
|
let gate = self.add_gate(ConstantGate::get(), vec![c]);
|
||||||
let target = Target::Wire(Wire { gate, input: ConstantGate::WIRE_OUTPUT });
|
let target = Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: ConstantGate::WIRE_OUTPUT,
|
||||||
|
});
|
||||||
self.constants_to_targets.insert(c, target);
|
self.constants_to_targets.insert(c, target);
|
||||||
self.targets_to_constants.insert(target, c);
|
self.targets_to_constants.insert(target, c);
|
||||||
target
|
target
|
||||||
@ -175,11 +194,15 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn constant_polys(&self) -> Vec<PolynomialValues<F>> {
|
fn constant_polys(&self) -> Vec<PolynomialValues<F>> {
|
||||||
let num_constants = self.gate_instances.iter()
|
let num_constants = self
|
||||||
|
.gate_instances
|
||||||
|
.iter()
|
||||||
.map(|gate_inst| gate_inst.constants.len())
|
.map(|gate_inst| gate_inst.constants.len())
|
||||||
.max()
|
.max()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let constants_per_gate = self.gate_instances.iter()
|
let constants_per_gate = self
|
||||||
|
.gate_instances
|
||||||
|
.iter()
|
||||||
.map(|gate_inst| {
|
.map(|gate_inst| {
|
||||||
let mut padded_constants = gate_inst.constants.clone();
|
let mut padded_constants = gate_inst.constants.clone();
|
||||||
for _ in padded_constants.len()..num_constants {
|
for _ in padded_constants.len()..num_constants {
|
||||||
@ -196,13 +219,17 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sigma_vecs(&self) -> Vec<PolynomialValues<F>> {
|
fn sigma_vecs(&self) -> Vec<PolynomialValues<F>> {
|
||||||
vec![PolynomialValues::zero(self.gate_instances.len()); self.config.num_routed_wires] // TODO
|
vec![PolynomialValues::zero(self.gate_instances.len()); self.config.num_routed_wires]
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a "full circuit", with both prover and verifier data.
|
/// Builds a "full circuit", with both prover and verifier data.
|
||||||
pub fn build(mut self) -> CircuitData<F> {
|
pub fn build(mut self) -> CircuitData<F> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
info!("degree before blinding & padding: {}", self.gate_instances.len());
|
info!(
|
||||||
|
"degree before blinding & padding: {}",
|
||||||
|
self.gate_instances.len()
|
||||||
|
);
|
||||||
self.blind_and_pad();
|
self.blind_and_pad();
|
||||||
let degree = self.gate_instances.len();
|
let degree = self.gate_instances.len();
|
||||||
info!("degree after blinding & padding: {}", degree);
|
info!("degree after blinding & padding: {}", degree);
|
||||||
@ -218,7 +245,11 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
let sigmas_root = merkle_root_bit_rev_order(sigma_ldes_t.clone());
|
let sigmas_root = merkle_root_bit_rev_order(sigma_ldes_t.clone());
|
||||||
|
|
||||||
let generators = self.generators;
|
let generators = self.generators;
|
||||||
let prover_only = ProverOnlyCircuitData { generators, constant_ldes_t, sigma_ldes_t };
|
let prover_only = ProverOnlyCircuitData {
|
||||||
|
generators,
|
||||||
|
constant_ldes_t,
|
||||||
|
sigma_ldes_t,
|
||||||
|
};
|
||||||
let verifier_only = VerifierOnlyCircuitData {};
|
let verifier_only = VerifierOnlyCircuitData {};
|
||||||
|
|
||||||
// The HashSet of gates will have a non-deterministic order. When converting to a Vec, we
|
// The HashSet of gates will have a non-deterministic order. When converting to a Vec, we
|
||||||
@ -226,7 +257,8 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
let mut gates = self.gates.iter().cloned().collect::<Vec<_>>();
|
let mut gates = self.gates.iter().cloned().collect::<Vec<_>>();
|
||||||
gates.sort_unstable_by_key(|gate| gate.0.id());
|
gates.sort_unstable_by_key(|gate| gate.0.id());
|
||||||
|
|
||||||
let num_gate_constraints = gates.iter()
|
let num_gate_constraints = gates
|
||||||
|
.iter()
|
||||||
.map(|gate| gate.0.num_constraints())
|
.map(|gate| gate.0.num_constraints())
|
||||||
.max()
|
.max()
|
||||||
.expect("No gates?");
|
.expect("No gates?");
|
||||||
@ -234,6 +266,13 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
let degree_bits = log2_strict(degree);
|
let degree_bits = log2_strict(degree);
|
||||||
let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires);
|
let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires);
|
||||||
|
|
||||||
|
// TODO: This should also include an encoding of gate constraints.
|
||||||
|
let circuit_digest_parts = [
|
||||||
|
constants_root.elements,
|
||||||
|
sigmas_root.elements,
|
||||||
|
];
|
||||||
|
let circuit_digest = hash_n_to_hash(circuit_digest_parts.concat(), false);
|
||||||
|
|
||||||
let common = CommonCircuitData {
|
let common = CommonCircuitData {
|
||||||
config: self.config,
|
config: self.config,
|
||||||
degree_bits,
|
degree_bits,
|
||||||
@ -242,6 +281,7 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
constants_root,
|
constants_root,
|
||||||
sigmas_root,
|
sigmas_root,
|
||||||
k_is,
|
k_is,
|
||||||
|
circuit_digest,
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Building circuit took {}s", start.elapsed().as_secs_f32());
|
info!("Building circuit took {}s", start.elapsed().as_secs_f32());
|
||||||
@ -255,14 +295,28 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
/// Builds a "prover circuit", with data needed to generate proofs but not verify them.
|
/// Builds a "prover circuit", with data needed to generate proofs but not verify them.
|
||||||
pub fn build_prover(self) -> ProverCircuitData<F> {
|
pub fn build_prover(self) -> ProverCircuitData<F> {
|
||||||
// TODO: Can skip parts of this.
|
// TODO: Can skip parts of this.
|
||||||
let CircuitData { prover_only, common, .. } = self.build();
|
let CircuitData {
|
||||||
ProverCircuitData { prover_only, common }
|
prover_only,
|
||||||
|
common,
|
||||||
|
..
|
||||||
|
} = self.build();
|
||||||
|
ProverCircuitData {
|
||||||
|
prover_only,
|
||||||
|
common,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a "verifier circuit", with data needed to verify proofs but not generate them.
|
/// Builds a "verifier circuit", with data needed to verify proofs but not generate them.
|
||||||
pub fn build_verifier(self) -> VerifierCircuitData<F> {
|
pub fn build_verifier(self) -> VerifierCircuitData<F> {
|
||||||
// TODO: Can skip parts of this.
|
// TODO: Can skip parts of this.
|
||||||
let CircuitData { verifier_only, common, .. } = self.build();
|
let CircuitData {
|
||||||
VerifierCircuitData { verifier_only, common }
|
verifier_only,
|
||||||
|
common,
|
||||||
|
..
|
||||||
|
} = self.build();
|
||||||
|
VerifierCircuitData {
|
||||||
|
verifier_only,
|
||||||
|
common,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,6 +112,10 @@ pub(crate) struct CommonCircuitData<F: Field> {
|
|||||||
|
|
||||||
/// The `{k_i}` valued used in `S_ID_i` in Plonk's permutation argument.
|
/// The `{k_i}` valued used in `S_ID_i` in Plonk's permutation argument.
|
||||||
pub(crate) k_is: Vec<F>,
|
pub(crate) k_is: Vec<F>,
|
||||||
|
|
||||||
|
/// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to
|
||||||
|
/// seed Fiat-Shamir.
|
||||||
|
pub(crate) circuit_digest: Hash<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> CommonCircuitData<F> {
|
impl<F: Field> CommonCircuitData<F> {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gates::arithmetic::ArithmeticGate;
|
use crate::gates::arithmetic::ArithmeticGate;
|
||||||
|
use crate::generator::SimpleGenerator;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
use crate::generator::SimpleGenerator;
|
|
||||||
use crate::witness::PartialWitness;
|
use crate::witness::PartialWitness;
|
||||||
|
|
||||||
impl<F: Field> CircuitBuilder<F> {
|
impl<F: Field> CircuitBuilder<F> {
|
||||||
@ -22,8 +22,9 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
addend: Target,
|
addend: Target,
|
||||||
) -> Target {
|
) -> Target {
|
||||||
// See if we can determine the result without adding an `ArithmeticGate`.
|
// See if we can determine the result without adding an `ArithmeticGate`.
|
||||||
if let Some(result) = self.arithmetic_special_cases(
|
if let Some(result) =
|
||||||
const_0, multiplicand_0, multiplicand_1, const_1, addend) {
|
self.arithmetic_special_cases(const_0, multiplicand_0, multiplicand_1, const_1, addend)
|
||||||
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +70,8 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
let mul_1_const = self.target_as_constant(multiplicand_1);
|
let mul_1_const = self.target_as_constant(multiplicand_1);
|
||||||
let addend_const = self.target_as_constant(addend);
|
let addend_const = self.target_as_constant(addend);
|
||||||
|
|
||||||
let first_term_zero = const_0 == F::ZERO || multiplicand_0 == zero || multiplicand_1 == zero;
|
let first_term_zero =
|
||||||
|
const_0 == F::ZERO || multiplicand_0 == zero || multiplicand_1 == zero;
|
||||||
let second_term_zero = const_1 == F::ZERO || addend == zero;
|
let second_term_zero = const_1 == F::ZERO || addend == zero;
|
||||||
|
|
||||||
// If both terms are constant, return their (constant) sum.
|
// If both terms are constant, return their (constant) sum.
|
||||||
@ -156,17 +158,31 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
if y == one {
|
if y == one {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
if let (Some(x_const), Some(y_const)) = (self.target_as_constant(x), self.target_as_constant(y)) {
|
if let (Some(x_const), Some(y_const)) =
|
||||||
|
(self.target_as_constant(x), self.target_as_constant(y))
|
||||||
|
{
|
||||||
return self.constant(x_const / y_const);
|
return self.constant(x_const / y_const);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an `ArithmeticGate` to compute `q * y`.
|
// Add an `ArithmeticGate` to compute `q * y`.
|
||||||
let gate = self.add_gate(ArithmeticGate::new(), vec![F::ONE, F::ZERO]);
|
let gate = self.add_gate(ArithmeticGate::new(), vec![F::ONE, F::ZERO]);
|
||||||
|
|
||||||
let wire_multiplicand_0 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_0 };
|
let wire_multiplicand_0 = Wire {
|
||||||
let wire_multiplicand_1 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_1 };
|
gate,
|
||||||
let wire_addend = Wire { gate, input: ArithmeticGate::WIRE_ADDEND };
|
input: ArithmeticGate::WIRE_MULTIPLICAND_0,
|
||||||
let wire_output = Wire { gate, input: ArithmeticGate::WIRE_OUTPUT };
|
};
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
let q = Target::Wire(wire_multiplicand_0);
|
let q = Target::Wire(wire_multiplicand_0);
|
||||||
self.add_generator(QuotientGenerator {
|
self.add_generator(QuotientGenerator {
|
||||||
|
|||||||
@ -68,6 +68,10 @@ pub(crate) fn prove<F: Field>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut challenger = Challenger::new();
|
let mut challenger = Challenger::new();
|
||||||
|
// Observe the instance.
|
||||||
|
// TODO: Need to include public inputs as well.
|
||||||
|
challenger.observe_hash(&common_data.circuit_digest);
|
||||||
|
|
||||||
challenger.observe_hash(&wires_root);
|
challenger.observe_hash(&wires_root);
|
||||||
let betas = challenger.get_n_challenges(num_checks);
|
let betas = challenger.get_n_challenges(num_checks);
|
||||||
let gammas = challenger.get_n_challenges(num_checks);
|
let gammas = challenger.get_n_challenges(num_checks);
|
||||||
|
|||||||
@ -17,4 +17,6 @@ pub fn add_recursive_verifier<F: Field>(
|
|||||||
) {
|
) {
|
||||||
assert!(builder.config.num_wires >= MIN_WIRES);
|
assert!(builder.config.num_wires >= MIN_WIRES);
|
||||||
assert!(builder.config.num_wires >= MIN_ROUTED_WIRES);
|
assert!(builder.config.num_wires >= MIN_ROUTED_WIRES);
|
||||||
|
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user