Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prover for protostar #15

Merged
merged 5 commits into from
Nov 26, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions src/circuit.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use elsa::map::FrozenMap;
use ff::PrimeField;
use itertools::Itertools;

use crate::{witness::{CSWtns, ProtostarWtns, ProtostarLhsWtns}, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub}, external_interface::{RunIndex, RunAllocator} };
use crate::{witness::{CSWtns, ProtostarWtns, ProtostarLhsWtns}, gate::{Gatebb, Gate}, constraint_system::{Variable, ProtoGalaxyConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub}, external_interface::{RunIndex, RunAllocator} };

use self::circuit_operations::CircuitOperation;

@@ -184,7 +184,7 @@ pub mod circuit_operations {

pub struct Circuit<'circuit, F: PrimeField, G: Gate<'circuit, F> + From<PolyOp<'circuit, F>>> {
gate_registry: FrozenMap<String, Box<G>>,
pub cs: ConstraintSystem<'circuit, F, G>,
pub cs: ProtoGalaxyConstraintSystem<'circuit, F, G>,
ops: Vec<Vec<Box<dyn CircuitOperation<'circuit, F, G> + 'circuit>>>,
max_degree: usize,
// round_counter : usize,
@@ -197,7 +197,7 @@ where
G: Gate<'circuit, F> + From<PolyOp<'circuit, F>>,
{
pub fn new(max_degree: usize, num_rounds: usize) -> Self {
let cs = ConstraintSystem::new(num_rounds, max_degree);
let cs = ProtoGalaxyConstraintSystem::new(num_rounds);
let mut prep = Self {
gate_registry: FrozenMap::new(),
cs,
@@ -325,7 +325,7 @@ where
}

pub struct ConstructedCircuit<'circuit, F: PrimeField, G: Gate<'circuit, F> + From<PolyOp<'circuit, F>>> {
circuit: Circuit<'circuit, F, G>,
pub circuit: Circuit<'circuit, F, G>,
run_allocator: RefCell<RunAllocator>,
}

@@ -342,6 +342,18 @@ impl<'circuit, F: PrimeField, G: Gate<'circuit, F> + From<PolyOp<'circuit, F>>>
fn deallocate<'constructed>(&'constructed self, idx: RunIndex) {
self.run_allocator.borrow_mut().deallocate(idx);
}

pub fn perepare_protostar_chellanges(&self, mut beta: F) -> Vec<F> {
let m = self.circuit.cs.constr_spec().num_nonlinear_constraints;
let mut p = 1;
let mut protostar_challenges = vec![];
while p < m {
protostar_challenges.push(beta);
beta = beta * beta;
p = p * 2;
}
protostar_challenges
}
}

pub struct CircuitRun<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From<PolyOp<'circuit, F>>>{
@@ -368,15 +380,8 @@ where
}
}

pub fn end(&self, mut beta: F) -> ProtostarWtns<'constructed, 'circuit, F, G> {
let m = self.constructed.circuit.cs.constr_spec().num_nonlinear_constraints;
let mut p = 1;
let mut protostar_challenges = vec![];
while p <= m {
protostar_challenges.push(beta);
beta = beta * beta;
p = p * 2;
}
pub fn end(&self, beta: F) -> ProtostarWtns<F> {
let protostar_challenges = self.constructed.perepare_protostar_chellanges(beta);

let mut pubs = vec![];
let mut round_wtns = vec![];
@@ -391,7 +396,6 @@ where
round_wtns,
pubs,
protostar_challenges,
circuit: self.constructed,
},
error: F::ZERO,
}
@@ -415,7 +419,7 @@ where
self.constructed.circuit.cs.iter_constraints()
}

