Change API to support constraint/variable annotation.

This commit is contained in:
Sean Bowe 2017-11-11 04:50:30 -07:00
parent 3bb6596507
commit bc19c76326
4 changed files with 94 additions and 23 deletions

View File

@ -69,7 +69,13 @@ pub fn generate_parameters<E, C>(
} }
impl<E: Engine> PublicConstraintSystem<E> for KeypairAssembly<E> { impl<E: Engine> PublicConstraintSystem<E> for KeypairAssembly<E> {
fn alloc_input<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, f: F) -> Result<Variable, Error> { fn alloc_input<NR, N, F>(
&mut self,
_: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>
{
// In this context, we don't have an assignment. // In this context, we don't have an assignment.
let _ = f(); let _ = f();
@ -85,7 +91,13 @@ pub fn generate_parameters<E, C>(
} }
impl<E: Engine> ConstraintSystem<E> for KeypairAssembly<E> { impl<E: Engine> ConstraintSystem<E> for KeypairAssembly<E> {
fn alloc<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, f: F) -> Result<Variable, Error> { fn alloc<NR, N, F>(
&mut self,
_: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>
{
// In this context, we don't have an assignment. // In this context, we don't have an assignment.
let _ = f(); let _ = f();
@ -99,8 +111,9 @@ pub fn generate_parameters<E, C>(
Ok(Variable(Index::Aux(index))) Ok(Variable(Index::Aux(index)))
} }
fn enforce( fn enforce<NR: Into<String>, N: FnOnce() -> NR>(
&mut self, &mut self,
_: N,
a: LinearCombination<E>, a: LinearCombination<E>,
b: LinearCombination<E>, b: LinearCombination<E>,
c: LinearCombination<E> c: LinearCombination<E>
@ -142,14 +155,15 @@ pub fn generate_parameters<E, C>(
}; };
// Allocate the "one" input variable // Allocate the "one" input variable
assembly.alloc_input(|| Ok(E::Fr::one()))?; assembly.alloc_input(|| "", || Ok(E::Fr::one()))?;
// Synthesize the circuit. // Synthesize the circuit.
circuit.synthesize(&mut assembly)?.synthesize(&mut assembly)?; circuit.synthesize(&mut assembly)?.synthesize(&mut assembly)?;
// Input consistency constraints: x * 0 = 0 // Input consistency constraints: x * 0 = 0
for i in 0..assembly.num_inputs { for i in 0..assembly.num_inputs {
assembly.enforce(LinearCombination::zero() + Variable(Index::Input(i)), assembly.enforce(|| "",
LinearCombination::zero() + Variable(Index::Input(i)),
LinearCombination::zero(), LinearCombination::zero(),
LinearCombination::zero()); LinearCombination::zero());
} }

View File

@ -55,8 +55,14 @@ pub fn create_proof<E, C, P: ParameterSource<E>>(
} }
impl<E: Engine> PublicConstraintSystem<E> for ProvingAssignment<E> { impl<E: Engine> PublicConstraintSystem<E> for ProvingAssignment<E> {
fn alloc_input<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, value: F) -> Result<Variable, Error> { fn alloc_input<NR, N, F>(
self.input_assignment.push(value()?); &mut self,
_: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>
{
self.input_assignment.push(f()?);
self.b_input_density.add_element(); self.b_input_density.add_element();
Ok(Variable(Index::Input(self.input_assignment.len() - 1))) Ok(Variable(Index::Input(self.input_assignment.len() - 1)))
@ -64,16 +70,23 @@ pub fn create_proof<E, C, P: ParameterSource<E>>(
} }
impl<E: Engine> ConstraintSystem<E> for ProvingAssignment<E> { impl<E: Engine> ConstraintSystem<E> for ProvingAssignment<E> {
fn alloc<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, value: F) -> Result<Variable, Error> { fn alloc<NR, N, F>(
self.aux_assignment.push(value()?); &mut self,
_: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>
{
self.aux_assignment.push(f()?);
self.a_aux_density.add_element(); self.a_aux_density.add_element();
self.b_aux_density.add_element(); self.b_aux_density.add_element();
Ok(Variable(Index::Aux(self.aux_assignment.len() - 1))) Ok(Variable(Index::Aux(self.aux_assignment.len() - 1)))
} }
fn enforce( fn enforce<NR: Into<String>, N: FnOnce() -> NR>(
&mut self, &mut self,
_: N,
a: LinearCombination<E>, a: LinearCombination<E>,
b: LinearCombination<E>, b: LinearCombination<E>,
c: LinearCombination<E> c: LinearCombination<E>
@ -96,13 +109,14 @@ pub fn create_proof<E, C, P: ParameterSource<E>>(
aux_assignment: vec![] aux_assignment: vec![]
}; };
prover.alloc_input(|| Ok(E::Fr::one()))?; prover.alloc_input(|| "", || Ok(E::Fr::one()))?;
circuit.synthesize(&mut prover)?.synthesize(&mut prover)?; circuit.synthesize(&mut prover)?.synthesize(&mut prover)?;
// Input consistency constraints: x * 0 = 0 // Input consistency constraints: x * 0 = 0
for i in 0..prover.input_assignment.len() { for i in 0..prover.input_assignment.len() {
prover.enforce(LinearCombination::zero() + Variable(Index::Input(i)), prover.enforce(|| "",
LinearCombination::zero() + Variable(Index::Input(i)),
LinearCombination::zero(), LinearCombination::zero(),
LinearCombination::zero()); LinearCombination::zero());
} }

View File

@ -22,7 +22,13 @@ pub struct VerifierInput<'a, E: Engine> {
} }
impl<'a, E: Engine> ConstraintSystem<E> for VerifierInput<'a, E> { impl<'a, E: Engine> ConstraintSystem<E> for VerifierInput<'a, E> {
fn alloc<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, f: F) -> Result<Variable, Error> { fn alloc<NR, N, F>(
&mut self,
_: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>
{
// Run the function for calculating the allocation but ignore the output, // Run the function for calculating the allocation but ignore the output,
// since we don't care about the assignment of auxillary variables during // since we don't care about the assignment of auxillary variables during
// verification. // verification.
@ -34,8 +40,9 @@ impl<'a, E: Engine> ConstraintSystem<E> for VerifierInput<'a, E> {
Ok(Variable(Index::Aux(index))) Ok(Variable(Index::Aux(index)))
} }
fn enforce( fn enforce<NR: Into<String>, N: FnOnce() -> NR>(
&mut self, &mut self,
_: N,
_: LinearCombination<E>, _: LinearCombination<E>,
_: LinearCombination<E>, _: LinearCombination<E>,
_: LinearCombination<E> _: LinearCombination<E>
@ -51,12 +58,19 @@ impl<'a, E: Engine> ConstraintSystem<E> for VerifierInput<'a, E> {
struct InputAllocator<T>(T); struct InputAllocator<T>(T);
impl<'a, 'b, E: Engine> ConstraintSystem<E> for InputAllocator<&'a mut VerifierInput<'b, E>> { impl<'a, 'b, E: Engine> ConstraintSystem<E> for InputAllocator<&'a mut VerifierInput<'b, E>> {
fn alloc<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, value: F) -> Result<Variable, Error> { fn alloc<NR, N, F>(
self.0.alloc(value) &mut self,
name_fn: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>
{
self.0.alloc(name_fn, f)
} }
fn enforce( fn enforce<NR: Into<String>, N: FnOnce() -> NR>(
&mut self, &mut self,
_: N,
_: LinearCombination<E>, _: LinearCombination<E>,
_: LinearCombination<E>, _: LinearCombination<E>,
_: LinearCombination<E> _: LinearCombination<E>
@ -68,11 +82,17 @@ impl<'a, 'b, E: Engine> ConstraintSystem<E> for InputAllocator<&'a mut VerifierI
} }
impl<'a, 'b, E: Engine> PublicConstraintSystem<E> for InputAllocator<&'a mut VerifierInput<'b, E>> { impl<'a, 'b, E: Engine> PublicConstraintSystem<E> for InputAllocator<&'a mut VerifierInput<'b, E>> {
fn alloc_input<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, value: F) -> Result<Variable, Error> { fn alloc_input<NR, N, F>(
&mut self,
_: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>
{
if self.0.ic.len() == 0 { if self.0.ic.len() == 0 {
self.0.insufficient_inputs = true; self.0.insufficient_inputs = true;
} else { } else {
self.0.acc.add_assign(&self.0.ic[0].mul(value()?)); self.0.acc.add_assign(&self.0.ic[0].mul(f()?));
self.0.ic = &self.0.ic[1..]; self.0.ic = &self.0.ic[1..];
} }

View File

@ -25,7 +25,8 @@ pub enum Error {
AssignmentMissing, AssignmentMissing,
UnexpectedIdentity, UnexpectedIdentity,
UnconstrainedVariable(Variable), UnconstrainedVariable(Variable),
IoError(io::Error) IoError(io::Error),
NameConflict(&'static str, String)
} }
impl From<io::Error> for Error { impl From<io::Error> for Error {
@ -185,7 +186,12 @@ pub trait Input<E: Engine> {
pub trait PublicConstraintSystem<E: Engine>: ConstraintSystem<E> { pub trait PublicConstraintSystem<E: Engine>: ConstraintSystem<E> {
/// Allocate a public input that the verifier knows. The provided function is used to /// Allocate a public input that the verifier knows. The provided function is used to
/// determine the assignment of the variable. /// determine the assignment of the variable.
fn alloc_input<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, f: F) -> Result<Variable, Error>; fn alloc_input<NR, N, F>(
&mut self,
name_fn: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>;
} }
pub trait ConstraintSystem<E: Engine> { pub trait ConstraintSystem<E: Engine> {
@ -196,13 +202,30 @@ pub trait ConstraintSystem<E: Engine> {
/// Allocate a private variable in the constraint system. The provided function is used to /// Allocate a private variable in the constraint system. The provided function is used to
/// determine the assignment of the variable. /// determine the assignment of the variable.
fn alloc<F: FnOnce() -> Result<E::Fr, Error>>(&mut self, f: F) -> Result<Variable, Error>; fn alloc<NR, N, F>(
&mut self,
name_fn: N,
f: F
) -> Result<Variable, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce() -> Result<E::Fr, Error>;
/// Enforce that `A` * `B` = `C`. /// Enforce that `A` * `B` = `C`.
fn enforce( fn enforce<NR: Into<String>, N: FnOnce() -> NR>(
&mut self, &mut self,
name_fn: N,
a: LinearCombination<E>, a: LinearCombination<E>,
b: LinearCombination<E>, b: LinearCombination<E>,
c: LinearCombination<E> c: LinearCombination<E>
); );
/// Begin a namespace for the constraint system
fn namespace<NR, N, R, F>(
&mut self,
_: N,
space_fn: F
) -> Result<R, Error>
where NR: Into<String>, N: FnOnce() -> NR, F: FnOnce(&mut Self) -> Result<R, Error>
{
space_fn(self)
}
} }