From bdd71fc6dd90b4ebb764f035e980881644f935a8 Mon Sep 17 00:00:00 2001 From: aurel Date: Mon, 19 Oct 2020 22:21:31 +0200 Subject: [PATCH 1/2] fix-simul: unified validator and simulator interface, streaming only, supports stdin --- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- rust/src/cli.rs | 32 ++++++++++--------- rust/src/consumers/simulator.rs | 54 ++++++++++++++++++--------------- rust/src/consumers/validator.rs | 51 ++++++++----------------------- 5 files changed, 62 insertions(+), 79 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index d0fc4a1..54e3b1c 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -390,7 +390,7 @@ dependencies = [ [[package]] name = "zkinterface" -version = "1.3.1" +version = "1.3.2" dependencies = [ "colored 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "flatbuffers 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 25e6984..9b9ca15 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zkinterface" -version = "1.3.1" +version = "1.3.2" authors = ["Aurélien Nicolas "] license = "MIT" build = "build.rs" diff --git a/rust/src/cli.rs b/rust/src/cli.rs index 7fae4c2..63975c9 100644 --- a/rust/src/cli.rs +++ b/rust/src/cli.rs @@ -195,32 +195,36 @@ fn main_explain(reader: &Reader) -> Result<()> { fn main_validate(ws: &Workspace) -> Result<()> { // Validate semantics as verifier. let mut validator = Validator::new_as_verifier(); - validator.ingest_workspace(ws); - print_violations(&validator.get_violations()) + for msg in ws.iter_messages() { + validator.ingest_message(&msg); + } + print_violations(&validator.get_violations(), "COMPLIANT with the specification") } fn main_simulate(ws: &Workspace) -> Result<()> { // Validate semantics as prover. let mut validator = Validator::new_as_prover(); - validator.ingest_workspace(ws); - print_violations(&validator.get_violations())?; - // Check whether the statement is true. - let ok = Simulator::default().simulate_workspace(ws); - match ok { - Err(_) => eprintln!("The statement is NOT TRUE!"), - Ok(_) => eprintln!("The statement is TRUE!"), + let mut simulator = Simulator::default(); + + // Must validate and simulate in parallel to support stdin. + for msg in ws.iter_messages() { + validator.ingest_message(&msg); + simulator.ingest_message(&msg); } - ok + + let result_val = print_violations(&validator.get_violations(), "COMPLIANT with the specification"); + print_violations(&simulator.get_violations(), "TRUE")?; + result_val } -fn print_violations(errors: &[String]) -> Result<()> { +fn print_violations(errors: &[String], what_it_is_supposed_to_be: &str) -> Result<()> { if errors.len() > 0 { - eprintln!("The statement is NOT COMPLIANT with the specification!"); + eprintln!("The statement is NOT {}!", what_it_is_supposed_to_be); eprintln!("Violations:\n- {}\n", errors.join("\n- ")); - Err(format!("Found {} violations of the specification.", errors.len()).into()) + Err(format!("Found {} violations.", errors.len()).into()) } else { - eprintln!("The statement is COMPLIANT with the specification!"); + eprintln!("The statement is {}!", what_it_is_supposed_to_be); Ok(()) } } diff --git a/rust/src/consumers/simulator.rs b/rust/src/consumers/simulator.rs index 377aefc..fe60565 100644 --- a/rust/src/consumers/simulator.rs +++ b/rust/src/consumers/simulator.rs @@ -1,4 +1,4 @@ -use crate::{Result, CircuitHeader, Witness, ConstraintSystem, Messages, Variables, Workspace, Message}; +use crate::{Result, CircuitHeader, Witness, ConstraintSystem, Variables, Message}; use crate::structs::constraints::BilinearConstraint; use std::collections::HashMap; @@ -13,38 +13,38 @@ pub struct Simulator { values: HashMap, modulus: Field, - violations: Vec, + verified_at_least_one_constraint: bool, + found_error: Option, } impl Simulator { - pub fn simulate(&mut self, messages: &Messages) -> Result<()> { - for header in &messages.circuit_headers { - self.ingest_header(header)?; + pub fn get_violations(self) -> Vec { + let mut violations = vec![]; + if !self.verified_at_least_one_constraint { + violations.push("Did not receive any constraint to verify.".to_string()); } - for witness in &messages.witnesses { - self.ingest_witness(witness)?; + if let Some(err) = self.found_error { + violations.push(err); } - for cs in &messages.constraint_systems { - self.ingest_constraint_system(cs)?; + violations + } + + pub fn ingest_message(&mut self, msg: &Message) { + if self.found_error.is_some() { return; } + + match self.ingest_message_(msg) { + Err(err) => self.found_error = Some(err.to_string()), + Ok(()) => {} } - Ok(()) } - pub fn simulate_workspace(&mut self, ws: &Workspace) -> Result<()> { - for msg in ws.iter_messages() { - match msg { - Message::Header(header) => { - self.ingest_header(&header)?; - } - Message::ConstraintSystem(cs) => { - self.ingest_constraint_system(&cs)?; - } - Message::Witness(witness) => { - self.ingest_witness(&witness)?; - } - Message::Command(_) => {} - Message::Err(_) => {} - } + fn ingest_message_(&mut self, msg: &Message) -> Result<()> { + match msg { + Message::Header(h) => self.ingest_header(&h)?, + Message::ConstraintSystem(cs) => self.ingest_constraint_system(&cs)?, + Message::Witness(w) => self.ingest_witness(&w)?, + Message::Command(_) => {} + Message::Err(_) => {} } Ok(()) } @@ -76,6 +76,10 @@ impl Simulator { pub fn ingest_constraint_system(&mut self, system: &ConstraintSystem) -> Result<()> { self.ensure_header()?; + if system.constraints.len() > 0 { + self.verified_at_least_one_constraint = true; + } + for constraint in &system.constraints { self.verify_constraint(constraint)?; } diff --git a/rust/src/consumers/validator.rs b/rust/src/consumers/validator.rs index 32a0677..51e170d 100644 --- a/rust/src/consumers/validator.rs +++ b/rust/src/consumers/validator.rs @@ -1,4 +1,4 @@ -use crate::{CircuitHeader, Witness, ConstraintSystem, Messages, Variables, Message, Workspace}; +use crate::{CircuitHeader, Witness, ConstraintSystem, Variables, Message}; use std::collections::HashMap; use num_bigint::BigUint; @@ -37,40 +37,6 @@ impl Validator { Validator { as_prover: true, ..Self::default() } } - pub fn ingest_messages(&mut self, messages: &Messages) { - for header in &messages.circuit_headers { - self.ingest_header(header); - } - if self.as_prover { - for witness in &messages.witnesses { - self.ingest_witness(witness); - } - } - for cs in &messages.constraint_systems { - self.ingest_constraint_system(cs); - } - } - - pub fn ingest_workspace(&mut self, ws: &Workspace) { - for msg in ws.iter_messages() { - match msg { - Message::Header(header) => { - self.ingest_header(&header); - } - Message::ConstraintSystem(cs) => { - self.ingest_constraint_system(&cs); - } - Message::Witness(witness) => { - if self.as_prover { - self.ingest_witness(&witness); - } - } - Message::Command(_) => {} - Message::Err(err) => self.violate(err.to_string()), - } - } - } - pub fn get_violations(mut self) -> Vec { self.ensure_all_variables_used(); if !self.got_header { @@ -79,6 +45,16 @@ impl Validator { self.violations } + pub fn ingest_message(&mut self, msg: &Message) { + match msg { + Message::Header(h) => self.ingest_header(&h), + Message::ConstraintSystem(cs) => self.ingest_constraint_system(&cs), + Message::Witness(w) => self.ingest_witness(&w), + Message::Command(_) => {} + Message::Err(err) => self.violate(err.to_string()), + } + } + pub fn ingest_header(&mut self, header: &CircuitHeader) { if self.got_header { self.violate("Multiple headers."); @@ -107,10 +83,9 @@ impl Validator { } pub fn ingest_witness(&mut self, witness: &Witness) { + if !self.as_prover { return; } + self.ensure_header(); - if !self.as_prover { - self.violate("As verifier, got an unexpected Witness message."); - } for var in witness.assigned_variables.get_variables() { self.define(var.id, var.value, || format!("value of the witness variable_{}", var.id)); From b0e9876252f752f453ee73e3f627e33a5574b5f8 Mon Sep 17 00:00:00 2001 From: aurel Date: Wed, 21 Oct 2020 20:49:15 +0200 Subject: [PATCH 2/2] Header.list_witness_ids() --- Changelog.md | 7 +++++++ rust/src/structs/header.rs | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/Changelog.md b/Changelog.md index 3b06bfb..5bceb55 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,10 @@ +# Version v1.3.2, 2020-10, Improve simulator + +Rust: +- Fix a bug when using simulate from stdin. +- Simplify and unify the interface of Validator and Simulator. +- Method `CircuitHeader.list_witness_ids()`. + # Version v1.3.1, 2020-10, Rust streaming Rust: diff --git a/rust/src/structs/header.rs b/rust/src/structs/header.rs index 411d2d1..99832c8 100644 --- a/rust/src/structs/header.rs +++ b/rust/src/structs/header.rs @@ -9,6 +9,8 @@ use super::keyvalue::KeyValue; use crate::Result; use std::convert::TryFrom; use std::error::Error; +use std::collections::HashSet; + #[derive(Clone, Default, Debug, Eq, PartialEq, Deserialize, Serialize)] pub struct CircuitHeader { @@ -45,6 +47,22 @@ impl<'a> TryFrom<&'a [u8]> for CircuitHeader { } impl CircuitHeader { + /// Enumerate the IDs of witness variables based on a header. + /// # Example + /// ``` + /// use zkinterface_bellman::export::list_witness_ids; + /// let header = zkinterface::producers::examples::example_circuit_header(); + /// let witness_ids = list_witness_ids(&header); + /// assert_eq!(witness_ids, vec![4, 5]); + /// ``` + pub fn list_witness_ids(&self) -> Vec { + let instance_ids = self.instance_variables.variable_ids.iter().cloned().collect::>(); + + (1..self.free_variable_id) + .filter(|id| !instance_ids.contains(id)) + .collect() + } + pub fn with_instance_values(mut self, vars: Variables) -> Result { if self.instance_variables.variable_ids != vars.variable_ids { return Err(format!("The provided instance variables do not match.\nGot : {:?}\nExpected:{:?}", vars.variable_ids, self.instance_variables.variable_ids).into());