Skip to content

Commit

Permalink
Infrastructure for public input namespacing.
Browse files Browse the repository at this point in the history
  • Loading branch information
ebfull committed Nov 21, 2017
1 parent b7f2f9e commit af91dcd
Showing 1 changed file with 68 additions and 4 deletions.
72 changes: 68 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,12 @@ pub trait ConstraintSystem<E: Engine>: Sized {
}
}

pub trait PublicConstraintSystem<E: Engine>: ConstraintSystem<E> {
pub trait PublicConstraintSystem<E: Engine>: ConstraintSystem<E>
{
/// Represents the type of the "root" of this constraint system
/// so that nested namespaces can minimize indirection.
type PublicRoot: PublicConstraintSystem<E>;

/// Allocate a public variable in the constraint system. The provided function is used to
/// determine the assignment of the variable.
fn alloc_input<F, A, AR>(
Expand All @@ -151,6 +156,22 @@ pub trait PublicConstraintSystem<E: Engine>: ConstraintSystem<E> {
f: F
) -> Result<Self::Variable, SynthesisError>
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>;

/// Gets the "root" constraint system, bypassing the namespacing.
/// Not intended for downstream use; use `namespace` instead.
fn get_public_root(&mut self) -> &mut Self::PublicRoot;

/// Begin a namespace for this constraint system.
fn public_namespace<'a, NR, N>(
&'a mut self,
name_fn: N
) -> Namespace<'a, E, Self::PublicRoot>
where NR: Into<String>, N: FnOnce() -> NR
{
self.get_root().push_namespace(name_fn);

Namespace(self.get_public_root(), PhantomData)
}
}

use std::marker::PhantomData;
Expand All @@ -160,6 +181,8 @@ use std::marker::PhantomData;
pub struct Namespace<'a, E: Engine, CS: ConstraintSystem<E> + 'a>(&'a mut CS, PhantomData<E>);

impl<'cs, E: Engine, CS: PublicConstraintSystem<E>> PublicConstraintSystem<E> for Namespace<'cs, E, CS> {
type PublicRoot = CS::PublicRoot;

fn alloc_input<F, A, AR>(
&mut self,
annotation: A,
Expand All @@ -169,6 +192,11 @@ impl<'cs, E: Engine, CS: PublicConstraintSystem<E>> PublicConstraintSystem<E> fo
{
self.0.alloc_input(annotation, f)
}

fn get_public_root(&mut self) -> &mut Self::PublicRoot
{
self.0.get_public_root()
}
}

impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<'cs, E, CS> {
Expand Down Expand Up @@ -201,15 +229,19 @@ impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<
self.0.enforce(annotation, a, b, c)
}

fn push_namespace<NR, N>(&mut self, name_fn: N)
// Downstream users who use `namespace` will never interact with these
// functions and they will never be invoked because the namespace is
// never a root constraint system.

fn push_namespace<NR, N>(&mut self, _: N)
where NR: Into<String>, N: FnOnce() -> NR
{
self.0.push_namespace(name_fn)
panic!("only the root's push_namespace should be called");
}

fn pop_namespace(&mut self)
{
self.0.pop_namespace()
panic!("only the root's pop_namespace should be called");
}

fn get_root(&mut self) -> &mut Self::Root
Expand All @@ -227,6 +259,8 @@ impl<'a, E: Engine, CS: ConstraintSystem<E>> Drop for Namespace<'a, E, CS> {
/// Convenience implementation of PublicConstraintSystem<E> for mutable references to
/// public constraint systems.
impl<'cs, E: Engine, CS: PublicConstraintSystem<E>> PublicConstraintSystem<E> for &'cs mut CS {
type PublicRoot = CS::PublicRoot;

fn alloc_input<F, A, AR>(
&mut self,
annotation: A,
Expand All @@ -236,6 +270,11 @@ impl<'cs, E: Engine, CS: PublicConstraintSystem<E>> PublicConstraintSystem<E> fo
{
(**self).alloc_input(annotation, f)
}

fn get_public_root(&mut self) -> &mut Self::PublicRoot
{
(**self).get_public_root()
}
}

/// Convenience implementation of ConstraintSystem<E> for mutable references to
Expand Down Expand Up @@ -322,6 +361,8 @@ fn test_cs() {
}

impl<E: Engine> PublicConstraintSystem<E> for MySillyConstraintSystem<E> {
type PublicRoot = Self;

fn alloc_input<F, A, AR>(
&mut self,
annotation: A,
Expand All @@ -335,6 +376,11 @@ fn test_cs() {

Ok(Var::Input(index))
}

fn get_public_root(&mut self) -> &mut Self::PublicRoot
{
self
}
}

impl<E: Engine> ConstraintSystem<E> for MySillyConstraintSystem<E> {
Expand Down Expand Up @@ -390,6 +436,15 @@ fn test_cs() {
}
}

fn do_stuff_with_pcs<E: Engine, CS: PublicConstraintSystem<E>>(mut cs: CS, one_more: bool)
{
cs.alloc_input(|| "something", || Ok(E::Fr::zero())).unwrap();

if one_more {
do_stuff_with_pcs(cs.public_namespace(|| "cool namespace"), false);
}
}

let mut cs = MySillyConstraintSystem::<Bls12> {
inputs: vec![(Fr::one(), "ONE".into())],
aux: vec![],
Expand Down Expand Up @@ -438,4 +493,13 @@ fn test_cs() {
assert!((cs.constraints[0].1).0 == vec![(Var::Input(0), Fr::one())]);
assert!((cs.constraints[0].2).0 == vec![(Var::Input(1), Fr::one())]);
assert!(cs.constraints[0].3 == "woohoo/hehe/great constraint");

do_stuff_with_pcs(cs.namespace(|| "namey"), true);

assert_eq!(cs.inputs, vec![
(Fr::one(), "ONE".into()),
(Fr::zero(), "woohoo/hehe/works lol".into()),
(Fr::zero(), "namey/something".into()),
(Fr::zero(), "namey/cool namespace/something".into()),
]);
}

0 comments on commit af91dcd

Please sign in to comment.