1
0
Fork 0
mirror of synced 2025-09-23 20:28:36 +00:00

minor refactor and cleanup, add tests to vk parser

This commit is contained in:
dark64 2020-04-24 16:09:03 +02:00
parent c9b68a5147
commit f2ebddb2fc
15 changed files with 200 additions and 159 deletions

View file

@ -42,9 +42,9 @@ jobs:
- restore_cache:
keys:
- v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }}
# - run:
# name: Check format
# command: rustup component add rustfmt; cargo fmt --all -- --check
- run:
name: Check format
command: rustup component add rustfmt; cargo fmt --all -- --check
- run:
name: Install libsnark prerequisites
command: ./scripts/install_libsnark_prerequisites.sh

View file

@ -264,7 +264,7 @@ fn cli() -> Result<(), String> {
)
)
.subcommand(SubCommand::with_name("verify")
.about("Verifies a given proof with the given constraint system and verification key")
.about("Verifies a given proof with the given verification key")
.arg(Arg::with_name("proof-path")
.short("j")
.long("proof-path")
@ -367,7 +367,7 @@ fn cli() -> Result<(), String> {
if !light {
// write human-readable output file
let hr_output_file = File::create(&hr_output_path).map_err(|why| {
format!("couldn't create {}: {}", hr_output_path.display(), why)
format!("Couldn't create {}: {}", hr_output_path.display(), why)
})?;
let mut hrofb = BufWriter::new(hr_output_file);
@ -397,7 +397,7 @@ fn cli() -> Result<(), String> {
// read compiled program
let path = Path::new(sub_matches.value_of("input").unwrap());
let file = File::open(&path)
.map_err(|why| format!("couldn't open {}: {}", path.display(), why))?;
.map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
let mut reader = BufReader::new(file);
@ -422,7 +422,7 @@ fn cli() -> Result<(), String> {
true => {
let path = Path::new(sub_matches.value_of("abi_spec").unwrap());
let file = File::open(&path)
.map_err(|why| format!("couldn't open {}: {}", path.display(), why))?;
.map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
let mut reader = BufReader::new(file);
let abi: Abi = from_reader(&mut reader).map_err(|why| why.to_string())?;
@ -502,13 +502,13 @@ fn cli() -> Result<(), String> {
// write witness to file
let output_path = Path::new(sub_matches.value_of("output").unwrap());
let output_file = File::create(&output_path)
.map_err(|why| format!("couldn't create {}: {}", output_path.display(), why))?;
.map_err(|why| format!("Couldn't create {}: {}", output_path.display(), why))?;
let writer = BufWriter::new(output_file);
witness
.write(writer)
.map_err(|why| format!("could not save witness: {:?}", why))?;
.map_err(|why| format!("Could not save witness: {:?}", why))?;
}
("setup", Some(sub_matches)) => {
let scheme = get_scheme(sub_matches.value_of("proving-scheme").unwrap())?;
@ -517,7 +517,7 @@ fn cli() -> Result<(), String> {
let path = Path::new(sub_matches.value_of("input").unwrap());
let file = File::open(&path)
.map_err(|why| format!("couldn't open {}: {}", path.display(), why))?;
.map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
let mut reader = BufReader::new(file);
@ -538,17 +538,17 @@ fn cli() -> Result<(), String> {
// write verification key
let mut vk_file = File::create(vk_path)
.map_err(|why| format!("couldn't create {}: {}", vk_path.display(), why))?;
.map_err(|why| format!("Couldn't create {}: {}", vk_path.display(), why))?;
vk_file
.write(keypair.vk.as_ref())
.map_err(|why| format!("couldn't write to {}: {}", vk_path.display(), why))?;
.map_err(|why| format!("Couldn't write to {}: {}", vk_path.display(), why))?;
// write proving key
let mut pk_file = File::create(pk_path)
.map_err(|why| format!("couldn't create {}: {}", pk_path.display(), why))?;
.map_err(|why| format!("Couldn't create {}: {}", pk_path.display(), why))?;
pk_file
.write(keypair.pk.as_ref())
.map_err(|why| format!("couldn't write to {}: {}", pk_path.display(), why))?;
.map_err(|why| format!("Couldn't write to {}: {}", pk_path.display(), why))?;
println!("Setup completed.");
}
@ -556,26 +556,27 @@ fn cli() -> Result<(), String> {
{
let scheme = get_scheme(sub_matches.value_of("proving-scheme").unwrap())?;
let is_abi_v2 = sub_matches.value_of("solidity-abi").unwrap() == "v2";
let abi_version = AbiVersion::from(sub_matches.value_of("solidity-abi").unwrap())?;
println!("Exporting verifier...");
// read vk file
let vk_path = Path::new(sub_matches.value_of("input").unwrap());
let vk_file = File::open(&vk_path)
.map_err(|why| format!("couldn't open {}: {}", vk_path.display(), why))?;
.map_err(|why| format!("Couldn't open {}: {}", vk_path.display(), why))?;
let mut reader = BufReader::new(vk_file);
let mut vk = String::new();
reader
.read_to_string(&mut vk)
.map_err(|why| format!("couldn't read {}: {}", vk_path.display(), why))?;
.map_err(|why| format!("Couldn't read {}: {}", vk_path.display(), why))?;
let verifier = scheme.export_solidity_verifier(vk, is_abi_v2);
let verifier = scheme.export_solidity_verifier(vk, abi_version);
//write output file
let output_path = Path::new(sub_matches.value_of("output").unwrap());
let output_file = File::create(&output_path)
.map_err(|why| format!("couldn't create {}: {}", output_path.display(), why))?;
.map_err(|why| format!("Couldn't create {}: {}", output_path.display(), why))?;
let mut writer = BufWriter::new(output_file);
@ -592,20 +593,18 @@ fn cli() -> Result<(), String> {
// deserialize witness
let witness_path = Path::new(sub_matches.value_of("witness").unwrap());
let witness_file = match File::open(&witness_path) {
Ok(file) => file,
Err(why) => panic!("couldn't open {}: {}", witness_path.display(), why),
};
let witness_file = File::open(&witness_path)
.map_err(|why| format!("Couldn't open {}: {}", witness_path.display(), why))?;
let witness = ir::Witness::read(witness_file)
.map_err(|why| format!("could not load witness: {:?}", why))?;
.map_err(|why| format!("Could not load witness: {:?}", why))?;
let pk_path = Path::new(sub_matches.value_of("proving-key-path").unwrap());
let proof_path = Path::new(sub_matches.value_of("proof-path").unwrap());
let program_path = Path::new(sub_matches.value_of("input").unwrap());
let program_file = File::open(&program_path)
.map_err(|why| format!("couldn't open {}: {}", program_path.display(), why))?;
.map_err(|why| format!("Couldn't open {}: {}", program_path.display(), why))?;
let mut reader = BufReader::new(program_file);
@ -613,22 +612,22 @@ fn cli() -> Result<(), String> {
deserialize_from(&mut reader, Infinite).map_err(|why| format!("{:?}", why))?;
let pk_file = File::open(&pk_path)
.map_err(|why| format!("couldn't open {}: {}", pk_path.display(), why))?;
.map_err(|why| format!("Couldn't open {}: {}", pk_path.display(), why))?;
let mut pk: Vec<u8> = Vec::new();
let mut pk_reader = BufReader::new(pk_file);
pk_reader
.read_to_end(&mut pk)
.map_err(|why| format!("couldn't read {}: {}", pk_path.display(), why))?;
.map_err(|why| format!("Couldn't read {}: {}", pk_path.display(), why))?;
let proof = scheme.generate_proof(program, witness, pk);
let mut proof_file = File::create(proof_path).unwrap();
proof_file
.write(proof.as_ref())
.map_err(|why| format!("couldn't write to {}: {}", proof_path.display(), why))?;
.map_err(|why| format!("Couldn't write to {}: {}", proof_path.display(), why))?;
println!("Proof: \n\n{}", format!("{}", proof));
println!("\nProof:\n{}", format!("{}", proof));
}
("print-proof", Some(sub_matches)) => {
let format = sub_matches.value_of("format").unwrap();
@ -636,7 +635,7 @@ fn cli() -> Result<(), String> {
let path = Path::new(sub_matches.value_of("proof-path").unwrap());
let file = File::open(&path)
.map_err(|why| format!("couldn't open {}: {}", path.display(), why))?;
.map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
let proof_object: Value =
serde_json::from_reader(file).map_err(|why| format!("{:?}", why))?;
@ -672,11 +671,11 @@ fn cli() -> Result<(), String> {
let vk_path = Path::new(sub_matches.value_of("verification-key-path").unwrap());
let vk = std::fs::read_to_string(vk_path)
.map_err(|why| format!("couldn't read {}: {}", vk_path.display(), why))?;
.map_err(|why| format!("Couldn't read {}: {}", vk_path.display(), why))?;
let proof_path = Path::new(sub_matches.value_of("proof-path").unwrap());
let proof = std::fs::read_to_string(proof_path)
.map_err(|why| format!("couldn't read {}: {}", proof_path.display(), why))?;
.map_err(|why| format!("Couldn't read {}: {}", proof_path.display(), why))?;
println!("Performing verification...");
println!(

View file

@ -8,7 +8,6 @@
#include "gm17.hpp"
#include "util.hpp"
#include <cassert>
#include <fstream>
#include <sstream>
#include <string>

View file

@ -18,6 +18,7 @@ use crate::proof_system::bn128::utils::solidity::{
};
use crate::proof_system::{ProofSystem, SetupKeypair};
use proof_system::bn128::{G1PairingPoint, G2PairingPoint, Proof};
use proof_system::AbiVersion;
const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/reference/proving_schemes.html#g16-malleability for implications.";
@ -42,15 +43,6 @@ impl G16ProofPoints {
}
}
impl Proof<G16ProofPoints> {
fn from_json(str: &str) -> Self {
serde_json::from_str(str).unwrap()
}
fn to_json_pretty(&self) -> String {
serde_json::to_string_pretty(&self).unwrap()
}
}
impl ProofSystem for G16 {
fn setup(&self, program: ir::Prog<FieldPrime>) -> SetupKeypair {
#[cfg(not(target_arch = "wasm32"))]
@ -60,9 +52,7 @@ impl ProofSystem for G16 {
let parameters = Computation::without_witness(program).setup();
let mut pk: Vec<u8> = Vec::new();
parameters
.write(&mut pk)
.expect("Could not write proving key to buffer");
parameters.write(&mut pk).unwrap();
SetupKeypair::from(serialize_vk(parameters.vk), pk)
}
@ -97,18 +87,17 @@ impl ProofSystem for G16 {
Proof::<G16ProofPoints>::new(proof_points, inputs, hex::encode(&raw)).to_json_pretty()
}
fn export_solidity_verifier(&self, vk: String, abi_v2: bool) -> String {
let vk_map = parse_vk(vk);
let (mut template_text, solidity_pairing_lib) = if abi_v2 {
(
String::from(CONTRACT_TEMPLATE_V2),
String::from(SOLIDITY_PAIRING_LIB_V2),
)
} else {
(
fn export_solidity_verifier(&self, vk: String, abi_version: AbiVersion) -> String {
let vk_map = parse_vk(vk).unwrap();
let (mut template_text, solidity_pairing_lib) = match abi_version {
AbiVersion::V1 => (
String::from(CONTRACT_TEMPLATE),
String::from(SOLIDITY_PAIRING_LIB),
)
),
AbiVersion::V2 => (
String::from(CONTRACT_TEMPLATE_V2),
String::from(SOLIDITY_PAIRING_LIB_V2),
),
};
let vk_regex = Regex::new(r#"(<%vk_[^i%]*%>)"#).unwrap();
@ -170,15 +159,15 @@ impl ProofSystem for G16 {
}
fn verify(&self, vk: String, proof: String) -> bool {
let map = parse_vk(vk);
let map = parse_vk(vk).unwrap();
let vk_raw = hex::decode(map.get("vk.raw").unwrap()).unwrap();
let vk: VerifyingKey<Bn256> = VerifyingKey::read(vk_raw.as_slice()).unwrap();
let pvk: PreparedVerifyingKey<Bn256> = prepare_verifying_key(&vk);
let g16_proof: Proof<G16ProofPoints> = Proof::from_json(proof.as_str());
let raw_proof = hex::decode(g16_proof.raw).unwrap();
let g16_proof = Proof::<G16ProofPoints>::from_str(proof.as_str());
let raw_proof = hex::decode(g16_proof.raw).unwrap();
let proof: BellmanProof<Bn256> = BellmanProof::read(raw_proof.as_slice()).unwrap();
let public_inputs: Vec<Fr> = g16_proof
@ -186,7 +175,7 @@ impl ProofSystem for G16 {
.iter()
.map(|s| {
FieldPrime::try_from_str(s.trim_start_matches("0x"), 16)
.unwrap()
.expect(format!("Invalid field value: {}", s).as_str())
.into_bellman()
})
.collect::<Vec<_>>();

View file

@ -10,8 +10,8 @@ use proof_system::bn128::utils::solidity::{
SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
};
use proof_system::bn128::{G1PairingPoint, G2PairingPoint, Proof};
use proof_system::{ProofSystem, SetupKeypair};
use zokrates_field::field::FieldPrime;
use proof_system::{AbiVersion, ProofSystem, SetupKeypair};
use zokrates_field::field::{Field, FieldPrime};
pub struct GM17 {}
@ -28,12 +28,6 @@ struct GM17ProofPoints {
c: G1PairingPoint,
}
impl Proof<GM17ProofPoints> {
fn from_json(str: &str) -> Self {
serde_json::from_str(str).unwrap()
}
}
extern "C" {
fn gm17_setup(
a: *const u8,
@ -106,8 +100,9 @@ impl ProofSystem for GM17 {
let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) =
prepare_generate_proof(program, witness);
let mut pk_buffer = Buffer::from_vec(&proving_key);
let proof = unsafe {
let mut pk_buffer = Buffer::from_vec(&proving_key);
let result = gm17_generate_proof(
&mut pk_buffer as *mut _,
public_inputs_arr[0].as_ptr(),
@ -132,18 +127,17 @@ impl ProofSystem for GM17 {
String::from_utf8(proof).unwrap()
}
fn export_solidity_verifier(&self, vk: String, abi_v2: bool) -> String {
let vk_map = parse_vk(vk);
let (mut template_text, solidity_pairing_lib) = if abi_v2 {
(
String::from(CONTRACT_TEMPLATE_V2),
String::from(SOLIDITY_PAIRING_LIB_V2),
)
} else {
(
fn export_solidity_verifier(&self, vk: String, abi_version: AbiVersion) -> String {
let vk_map = parse_vk(vk).unwrap();
let (mut template_text, solidity_pairing_lib) = match abi_version {
AbiVersion::V1 => (
String::from(CONTRACT_TEMPLATE),
String::from(SOLIDITY_PAIRING_LIB),
)
),
AbiVersion::V2 => (
String::from(CONTRACT_TEMPLATE_V2),
String::from(SOLIDITY_PAIRING_LIB_V2),
),
};
// replace things in template
@ -210,20 +204,27 @@ impl ProofSystem for GM17 {
}
fn verify(&self, vk: String, proof: String) -> bool {
let map = parse_vk(vk);
let map = parse_vk(vk).unwrap();
let vk_raw = hex::decode(map.get("vk.raw").unwrap()).unwrap();
let proof: Proof<GM17ProofPoints> = Proof::from_json(proof.as_str());
let proof = Proof::<GM17ProofPoints>::from_str(proof.as_str());
let proof_raw = hex::decode(proof.raw).unwrap();
let public_inputs: Vec<&str> = proof.inputs.iter().map(|v| v.as_str()).collect();
let public_inputs: Vec<FieldPrime> = proof
.inputs
.iter()
.map(|v| {
FieldPrime::try_from_str(v.as_str().trim_start_matches("0x"), 16)
.expect(format!("Invalid field value: {}", v.as_str()).as_str())
})
.collect();
let (public_inputs_arr, public_inputs_length) = prepare_public_inputs(public_inputs);
unsafe {
let mut vk_buffer = Buffer::from_vec(&vk_raw);
let mut proof_buffer = Buffer::from_vec(&proof_raw);
let mut vk_buffer = Buffer::from_vec(&vk_raw);
let mut proof_buffer = Buffer::from_vec(&proof_raw);
unsafe {
let ans = gm17_verify(
&mut vk_buffer as *mut _,
&mut proof_buffer as *mut _,

View file

@ -11,6 +11,7 @@ pub use self::g16::G16;
pub use self::gm17::GM17;
#[cfg(feature = "libsnark")]
pub use self::pghr13::PGHR13;
use serde::{Deserialize, Serialize};
type G1PairingPoint = (String, String);
type G2PairingPoint = (G1PairingPoint, G1PairingPoint);
@ -22,8 +23,14 @@ struct Proof<T> {
raw: String,
}
impl<T> Proof<T> {
impl<'a, T: Serialize + Deserialize<'a>> Proof<T> {
fn new(proof: T, inputs: Vec<String>, raw: String) -> Self {
Proof { proof, inputs, raw }
}
fn from_str(proof: &'a str) -> Proof<T> {
serde_json::from_str(proof).expect("Invalid proof json format")
}
fn to_json_pretty(&self) -> String {
serde_json::to_string_pretty(self).unwrap()
}
}

View file

@ -8,9 +8,9 @@ use proof_system::bn128::utils::solidity::{
SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
};
use proof_system::bn128::{G1PairingPoint, G2PairingPoint, Proof};
use proof_system::{ProofSystem, SetupKeypair};
use proof_system::{AbiVersion, ProofSystem, SetupKeypair};
use regex::Regex;
use zokrates_field::field::FieldPrime;
use zokrates_field::field::{Field, FieldPrime};
pub struct PGHR13 {}
@ -21,7 +21,7 @@ impl PGHR13 {
}
#[derive(Serialize, Deserialize)]
struct PGHR13ProofPoints {
pub struct PGHR13ProofPoints {
a: G1PairingPoint,
a_p: G1PairingPoint,
b: G2PairingPoint,
@ -32,12 +32,6 @@ struct PGHR13ProofPoints {
k: G1PairingPoint,
}
impl Proof<PGHR13ProofPoints> {
fn from_json(str: &str) -> Self {
serde_json::from_str(str).unwrap()
}
}
extern "C" {
fn pghr13_setup(
a: *const u8,
@ -110,9 +104,9 @@ impl ProofSystem for PGHR13 {
let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) =
prepare_generate_proof(program, witness);
let proof_vec = unsafe {
let mut pk_buf = Buffer::from_vec(&proving_key);
let mut pk_buf = Buffer::from_vec(&proving_key);
let proof_vec = unsafe {
let result = pghr13_generate_proof(
&mut pk_buf as *mut _,
public_inputs_arr[0].as_ptr(),
@ -137,18 +131,17 @@ impl ProofSystem for PGHR13 {
String::from_utf8(proof_vec).unwrap()
}
fn export_solidity_verifier(&self, vk: String, abi_v2: bool) -> String {
let vk_map = parse_vk(vk);
let (mut template_text, solidity_pairing_lib) = if abi_v2 {
(
String::from(CONTRACT_TEMPLATE_V2),
String::from(SOLIDITY_PAIRING_LIB_V2),
)
} else {
(
fn export_solidity_verifier(&self, vk: String, abi_version: AbiVersion) -> String {
let vk_map = parse_vk(vk).unwrap();
let (mut template_text, solidity_pairing_lib) = match abi_version {
AbiVersion::V1 => (
String::from(CONTRACT_TEMPLATE),
String::from(SOLIDITY_PAIRING_LIB),
)
),
AbiVersion::V2 => (
String::from(CONTRACT_TEMPLATE_V2),
String::from(SOLIDITY_PAIRING_LIB_V2),
),
};
// replace things in template
@ -214,20 +207,27 @@ impl ProofSystem for PGHR13 {
}
fn verify(&self, vk: String, proof: String) -> bool {
let map = parse_vk(vk);
let map = parse_vk(vk).unwrap();
let vk_raw = hex::decode(map.get("vk.raw").unwrap()).unwrap();
let proof: Proof<PGHR13ProofPoints> = Proof::from_json(proof.as_str());
let proof = Proof::<PGHR13ProofPoints>::from_str(proof.as_str());
let proof_raw = hex::decode(proof.raw).unwrap();
let public_inputs: Vec<&str> = proof.inputs.iter().map(|v| v.as_str()).collect();
let public_inputs: Vec<FieldPrime> = proof
.inputs
.iter()
.map(|v| {
FieldPrime::try_from_str(v.as_str().trim_start_matches("0x"), 16)
.expect(format!("Invalid field value: {}", v.as_str()).as_str())
})
.collect();
let (public_inputs_arr, public_inputs_length) = prepare_public_inputs(public_inputs);
unsafe {
let mut vk_buffer = Buffer::from_vec(&vk_raw);
let mut proof_buffer = Buffer::from_vec(&proof_raw);
let mut vk_buffer = Buffer::from_vec(&vk_raw);
let mut proof_buffer = Buffer::from_vec(&proof_raw);
unsafe {
let ans = pghr13_verify(
&mut vk_buffer as *mut _,
&mut proof_buffer as *mut _,

View file

@ -20,7 +20,7 @@ extern "C" {
}
impl Buffer {
pub unsafe fn from_vec(v: &Vec<u8>) -> Buffer {
pub fn from_vec(v: &Vec<u8>) -> Buffer {
let mut buf = vec![0; v.len()].into_boxed_slice();
buf.copy_from_slice(v.as_slice());

View file

@ -2,7 +2,7 @@ use flat_absy::FlatVariable;
use ir::{self, Statement};
use std::cmp::max;
use std::collections::HashMap;
use zokrates_field::field::{Field, FieldPrime};
use zokrates_field::field::Field;
// utility function. Converts a Field's vector-based byte representation to fixed size array.
fn vec_as_u8_32_array(vec: &Vec<u8>) -> [u8; 32] {
@ -14,14 +14,12 @@ fn vec_as_u8_32_array(vec: &Vec<u8>) -> [u8; 32] {
array
}
pub fn prepare_public_inputs(public_inputs: Vec<&str>) -> (Vec<[u8; 32]>, usize) {
pub fn prepare_public_inputs<T: Field>(public_inputs: Vec<T>) -> (Vec<[u8; 32]>, usize) {
let public_inputs_length = public_inputs.len();
let mut public_inputs_arr: Vec<[u8; 32]> = vec![[0u8; 32]; public_inputs_length];
for (index, value) in public_inputs.into_iter().enumerate() {
let field: FieldPrime =
FieldPrime::try_from_str(value.trim_start_matches("0x"), 16).unwrap();
public_inputs_arr[index] = vec_as_u8_32_array(&field.into_byte_vector());
public_inputs_arr[index] = vec_as_u8_32_array(&value.into_byte_vector());
}
(public_inputs_arr, public_inputs_length)

View file

@ -1,22 +1,21 @@
use std::collections::HashMap;
pub fn parse_vk(vk: String) -> HashMap<String, String> {
pub fn parse_vk(vk: String) -> Result<HashMap<String, String>, csv::Error> {
let mut reader = csv::ReaderBuilder::new()
.delimiter(b'=')
.has_headers(false)
.trim(csv::Trim::All)
.from_reader(vk.as_bytes());
.flexible(false)
.from_reader(vk.trim().as_bytes());
let mut map = HashMap::new();
let mut iterator = reader.deserialize::<(String, String)>();
while let Some(r) = iterator.next() {
if r.is_ok() {
let r = r.unwrap();
map.insert(r.0, r.1);
}
let r = r?;
map.insert(r.0, r.1);
}
map
Ok(map)
}
#[cfg(test)]
@ -24,20 +23,38 @@ mod tests {
use proof_system::bn128::utils::parser::parse_vk;
#[test]
fn parse_example() {
let example: &str = r#"
fn parse_valid_input() {
let example: String = r#"
a = 1
b = 2
"#;
"#
.to_string();
let map = parse_vk(example.to_string());
let map = parse_vk(example).unwrap();
assert_eq!("1", map.get("a").unwrap());
assert_eq!("2", map.get("b").unwrap());
}
#[test]
#[should_panic]
fn panic_on_invalid_delimiter() {
parse_vk("a , 1".to_string()).unwrap();
}
#[test]
#[should_panic]
fn panic_on_unequal_lengths() {
let example: String = r#"
a = 1
b = 2 = 3
"#
.to_string();
parse_vk(example).unwrap();
}
#[test]
fn parse_empty() {
let map = parse_vk(String::new());
let map = parse_vk(String::new()).unwrap();
assert!(map.is_empty());
}
}

View file

@ -24,6 +24,21 @@ impl SetupKeypair {
}
}
pub enum AbiVersion {
V1,
V2,
}
impl AbiVersion {
pub fn from(v: &str) -> Result<Self, &str> {
match v {
"v1" => Ok(AbiVersion::V1),
"v2" => Ok(AbiVersion::V2),
_ => Err("Invalid ABI version"),
}
}
}
pub trait ProofSystem {
fn setup(&self, program: ir::Prog<FieldPrime>) -> SetupKeypair;
@ -34,7 +49,7 @@ pub trait ProofSystem {
proving_key: Vec<u8>,
) -> String;
fn export_solidity_verifier(&self, vk: String, abi_v2: bool) -> String;
fn export_solidity_verifier(&self, vk: String, abi_version: AbiVersion) -> String;
fn verify(&self, vk: String, proof: String) -> bool;
}

View file

@ -795,7 +795,6 @@ impl<'ast> Checker<'ast> {
module_id: &ModuleId,
types: &TypeMap,
) -> Result<TypedStatement<'ast, T>, Vec<ErrorInner>> {
let pos = stat.pos();
match stat.value {
@ -3184,9 +3183,7 @@ mod tests {
let foo_statements: Vec<StatementNode<FieldPrime>> = vec![Statement::Return(
ExpressionList {
expressions: vec![
Expression::FieldConstant(FieldPrime::from(1)).mock(),
],
expressions: vec![Expression::FieldConstant(FieldPrime::from(1)).mock()],
}
.mock(),
)
@ -3197,20 +3194,36 @@ mod tests {
statements: foo_statements,
signature: UnresolvedSignature {
inputs: vec![],
outputs: vec![
UnresolvedType::FieldElement.mock(),
],
outputs: vec![UnresolvedType::FieldElement.mock()],
},
}
.mock();
let main_statements: Vec<StatementNode<FieldPrime>> = vec![
Statement::Declaration(absy::Variable::new("a", UnresolvedType::array(UnresolvedType::FieldElement.mock(), 1).mock()).mock()).mock(),
Statement::Definition(Assignee::Identifier("a".into()).mock(), Expression::InlineArray(vec![absy::SpreadOrExpression::Expression(Expression::FieldConstant(FieldPrime::from(0)).mock())]).mock()).mock(),
Statement::Declaration(
absy::Variable::new(
"a",
UnresolvedType::array(UnresolvedType::FieldElement.mock(), 1).mock(),
)
.mock(),
)
.mock(),
Statement::Definition(
Assignee::Identifier("a".into()).mock(),
Expression::InlineArray(vec![absy::SpreadOrExpression::Expression(
Expression::FieldConstant(FieldPrime::from(0)).mock(),
)])
.mock(),
)
.mock(),
Statement::MultipleDefinition(
vec![
Assignee::Select(box Assignee::Identifier("a").mock(), box RangeOrExpression::Expression(absy::Expression::FieldConstant(FieldPrime::from(0)).mock())).mock(),
],
vec![Assignee::Select(
box Assignee::Identifier("a").mock(),
box RangeOrExpression::Expression(
absy::Expression::FieldConstant(FieldPrime::from(0)).mock(),
),
)
.mock()],
Expression::FunctionCall("foo", vec![]).mock(),
)
.mock(),
@ -3254,15 +3267,13 @@ mod tests {
let mut checker = new_with_args(HashSet::new(), 0, HashSet::new());
assert_eq!(
checker.check_module(&"main".into(), &mut state),
Err(vec![
Error {
inner: ErrorInner {
pos: Some((Position::mock(), Position::mock())),
message: "Only assignment to identifiers is supported, found a[0]".into()
},
module_id: "main".into()
}
])
Err(vec![Error {
inner: ErrorInner {
pos: Some((Position::mock(), Position::mock())),
message: "Only assignment to identifiers is supported, found a[0]".into()
},
module_id: "main".into()
}])
);
}

View file

@ -20,13 +20,14 @@ declare module 'zokrates-js' {
pk: Uint8Array,
}
export type AbiVersion = "v1" | "v2";
export type ResolveCallback = (location: string, path: string) => ResolverResult;
export interface ZoKratesProvider {
compile(source: string, location: string, callback: ResolveCallback): CompilationArtifacts;
setup(program: Uint8Array): SetupKeypair;
computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult;
exportSolidityVerifier(verifyingKey: string, isAbiv2: boolean): string
exportSolidityVerifier(verifyingKey: string, abiVersion: AbiVersion): string;
generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array): string;
}

View file

@ -49,8 +49,8 @@ const initialize = async () => {
computeWitness: (artifacts, args) => {
return zokrates.compute_witness(artifacts, JSON.stringify(Array.from(args)));
},
exportSolidityVerifier: (verifyingKey, isAbiv2) => {
return zokrates.export_solidity_verifier(verifyingKey, isAbiv2);
exportSolidityVerifier: (verifyingKey, abiVersion) => {
return zokrates.export_solidity_verifier(verifyingKey, abiVersion);
},
generateProof: (program, witness, provingKey) => {
return zokrates.generate_proof(program, witness, provingKey);

View file

@ -8,7 +8,7 @@ use zokrates_common::Resolver;
use zokrates_core::compile::{compile as core_compile, CompilationArtifacts, CompileError};
use zokrates_core::imports::Error;
use zokrates_core::ir;
use zokrates_core::proof_system::{self, ProofSystem};
use zokrates_core::proof_system::{self, ProofSystem, AbiVersion};
use zokrates_core::typed_absy::abi::Abi;
use zokrates_core::typed_absy::types::Signature;
use zokrates_field::field::FieldPrime;
@ -162,10 +162,14 @@ pub fn setup(program: JsValue) -> Result<JsValue, JsValue> {
}
#[wasm_bindgen]
pub fn export_solidity_verifier(vk: JsValue, is_abi_v2: JsValue) -> JsValue {
pub fn export_solidity_verifier(vk: JsValue, abi_version: JsValue) -> Result<JsValue, JsValue> {
let abi_version = AbiVersion::from(abi_version.as_string().unwrap().as_str())
.map_err(|err| JsValue::from_str(err))?;
let verifier = proof_system::G16 {}
.export_solidity_verifier(vk.as_string().unwrap(), is_abi_v2.as_bool().unwrap());
JsValue::from_str(verifier.as_str())
.export_solidity_verifier(vk.as_string().unwrap(), abi_version);
Ok(JsValue::from_str(verifier.as_str()))
}
#[wasm_bindgen]