minor refactor and cleanup, add tests to vk parser
This commit is contained in:
parent
c9b68a5147
commit
f2ebddb2fc
15 changed files with 200 additions and 159 deletions
|
@ -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
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "gm17.hpp"
|
||||
#include "util.hpp"
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
|
|
@ -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<_>>();
|
||||
|
|
|
@ -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 _,
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 _,
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}])
|
||||
);
|
||||
}
|
||||
|
||||
|
|
3
zokrates_js/index.d.ts
vendored
3
zokrates_js/index.d.ts
vendored
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in a new issue