Skip to content

Commit

Permalink
Support for arithmetic circuits
Browse files Browse the repository at this point in the history
  • Loading branch information
naure committed Jun 16, 2020
1 parent 0315914 commit 4ab9b60
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 4 deletions.
11 changes: 11 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# Version 1.2.0, 2020-06, Arithmetic circuits

Interface definition:
- Added constraint_type to support for both R1CS and arithmetic circuits.
- *(breaking)* Position of the field `ConstraintSystem.info` (unused afaik.).

Rust:
- *(breaking)* New field `ConstraintSystemOwned.constraint_type`
- A function to validate that a constraint system is indeed an arithmetic circuit (`validate_constraint_type`).


# Version 1.1.0, 2020-06, Simplifications

Interface definition:
Expand Down
3 changes: 2 additions & 1 deletion examples/example.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@
]
}
}
]
],
"constraint_type": "R1CS"
}
],
"witnesses": [
Expand Down
3 changes: 2 additions & 1 deletion rust/src/examples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::io;
use std::mem::size_of;
use owned::circuit::CircuitOwned;
use owned::variables::VariablesOwned;
use zkinterface_generated::zkinterface::{BilinearConstraint, BilinearConstraintArgs, Message, ConstraintSystem, ConstraintSystemArgs, Root, RootArgs, Variables, VariablesArgs, Witness, WitnessArgs};
use zkinterface_generated::zkinterface::{BilinearConstraint, BilinearConstraintArgs, Message, ConstraintSystem, ConstraintSystemArgs, Root, RootArgs, Variables, VariablesArgs, Witness, WitnessArgs, ConstraintType};


pub fn example_circuit() -> CircuitOwned {
Expand Down Expand Up @@ -58,6 +58,7 @@ pub fn write_example_constraints<W: io::Write>(mut writer: W) -> io::Result<()>
let constraints_built = builder.create_vector(&constraints_built);
let r1cs = ConstraintSystem::create(&mut builder, &ConstraintSystemArgs {
constraints: Some(constraints_built),
constraint_type: ConstraintType::R1CS,
info: None,
});

Expand Down
32 changes: 31 additions & 1 deletion rust/src/owned/constraints.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use owned::variables::VariablesOwned;
use serde::{Deserialize, Serialize};
use zkinterface_generated::zkinterface::ConstraintSystem;
use zkinterface_generated::zkinterface::{ConstraintSystem, ConstraintType};

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct ConstraintSystemOwned {
pub constraints: Vec<BilinearConstraintOwned>,

pub constraint_type: ConstraintTypeOwned,
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
Expand All @@ -19,6 +21,7 @@ impl<'a> From<ConstraintSystem<'a>> for ConstraintSystemOwned {
fn from(constraints_ref: ConstraintSystem) -> ConstraintSystemOwned {
let mut owned = ConstraintSystemOwned {
constraints: vec![],
constraint_type: constraints_ref.constraint_type().into(),
};

let cons_ref = constraints_ref.constraints().unwrap();
Expand All @@ -34,3 +37,30 @@ impl<'a> From<ConstraintSystem<'a>> for ConstraintSystemOwned {
owned
}
}


#[allow(non_camel_case_types)]
#[repr(i8)]
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum ConstraintTypeOwned {
R1CS = 0,
arithmetic = 1,
}

impl From<ConstraintType> for ConstraintTypeOwned {
fn from(ct: ConstraintType) -> Self {
match ct {
ConstraintType::R1CS => ConstraintTypeOwned::R1CS,
ConstraintType::arithmetic => ConstraintTypeOwned::arithmetic,
}
}
}

impl Into<ConstraintType> for ConstraintTypeOwned {
fn into(self) -> ConstraintType {
match self {
ConstraintTypeOwned::R1CS => ConstraintType::R1CS,
ConstraintTypeOwned::arithmetic => ConstraintType::arithmetic,
}
}
}
31 changes: 31 additions & 0 deletions rust/src/reading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::path::Path;
use zkinterface_generated::zkinterface::{
BilinearConstraint,
Circuit,
ConstraintType,
get_size_prefixed_root_as_root,
Root,
Variables,
Expand Down Expand Up @@ -299,6 +300,36 @@ impl Messages {
constraints: None,
}
}

pub fn validate_constraint_type(&self) -> Result<(), String> {
for message in self.into_iter() {
match message.message_as_constraint_system() {
None => continue,
Some(cs) => {
if cs.constraint_type() == ConstraintType::arithmetic {
let constraints = cs.constraints().unwrap();
for i in 0..constraints.len() {
let constraint = constraints.get(i);
let n_a = constraint.linear_combination_a().unwrap().variable_ids().unwrap().len();
let n_b = constraint.linear_combination_b().unwrap().variable_ids().unwrap().len();
let n_c = constraint.linear_combination_c().unwrap().variable_ids().unwrap().len();

let is_pure_multiplication =
n_a == 1 && n_b == 1 && n_c == 1;

let is_pure_linear =
n_a == 0 && n_b == 0;

if !(is_pure_multiplication || is_pure_linear) {
return Err("The circuit should be fan-in 2 but constraints are not in the correct format.".to_string());
}
}
}
}
};
}
Ok(())
}
}

pub type Term<'a> = Variable<'a>;
Expand Down
77 changes: 76 additions & 1 deletion rust/src/zkinterface_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,66 @@ pub fn enum_name_message(e: Message) -> &'static str {
}

pub struct MessageUnionTableOffset {}
#[allow(non_camel_case_types)]
#[repr(i8)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum ConstraintType {
R1CS = 0,
arithmetic = 1,

}

pub const ENUM_MIN_CONSTRAINT_TYPE: i8 = 0;
pub const ENUM_MAX_CONSTRAINT_TYPE: i8 = 1;

impl<'a> flatbuffers::Follow<'a> for ConstraintType {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
flatbuffers::read_scalar_at::<Self>(buf, loc)
}
}

impl flatbuffers::EndianScalar for ConstraintType {
#[inline]
fn to_little_endian(self) -> Self {
let n = i8::to_le(self as i8);
let p = &n as *const i8 as *const ConstraintType;
unsafe { *p }
}
#[inline]
fn from_little_endian(self) -> Self {
let n = i8::from_le(self as i8);
let p = &n as *const i8 as *const ConstraintType;
unsafe { *p }
}
}

impl flatbuffers::Push for ConstraintType {
type Output = ConstraintType;
#[inline]
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
flatbuffers::emplace_scalar::<ConstraintType>(dst, *self);
}
}

#[allow(non_camel_case_types)]
pub const ENUM_VALUES_CONSTRAINT_TYPE:[ConstraintType; 2] = [
ConstraintType::R1CS,
ConstraintType::arithmetic
];

#[allow(non_camel_case_types)]
pub const ENUM_NAMES_CONSTRAINT_TYPE:[&'static str; 2] = [
"R1CS",
"arithmetic"
];

pub fn enum_name_constraint_type(e: ConstraintType) -> &'static str {
let index = e as i8;
ENUM_NAMES_CONSTRAINT_TYPE[index as usize]
}

pub enum CircuitOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]

Expand Down Expand Up @@ -253,16 +313,25 @@ impl<'a> ConstraintSystem<'a> {
let mut builder = ConstraintSystemBuilder::new(_fbb);
if let Some(x) = args.info { builder.add_info(x); }
if let Some(x) = args.constraints { builder.add_constraints(x); }
builder.add_constraint_type(args.constraint_type);
builder.finish()
}

pub const VT_CONSTRAINTS: flatbuffers::VOffsetT = 4;
pub const VT_INFO: flatbuffers::VOffsetT = 6;
pub const VT_CONSTRAINT_TYPE: flatbuffers::VOffsetT = 6;
pub const VT_INFO: flatbuffers::VOffsetT = 8;

#[inline]
pub fn constraints(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<BilinearConstraint<'a>>>> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<BilinearConstraint<'a>>>>>(ConstraintSystem::VT_CONSTRAINTS, None)
}
/// Whether this is an R1CS or fan-in-2 arithmetic circuit.
/// A special case is a boolean circuit with XOR and AND gates,
/// then constraint_type == arithmetic and circuit.field_maximum == 1.
#[inline]
pub fn constraint_type(&self) -> ConstraintType {
self._tab.get::<ConstraintType>(ConstraintSystem::VT_CONSTRAINT_TYPE, Some(ConstraintType::R1CS)).unwrap()
}
/// Optional: Any complementary info that may be useful.
///
/// Example: human-readable descriptions.
Expand All @@ -275,13 +344,15 @@ impl<'a> ConstraintSystem<'a> {

pub struct ConstraintSystemArgs<'a> {
pub constraints: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a , flatbuffers::ForwardsUOffset<BilinearConstraint<'a >>>>>,
pub constraint_type: ConstraintType,
pub info: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a , flatbuffers::ForwardsUOffset<KeyValue<'a >>>>>,
}
impl<'a> Default for ConstraintSystemArgs<'a> {
#[inline]
fn default() -> Self {
ConstraintSystemArgs {
constraints: None,
constraint_type: ConstraintType::R1CS,
info: None,
}
}
Expand All @@ -296,6 +367,10 @@ impl<'a: 'b, 'b> ConstraintSystemBuilder<'a, 'b> {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(ConstraintSystem::VT_CONSTRAINTS, constraints);
}
#[inline]
pub fn add_constraint_type(&mut self, constraint_type: ConstraintType) {
self.fbb_.push_slot::<ConstraintType>(ConstraintSystem::VT_CONSTRAINT_TYPE, constraint_type, ConstraintType::R1CS);
}
#[inline]
pub fn add_info(&mut self, info: flatbuffers::WIPOffset<flatbuffers::Vector<'b , flatbuffers::ForwardsUOffset<KeyValue<'b >>>>) {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(ConstraintSystem::VT_INFO, info);
}
Expand Down
8 changes: 8 additions & 0 deletions zkinterface.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,20 @@ table Circuit {
configuration :[KeyValue];
}

// A circuit can be R1CS or arithmetic (fan-in 2 multiplications).
enum ConstraintType : byte { R1CS = 0, arithmetic = 1 }

/// ConstraintSystem represents constraints to be added to the constraint system.
///
/// Multiple such messages are equivalent to the concatenation of `constraints` arrays.
table ConstraintSystem {
constraints :[BilinearConstraint];

/// Whether this is an R1CS or fan-in-2 arithmetic circuit.
/// A special case is a boolean circuit with XOR and AND gates,
/// then constraint_type == arithmetic and circuit.field_maximum == 1.
constraint_type :ConstraintType;

/// Optional: Any complementary info that may be useful.
///
/// Example: human-readable descriptions.
Expand Down

0 comments on commit 4ab9b60

Please sign in to comment.