fix following review: extract witness with write read, rename scheme to proving scheme, typos
This commit is contained in:
parent
869b516d44
commit
0be493fdd1
19 changed files with 313 additions and 242 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1149,7 +1149,6 @@ dependencies = [
|
|||
"assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1169,6 +1168,7 @@ dependencies = [
|
|||
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ff 0.5.0 (git+https://github.com/matterinc/ff?tag=0.5)",
|
||||
"git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
# Schemes
|
||||
# Provin schemes
|
||||
|
||||
ZoKrates supports different proof systems we refer to as schemes. All of the available schemes rely on the ALT_BN128 curve, which means that they're all compatible with Ethereum.
|
||||
ZoKrates supports different proving schemes. All of the available schemes rely on the ALT_BN128 curve, which means that they're all compatible with Ethereum.
|
||||
|
||||
We identify the schemes by the reference to the paper that introduced them. Currently the options available are:
|
||||
|
||||
| Name | Paper | CLI flag |
|
||||
| ---- | ----- | -------- |
|
||||
| PGHR13 | [Here](https://eprint.iacr.org/2013/279) | `--scheme pghr13` |
|
||||
| G16 | [Here](https://eprint.iacr.org/2016/260) | `--scheme gm17` |
|
||||
| GM17 | [Here](https://eprint.iacr.org/2017/540) | `--scheme gm17` |
|
||||
| Name | Paper | CLI flag | Requires libsnark |
|
||||
| ---- | ----- | -------- | --------- |
|
||||
| PGHR13 | [Here](https://eprint.iacr.org/2013/279) | `--proving-scheme pghr13` | Yes |
|
||||
| G16 | [Here](https://eprint.iacr.org/2016/260) | `--proving-scheme g16` | No |
|
||||
| GM17 | [Here](https://eprint.iacr.org/2017/540) | `--proving-scheme gm17` | Yes |
|
||||
|
||||
The default scheme is G16.
|
||||
The default proving scheme is G16.
|
||||
|
||||
When not using the default, the CLI flag has to be provided for the following commands:
|
||||
- `setup`
|
||||
- `export-verifier`
|
||||
- `generate-proof`
|
||||
|
||||
## Groth16 malleability
|
||||
## G16 malleability
|
||||
|
||||
When using Groth16, developers should pay attention to the fact that an attacker seeing a valid proof can very easily generate a different but still valid proof. Therefore, depending on the use case, making sure on chain that the same proof cannot be submitted twice is *not* enough to guarantee that attackers cannot replay proofs. Mechanisms to solve this issue include:
|
||||
When using G16, developers should pay attention to the fact that an attacker seeing a valid proof can very easily generate a different but still valid proof. Therefore, depending on the use case, making sure on chain that the same proof cannot be submitted twice may *not* be enough to guarantee that attackers cannot replay proofs. Mechanisms to solve this issue include:
|
||||
- signed proofs
|
||||
- nullifiers
|
||||
- usage of an ethereum address as a public input to the program
|
||||
|
|
|
@ -17,7 +17,6 @@ zokrates_field = { version = "0.3", path = "../zokrates_field" }
|
|||
zokrates_core = { version = "0.3", path = "../zokrates_core" }
|
||||
zokrates_fs_resolver = { version = "0.4", path = "../zokrates_fs_resolver"}
|
||||
serde_json = "1.0"
|
||||
csv = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
glob = "0.2.11"
|
||||
|
|
|
@ -31,7 +31,7 @@ fn cli() -> Result<(), String> {
|
|||
const VERIFICATION_CONTRACT_DEFAULT_PATH: &str = "verifier.sol";
|
||||
const WITNESS_DEFAULT_PATH: &str = "witness";
|
||||
const JSON_PROOF_PATH: &str = "proof.json";
|
||||
let default_scheme = env::var("ZOKRATES_BACKEND").unwrap_or(String::from("g16"));
|
||||
let default_scheme = env::var("ZOKRATES_PROVING_SCHEME").unwrap_or(String::from("g16"));
|
||||
|
||||
// cli specification using clap library
|
||||
let matches = App::new("ZoKrates")
|
||||
|
@ -91,10 +91,10 @@ fn cli() -> Result<(), String> {
|
|||
.required(false)
|
||||
.default_value(VERIFICATION_KEY_DEFAULT_PATH)
|
||||
)
|
||||
.arg(Arg::with_name("scheme")
|
||||
.arg(Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("scheme")
|
||||
.help("Backend to use in the setup. Available options are PGHR13 and GM17")
|
||||
.long("proving-scheme")
|
||||
.help("Proving scheme to use in the setup. Available options are G16 (default), PGHR13 and GM17")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
|
@ -120,10 +120,10 @@ fn cli() -> Result<(), String> {
|
|||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(VERIFICATION_CONTRACT_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("scheme")
|
||||
).arg(Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("scheme")
|
||||
.help("Backend to use to export the verifier. Available options are PGHR13 and GM17")
|
||||
.long("proving-scheme")
|
||||
.help("Proving scheme to use to export the verifier. Available options are G16 (default), PGHR13 and GM17")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
|
@ -191,10 +191,10 @@ fn cli() -> Result<(), String> {
|
|||
.takes_value(true)
|
||||
.required(false)
|
||||
.default_value(FLATTENED_CODE_DEFAULT_PATH)
|
||||
).arg(Arg::with_name("scheme")
|
||||
).arg(Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("scheme")
|
||||
.help("Backend to use to generate the proof. Available options are PGHR13 and GM17")
|
||||
.long("proving-scheme")
|
||||
.help("Proving scheme to use to generate the proof. Available options are G16 (default), PGHR13 and GM17")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
|
@ -289,7 +289,7 @@ fn cli() -> Result<(), String> {
|
|||
let arguments: Vec<_> = match sub_matches.values_of("arguments") {
|
||||
// take inline arguments
|
||||
Some(p) => p
|
||||
.map(|x| FieldPrime::try_from_str(x).map_err(|_| x.to_string()))
|
||||
.map(|x| FieldPrime::try_from_dec_str(x).map_err(|_| x.to_string()))
|
||||
.collect(),
|
||||
// take stdin arguments
|
||||
None => {
|
||||
|
@ -301,7 +301,9 @@ fn cli() -> Result<(), String> {
|
|||
input.retain(|x| x != '\n');
|
||||
input
|
||||
.split(" ")
|
||||
.map(|x| FieldPrime::try_from_str(x).map_err(|_| x.to_string()))
|
||||
.map(|x| {
|
||||
FieldPrime::try_from_dec_str(x).map_err(|_| x.to_string())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
Err(_) => Err(String::from("???")),
|
||||
|
@ -332,24 +334,12 @@ fn cli() -> Result<(), String> {
|
|||
let output_file = File::create(&output_path)
|
||||
.map_err(|why| format!("couldn't create {}: {}", output_path.display(), why))?;
|
||||
|
||||
// create a CSV writer
|
||||
let mut wtr = csv::WriterBuilder::new()
|
||||
.delimiter(b' ')
|
||||
.flexible(true)
|
||||
.has_headers(false)
|
||||
.from_writer(output_file);
|
||||
|
||||
// Write each line of the witness to the file
|
||||
for line in witness.into_human_readable() {
|
||||
wtr.serialize(line)
|
||||
.map_err(|_| "Error writing witness to file".to_string())?;
|
||||
}
|
||||
|
||||
wtr.flush()
|
||||
.map_err(|_| "Unable to flush buffer.".to_string())?;
|
||||
witness
|
||||
.write(output_file)
|
||||
.map_err(|why| format!("could not save witness: {:?}", why))?;
|
||||
}
|
||||
("setup", Some(sub_matches)) => {
|
||||
let scheme = get_scheme(sub_matches.value_of("scheme").unwrap())?;
|
||||
let scheme = get_scheme(sub_matches.value_of("proving-scheme").unwrap())?;
|
||||
|
||||
println!("Performing setup...");
|
||||
|
||||
|
@ -372,7 +362,7 @@ fn cli() -> Result<(), String> {
|
|||
}
|
||||
("export-verifier", Some(sub_matches)) => {
|
||||
{
|
||||
let scheme = get_scheme(sub_matches.value_of("scheme").unwrap())?;
|
||||
let scheme = get_scheme(sub_matches.value_of("proving-scheme").unwrap())?;
|
||||
|
||||
println!("Exporting verifier...");
|
||||
|
||||
|
@ -398,7 +388,7 @@ fn cli() -> Result<(), String> {
|
|||
("generate-proof", Some(sub_matches)) => {
|
||||
println!("Generating proof...");
|
||||
|
||||
let scheme = get_scheme(sub_matches.value_of("scheme").unwrap())?;
|
||||
let scheme = get_scheme(sub_matches.value_of("proving-scheme").unwrap())?;
|
||||
|
||||
// deserialize witness
|
||||
let witness_path = Path::new(sub_matches.value_of("witness").unwrap());
|
||||
|
@ -407,13 +397,8 @@ fn cli() -> Result<(), String> {
|
|||
Err(why) => panic!("couldn't open {}: {}", witness_path.display(), why),
|
||||
};
|
||||
|
||||
let mut rdr = csv::ReaderBuilder::new()
|
||||
.delimiter(b' ')
|
||||
.flexible(true)
|
||||
.has_headers(false)
|
||||
.from_reader(witness_file);
|
||||
|
||||
let witness = ir::Witness::from_human_readable(rdr.deserialize().map(|i| i.unwrap()));
|
||||
let witness = ir::Witness::read(witness_file)
|
||||
.map_err(|why| format!("could not load witness: {:?}", why))?;
|
||||
|
||||
let pk_path = sub_matches.value_of("provingkey").unwrap();
|
||||
let proof_path = sub_matches.value_of("proofpath").unwrap();
|
||||
|
|
|
@ -185,7 +185,7 @@ mod integration {
|
|||
proving_key_path.to_str().unwrap(),
|
||||
"-v",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
"--scheme",
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
])
|
||||
.succeeds()
|
||||
|
@ -199,7 +199,7 @@ mod integration {
|
|||
verification_key_path.to_str().unwrap(),
|
||||
"-o",
|
||||
verification_contract_path.to_str().unwrap(),
|
||||
"--scheme",
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
])
|
||||
.succeeds()
|
||||
|
@ -231,7 +231,7 @@ mod integration {
|
|||
witness_path.to_str().unwrap(),
|
||||
"-p",
|
||||
proving_key_path.to_str().unwrap(),
|
||||
"--scheme",
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
])
|
||||
.succeeds()
|
||||
|
|
|
@ -33,6 +33,7 @@ rand = "0.4"
|
|||
wasmi = "0.4.2"
|
||||
parity-wasm = "0.35.3"
|
||||
rustc-hex = "1.0"
|
||||
csv = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
glob = "0.2.11"
|
||||
|
|
|
@ -32,21 +32,28 @@ impl FlatVariable {
|
|||
(self.id as usize) - 1
|
||||
}
|
||||
|
||||
pub fn from_human_readable(s: &str) -> Self {
|
||||
pub fn try_from_human_readable(s: &str) -> Result<Self, &str> {
|
||||
if s == "~one" {
|
||||
return FlatVariable::one();
|
||||
return Ok(FlatVariable::one());
|
||||
}
|
||||
|
||||
let mut public = s.split("~out_");
|
||||
match public.nth(1) {
|
||||
Some(v) => return FlatVariable::public(v.parse().unwrap()),
|
||||
None => {}
|
||||
Some(v) => {
|
||||
let v = v.parse().map_err(|_| s)?;
|
||||
Ok(FlatVariable::public(v))
|
||||
}
|
||||
None => {
|
||||
let mut private = s.split("_");
|
||||
match private.nth(1) {
|
||||
Some(v) => {
|
||||
let v = v.parse().map_err(|_| s)?;
|
||||
Ok(FlatVariable::new(v))
|
||||
}
|
||||
None => Err(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut private = s.split("_");
|
||||
match private.nth(1) {
|
||||
Some(v) => return FlatVariable::new(v.parse().unwrap()),
|
||||
None => {}
|
||||
}
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,75 +1,12 @@
|
|||
use flat_absy::flat_variable::FlatVariable;
|
||||
use helpers::Executable;
|
||||
use ir::*;
|
||||
use ir::{LinComb, Prog, QuadComb, Statement, Witness};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use zokrates_field::field::Field;
|
||||
|
||||
pub type ExecutionResult<T> = Result<Witness<T>, Error>;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Witness<T: Field>(pub BTreeMap<FlatVariable, T>);
|
||||
|
||||
impl<T: Field> Witness<T> {
|
||||
pub fn return_values(&self) -> Vec<T> {
|
||||
let out = self
|
||||
.0
|
||||
.iter()
|
||||
.filter(|(k, _)| k.is_output())
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
(0..out.len())
|
||||
.map(|i| *out.get(&FlatVariable::public(i)).unwrap())
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn format_outputs(&self) -> String {
|
||||
self.0
|
||||
.iter()
|
||||
.filter_map(|(variable, value)| match variable {
|
||||
variable if variable.is_output() => Some(format!("{} {}", variable, value)),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Witness(BTreeMap::new())
|
||||
}
|
||||
|
||||
pub fn into_human_readable(self) -> impl Iterator<Item = (String, String)> {
|
||||
self.0
|
||||
.into_iter()
|
||||
.map(|(var, val)| (var.to_string(), val.to_dec_string()))
|
||||
}
|
||||
|
||||
pub fn from_human_readable<I: Iterator<Item = (String, String)>>(i: I) -> Witness<T> {
|
||||
Witness(
|
||||
i.map(|(var, val)| {
|
||||
(
|
||||
FlatVariable::from_human_readable(&var),
|
||||
T::from_dec_string(val),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Field> fmt::Display for Witness<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
self.0
|
||||
.iter()
|
||||
.map(|(k, v)| format!("{} {}", k, v.to_dec_string()))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Field> Prog<T> {
|
||||
pub fn execute<U: Into<T> + Clone>(&self, inputs: &Vec<U>) -> ExecutionResult<T> {
|
||||
let main = &self.main;
|
||||
|
@ -188,28 +125,3 @@ impl fmt::Debug for Error {
|
|||
write!(f, "{}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use zokrates_field::field::FieldPrime;
|
||||
|
||||
#[test]
|
||||
fn human_readable_witness() {
|
||||
let witness = Witness(
|
||||
vec![
|
||||
(FlatVariable::public(0), 3),
|
||||
(FlatVariable::new(0), 2),
|
||||
(FlatVariable::one(), 1),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|(x, y)| (x, FieldPrime::from(y)))
|
||||
.collect(),
|
||||
);
|
||||
assert_eq!(
|
||||
witness.clone(),
|
||||
Witness::from_human_readable(witness.into_human_readable())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
use flat_absy::flat_parameter::FlatParameter;
|
||||
use flat_absy::FlatVariable;
|
||||
use helpers::Helper;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use zokrates_field::field::Field;
|
||||
|
||||
mod expression;
|
||||
mod from_flat;
|
||||
mod interpreter;
|
||||
mod witness;
|
||||
|
||||
pub use self::expression::LinComb;
|
||||
use self::expression::QuadComb;
|
||||
|
||||
pub use self::interpreter::{Error, ExecutionResult, Witness};
|
||||
pub use self::interpreter::{Error, ExecutionResult};
|
||||
pub use self::witness::Witness;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub enum Statement<T: Field> {
|
||||
|
|
167
zokrates_core/src/ir/witness.rs
Normal file
167
zokrates_core/src/ir/witness.rs
Normal file
|
@ -0,0 +1,167 @@
|
|||
use flat_absy::FlatVariable;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use zokrates_field::field::Field;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Witness<T: Field>(pub BTreeMap<FlatVariable, T>);
|
||||
|
||||
impl<T: Field> Witness<T> {
|
||||
pub fn return_values(&self) -> Vec<T> {
|
||||
let out = self
|
||||
.0
|
||||
.iter()
|
||||
.filter(|(k, _)| k.is_output())
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
(0..out.len())
|
||||
.map(|i| *out.get(&FlatVariable::public(i)).unwrap())
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn format_outputs(&self) -> String {
|
||||
self.0
|
||||
.iter()
|
||||
.filter_map(|(variable, value)| match variable {
|
||||
variable if variable.is_output() => Some(format!("{} {}", variable, value)),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Witness(BTreeMap::new())
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, writer: W) -> io::Result<()> {
|
||||
let mut wtr = csv::WriterBuilder::new()
|
||||
.delimiter(b' ')
|
||||
.flexible(true)
|
||||
.has_headers(false)
|
||||
.from_writer(writer);
|
||||
|
||||
// Write each line of the witness to the file
|
||||
for (variable, value) in &self.0 {
|
||||
wtr.serialize((variable.to_string(), value.to_dec_string()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
||||
let mut rdr = csv::ReaderBuilder::new()
|
||||
.delimiter(b' ')
|
||||
.flexible(true)
|
||||
.has_headers(false)
|
||||
.from_reader(&mut reader);
|
||||
|
||||
let map = rdr
|
||||
.deserialize::<(String, String)>()
|
||||
.map(|r| {
|
||||
r.map(|(variable, value)| {
|
||||
let variable =
|
||||
FlatVariable::try_from_human_readable(&variable).map_err(|why| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Invalid variable in witness: {}", why),
|
||||
)
|
||||
})?;
|
||||
let value = T::try_from_dec_str(&value).map_err(|_| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Invalid value in witness: {}", value),
|
||||
)
|
||||
})?;
|
||||
Ok((variable, value))
|
||||
})
|
||||
.map_err(|e| match e.into_kind() {
|
||||
csv::ErrorKind::Io(e) => e,
|
||||
e => io::Error::new(io::ErrorKind::Other, format!("{:?}", e)),
|
||||
})?
|
||||
})
|
||||
.collect::<io::Result<BTreeMap<FlatVariable, T>>>()?;
|
||||
|
||||
Ok(Witness(map))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Field> fmt::Display for Witness<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
self.0
|
||||
.iter()
|
||||
.map(|(k, v)| format!("{} {}", k, v.to_dec_string()))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use zokrates_field::field::FieldPrime;
|
||||
|
||||
mod io {
|
||||
use super::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize() {
|
||||
let w = Witness(
|
||||
vec![
|
||||
(FlatVariable::new(42), FieldPrime::from(42)),
|
||||
(FlatVariable::public(8), FieldPrime::from(8)),
|
||||
(FlatVariable::one(), FieldPrime::from(1)),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let mut buff = Cursor::new(vec![]);
|
||||
|
||||
w.write(&mut buff).unwrap();
|
||||
buff.set_position(0);
|
||||
|
||||
let r = Witness::read(buff).unwrap();
|
||||
|
||||
assert_eq!(w, r);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_value() {
|
||||
let mut buff = Cursor::new(vec![]);
|
||||
|
||||
buff.write("_1 123bug".as_ref()).unwrap();
|
||||
buff.set_position(0);
|
||||
|
||||
assert!(Witness::<FieldPrime>::read(buff).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_variable() {
|
||||
let mut buff = Cursor::new(vec![]);
|
||||
|
||||
buff.write("_1bug 123".as_ref()).unwrap();
|
||||
buff.set_position(0);
|
||||
|
||||
assert!(Witness::<FieldPrime>::read(buff).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn not_csv() {
|
||||
let mut buff = Cursor::new(vec![]);
|
||||
buff.write("whatwhat".as_ref()).unwrap();
|
||||
buff.set_position(0);
|
||||
|
||||
assert!(Witness::<FieldPrime>::read(buff).is_err());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,5 +41,4 @@ pub mod flat_absy;
|
|||
pub mod ir;
|
||||
#[cfg(feature = "libsnark")]
|
||||
pub mod libsnark;
|
||||
// #[cfg(feature = "libsnark")]
|
||||
pub mod proof_system;
|
||||
|
|
|
@ -100,7 +100,7 @@ mod tests {
|
|||
)
|
||||
.unwrap()
|
||||
.to_bytes_le(),
|
||||
FieldPrime::try_from_str(
|
||||
FieldPrime::try_from_dec_str(
|
||||
"5472060717959818805561601436314318772174077789324455915672259473661306552146"
|
||||
)
|
||||
.unwrap()
|
||||
|
@ -112,7 +112,7 @@ mod tests {
|
|||
fn serialization_bin() {
|
||||
assert_eq!(
|
||||
BigUint::parse_bytes(b"110000011001000100111001110010111000010011000110100000001010011011100001010000010001011011011010000001100000010101100001011101100101111000000101101010100100010110100001110001110010101000110100111100001000001000110000010110110110000111110011111101010010",2).unwrap().to_bytes_le(),
|
||||
FieldPrime::try_from_str("5472060717959818805561601436314318772174077789324455915672259473661306552146").unwrap().into_byte_vector()
|
||||
FieldPrime::try_from_dec_str("5472060717959818805561601436314318772174077789324455915672259473661306552146").unwrap().into_byte_vector()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ pub fn parse_num<T: Field>(input: &String, pos: &Position) -> (Token<T>, String,
|
|||
}
|
||||
assert!(end > 0);
|
||||
(
|
||||
Token::Num(T::try_from_str(&input[0..end]).unwrap()),
|
||||
Token::Num(T::try_from_dec_str(&input[0..end]).unwrap()),
|
||||
input[end..].to_string(),
|
||||
Position {
|
||||
line: pos.line,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use bellman::groth16::Parameters;
|
||||
use ir;
|
||||
use proof_system::bn128::utils::bellman::{serialize_proof, serialize_vk, Computation};
|
||||
use proof_system::bn128::utils::bellman::Computation;
|
||||
use proof_system::bn128::utils::solidity::{SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB};
|
||||
use proof_system::ProofSystem;
|
||||
use regex::Regex;
|
||||
|
@ -22,7 +22,9 @@ impl ProofSystem for G16 {
|
|||
let parameters_file = File::create(PathBuf::from(pk_path)).unwrap();
|
||||
parameters.write(parameters_file).unwrap();
|
||||
let mut vk_file = File::create(PathBuf::from(vk_path)).unwrap();
|
||||
vk_file.write(serialize_vk(parameters.vk).as_ref()).unwrap();
|
||||
vk_file
|
||||
.write(serialize::serialize_vk(parameters.vk).as_ref())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn generate_proof(
|
||||
|
@ -47,7 +49,7 @@ impl ProofSystem for G16 {
|
|||
write!(
|
||||
proof_file,
|
||||
"{}",
|
||||
serialize_proof(&proof, &computation.public_inputs_values())
|
||||
serialize::serialize_proof(&proof, &computation.public_inputs_values())
|
||||
)
|
||||
.unwrap();
|
||||
true
|
||||
|
@ -134,6 +136,72 @@ impl ProofSystem for G16 {
|
|||
}
|
||||
}
|
||||
|
||||
mod serialize {
|
||||
|
||||
use bellman::groth16::{Proof, VerifyingKey};
|
||||
use pairing::bn256::{Bn256, Fr};
|
||||
|
||||
pub fn serialize_vk(vk: VerifyingKey<Bn256>) -> String {
|
||||
format!(
|
||||
"vk.alpha = {}
|
||||
vk.beta = {}
|
||||
vk.gamma = {}
|
||||
vk.delta = {}
|
||||
vk.gammaABC.len() = {}
|
||||
{}",
|
||||
vk.alpha_g1,
|
||||
vk.beta_g2,
|
||||
vk.gamma_g2,
|
||||
vk.delta_g2,
|
||||
vk.ic.len(),
|
||||
vk.ic
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, x)| format!("vk.gammaABC[{}] = {}", i, x))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
.replace("G2(x=Fq2(Fq(", "[")
|
||||
.replace("), y=Fq(", ", ")
|
||||
.replace("G1(x=Fq(", "")
|
||||
.replace(") + Fq(", ", ")
|
||||
.replace("))", "")
|
||||
.replace(") * u), y=Fq2(Fq(", "], [")
|
||||
.replace(") * u", "]")
|
||||
}
|
||||
|
||||
pub fn serialize_proof(p: &Proof<Bn256>, inputs: &Vec<Fr>) -> String {
|
||||
format!(
|
||||
"{{
|
||||
\"proof\": {{
|
||||
\"a\": {},
|
||||
\"b\": {},
|
||||
\"c\": {}
|
||||
}},
|
||||
\"inputs\": [{}]
|
||||
}}",
|
||||
p.a,
|
||||
p.b,
|
||||
p.c,
|
||||
inputs
|
||||
.iter()
|
||||
.map(|v| format!("\"{}\"", v))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
.replace("G2(x=Fq2(Fq(", "[[\"")
|
||||
.replace("), y=Fq(", "\", \"")
|
||||
.replace("G1(x=Fq(", "[\"")
|
||||
.replace(") + Fq(", "\", \"")
|
||||
.replace(") * u), y=Fq2(Fq(", "\"], [\"")
|
||||
.replace(") * u]", "\"]]")
|
||||
.replace(") * u))", "\"]]")
|
||||
.replace("))", "\"]")
|
||||
.replace("Fr(", "")
|
||||
.replace(")", "")
|
||||
}
|
||||
}
|
||||
|
||||
const CONTRACT_TEMPLATE: &str = r#"
|
||||
contract Verifier {
|
||||
using Pairing for *;
|
||||
|
|
|
@ -3,7 +3,7 @@ extern crate rand;
|
|||
use bellman::groth16::Proof;
|
||||
use bellman::groth16::{
|
||||
create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof,
|
||||
Parameters, VerifyingKey,
|
||||
Parameters,
|
||||
};
|
||||
use bellman::{Circuit, ConstraintSystem, LinearCombination, SynthesisError, Variable};
|
||||
use ir::{LinComb, Prog, Statement, Witness};
|
||||
|
@ -189,66 +189,6 @@ impl Circuit<Bn256> for Computation<FieldPrime> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn serialize_vk(vk: VerifyingKey<Bn256>) -> String {
|
||||
format!(
|
||||
"vk.alpha = {}
|
||||
vk.beta = {}
|
||||
vk.gamma = {}
|
||||
vk.delta = {}
|
||||
vk.gammaABC.len() = {}
|
||||
{}",
|
||||
vk.alpha_g1,
|
||||
vk.beta_g2,
|
||||
vk.gamma_g2,
|
||||
vk.delta_g2,
|
||||
vk.ic.len(),
|
||||
vk.ic
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, x)| format!("vk.gammaABC[{}] = {}", i, x))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
.replace("G2(x=Fq2(Fq(", "[")
|
||||
.replace("), y=Fq(", ", ")
|
||||
.replace("G1(x=Fq(", "")
|
||||
.replace(") + Fq(", ", ")
|
||||
.replace("))", "")
|
||||
.replace(") * u), y=Fq2(Fq(", "], [")
|
||||
.replace(") * u", "]")
|
||||
}
|
||||
|
||||
pub fn serialize_proof(p: &Proof<Bn256>, inputs: &Vec<Fr>) -> String {
|
||||
format!(
|
||||
"{{
|
||||
\"proof\": {{
|
||||
\"a\": {},
|
||||
\"b\": {},
|
||||
\"c\": {}
|
||||
}},
|
||||
\"inputs\": [{}]
|
||||
}}",
|
||||
p.a,
|
||||
p.b,
|
||||
p.c,
|
||||
inputs
|
||||
.iter()
|
||||
.map(|v| format!("\"{}\"", v))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
.replace("G2(x=Fq2(Fq(", "[[\"")
|
||||
.replace("), y=Fq(", "\", \"")
|
||||
.replace("G1(x=Fq(", "[\"")
|
||||
.replace(") + Fq(", "\", \"")
|
||||
.replace(") * u), y=Fq2(Fq(", "\"], [\"")
|
||||
.replace(") * u]", "\"]]")
|
||||
.replace(") * u))", "\"]]")
|
||||
.replace("))", "\"]")
|
||||
.replace("Fr(", "")
|
||||
.replace(")", "")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -44,8 +44,8 @@ impl From<TestResult> for ComparableResult {
|
|||
fn from(r: TestResult) -> ComparableResult {
|
||||
ComparableResult(r.map(|v| {
|
||||
v.values
|
||||
.into_iter()
|
||||
.map(|v| FieldPrime::from_dec_string(v))
|
||||
.iter()
|
||||
.map(|v| FieldPrime::try_from_dec_str(v).unwrap())
|
||||
.collect()
|
||||
}))
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ macro_rules! zokrates_test {
|
|||
|
||||
for test in t.tests.into_iter() {
|
||||
let input = &test.input.values;
|
||||
let output = bin.execute(&input.iter().map(|v| FieldPrime::from_dec_string(v.clone())).collect());
|
||||
let output = bin.execute(&input.iter().map(|v| FieldPrime::try_from_dec_str(v).unwrap()).collect());
|
||||
|
||||
let context = format!("
|
||||
{}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use lazy_static::lazy_static;
|
||||
use num_bigint::{BigInt, BigUint, Sign, ToBigInt};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{Num, One, Zero};
|
||||
use num_traits::{One, Zero};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::From;
|
||||
use std::fmt;
|
||||
|
@ -59,8 +59,6 @@ pub trait Field:
|
|||
fn from_byte_vector(_: Vec<u8>) -> Self;
|
||||
/// Returns this `Field`'s contents as decimal string
|
||||
fn to_dec_string(&self) -> String;
|
||||
/// Returns an element of this `Field` from a decimal string
|
||||
fn from_dec_string(val: String) -> Self;
|
||||
/// Returns the multiplicative inverse, i.e.: self * self.inverse_mul() = Self::one()
|
||||
fn inverse_mul(&self) -> Self;
|
||||
/// Returns the smallest value that can be represented by this field type.
|
||||
|
@ -70,7 +68,7 @@ pub trait Field:
|
|||
/// Returns the number of required bits to represent this field type.
|
||||
fn get_required_bits() -> usize;
|
||||
/// Tries to parse a string into this representation
|
||||
fn try_from_str<'a>(s: &'a str) -> Result<Self, ()>;
|
||||
fn try_from_dec_str<'a>(s: &'a str) -> Result<Self, ()>;
|
||||
/// Returns a decimal string representing a the member of the equivalence class of this `Field` in Z/pZ
|
||||
/// which lies in [-(p-1)/2, (p-1)/2]
|
||||
fn to_compact_dec_string(&self) -> String;
|
||||
|
@ -100,12 +98,6 @@ impl Field for FieldPrime {
|
|||
self.value.to_str_radix(10)
|
||||
}
|
||||
|
||||
fn from_dec_string(val: String) -> Self {
|
||||
FieldPrime {
|
||||
value: BigInt::from_str_radix(val.as_str(), 10).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn inverse_mul(&self) -> FieldPrime {
|
||||
let (b, s, _) = extended_euclid(&self.value, &*P);
|
||||
assert_eq!(b, BigInt::one());
|
||||
|
@ -126,7 +118,7 @@ impl Field for FieldPrime {
|
|||
fn get_required_bits() -> usize {
|
||||
(*P).bits()
|
||||
}
|
||||
fn try_from_str<'a>(s: &'a str) -> Result<Self, ()> {
|
||||
fn try_from_dec_str<'a>(s: &'a str) -> Result<Self, ()> {
|
||||
let x = BigInt::parse_bytes(s.as_bytes(), 10).ok_or(())?;
|
||||
Ok(FieldPrime {
|
||||
value: &x - x.div_floor(&*P) * &*P,
|
||||
|
@ -364,7 +356,7 @@ mod tests {
|
|||
|
||||
impl<'a> From<&'a str> for FieldPrime {
|
||||
fn from(s: &'a str) -> FieldPrime {
|
||||
FieldPrime::try_from_str(s).unwrap()
|
||||
FieldPrime::try_from_dec_str(s).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,7 +616,7 @@ mod tests {
|
|||
fn dec_string_ser_deser() {
|
||||
let fp = FieldPrime::from("101");
|
||||
let bv = fp.to_dec_string();
|
||||
assert_eq!(fp, FieldPrime::from_dec_string(bv));
|
||||
assert_eq!(fp, FieldPrime::try_from_dec_str(&bv).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -27,7 +27,7 @@ fn {test_name}() {{
|
|||
|
||||
for test in t.tests.into_iter() {{
|
||||
let input = &test.input.values;
|
||||
let output = bin.execute(&input.iter().map(|v| FieldPrime::from_dec_string(v.clone())).collect());
|
||||
let output = bin.execute(&input.iter().map(|v| FieldPrime::try_from_dec_str(&v.clone()).unwrap()).collect());
|
||||
|
||||
match utils::compare(output, test.output) {{
|
||||
Err(e) => {{
|
||||
|
|
|
@ -41,8 +41,8 @@ impl From<TestResult> for ComparableResult {
|
|||
fn from(r: TestResult) -> ComparableResult {
|
||||
ComparableResult(r.map(|v| {
|
||||
v.values
|
||||
.into_iter()
|
||||
.map(|v| FieldPrime::from_dec_string(v))
|
||||
.iter()
|
||||
.map(|v| FieldPrime::try_from_dec_str(v).unwrap())
|
||||
.collect()
|
||||
}))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue