1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

gm17 and pghr13 native verification

This commit is contained in:
dark64 2020-04-14 20:48:17 +02:00
parent e3c4d863a7
commit e8d655e5ce
17 changed files with 633 additions and 380 deletions

43
Cargo.lock generated
View file

@ -80,6 +80,12 @@ dependencies = [
"libc",
]
[[package]]
name = "base64"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
[[package]]
name = "bellman_ce"
version = "0.3.1"
@ -384,21 +390,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "curl-sys"
version = "0.4.30+curl-7.69.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "923b38e423a8f47a4058e96f2a1fa2865a6231097ee860debd678d244277d50c"
dependencies = [
"cc",
"libc",
"libz-sys",
"openssl-sys",
"pkg-config",
"vcpkg",
"winapi",
]
[[package]]
name = "difference"
version = "1.0.0"
@ -559,9 +550,9 @@ dependencies = [
[[package]]
name = "git2"
version = "0.8.0"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0"
checksum = "ef222034f2069cfc5af01ce423574d3d9a3925bd4052912a14e5bcfd7ca9e47a"
dependencies = [
"bitflags",
"libc",
@ -607,9 +598,9 @@ checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
[[package]]
name = "idna"
version = "0.1.5"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
dependencies = [
"matches",
"unicode-bidi",
@ -663,12 +654,11 @@ checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
[[package]]
name = "libgit2-sys"
version = "0.7.11"
version = "0.12.2+1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1"
checksum = "a12c878ccc1a49ff71e264233a66d2114cdcc7fdc44c0ebe2b54075240831238"
dependencies = [
"cc",
"curl-sys",
"libc",
"libssh2-sys",
"libz-sys",
@ -870,9 +860,9 @@ dependencies = [
[[package]]
name = "percent-encoding"
version = "1.0.1"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pest"
@ -1439,9 +1429,9 @@ checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "url"
version = "1.7.2"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
dependencies = [
"idna",
"matches",
@ -1664,6 +1654,7 @@ name = "zokrates_core"
version = "0.4.2"
dependencies = [
"assert_cli",
"base64",
"bellman_ce 0.3.1 (git+https://github.com/matter-labs/bellman?rev=9e35737)",
"bincode",
"cc",

View file

@ -687,7 +687,13 @@ fn cli() -> Result<(), String> {
.map_err(|why| format!("couldn't read {}: {}", proof_path.display(), why))?;
println!("Performing verification...");
println!("Verified: {}", scheme.verify(vk, proof));
println!(
"The verification result is: {}",
match scheme.verify(vk, proof) {
true => "PASS",
false => "FAIL",
}
);
}
_ => unreachable!(),
}

View file

@ -7,7 +7,7 @@ readme = "README.md"
build = "build.rs"
[features]
default = []
default = ["libsnark"]
libsnark = ["cc", "cmake", "git2"]
wasm = ["bellman_ce/wasm", "zokrates_embed/wasm"]
multicore = ["bellman_ce/multicore"]
@ -25,6 +25,7 @@ serde_json = "1.0"
serde_bytes = "0.10"
bincode = "0.8.0"
hex = "0.4.2"
base64 = "0.12.0"
regex = "0.2"
pairing_ce = "0.18"
ff_ce = "0.7"
@ -44,4 +45,4 @@ wasm-bindgen-test = "0.3.0"
[build-dependencies]
cc = { version = "1.0", features = ["parallel"], optional = true }
cmake = { version = "0.1.31", optional = true }
git2 = { version = "0.8.0", optional = true }
git2 = { version = "0.13.1", optional = true }

View file

@ -1,5 +1,6 @@
#include "ffi.hpp"
void __free(uint8_t* ptr) {
free(ptr);
void __free(uint8_t* ptr)
{
free(ptr);
}

View file

@ -1,26 +1,33 @@
#pragma once
#include <stdint.h>
#include <cstdlib>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct buffer_t {
uint8_t* data;
int32_t length;
uint8_t* data;
int32_t length;
};
struct setup_result_t {
buffer_t vk;
buffer_t pk;
setup_result_t(buffer_t& vk_buf, buffer_t& pk_buf) : vk(vk_buf), pk(pk_buf) { }
setup_result_t(buffer_t& vk_buf, buffer_t& pk_buf)
: vk(vk_buf)
, pk(pk_buf)
{
}
};
struct proof_result_t {
buffer_t proof;
proof_result_t(buffer_t& proof_buf) : proof(proof_buf) { }
proof_result_t(buffer_t& proof_buf)
: proof(proof_buf)
{
}
};
void __free(uint8_t* ptr);
@ -29,7 +36,8 @@ void __free(uint8_t* ptr);
} // extern "C"
#endif
static inline void __alloc(buffer_t* buffer, size_t length) {
static inline void make_buffer(buffer_t* buffer, size_t length)
{
buffer->data = (uint8_t*)malloc(length);
buffer->length = length;
}

View file

@ -5,11 +5,12 @@
* @date 2017
*/
#include "util.hpp"
#include "gm17.hpp"
#include "util.hpp"
#include <cassert>
#include <string>
#include <fstream>
#include <sstream>
#include <string>
// contains definition of alt_bn128 ec public parameters
#include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp"
@ -23,111 +24,125 @@ using namespace libsnark;
using std::cout;
using std::endl;
namespace gm17
namespace gm17 {
r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp> createConstraintSystem(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
{
r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp> createConstraintSystem(const uint8_t* a, const uint8_t* b, const uint8_t* c, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
{
r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp> cs;
cs.primary_input_size = inputs;
cs.auxiliary_input_size = variables - inputs - 1; // ~one not included
r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp> cs;
cs.primary_input_size = inputs;
cs.auxiliary_input_size = variables - inputs - 1; // ~one not included
cout << "num variables: " << variables <<endl;
cout << "num constraints: " << constraints <<endl;
cout << "num inputs: " << inputs <<endl;
cout << "num variables: " << variables << endl;
cout << "num constraints: " << constraints << endl;
cout << "num inputs: " << inputs << endl;
struct VariableValueMapping {
int constraint_id;
int variable_id;
uint8_t variable_value[32];
};
struct VariableValueMapping {
int constraint_id;
int variable_id;
uint8_t variable_value[32];
};
const VariableValueMapping* a_vvmap = (VariableValueMapping*) a;
const VariableValueMapping* b_vvmap = (VariableValueMapping*) b;
const VariableValueMapping* c_vvmap = (VariableValueMapping*) c;
const VariableValueMapping* a_vvmap = (VariableValueMapping*)a;
const VariableValueMapping* b_vvmap = (VariableValueMapping*)b;
const VariableValueMapping* c_vvmap = (VariableValueMapping*)c;
int a_id = 0;
int b_id = 0;
int c_id = 0;
int a_id = 0;
int b_id = 0;
int c_id = 0;
// initialize curve parameters
libff::alt_bn128_pp::init_public_params();
// initialize curve parameters
libff::alt_bn128_pp::init_public_params();
for (int row = 0; row < constraints; row++)
{
linear_combination<libff::Fr<libff::alt_bn128_pp> > lin_comb_A, lin_comb_B, lin_comb_C;
while (a_id < a_len && a_vvmap[a_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(a_vvmap[a_id].variable_value);
if (!value.is_zero()) {
lin_comb_A.add_term(a_vvmap[a_id].variable_id, value);
}
a_id++;
for (int row = 0; row < constraints; row++) {
linear_combination<libff::Fr<libff::alt_bn128_pp>> lin_comb_a, lin_comb_b, lin_comb_c;
while (a_id < a_len && a_vvmap[a_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(a_vvmap[a_id].variable_value);
if (!value.is_zero()) {
lin_comb_a.add_term(a_vvmap[a_id].variable_id, value);
}
while (b_id < b_len && b_vvmap[b_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(b_vvmap[b_id].variable_value);
if (!value.is_zero()) {
lin_comb_B.add_term(b_vvmap[b_id].variable_id, value);
}
b_id++;
}
while (c_id < c_len && c_vvmap[c_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(c_vvmap[c_id].variable_value);
if (!value.is_zero()) {
lin_comb_C.add_term(c_vvmap[c_id].variable_id, value);
}
c_id++;
}
cs.add_constraint(r1cs_constraint<libff::Fr<libff::alt_bn128_pp> >(lin_comb_A, lin_comb_B, lin_comb_C));
a_id++;
}
return cs;
}
r1cs_se_ppzksnark_keypair<libff::alt_bn128_pp> generateKeypair(const r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp> &cs) {
return r1cs_se_ppzksnark_generator<libff::alt_bn128_pp>(cs); //from r1cs_se_ppzksnark.hpp
}
std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_key<libff::alt_bn128_pp>* vk)
{
std::stringstream ss;
unsigned queryLength = vk->query.size();
ss << "vk.h = " << outputPointG2AffineAsHex(vk->H) << endl;
ss << "vk.g_alpha = " << outputPointG1AffineAsHex(vk->G_alpha) << endl;
ss << "vk.h_beta = " << outputPointG2AffineAsHex(vk->H_beta) << endl;
ss << "vk.g_gamma = " << outputPointG1AffineAsHex(vk->G_gamma) << endl;
ss << "vk.h_gamma = " << outputPointG2AffineAsHex(vk->H_gamma) << endl;
ss << "vk.query.len() = " << queryLength << endl;
for (size_t i = 0; i < queryLength; ++i)
{
auto vk_query_i = outputPointG1AffineAsHex(vk->query[i]);
ss << "vk.query[" << i << "] = " << vk_query_i << endl;
}
return ss.str();
}
std::string serializeProof(r1cs_se_ppzksnark_proof<libff::alt_bn128_pp>* proof, const uint8_t* public_inputs, int32_t public_inputs_length)
{
std::stringstream ss;
ss << "{" << "\n";
ss << "\t\"proof\": {" << "\n";
ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->A) << ",\n";
ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->B) << ",\n";
ss << "\t\t\"c\": " << outputPointG1AffineAsHexJson(proof->C) << "\n";
ss << "\t}," << "\n";
ss << "\t\"inputs\": " << "[";
for (int i = 1; i < public_inputs_length; i++) {
if (i != 1) {
ss << ",";
while (b_id < b_len && b_vvmap[b_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(b_vvmap[b_id].variable_value);
if (!value.is_zero()) {
lin_comb_b.add_term(b_vvmap[b_id].variable_id, value);
}
ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i * 32));
b_id++;
}
ss << "]" << "\n";
ss << "}" << "\n";
std::string str = ss.str();
return str;
while (c_id < c_len && c_vvmap[c_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(c_vvmap[c_id].variable_value);
if (!value.is_zero()) {
lin_comb_c.add_term(c_vvmap[c_id].variable_id, value);
}
c_id++;
}
cs.add_constraint(r1cs_constraint<libff::Fr<libff::alt_bn128_pp>>(lin_comb_a, lin_comb_b, lin_comb_c));
}
return cs;
}
setup_result_t gm17_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
r1cs_se_ppzksnark_keypair<libff::alt_bn128_pp> generateKeypair(const r1cs_se_ppzksnark_constraint_system<libff::alt_bn128_pp>& cs)
{
return r1cs_se_ppzksnark_generator<libff::alt_bn128_pp>(cs); //from r1cs_se_ppzksnark.hpp
}
std::string serializeVerificationKey(r1cs_se_ppzksnark_verification_key<libff::alt_bn128_pp>* vk, bool include_raw)
{
std::stringstream ss;
unsigned queryLength = vk->query.size();
ss << "vk.h=" << outputPointG2AffineAsHex(vk->H) << endl;
ss << "vk.g_alpha=" << outputPointG1AffineAsHex(vk->G_alpha) << endl;
ss << "vk.h_beta=" << outputPointG2AffineAsHex(vk->H_beta) << endl;
ss << "vk.g_gamma=" << outputPointG1AffineAsHex(vk->G_gamma) << endl;
ss << "vk.h_gamma=" << outputPointG2AffineAsHex(vk->H_gamma) << endl;
ss << "vk.query.len()=" << queryLength << endl;
for (size_t i = 0; i < queryLength; ++i) {
auto vk_query_i = outputPointG1AffineAsHex(vk->query[i]);
ss << "vk.query[" << i << "]=" << vk_query_i << endl;
}
if (include_raw) {
std::stringstream ss_;
ss_ << *vk;
ss << "vk.raw=" << toHex(ss_.str()) << endl;
}
std::string str = ss.str();
return str;
}
std::string serializeProof(r1cs_se_ppzksnark_proof<libff::alt_bn128_pp>* proof, const uint8_t* public_inputs, int32_t public_inputs_length, bool include_raw)
{
std::stringstream ss;
ss << "{"
<< "\n";
ss << "\t\"proof\": {"
<< "\n";
ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->A) << ",\n";
ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->B) << ",\n";
ss << "\t\t\"c\": " << outputPointG1AffineAsHexJson(proof->C) << "\n";
ss << "\t},"
<< "\n";
ss << "\t\"inputs\": "
<< "[";
for (int i = 1; i < public_inputs_length; i++) {
if (i != 1) {
ss << ",";
}
ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i * 32));
}
ss << "]";
if (include_raw) {
std::stringstream ss_;
ss_ << *proof;
ss << ",\n\t\"raw\": \"" << toHex(ss_.str()) << "\"";
}
ss << "\n}"
<< "\n";
std::string str = ss.str();
return str;
}
}
setup_result_t gm17_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs, bool include_raw)
{
libff::inhibit_profiling_info = true;
libff::inhibit_profiling_counters = true;
@ -142,37 +157,25 @@ setup_result_t gm17_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C,
// create keypair
auto keypair = r1cs_se_ppzksnark_generator<libff::alt_bn128_pp>(cs);
auto vk = gm17::serializeVerificationKey(&keypair.vk);
auto vk = gm17::serializeVerificationKey(&keypair.vk, include_raw);
std::stringstream ss;
ss << keypair.pk;
std::string pk = ss.str();
buffer_t vk_buf, pk_buf;
__alloc(&vk_buf, vk.size());
__alloc(&pk_buf, pk.size());
vk.copy(reinterpret_cast<char*>(vk_buf.data), vk_buf.length);
pk.copy(reinterpret_cast<char*>(pk_buf.data), pk_buf.length);
buffer_t vk_buf = create_buffer(vk);
buffer_t pk_buf = create_buffer(keypair.pk);
setup_result_t result(vk_buf, pk_buf);
return result;
}
proof_result_t gm17_generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length)
proof_result_t gm17_generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length, bool include_raw)
{
libff::inhibit_profiling_info = true;
libff::inhibit_profiling_counters = true;
//initialize curve parameters
libff::alt_bn128_pp::init_public_params();
r1cs_se_ppzksnark_proving_key<libff::alt_bn128_pp> proving_key;
std::stringstream ss;
ss.write(reinterpret_cast<const char*>(pk_buf->data), pk_buf->length);
ss.rdbuf()->pubseekpos(0, std::ios_base::in);
ss >> proving_key;
r1cs_se_ppzksnark_proving_key<libff::alt_bn128_pp> proving_key;
from_buffer<r1cs_se_ppzksnark_proving_key<libff::alt_bn128_pp>>(pk_buf, proving_key);
// assign variables based on witness values, excludes ~one
r1cs_variable_assignment<libff::Fr<libff::alt_bn128_pp>> full_variable_assignment;
@ -195,12 +198,31 @@ proof_result_t gm17_generate_proof(buffer_t* pk_buf, const uint8_t* public_input
// Proof Generation
auto proof = r1cs_se_ppzksnark_prover<libff::alt_bn128_pp>(proving_key, primary_input, auxiliary_input);
auto proof_json = gm17::serializeProof(&proof, public_inputs, public_inputs_length);
auto proof_json = gm17::serializeProof(&proof, public_inputs, public_inputs_length, include_raw);
buffer_t proof_buf;
__alloc(&proof_buf, proof_json.size());
proof_json.copy(reinterpret_cast<char*>(proof_buf.data), proof_buf.length);
buffer_t proof_buf = create_buffer(proof_json);
proof_result_t result(proof_buf);
return result;
}
bool gm17_verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length)
{
libff::inhibit_profiling_info = true;
libff::inhibit_profiling_counters = true;
// initialize curve parameters
libff::alt_bn128_pp::init_public_params();
r1cs_se_ppzksnark_verification_key<libff::alt_bn128_pp> vk;
r1cs_se_ppzksnark_proof<libff::alt_bn128_pp> proof;
from_buffer<r1cs_se_ppzksnark_verification_key<libff::alt_bn128_pp>>(vk_buf, vk);
from_buffer<r1cs_se_ppzksnark_proof<libff::alt_bn128_pp>>(proof_buf, proof);
r1cs_primary_input<libff::Fr<libff::alt_bn128_pp>> primary_input;
for (int i = 0; i < public_inputs_length; i++) {
primary_input.push_back(libff::Fr<libff::alt_bn128_pp>(libsnarkBigintFromBytes(public_inputs + i * 32)));
}
return r1cs_se_ppzksnark_verifier_strong_IC<libff::alt_bn128_pp>(vk, primary_input, proof);
}

View file

@ -22,16 +22,22 @@ setup_result_t gm17_setup(
int32_t c_len,
int32_t constraints,
int32_t variables,
int32_t inputs
);
int32_t inputs,
bool include_raw);
proof_result_t gm17_generate_proof(
buffer_t* pk_buf,
const uint8_t* public_inputs,
int32_t public_inputs_length,
const uint8_t* private_inputs,
int32_t private_inputs_length
);
int32_t private_inputs_length,
bool include_raw);
bool gm17_verify(
buffer_t* vk_buf,
buffer_t* proof_buf,
const uint8_t* public_inputs,
int32_t public_inputs_length);
#ifdef __cplusplus
} // extern "C"

View file

@ -5,11 +5,11 @@
* @date 2017
*/
#include "util.hpp"
#include "pghr13.hpp"
#include "util.hpp"
#include <cassert>
#include <string>
#include <sstream>
#include <string>
// contains definitions of alt_bn128 ec public parameters
#include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp"
@ -23,119 +23,133 @@ using namespace libsnark;
using std::cout;
using std::endl;
namespace pghr13
namespace pghr13 {
r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp> createConstraintSystem(const uint8_t* a, const uint8_t* b, const uint8_t* c, int a_len, int b_len, int c_len, int constraints, int variables, int inputs)
{
r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp> createConstraintSystem(const uint8_t* a, const uint8_t* b, const uint8_t* c, int a_len, int b_len, int c_len, int constraints, int variables, int inputs)
{
r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp> cs;
cs.primary_input_size = inputs;
cs.auxiliary_input_size = variables - inputs - 1; // ~one not included
r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp> cs;
cs.primary_input_size = inputs;
cs.auxiliary_input_size = variables - inputs - 1; // ~one not included
cout << "num variables: " << variables <<endl;
cout << "num constraints: " << constraints <<endl;
cout << "num inputs: " << inputs <<endl;
cout << "num variables: " << variables << endl;
cout << "num constraints: " << constraints << endl;
cout << "num inputs: " << inputs << endl;
struct VariableValueMapping {
int constraint_id;
int variable_id;
uint8_t variable_value[32];
};
struct VariableValueMapping {
int constraint_id;
int variable_id;
uint8_t variable_value[32];
};
const VariableValueMapping* a_vvmap = (VariableValueMapping*) a;
const VariableValueMapping* b_vvmap = (VariableValueMapping*) b;
const VariableValueMapping* c_vvmap = (VariableValueMapping*) c;
const VariableValueMapping* a_vvmap = (VariableValueMapping*)a;
const VariableValueMapping* b_vvmap = (VariableValueMapping*)b;
const VariableValueMapping* c_vvmap = (VariableValueMapping*)c;
int a_id = 0;
int b_id = 0;
int c_id = 0;
int a_id = 0;
int b_id = 0;
int c_id = 0;
// initialize curve parameters
libff::alt_bn128_pp::init_public_params();
// initialize curve parameters
libff::alt_bn128_pp::init_public_params();
for (int row = 0; row < constraints; row++) {
linear_combination<libff::Fr<libff::alt_bn128_pp>> lin_comb_a, lin_comb_b, lin_comb_c;
while (a_id < a_len && a_vvmap[a_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(a_vvmap[a_id].variable_value);
if (!value.is_zero()) {
lin_comb_a.add_term(a_vvmap[a_id].variable_id, value);
}
a_id++;
for (int row = 0; row < constraints; row++) {
linear_combination<libff::Fr<libff::alt_bn128_pp>> lin_comb_a, lin_comb_b, lin_comb_c;
while (a_id < a_len && a_vvmap[a_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(a_vvmap[a_id].variable_value);
if (!value.is_zero()) {
lin_comb_a.add_term(a_vvmap[a_id].variable_id, value);
}
while (b_id < b_len && b_vvmap[b_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(b_vvmap[b_id].variable_value);
if (!value.is_zero()) {
lin_comb_b.add_term(b_vvmap[b_id].variable_id, value);
}
b_id++;
}
while (c_id < c_len && c_vvmap[c_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(c_vvmap[c_id].variable_value);
if (!value.is_zero()) {
lin_comb_c.add_term(c_vvmap[c_id].variable_id, value);
}
c_id++;
}
cs.add_constraint(r1cs_constraint<libff::Fr<libff::alt_bn128_pp>>(lin_comb_a, lin_comb_b, lin_comb_c));
a_id++;
}
return cs;
}
r1cs_ppzksnark_keypair<libff::alt_bn128_pp> generateKeypair(const r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp> &cs) {
return r1cs_ppzksnark_generator<libff::alt_bn128_pp>(cs); // from r1cs_ppzksnark.hpp
}
std::string serializeVerificationKey(r1cs_ppzksnark_verification_key<libff::alt_bn128_pp>* vk)
{
std::stringstream ss;
unsigned icLength = vk->encoded_IC_query.rest.indices.size() + 1;
ss << "vk.a = " << outputPointG2AffineAsHex(vk->alphaA_g2) << endl;
ss << "vk.b = " << outputPointG1AffineAsHex(vk->alphaB_g1) << endl;
ss << "vk.c = " << outputPointG2AffineAsHex(vk->alphaC_g2) << endl;
ss << "vk.gamma = " << outputPointG2AffineAsHex(vk->gamma_g2) << endl;
ss << "vk.gamma_beta_1 = " << outputPointG1AffineAsHex(vk->gamma_beta_g1) << endl;
ss << "vk.gamma_beta_2 = " << outputPointG2AffineAsHex(vk->gamma_beta_g2) << endl;
ss << "vk.z = " << outputPointG2AffineAsHex(vk->rC_Z_g2) << endl;
ss << "vk.ic.len() = " << icLength << endl;
ss << "vk.ic[0] = " << outputPointG1AffineAsHex(vk->encoded_IC_query.first) << endl;
for (size_t i = 1; i < icLength; ++i)
{
auto vk_ic_i = outputPointG1AffineAsHex(vk->encoded_IC_query.rest.values[i - 1]);
ss << "vk.ic[" << i << "] = " << vk_ic_i << endl;
}
std::string str = ss.str();
return str;
}
std::string serializeProof(r1cs_ppzksnark_proof<libff::alt_bn128_pp>* proof, const uint8_t* public_inputs, int public_inputs_length)
{
std::stringstream ss;
ss << "{" << "\n";
ss << "\t\"proof\": {" << "\n";
ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->g_A.g) << ",\n";
ss << "\t\t\"a_p\": " << outputPointG1AffineAsHexJson(proof->g_A.h) << ",\n";
ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->g_B.g) << ",\n";
ss << "\t\t\"b_p\": " << outputPointG1AffineAsHexJson(proof->g_B.h) << ",\n";
ss << "\t\t\"c\": " << outputPointG1AffineAsHexJson(proof->g_C.g) << ",\n";
ss << "\t\t\"c_p\": " << outputPointG1AffineAsHexJson(proof->g_C.h) << ",\n";
ss << "\t\t\"h\": " << outputPointG1AffineAsHexJson(proof->g_H) << ",\n";
ss << "\t\t\"k\": " << outputPointG1AffineAsHexJson(proof->g_K) << "\n";
ss << "\t}," << "\n";
ss << "\t\"inputs\": " << "[";
for (int i = 1; i < public_inputs_length; i++) {
if (i != 1) {
ss << ",";
while (b_id < b_len && b_vvmap[b_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(b_vvmap[b_id].variable_value);
if (!value.is_zero()) {
lin_comb_b.add_term(b_vvmap[b_id].variable_id, value);
}
ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i * 32));
b_id++;
}
ss << "]" << "\n";
ss << "}" << "\n";
std::string str = ss.str();
return str;
while (c_id < c_len && c_vvmap[c_id].constraint_id == row) {
libff::bigint<libff::alt_bn128_r_limbs> value = libsnarkBigintFromBytes(c_vvmap[c_id].variable_value);
if (!value.is_zero()) {
lin_comb_c.add_term(c_vvmap[c_id].variable_id, value);
}
c_id++;
}
cs.add_constraint(r1cs_constraint<libff::Fr<libff::alt_bn128_pp>>(lin_comb_a, lin_comb_b, lin_comb_c));
}
return cs;
}
setup_result_t pghr13_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs)
r1cs_ppzksnark_keypair<libff::alt_bn128_pp> generateKeypair(const r1cs_ppzksnark_constraint_system<libff::alt_bn128_pp>& cs)
{
return r1cs_ppzksnark_generator<libff::alt_bn128_pp>(cs); // from r1cs_ppzksnark.hpp
}
std::string serializeVerificationKey(r1cs_ppzksnark_verification_key<libff::alt_bn128_pp>* vk, bool include_raw)
{
std::stringstream ss;
unsigned icLength = vk->encoded_IC_query.rest.indices.size() + 1;
ss << "vk.a=" << outputPointG2AffineAsHex(vk->alphaA_g2) << endl;
ss << "vk.b=" << outputPointG1AffineAsHex(vk->alphaB_g1) << endl;
ss << "vk.c=" << outputPointG2AffineAsHex(vk->alphaC_g2) << endl;
ss << "vk.gamma=" << outputPointG2AffineAsHex(vk->gamma_g2) << endl;
ss << "vk.gamma_beta_1=" << outputPointG1AffineAsHex(vk->gamma_beta_g1) << endl;
ss << "vk.gamma_beta_2=" << outputPointG2AffineAsHex(vk->gamma_beta_g2) << endl;
ss << "vk.z=" << outputPointG2AffineAsHex(vk->rC_Z_g2) << endl;
ss << "vk.ic.len()=" << icLength << endl;
ss << "vk.ic[0]=" << outputPointG1AffineAsHex(vk->encoded_IC_query.first) << endl;
for (size_t i = 1; i < icLength; ++i) {
auto vk_ic_i = outputPointG1AffineAsHex(vk->encoded_IC_query.rest.values[i - 1]);
ss << "vk.ic[" << i << "]=" << vk_ic_i << endl;
}
if (include_raw) {
std::stringstream ss_;
ss_ << *vk;
ss << "vk.raw=" << toHex(ss_.str()) << endl;
}
std::string str = ss.str();
return str;
}
std::string serializeProof(r1cs_ppzksnark_proof<libff::alt_bn128_pp>* proof, const uint8_t* public_inputs, int public_inputs_length, bool include_raw)
{
std::stringstream ss;
ss << "{"
<< "\n";
ss << "\t\"proof\": {"
<< "\n";
ss << "\t\t\"a\": " << outputPointG1AffineAsHexJson(proof->g_A.g) << ",\n";
ss << "\t\t\"a_p\": " << outputPointG1AffineAsHexJson(proof->g_A.h) << ",\n";
ss << "\t\t\"b\": " << outputPointG2AffineAsHexJson(proof->g_B.g) << ",\n";
ss << "\t\t\"b_p\": " << outputPointG1AffineAsHexJson(proof->g_B.h) << ",\n";
ss << "\t\t\"c\": " << outputPointG1AffineAsHexJson(proof->g_C.g) << ",\n";
ss << "\t\t\"c_p\": " << outputPointG1AffineAsHexJson(proof->g_C.h) << ",\n";
ss << "\t\t\"h\": " << outputPointG1AffineAsHexJson(proof->g_H) << ",\n";
ss << "\t\t\"k\": " << outputPointG1AffineAsHexJson(proof->g_K) << "\n";
ss << "\t},"
<< "\n";
ss << "\t\"inputs\": "
<< "[";
for (int i = 1; i < public_inputs_length; i++) {
if (i != 1) {
ss << ",";
}
ss << outputInputAsHex(libsnarkBigintFromBytes(public_inputs + i * 32));
}
ss << "]";
if (include_raw) {
std::stringstream ss_;
ss_ << *proof;
ss << ",\n\t\"raw\": \"" << toHex(ss_.str()) << "\"";
}
ss << "\n}"
<< "\n";
std::string str = ss.str();
return str;
}
}
setup_result_t pghr13_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C, int32_t a_len, int32_t b_len, int32_t c_len, int32_t constraints, int32_t variables, int32_t inputs, bool include_raw)
{
libff::inhibit_profiling_info = true;
libff::inhibit_profiling_counters = true;
@ -151,37 +165,25 @@ setup_result_t pghr13_setup(const uint8_t* A, const uint8_t* B, const uint8_t* C
// create keypair
auto keypair = r1cs_ppzksnark_generator<libff::alt_bn128_pp>(cs);
auto vk = pghr13::serializeVerificationKey(&keypair.vk);
auto vk = pghr13::serializeVerificationKey(&keypair.vk, include_raw);
std::stringstream ss;
ss << keypair.pk;
std::string pk = ss.str();
buffer_t vk_buf, pk_buf;
__alloc(&vk_buf, vk.size());
__alloc(&pk_buf, pk.size());
vk.copy(reinterpret_cast<char*>(vk_buf.data), vk_buf.length);
pk.copy(reinterpret_cast<char*>(pk_buf.data), pk_buf.length);
buffer_t vk_buf = create_buffer(vk);
buffer_t pk_buf = create_buffer(keypair.pk);
setup_result_t result(vk_buf, pk_buf);
return result;
}
proof_result_t pghr13_generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length)
proof_result_t pghr13_generate_proof(buffer_t* pk_buf, const uint8_t* public_inputs, int32_t public_inputs_length, const uint8_t* private_inputs, int32_t private_inputs_length, bool include_raw)
{
libff::inhibit_profiling_info = true;
libff::inhibit_profiling_counters = true;
// initialize curve parameters
libff::alt_bn128_pp::init_public_params();
r1cs_ppzksnark_proving_key<libff::alt_bn128_pp> proving_key;
std::stringstream ss;
ss.write(reinterpret_cast<const char*>(pk_buf->data), pk_buf->length);
ss.rdbuf()->pubseekpos(0, std::ios_base::in);
ss >> proving_key;
r1cs_ppzksnark_proving_key<libff::alt_bn128_pp> proving_key;
from_buffer<r1cs_ppzksnark_proving_key<libff::alt_bn128_pp>>(pk_buf, proving_key);
// assign variables based on witness values, excludes ~one
r1cs_variable_assignment<libff::Fr<libff::alt_bn128_pp>> full_variable_assignment;
@ -204,12 +206,31 @@ proof_result_t pghr13_generate_proof(buffer_t* pk_buf, const uint8_t* public_inp
// Proof Generation
auto proof = r1cs_ppzksnark_prover<libff::alt_bn128_pp>(proving_key, primary_input, auxiliary_input);
auto proof_json = pghr13::serializeProof(&proof, public_inputs, public_inputs_length);
auto proof_json = pghr13::serializeProof(&proof, public_inputs, public_inputs_length, include_raw);
buffer_t proof_buf;
__alloc(&proof_buf, proof_json.size());
proof_json.copy(reinterpret_cast<char*>(proof_buf.data), proof_buf.length);
buffer_t proof_buf = create_buffer(proof_json);
proof_result_t result(proof_buf);
return result;
}
bool pghr13_verify(buffer_t* vk_buf, buffer_t* proof_buf, const uint8_t* public_inputs, int32_t public_inputs_length)
{
libff::inhibit_profiling_info = true;
libff::inhibit_profiling_counters = true;
// initialize curve parameters
libff::alt_bn128_pp::init_public_params();
r1cs_ppzksnark_verification_key<libff::alt_bn128_pp> vk;
r1cs_ppzksnark_proof<libff::alt_bn128_pp> proof;
from_buffer<r1cs_ppzksnark_verification_key<libff::alt_bn128_pp>>(vk_buf, vk);
from_buffer<r1cs_ppzksnark_proof<libff::alt_bn128_pp>>(proof_buf, proof);
r1cs_primary_input<libff::Fr<libff::alt_bn128_pp>> primary_input;
for (int i = 0; i < public_inputs_length; i++) {
primary_input.push_back(libff::Fr<libff::alt_bn128_pp>(libsnarkBigintFromBytes(public_inputs + i * 32)));
}
return r1cs_ppzksnark_verifier_strong_IC<libff::alt_bn128_pp>(vk, primary_input, proof);
}

View file

@ -22,16 +22,22 @@ setup_result_t pghr13_setup(
int32_t c_len,
int32_t constraints,
int32_t variables,
int32_t inputs
);
int32_t inputs,
bool include_raw);
proof_result_t pghr13_generate_proof(
buffer_t* pk_buf,
const uint8_t* public_inputs,
int32_t public_inputs_length,
const uint8_t* private_inputs,
int32_t private_inputs_length
);
int32_t private_inputs_length,
bool include_raw);
bool pghr13_verify(
buffer_t* vk_buf,
buffer_t* proof_buf,
const uint8_t* public_inputs,
int32_t public_inputs_length);
#ifdef __cplusplus
} // extern "C"

View file

@ -16,10 +16,21 @@ libff::bigint<libff::alt_bn128_r_limbs> libsnarkBigintFromBytes(const uint8_t* _
x.data[3 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7 - j));
}
}
return x;
}
std::string toHex(const std::string& in)
{
std::ostringstream out;
out << std::setfill('0');
for (unsigned char const& c : in) {
out << std::hex << std::setw(2) << static_cast<unsigned int>(c);
}
return out.str();
}
std::string HexStringFromLibsnarkBigint(libff::bigint<libff::alt_bn128_r_limbs> _x)
{
uint8_t x[32];
@ -28,15 +39,12 @@ std::string HexStringFromLibsnarkBigint(libff::bigint<libff::alt_bn128_r_limbs>
x[i * 8 + j] = uint8_t(uint64_t(_x.data[3 - i]) >> (8 * (7 - j)));
}
}
std::stringstream ss;
ss << std::setfill('0');
for (unsigned i = 0; i < 32; i++) {
ss << std::hex << std::setw(2) << (int)x[i];
}
return ss.str();
std::string tmp((char*)x, 32);
return toHex(tmp);
}
std::string outputInputAsHex(libff::bigint<libff::alt_bn128_r_limbs> _x) {
std::string outputInputAsHex(libff::bigint<libff::alt_bn128_r_limbs> _x)
{
return "\"0x" + HexStringFromLibsnarkBigint(_x) + "\"";
}
@ -44,38 +52,26 @@ std::string outputPointG1AffineAsHex(libff::alt_bn128_G1 _p)
{
libff::alt_bn128_G1 aff = _p;
aff.to_affine_coordinates();
return "0x" +
HexStringFromLibsnarkBigint(aff.X.as_bigint()) + ", 0x" +
HexStringFromLibsnarkBigint(aff.Y.as_bigint());
return "0x" + HexStringFromLibsnarkBigint(aff.X.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.Y.as_bigint());
}
std::string outputPointG1AffineAsHexJson(libff::alt_bn128_G1 _p)
{
libff::alt_bn128_G1 aff = _p;
aff.to_affine_coordinates();
return "[\"0x" +
HexStringFromLibsnarkBigint(aff.X.as_bigint()) + "\", \"0x" +
HexStringFromLibsnarkBigint(aff.Y.as_bigint())+"\"]";
return "[\"0x" + HexStringFromLibsnarkBigint(aff.X.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.Y.as_bigint()) + "\"]";
}
std::string outputPointG2AffineAsHex(libff::alt_bn128_G2 _p)
{
libff::alt_bn128_G2 aff = _p;
aff.to_affine_coordinates();
return "[0x" +
HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + ", 0x" +
HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "], [0x" +
HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + ", 0x" +
HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "]";
return "[0x" + HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "], [0x" + HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + ", 0x" + HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "]";
}
std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p)
{
libff::alt_bn128_G2 aff = _p;
aff.to_affine_coordinates();
return "[[\"0x" +
HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + "\", \"0x" +
HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "\"], [\"0x" +
HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + "\", \"0x" +
HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "\"]]";
}
return "[[\"0x" + HexStringFromLibsnarkBigint(aff.X.c1.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.X.c0.as_bigint()) + "\"], [\"0x" + HexStringFromLibsnarkBigint(aff.Y.c1.as_bigint()) + "\", \"0x" + HexStringFromLibsnarkBigint(aff.Y.c0.as_bigint()) + "\"]]";
}

View file

@ -1,18 +1,43 @@
#pragma once
// contains definitions of alt_bn128 ec public parameters
#include "ffi.hpp"
#include "libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#include <cassert>
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
libff::bigint<libff::alt_bn128_r_limbs> libsnarkBigintFromBytes(const uint8_t* _x);
std::string toHex(const std::string& s);
std::string HexStringFromLibsnarkBigint(libff::bigint<libff::alt_bn128_r_limbs> _x);
std::string outputInputAsHex(libff::bigint<libff::alt_bn128_r_limbs> _x);
std::string outputPointG1AffineAsHex(libff::alt_bn128_G1 _p);
std::string outputPointG1AffineAsHexJson(libff::alt_bn128_G1 _p);
std::string outputPointG2AffineAsHex(libff::alt_bn128_G2 _p);
std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p);
std::string outputPointG2AffineAsHexJson(libff::alt_bn128_G2 _p);
template <typename T>
inline void from_buffer(buffer_t* buffer, T& t)
{
std::string tmp((char*)buffer->data, buffer->length);
std::stringstream ss(tmp);
ss >> t;
}
template <typename T>
inline buffer_t create_buffer(T& t)
{
std::stringstream ss;
ss << t;
std::string tmp = ss.str();
buffer_t buffer;
make_buffer(&buffer, tmp.length());
tmp.copy(reinterpret_cast<char*>(buffer.data), buffer.length);
return buffer;
}

View file

@ -1,4 +1,7 @@
use bellman::groth16::*;
use bellman::groth16::{
prepare_verifying_key, verify_proof, Parameters, PreparedVerifyingKey, Proof as BellmanProof,
VerifyingKey,
};
use bellman::pairing::bn256::{Bn256, Fr};
use regex::Regex;
@ -14,6 +17,7 @@ use crate::proof_system::bn128::utils::solidity::{
SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
};
use crate::proof_system::{ProofSystem, SetupKeypair};
use proof_system::bn128::{G1PairingPoint, G2PairingPoint, Proof};
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.";
@ -25,9 +29,6 @@ impl G16 {
}
}
type G1PairingPoint = (String, String);
type G2PairingPoint = (G1PairingPoint, G1PairingPoint);
#[derive(Serialize, Deserialize)]
struct G16ProofPoints {
a: G1PairingPoint,
@ -35,24 +36,13 @@ struct G16ProofPoints {
c: G1PairingPoint,
}
#[derive(Serialize, Deserialize)]
struct G16Proof {
proof: G16ProofPoints,
inputs: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
raw: Option<String>,
}
impl G16ProofPoints {
fn new(a: G1PairingPoint, b: G2PairingPoint, c: G1PairingPoint) -> Self {
G16ProofPoints { a, b, c }
}
}
impl G16Proof {
fn new(proof: G16ProofPoints, inputs: Vec<String>, raw: Option<String>) -> Self {
G16Proof { proof, inputs, raw }
}
impl Proof<G16ProofPoints> {
fn from_json(str: &str) -> Self {
serde_json::from_str(str).unwrap()
}
@ -106,9 +96,10 @@ impl ProofSystem for G16 {
let mut raw: Vec<u8> = Vec::new();
proof.write(&mut raw).unwrap();
G16Proof::new(proof_points, inputs, Some(hex::encode(&raw))).to_json_pretty()
Proof::<G16ProofPoints>::new(proof_points, inputs, Some(base64::encode(&raw)))
.to_json_pretty()
} else {
G16Proof::new(proof_points, inputs, None).to_json_pretty()
Proof::<G16ProofPoints>::new(proof_points, inputs, None).to_json_pretty()
}
}
@ -185,26 +176,11 @@ impl ProofSystem for G16 {
}
fn verify(&self, vk: String, proof: String) -> bool {
let vk_map = parse_vk(vk);
let vk_raw = vk_map.get("vk.raw");
assert!(
vk_raw.is_some(),
"Missing \"vk.raw\" key; pass \"--raw\" flag when running setup"
);
let vk_raw = hex::decode(vk_raw.unwrap()).unwrap();
let vk: VerifyingKey<Bn256> = VerifyingKey::read(vk_raw.as_slice()).unwrap();
let vk: VerifyingKey<Bn256> = get_raw_vk(vk);
let pvk: PreparedVerifyingKey<Bn256> = prepare_verifying_key(&vk);
let g16_proof = G16Proof::from_json(proof.as_str());
assert!(
g16_proof.raw.is_some(),
"Missing \"raw\" field in proof; pass \"--raw\" flag when generating proof"
);
let raw_proof = hex::decode(g16_proof.raw.unwrap()).unwrap();
let bellman_proof: Proof<Bn256> = Proof::read(raw_proof.as_slice()).unwrap();
let g16_proof: Proof<G16ProofPoints> = Proof::from_json(proof.as_str());
let proof: BellmanProof<Bn256> = get_raw_proof(&g16_proof);
let public_inputs: Vec<Fr> = g16_proof
.inputs
@ -216,10 +192,30 @@ impl ProofSystem for G16 {
})
.collect::<Vec<_>>();
verify_proof(&pvk, &bellman_proof, &public_inputs).unwrap()
verify_proof(&pvk, &proof, &public_inputs).unwrap()
}
}
fn get_raw_proof(proof: &Proof<G16ProofPoints>) -> BellmanProof<Bn256> {
assert!(
proof.raw.is_some(),
"Missing \"raw\" field in proof: pass \"--raw\" flag when generating proof"
);
let proof = base64::decode(proof.raw.as_ref().unwrap()).unwrap();
BellmanProof::read(proof.as_slice()).unwrap()
}
fn get_raw_vk(vk: String) -> VerifyingKey<Bn256> {
let map = parse_vk(vk);
let raw = map.get("vk.raw");
assert!(
raw.is_some(),
"Missing \"vk.raw\" key: pass \"--raw\" flag when running setup"
);
let raw = base64::decode(raw.unwrap()).unwrap();
VerifyingKey::read(raw.as_slice()).unwrap()
}
fn serialize_vk(vk: VerifyingKey<Bn256>, include_raw: bool) -> String {
let mut writer = csv::WriterBuilder::new()
.delimiter(b'=')
@ -256,7 +252,7 @@ fn serialize_vk(vk: VerifyingKey<Bn256>, include_raw: bool) -> String {
vk.write(&mut raw).unwrap();
writer
.write_record(&["vk.raw", hex::encode(&raw).as_str()])
.write_record(&["vk.raw", base64::encode(&raw).as_str()])
.unwrap();
}

View file

@ -2,11 +2,14 @@ use regex::Regex;
use ir;
use proof_system::bn128::utils::ffi::{Buffer, ProofResult, SetupResult};
use proof_system::bn128::utils::libsnark::{prepare_generate_proof, prepare_setup};
use proof_system::bn128::utils::libsnark::{
prepare_generate_proof, prepare_public_inputs, prepare_setup,
};
use proof_system::bn128::utils::parser::parse_vk;
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;
@ -18,6 +21,19 @@ impl GM17 {
}
}
#[derive(Serialize, Deserialize)]
struct GM17ProofPoints {
a: G1PairingPoint,
b: G2PairingPoint,
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,
@ -29,6 +45,7 @@ extern "C" {
constraints: i32,
variables: i32,
inputs: i32,
include_raw: bool,
) -> SetupResult;
fn gm17_generate_proof(
@ -37,11 +54,19 @@ extern "C" {
public_query_inputs_length: i32,
private_inputs: *const u8,
private_inputs_length: i32,
include_raw: bool,
) -> ProofResult;
fn gm17_verify(
vk_buf: *mut Buffer,
proof_buf: *mut Buffer,
public_inputs: *const u8,
public_inputs_length: i32,
) -> bool;
}
impl ProofSystem for GM17 {
fn setup(&self, program: ir::Prog<FieldPrime>, _include_raw: bool) -> SetupKeypair {
fn setup(&self, program: ir::Prog<FieldPrime>, include_raw: bool) -> SetupKeypair {
let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) =
prepare_setup(program);
@ -56,6 +81,7 @@ impl ProofSystem for GM17 {
num_constraints as i32,
num_variables as i32,
num_inputs as i32,
include_raw,
);
let vk: Vec<u8> =
@ -79,34 +105,36 @@ impl ProofSystem for GM17 {
program: ir::Prog<FieldPrime>,
witness: ir::Witness<FieldPrime>,
proving_key: Vec<u8>,
_include_raw: bool,
include_raw: bool,
) -> String {
let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) =
prepare_generate_proof(program, witness);
let mut pk = proving_key.clone();
let mut pk_buf = Buffer::from_vec(pk.as_mut());
let proof_vec = unsafe {
let proof = unsafe {
let mut pk_buffer = Buffer::from_vec(&proving_key);
let result = gm17_generate_proof(
&mut pk_buf as *mut _,
&mut pk_buffer as *mut _,
public_inputs_arr[0].as_ptr(),
public_inputs_length as i32,
private_inputs_arr[0].as_ptr(),
private_inputs_length as i32,
include_raw,
);
pk_buffer.drop(); // drop the buffer manually
let proof: Vec<u8> =
std::slice::from_raw_parts(result.proof.data, result.proof.length as usize)
.to_vec();
// Memory is allocated in C and raw pointers are returned to Rust. The caller has to manually
// free the memory.
let proof_vec: Vec<u8> =
std::slice::from_raw_parts(result.proof.data, result.proof.length as usize)
.to_vec();
result.proof.free();
proof_vec
proof
};
String::from_utf8(proof_vec).unwrap()
String::from_utf8(proof).unwrap()
}
fn export_solidity_verifier(&self, vk: String, abi_v2: bool) -> String {
@ -186,8 +214,43 @@ impl ProofSystem for GM17 {
)
}
fn verify(&self, _vk: String, _proof: String) -> bool {
unimplemented!()
fn verify(&self, vk: String, proof: String) -> bool {
let map = parse_vk(vk);
let vk_raw = map.get("vk.raw");
assert!(
vk_raw.is_some(),
"Missing \"vk.raw\" key: pass \"--raw\" flag when running setup"
);
let proof: Proof<GM17ProofPoints> = Proof::from_json(proof.as_str());
assert!(
proof.raw.is_some(),
"Missing \"raw\" field in proof: pass \"--raw\" flag when generating proof"
);
let vk_raw = hex::decode(vk_raw.unwrap().clone()).unwrap();
let proof_raw = hex::decode(proof.raw.unwrap().clone()).unwrap();
let public_inputs: Vec<&str> = proof.inputs.iter().map(|v| v.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 ans = gm17_verify(
&mut vk_buffer as *mut _,
&mut proof_buffer as *mut _,
public_inputs_arr[0].as_ptr(),
public_inputs_length as i32,
);
vk_buffer.drop();
proof_buffer.drop();
ans
}
}
}

View file

@ -11,3 +11,20 @@ pub use self::g16::G16;
pub use self::gm17::GM17;
#[cfg(feature = "libsnark")]
pub use self::pghr13::PGHR13;
type G1PairingPoint = (String, String);
type G2PairingPoint = (G1PairingPoint, G1PairingPoint);
#[derive(Serialize, Deserialize)]
struct Proof<T> {
proof: T,
inputs: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
raw: Option<String>,
}
impl<T> Proof<T> {
fn new(proof: T, inputs: Vec<String>, raw: Option<String>) -> Self {
Proof { proof, inputs, raw }
}
}

View file

@ -1,10 +1,13 @@
use ir;
use proof_system::bn128::utils::ffi::{Buffer, ProofResult, SetupResult};
use proof_system::bn128::utils::libsnark::{prepare_generate_proof, prepare_setup};
use proof_system::bn128::utils::libsnark::{
prepare_generate_proof, prepare_public_inputs, prepare_setup,
};
use proof_system::bn128::utils::parser::parse_vk;
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 regex::Regex;
use zokrates_field::field::FieldPrime;
@ -17,6 +20,24 @@ impl PGHR13 {
}
}
#[derive(Serialize, Deserialize)]
struct PGHR13ProofPoints {
a: G1PairingPoint,
a_p: G1PairingPoint,
b: G2PairingPoint,
b_p: G1PairingPoint,
c: G1PairingPoint,
c_p: G1PairingPoint,
h: G1PairingPoint,
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,
@ -28,6 +49,7 @@ extern "C" {
constraints: i32,
variables: i32,
inputs: i32,
include_raw: bool,
) -> SetupResult;
fn pghr13_generate_proof(
@ -36,11 +58,19 @@ extern "C" {
public_query_inputs_length: i32,
private_inputs: *const u8,
private_inputs_length: i32,
include_raw: bool,
) -> ProofResult;
fn pghr13_verify(
vk_buf: *mut Buffer,
proof_buf: *mut Buffer,
public_inputs: *const u8,
public_inputs_length: i32,
) -> bool;
}
impl ProofSystem for PGHR13 {
fn setup(&self, program: ir::Prog<FieldPrime>, _include_raw: bool) -> SetupKeypair {
fn setup(&self, program: ir::Prog<FieldPrime>, include_raw: bool) -> SetupKeypair {
let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) =
prepare_setup(program);
@ -55,6 +85,7 @@ impl ProofSystem for PGHR13 {
num_constraints as i32,
num_variables as i32,
num_inputs as i32,
include_raw,
);
let vk: Vec<u8> =
@ -78,23 +109,25 @@ impl ProofSystem for PGHR13 {
program: ir::Prog<FieldPrime>,
witness: ir::Witness<FieldPrime>,
proving_key: Vec<u8>,
_include_raw: bool,
include_raw: bool,
) -> String {
let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) =
prepare_generate_proof(program, witness);
let mut pk = proving_key.clone();
let mut pk_buf = Buffer::from_vec(pk.as_mut());
let proof_vec = unsafe {
let mut pk_buf = Buffer::from_vec(&proving_key);
let result = pghr13_generate_proof(
&mut pk_buf as *mut _,
public_inputs_arr[0].as_ptr(),
public_inputs_length as i32,
private_inputs_arr[0].as_ptr(),
private_inputs_length as i32,
include_raw,
);
pk_buf.drop(); // drop the buffer manually
let proof_vec: Vec<u8> =
std::slice::from_raw_parts(result.proof.data, result.proof.length as usize)
.to_vec();
@ -185,8 +218,43 @@ impl ProofSystem for PGHR13 {
)
}
fn verify(&self, _vk: String, _proof: String) -> bool {
unimplemented!()
fn verify(&self, vk: String, proof: String) -> bool {
let map = parse_vk(vk);
let vk_raw = map.get("vk.raw");
assert!(
vk_raw.is_some(),
"Missing \"vk.raw\" key: pass \"--raw\" flag when running setup"
);
let proof: Proof<PGHR13ProofPoints> = Proof::from_json(proof.as_str());
assert!(
proof.raw.is_some(),
"Missing \"raw\" field in proof: pass \"--raw\" flag when generating proof"
);
let vk_raw = hex::decode(vk_raw.unwrap().clone()).unwrap();
let proof_raw = hex::decode(proof.raw.unwrap().clone()).unwrap();
let public_inputs: Vec<&str> = proof.inputs.iter().map(|v| v.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 ans = pghr13_verify(
&mut vk_buffer as *mut _,
&mut proof_buffer as *mut _,
public_inputs_arr[0].as_ptr(),
public_inputs_length as i32,
);
vk_buffer.drop();
proof_buffer.drop();
ans
}
}
}

View file

@ -20,14 +20,27 @@ extern "C" {
}
impl Buffer {
pub fn from_vec(v: &mut Vec<u8>) -> Buffer {
let length = v.len() as i32;
pub unsafe fn from_vec(v: &Vec<u8>) -> Buffer {
let mut buf = vec![0; v.len()].into_boxed_slice();
buf.copy_from_slice(v.as_slice());
let data = buf.as_mut_ptr();
let len = buf.len();
std::mem::forget(buf);
Buffer {
data: v.as_mut_ptr(),
length,
data,
length: len as i32,
}
}
pub unsafe fn drop(&self) {
let s = std::slice::from_raw_parts_mut(self.data, self.length as usize);
let s = s.as_mut_ptr();
Box::from_raw(s);
}
/// The purpose of this function is to free memory previously allocated by "malloc"
/// from C standard library. Do not use otherwise.
pub fn free(self) {

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;
use zokrates_field::field::{Field, FieldPrime};
// 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,6 +14,19 @@ 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) {
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, public_inputs_length)
}
// proof-system-independent preparation for the setup phase
pub fn prepare_setup<T: Field>(
program: ir::Prog<T>,