Infrastructure for public input namespacing.
This commit is contained in:
parent
b7f2f9e409
commit
af91dcda33
72
src/lib.rs
72
src/lib.rs
|
@ -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>(
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -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![],
|
||||
|
@ -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()),
|
||||
]);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue