public input booleans and integers

This commit is contained in:
collin 2020-06-10 16:14:55 -07:00
parent c6d3221289
commit 67b8a48fcf
15 changed files with 142 additions and 61 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
/target
/tmp/
**.idea/
outputs/
*.DS_Store

View File

@ -16,6 +16,7 @@ use snarkos_models::{
};
use sha2::{Digest, Sha256};
use snarkos_models::curves::PairingEngine;
use std::{fs, marker::PhantomData, path::PathBuf};
#[derive(Clone)]
@ -58,7 +59,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
pub fn set_inputs(&mut self, program_inputs: Vec<Option<InputValue>>) {
self.program_inputs.set_private_inputs(program_inputs);
self.program_inputs.set_inputs(program_inputs);
}
pub fn get_public_inputs<E: PairingEngine>(&self) -> Result<Vec<E::Fr>, CompilerError> {
Ok(self.program_inputs.get_public_inputs::<E>()?)
}
pub fn checksum(&self) -> Result<String, CompilerError> {
@ -78,7 +83,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
self,
cs: &mut CS,
) -> Result<ConstrainedValue<F, G>, CompilerError> {
generate_constraints(cs, self.program, self.program_inputs.get_private_inputs())
generate_constraints(cs, self.program, self.program_inputs.get_inputs())
}
pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem<F>) -> Result<(), CompilerError> {
@ -99,7 +104,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
let package_name = self.package_name.clone();
self.program = Program::from(syntax_tree, package_name);
self.program_inputs.set_private_inputs_size(self.program.num_parameters);
self.program_inputs.set_inputs_size(self.program.num_parameters);
log::debug!("Program parsing complete\n{:#?}", self.program);
@ -116,7 +121,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
// println!("{:?}", syntax_tree);
// Check number of private parameters here
self.program_inputs = Inputs::from_inputs_file(syntax_tree)?;
Ok(())
@ -125,8 +129,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {
fn generate_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
let _result =
generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_private_inputs()).unwrap();
let _result = generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_inputs()).unwrap();
// Write results to file or something

View File

@ -5,6 +5,7 @@ use leo_compiler::{
};
use leo_types::{InputValue, Integer, IntegerError};
use leo_inputs::types::{IntegerType, U32Type};
use snarkos_models::gadgets::utilities::uint::UInt32;
// [1, 1, 1]
@ -52,6 +53,10 @@ fn fail_synthesis(program: EdwardsTestCompiler) {
}
}
pub(crate) fn input_value_u32_one() -> InputValue {
InputValue::Integer(IntegerType::U32Type(U32Type {}), 1)
}
// Expressions
#[test]
@ -101,7 +106,7 @@ fn test_input_array() {
let bytes = include_bytes!("input.leo");
let mut program = parse_program(bytes).unwrap();
program.set_inputs(vec![Some(InputValue::Array(vec![InputValue::Integer(1u128); 3]))]);
program.set_inputs(vec![Some(InputValue::Array(vec![input_value_u32_one(); 3]))]);
output_ones(program)
}
@ -111,7 +116,7 @@ fn test_input_array_fail() {
let bytes = include_bytes!("input.leo");
let mut program = parse_program(bytes).unwrap();
program.set_inputs(vec![Some(InputValue::Integer(1u128))]);
program.set_inputs(vec![Some(input_value_u32_one())]);
fail_array(program);
}

View File

@ -5,6 +5,7 @@ use leo_compiler::{
};
use leo_types::InputValue;
use crate::array::input_value_u32_one;
use snarkos_models::gadgets::utilities::boolean::Boolean;
pub fn output_expected_boolean(program: EdwardsTestCompiler, boolean: bool) {
@ -76,7 +77,7 @@ fn test_input_bool_field() {
let bytes = include_bytes!("input_bool.leo");
let mut program = parse_program(bytes).unwrap();
program.set_inputs(vec![Some(InputValue::Integer(1u128))]);
program.set_inputs(vec![Some(input_value_u32_one())]);
fail_boolean(program);
}

View File

@ -5,6 +5,7 @@ use leo_compiler::{
};
use leo_types::{InputValue, Integer};
use crate::array::input_value_u32_one;
use snarkos_curves::edwards_bls12::Fq;
use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::uint::UInt32};
@ -84,7 +85,7 @@ fn test_function_input() {
let bytes = include_bytes!("function_input.leo");
let mut program = parse_program(bytes).unwrap();
program.set_inputs(vec![Some(InputValue::Integer(1))]);
program.set_inputs(vec![Some(input_value_u32_one())]);
mut_fail(program);
}
@ -93,6 +94,6 @@ fn test_function_input_mut() {
let bytes = include_bytes!("function_input_mut.leo");
let mut program = parse_program(bytes).unwrap();
program.set_inputs(vec![Some(InputValue::Integer(1))]);
program.set_inputs(vec![Some(input_value_u32_one())]);
mut_success(program);
}

View File

@ -2,7 +2,7 @@ use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_integer))]
pub enum IntegerType {
U8Type(U8Type),
@ -12,22 +12,22 @@ pub enum IntegerType {
U128Type(U128Type),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_u8))]
pub struct U8Type {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_u16))]
pub struct U16Type {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_u32))]
pub struct U32Type {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_u64))]
pub struct U64Type {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::type_u128))]
pub struct U128Type {}

View File

@ -10,7 +10,9 @@ use snarkos_algorithms::snark::{create_random_proof, Proof};
use snarkos_curves::bls12_377::Bls12_377;
use clap::ArgMatches;
use leo_compiler::{compiler::Compiler, edwards_bls12::EdwardsGroupType};
use rand::thread_rng;
use snarkos_curves::edwards_bls12::Fq;
use std::{convert::TryFrom, env::current_dir, time::Instant};
#[derive(Debug)]
@ -18,7 +20,7 @@ pub struct ProveCommand;
impl CLI for ProveCommand {
type Options = ();
type Output = Proof<Bls12_377>;
type Output = (Compiler<Fq, EdwardsGroupType>, Proof<Bls12_377>);
const ABOUT: AboutType = "Run the program and produce a proof";
const ARGUMENTS: &'static [ArgumentType] = &[];
@ -42,16 +44,12 @@ impl CLI for ProveCommand {
// Fetch private inputs here
program.parse_inputs(&path)?;
// let _res = LeoInputsParser::get_private(&path).unwrap();
// let inputs_path = path.clone().push("/inputs")
// LeoInputsParser::load_file()
// program.set_inputs();
// Start the timer
let start = Instant::now();
let rng = &mut thread_rng();
let program_proof = create_random_proof(program, &parameters, rng).unwrap();
let program_proof = create_random_proof(program.clone(), &parameters, rng).unwrap();
log::info!("Prover completed in {:?} milliseconds", start.elapsed().as_millis());
@ -62,6 +60,6 @@ impl CLI for ProveCommand {
log::info!("Completed program proving");
Ok(program_proof)
Ok((program, program_proof))
}
}

View File

@ -6,6 +6,7 @@ use crate::{
};
use snarkos_algorithms::snark::verify_proof;
use snarkos_curves::bls12_377::Bls12_377;
use clap::ArgMatches;
use std::time::{Duration, Instant};
@ -32,16 +33,16 @@ impl CLI for RunCommand {
#[cfg_attr(tarpaulin, skip)]
fn output(options: Self::Options) -> Result<(), CLIError> {
let (_program, _parameters, prepared_verifying_key) = SetupCommand::output(options)?;
let proof = ProveCommand::output(options)?;
let (program, proof) = ProveCommand::output(options)?;
let mut verifying = Duration::new(0, 0);
// fetch public inputs here
// let _inputs: Vec<_> = [1u32; 1].to_vec();
// fetch public inputs
let inputs: Vec<_> = program.get_public_inputs::<Bls12_377>().unwrap();
let start = Instant::now();
let is_success = verify_proof(&prepared_verifying_key, &proof, &[]).unwrap();
let is_success = verify_proof(&prepared_verifying_key, &proof, &inputs).unwrap();
verifying += start.elapsed();

View File

@ -1,2 +1,2 @@
[main]
a: private bool[2] = [true; 2];
a: public u128 = 120;

View File

@ -1,4 +1,4 @@
// The 'tmp' main function.
function main(a: bool[2]) -> bool {
return a[0]
function main(a: public u128) -> u128 {
return a
}

View File

@ -0,0 +1,34 @@
use leo_inputs::{types::IntegerType, InputParserError};
use snarkos_models::curves::{Field, PairingEngine};
pub struct InputFields<E: PairingEngine>(pub Vec<E::Fr>);
impl<E: PairingEngine> InputFields<E> {
pub(crate) fn from_boolean(boolean: &bool) -> Self {
if *boolean {
Self(vec![E::Fr::one()])
} else {
Self(vec![E::Fr::zero()])
}
}
pub(crate) fn from_integer(type_: &IntegerType, integer: &u128) -> Result<Self, InputParserError> {
let bits: usize = match type_ {
IntegerType::U8Type(_) => 8,
IntegerType::U16Type(_) => 16,
IntegerType::U32Type(_) => 32,
IntegerType::U64Type(_) => 64,
IntegerType::U128Type(_) => 128,
};
let mut fields = vec![];
for i in 0..bits {
let boolean = (integer.to_le() >> i) & 1 == 1;
let mut boolean_fields = InputFields::<E>::from_boolean(&boolean);
fields.append(&mut boolean_fields.0);
}
Ok(Self(fields))
}
}

View File

@ -1,14 +1,16 @@
use crate::InputFields;
use leo_inputs::{
errors::InputParserError,
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression},
types::{ArrayType, DataType, Type},
types::{ArrayType, DataType, IntegerType, Type},
values::{BooleanValue, FieldValue, GroupValue, NumberImplicitValue, NumberValue, Value},
};
use snarkos_models::curves::PairingEngine;
use std::fmt;
#[derive(Clone, PartialEq, Eq)]
pub enum InputValue {
Integer(u128),
Integer(IntegerType, u128),
Field(String),
Group(String),
Boolean(bool),
@ -21,9 +23,9 @@ impl<'ast> InputValue {
Ok(InputValue::Boolean(boolean))
}
fn from_number(number: NumberValue<'ast>) -> Result<Self, InputParserError> {
fn from_number(integer_type: IntegerType, number: NumberValue<'ast>) -> Result<Self, InputParserError> {
let integer = number.value.parse::<u128>()?;
Ok(InputValue::Integer(integer))
Ok(InputValue::Integer(integer_type, integer))
}
fn from_group(group: GroupValue<'ast>) -> Self {
@ -40,7 +42,7 @@ impl<'ast> InputValue {
"bool".to_string(),
"implicit number".to_string(),
)),
DataType::Integer(_) => InputValue::from_number(implicit.number),
DataType::Integer(integer_type) => InputValue::from_number(integer_type, implicit.number),
DataType::Group(_) => Ok(InputValue::Group(implicit.number.value)),
DataType::Field(_) => Ok(InputValue::Field(implicit.number.value)),
}
@ -49,7 +51,9 @@ impl<'ast> InputValue {
fn from_value(data_type: DataType, value: Value<'ast>) -> Result<Self, InputParserError> {
match (data_type, value) {
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
(DataType::Integer(_), Value::Integer(integer)) => InputValue::from_number(integer.number),
(DataType::Integer(integer_type), Value::Integer(integer)) => {
InputValue::from_number(integer_type, integer.number)
}
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)),
(DataType::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)),
(data_type, Value::Implicit(implicit)) => InputValue::from_implicit(data_type, implicit),
@ -69,8 +73,8 @@ impl<'ast> InputValue {
(Type::Array(array_type), Expression::ArrayInitializer(initializer)) => {
InputValue::from_array_initializer(array_type, initializer)
}
(Type::Circuit(_), Expression::CircuitInline(_)) => unimplemented!("circuit input values not implemented"),
(Type::Basic(_), Expression::Variable(_)) => unimplemented!("variable inputs not supported"),
(Type::Circuit(_), Expression::CircuitInline(_)) => unimplemented!("circuit input values not supported"),
(Type::Basic(_), Expression::Variable(_)) => unimplemented!("variable input values not supported"),
(type_, value) => Err(InputParserError::IncompatibleTypes(
type_.to_string(),
value.to_string(),
@ -146,15 +150,25 @@ impl<'ast> InputValue {
Ok(InputValue::Array(values))
}
pub(crate) fn to_input_fields<E: PairingEngine>(&self) -> Result<InputFields<E>, InputParserError> {
match self {
InputValue::Boolean(boolean) => Ok(InputFields::from_boolean(boolean)),
InputValue::Integer(type_, number) => InputFields::from_integer(type_, number),
InputValue::Group(_) => unimplemented!(),
InputValue::Field(_) => unimplemented!(),
InputValue::Array(_) => unimplemented!(),
}
}
}
impl fmt::Display for InputValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
InputValue::Integer(ref integer) => write!(f, "{}", integer),
InputValue::Field(ref field) => write!(f, "{}", field),
InputValue::Boolean(ref boolean) => write!(f, "{}", boolean),
InputValue::Integer(ref type_, ref number) => write!(f, "{}{:?}", number, type_),
InputValue::Group(ref group) => write!(f, "{}", group),
InputValue::Boolean(ref bool) => write!(f, "{}", bool),
InputValue::Field(ref field) => write!(f, "{}", field),
InputValue::Array(ref array) => {
write!(f, "[")?;
for (i, e) in array.iter().enumerate() {

View File

@ -1,48 +1,68 @@
use crate::InputValue;
use leo_inputs::{common::visibility::Visibility, files::File, InputParserError};
use snarkos_models::curves::PairingEngine;
#[derive(Clone)]
pub struct Inputs {
private: Vec<Option<InputValue>>,
//public: Vec<_>
program_inputs: Vec<Option<InputValue>>,
public: Vec<InputValue>,
}
impl Inputs {
pub fn new() -> Self {
Self { private: vec![] }
Self {
program_inputs: vec![],
public: vec![],
}
}
pub fn get_private_inputs(&self) -> Vec<Option<InputValue>> {
return self.private.clone();
pub fn get_inputs(&self) -> Vec<Option<InputValue>> {
self.program_inputs.clone()
}
pub fn set_private_inputs(&mut self, inputs: Vec<Option<InputValue>>) {
self.private = inputs;
pub fn set_inputs(&mut self, inputs: Vec<Option<InputValue>>) {
self.program_inputs = inputs;
}
pub fn set_private_inputs_size(&mut self, size: usize) {
self.private = vec![None; size];
pub fn set_inputs_size(&mut self, size: usize) {
self.program_inputs = vec![None; size];
}
pub fn from_inputs_file(file: File) -> Result<Self, InputParserError> {
let mut private = vec![];
let mut public = vec![];
for section in file.sections.into_iter() {
for assignment in section.assignments.into_iter() {
let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?;
if let Some(Visibility::Public(_)) = assignment.parameter.visibility {
// Collect public parameters here
} else {
// parameter is private by default
// Collect public inputs here
// evaluate expression
let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?;
// push value to vector
private.push(Some(value));
public.push(value.clone());
}
// push value to vector
private.push(Some(value));
}
}
Ok(Self { private })
Ok(Self {
program_inputs: private,
public,
})
}
pub fn get_public_inputs<E: PairingEngine>(&self) -> Result<Vec<E::Fr>, InputParserError> {
let mut input_vec = vec![];
for input in self.public.iter() {
// get fields
let mut input_fields = input.to_input_fields::<E>()?;
// push fields to input_vec
input_vec.append(&mut input_fields.0)
}
Ok(input_vec)
}
}

View File

@ -1,5 +1,8 @@
pub mod inputs;
pub use inputs::*;
pub mod input_fields;
pub use input_fields::*;
pub mod input_value;
pub use input_value::*;

View File

@ -87,7 +87,7 @@ impl Integer {
// Check that the input value is the correct type
let integer_option = match integer_value {
Some(input) => {
if let InputValue::Integer(integer) = input {
if let InputValue::Integer(_type_, integer) = input {
Some(integer)
} else {
return Err(IntegerError::InvalidInteger(input.to_string()));