gm17 and pghr13 native verification
This commit is contained in:
parent
e3c4d863a7
commit
e8d655e5ce
17 changed files with 633 additions and 380 deletions
43
Cargo.lock
generated
43
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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!(),
|
||||
}
|
||||
|
|
|
@ -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 }
|
|
@ -1,5 +1,6 @@
|
|||
#include "ffi.hpp"
|
||||
|
||||
void __free(uint8_t* ptr) {
|
||||
free(ptr);
|
||||
void __free(uint8_t* ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()) + "\"]]";
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>,
|
||||
|
|
Loading…
Reference in a new issue