pub fn finish(self) -> (CSWtns<'circuit, F, G>, &'constructed ConstraintSystem<'circuit, F, G>) {
pub fn finish(self) -> (CSWtns<'circuit, F, G>, &'constructed ProtoGalaxyConstraintSystem<'circuit, F, G>) {
let Self {constructed, cs, round_counter: _, run_idx} = self;

constructed.deallocate(run_idx);
90 changes: 48 additions & 42 deletions src/constraint_system.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::marker::PhantomData;
use std::{marker::PhantomData, collections::BTreeMap};

use ff::PrimeField;
use itertools::Itertools;

use crate::{gate::Gate, circuit::ExternalValue};

@@ -46,24 +47,18 @@ pub struct Constraint<'c, F: PrimeField, G: Gate<'c, F>>{
#[derive(Debug, Clone)]
struct ConstraintGroup<'c, F: PrimeField, G: Gate<'c, F>> {
pub entries: Vec<Constraint<'c, F, G>>,
#[allow(dead_code)]
pub kind: CommitKind,
pub num_rhs: usize,
pub max_degree: usize,
}

impl<'c, F: PrimeField, G: Gate<'c, F>> ConstraintGroup<'c, F, G> {
pub fn new(kind: CommitKind, max_degree: usize) -> Self {
pub fn new() -> Self {
Self {
entries: Default::default(),
kind,
num_rhs: Default::default(),
max_degree,
}
}

pub fn constrain(&mut self, inputs: &[Variable], gate: G) {
assert!(gate.d() <= self.max_degree, "Constraint degree is too large for this group.");
assert!(gate.i() == inputs.len(), "Invalid amount of arguments supplied.");

self.num_rhs += gate.o();
@@ -75,7 +70,10 @@ impl<'c, F: PrimeField, G: Gate<'c, F>> ConstraintGroup<'c, F, G> {
///
/// Any witness used for this constraint system has to at least comply with the spec.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct RoundWitnessSpec(pub usize, pub usize);
pub struct RoundWitnessSpec{
pub pubs: usize,
pub privs: usize,
}

/// Witness shape specification: a collection of specifications for each round
///
@@ -94,7 +92,7 @@ pub struct ConstrSpec {
pub max_degree: usize,
}

pub trait CS<'c, F: PrimeField, G: Gate<'c, F>> {
pub trait CS<'c, F: PrimeField, G: Gate<'c, F>> {
fn num_rounds(&self) -> usize;

fn last_round(&self) -> usize {
@@ -118,43 +116,42 @@ pub trait CS<'c, F: PrimeField, G: Gate<'c, F>> {
fn extval(&mut self, size: usize) -> Vec<ExternalValue<F>>;
}

/// This CS is made specifically for ProtoGalaxy.
/// We will probably make interface for this part
#[derive(Debug, Clone)]
pub struct ConstraintSystem<'c, F: PrimeField, G: Gate<'c, F>> {
spec: WitnessSpec,
constraint_groups: [ConstraintGroup<'c, F, G>; 3],
pub struct ProtoGalaxyConstraintSystem<'c, F: PrimeField, G: Gate<'c, F>> {
pub spec: WitnessSpec,
pub max_degree: usize,
linear_constraints: ConstraintGroup<'c, F, G>,
non_linear_constraints: BTreeMap<usize, ConstraintGroup<'c, F, G>>,
}

impl<'c, F: PrimeField, G: Gate<'c, F>> ConstraintSystem<'c, F, G> {
pub fn new(num_rounds: usize, max_degree: usize) -> Self {
let constraint_groups = [
ConstraintGroup::new(CommitKind::Trivial, 0), // FIXME: correct max_degree
ConstraintGroup::new(CommitKind::Group, max_degree),
ConstraintGroup::new(CommitKind::Zero, 1),
];

impl<'c, F: PrimeField, G: Gate<'c, F>> ProtoGalaxyConstraintSystem<'c, F, G> {
pub fn new(num_rounds: usize) -> Self {
Self {
spec: WitnessSpec{ round_specs: vec![RoundWitnessSpec::default(); num_rounds], num_exts: 0, num_ints: 0 },
constraint_groups,
}
}

/// A (short-lived) cursor to the constraint group of a given kind
fn constraint_group(&mut self, kind: CommitKind) -> &mut ConstraintGroup<'c, F, G> {
match kind {
CommitKind::Trivial => &mut self.constraint_groups[0],
CommitKind::Group => &mut self.constraint_groups[1],
CommitKind::Zero => &mut self.constraint_groups[2],
max_degree: 0,
linear_constraints: ConstraintGroup::new(),
non_linear_constraints: BTreeMap::new(),
}
}

// would love to add this to the trait, but crab god said not yet
// https://github.com/rust-lang/rust/issues/91611
pub fn iter_constraints(&self) -> impl Iterator<Item = &Constraint<'c, F, G>> {
self.constraint_groups.iter().flat_map(|cg| cg.entries.iter())
self.iter_linear_constraints().chain(self.iter_non_linear_constraints())
}

pub fn iter_linear_constraints(&self) -> impl Iterator<Item = &Constraint<'c, F, G>> {
self.linear_constraints.entries.iter()
}

pub fn iter_non_linear_constraints(&self) -> impl Iterator<Item = &Constraint<'c, F, G>> {
self.non_linear_constraints.iter().flat_map(|(_, cg)| cg.entries.iter())
}
}

impl<'c, F: PrimeField, G: Gate<'c, F>> CS<'c, F, G> for ConstraintSystem<'c, F, G> {
impl<'c, F: PrimeField, G: Gate<'c, F>> CS<'c, F, G> for ProtoGalaxyConstraintSystem<'c, F, G> {
fn num_rounds(&self) -> usize {
self.spec.round_specs.len()
}
@@ -168,31 +165,40 @@ impl<'c, F: PrimeField, G: Gate<'c, F>> CS<'c, F, G> for ConstraintSystem<'c, F,
}

fn constr_spec(&self) -> ConstrSpec {
let num_lin_constraints = self.constraint_groups[2].num_rhs;
let num_nonlinear_constraints = self.constraint_groups[1].num_rhs;
let max_degree = self.constraint_groups[1].max_degree;
let num_lin_constraints = self.linear_constraints.num_rhs;
let num_nonlinear_constraints = self.non_linear_constraints.iter().map(|(_, cg)| cg.num_rhs).sum();
let max_degree = self.max_degree;
ConstrSpec { num_lin_constraints, num_nonlinear_constraints, max_degree }
}

fn alloc_in_round(&mut self, round: usize, visibility: Visibility, size: usize) -> Vec<Variable> {
let prev = match visibility {
Visibility::Public => {
let prev = self.spec.round_specs[round].0;
self.spec.round_specs[round].0 += size;
let prev = self.spec.round_specs[round].pubs;
self.spec.round_specs[round].pubs += size;
prev
},
Visibility::Private => {
let prev = self.spec.round_specs[round].1;
self.spec.round_specs[round].1 += size;
let prev = self.spec.round_specs[round].privs;
self.spec.round_specs[round].privs += size;
prev
},
};

(prev..prev+size).into_iter().map(|index| Variable { visibility, round, index }).collect()
}

fn constrain(&mut self, kind: CommitKind, inputs: &[Variable], gate: G) {
self.constraint_group(kind).constrain(inputs, gate);
fn constrain(&mut self, _: CommitKind, inputs: &[Variable], gate: G) {
self.max_degree = self.max_degree.max(gate.d());
match gate.d().cmp(&1) {
std::cmp::Ordering::Less => panic!("Constraint of degree 0"),
std::cmp::Ordering::Equal => {
self.linear_constraints.constrain(inputs, gate)
},
std::cmp::Ordering::Greater => {
self.non_linear_constraints.entry(gate.d()).or_insert(ConstraintGroup::new()).constrain(inputs, gate)
},
}
}

fn extval(&mut self, size: usize) -> Vec<ExternalValue<F>> {
10 changes: 5 additions & 5 deletions src/folding/shape.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
use ff::PrimeField;
use halo2::halo2curves::CurveAffine;
use itertools::Itertools;
use crate::{utils::arith_helper::{log2_ceil, ev}, constraint_system::{WitnessSpec, ConstraintSystem, CS, ConstrSpec}, gate::Gate, witness::Module};
use crate::{utils::arith_helper::{log2_ceil, ev}, constraint_system::{WitnessSpec, ProtoGalaxyConstraintSystem, CS, ConstrSpec}, gate::Gate, witness::Module};

/// Encode value as field elements.
pub trait FEncoding <F: PrimeField> {
@@ -19,14 +19,14 @@ pub struct Shape {
}

impl Shape {
pub fn new<'c,F:PrimeField,G:Gate<'c,F>>(c: &ConstraintSystem<'c, F, G>) -> Self {
pub fn new<'c,F:PrimeField,G:Gate<'c,F>>(c: &ProtoGalaxyConstraintSystem<'c, F, G>) -> Self {
let wspec = c.witness_spec().clone();
let cspec = c.constr_spec().clone();
Self{wspec, cspec}
}
}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ProtostarLhs<F: PrimeField, C: CurveAffine<ScalarExt=F>> {
pub round_commitments: Vec<C>,
pub pubs: Vec<Vec<F>>,
@@ -37,7 +37,7 @@ impl<F: PrimeField, C: CurveAffine<ScalarExt = F>> ProtostarLhs<F, C> {
pub fn validate_shape(&self, shape: &Shape) {
shape.wspec.round_specs.iter().zip_eq(self.pubs.iter())
.map(|(rspec,rpubs)|{
assert_eq!(rspec.0,rpubs.len())
assert_eq!(rspec.pubs, rpubs.len())
}).count();

assert_eq!(self.pubs.len(), self.round_commitments.len());
@@ -115,7 +115,7 @@ impl<F: PrimeField, C: CurveAffine<ScalarExt = F>> Fold<F,C> {
lhs_acc.add_assign(diff);
let lhs = lhs_acc;
let nt = F::ONE-t;
let error = nt*error_acc + t*error_inc + t*nt*ev(&cross_terms, t);
let error = nt*error_acc + t*error_inc - t*nt*ev(&cross_terms, t);
ProtostarInstance { lhs, error }
}
}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -11,4 +11,5 @@ pub mod utils;
pub mod folding;
pub mod test;
pub mod gatelib;
pub mod external_interface;
pub mod external_interface;
pub mod prover;
Loading