Remove libsnark code for pre-Sapling Sprout proofs
This commit is contained in:
parent
93dae1db7d
commit
5f84491d82
|
@ -38,10 +38,8 @@ zcash_gtest_SOURCES += \
|
|||
gtest/test_transaction_builder.cpp \
|
||||
gtest/test_upgrades.cpp \
|
||||
gtest/test_validation.cpp \
|
||||
gtest/test_circuit.cpp \
|
||||
gtest/test_txid.cpp \
|
||||
gtest/test_libzcash_utils.cpp \
|
||||
gtest/test_proofs.cpp \
|
||||
gtest/test_pedersen_hash.cpp \
|
||||
gtest/test_checkblock.cpp \
|
||||
gtest/test_zip32.cpp
|
||||
|
|
|
@ -44,8 +44,6 @@ JSON_TEST_FILES = \
|
|||
test/data/merkle_witness_serialization_sapling.json \
|
||||
test/data/merkle_path_sapling.json \
|
||||
test/data/merkle_commitments_sapling.json \
|
||||
test/data/g1_compressed.json \
|
||||
test/data/g2_compressed.json \
|
||||
test/data/sapling_key_components.json
|
||||
|
||||
RAW_TEST_FILES = test/data/alertTests.raw
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
#include "zcash/JoinSplit.hpp"
|
||||
#include "util.h"
|
||||
|
||||
#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
|
||||
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
|
||||
|
||||
#include "librustzcash.h"
|
||||
|
||||
struct ECCryptoClosure
|
||||
|
@ -23,12 +20,7 @@ int main(int argc, char **argv) {
|
|||
assert(init_and_check_sodium() != -1);
|
||||
ECC_Start();
|
||||
|
||||
libsnark::default_r1cs_ppzksnark_pp::init_public_params();
|
||||
libsnark::inhibit_profiling_info = true;
|
||||
libsnark::inhibit_profiling_counters = true;
|
||||
boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key";
|
||||
boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
|
||||
params = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
|
||||
params = ZCJoinSplit::Prepared();
|
||||
|
||||
boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
|
||||
boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include "uint256.h"
|
||||
|
||||
#include "zcash/util.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
|
||||
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
|
||||
#include <libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp>
|
||||
#include <libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp>
|
||||
|
||||
#include "zcash/IncrementalMerkleTree.hpp"
|
||||
|
||||
using namespace libsnark;
|
||||
using namespace libzcash;
|
||||
|
||||
#include "zcash/circuit/utils.tcc"
|
||||
#include "zcash/circuit/merkle.tcc"
|
||||
|
||||
template<typename FieldT>
|
||||
void test_value_equals(uint64_t i) {
|
||||
protoboard<FieldT> pb;
|
||||
pb_variable_array<FieldT> num;
|
||||
num.allocate(pb, 64, "");
|
||||
num.fill_with_bits(pb, uint64_to_bool_vector(i));
|
||||
pb.add_r1cs_constraint(r1cs_constraint<FieldT>(
|
||||
packed_addition(num),
|
||||
FieldT::one(),
|
||||
FieldT::one() * i
|
||||
), "");
|
||||
ASSERT_TRUE(pb.is_satisfied());
|
||||
}
|
||||
|
||||
TEST(circuit, values)
|
||||
{
|
||||
typedef Fr<default_r1cs_ppzksnark_pp> FieldT;
|
||||
test_value_equals<FieldT>(0);
|
||||
test_value_equals<FieldT>(1);
|
||||
test_value_equals<FieldT>(3);
|
||||
test_value_equals<FieldT>(5391);
|
||||
test_value_equals<FieldT>(883128374);
|
||||
test_value_equals<FieldT>(173419028459);
|
||||
test_value_equals<FieldT>(2205843009213693953);
|
||||
}
|
||||
|
||||
TEST(circuit, endianness)
|
||||
{
|
||||
std::vector<unsigned char> before = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55,
|
||||
56, 57, 58, 59, 60, 61, 62, 63
|
||||
};
|
||||
auto result = swap_endianness_u64(before);
|
||||
|
||||
std::vector<unsigned char> after = {
|
||||
56, 57, 58, 59, 60, 61, 62, 63,
|
||||
48, 49, 50, 51, 52, 53, 54, 55,
|
||||
40, 41, 42, 43, 44, 45, 46, 47,
|
||||
32, 33, 34, 35, 36, 37, 38, 39,
|
||||
24, 25, 26, 27, 28, 29, 30, 31,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
0, 1, 2, 3, 4, 5, 6, 7
|
||||
};
|
||||
|
||||
EXPECT_EQ(after, result);
|
||||
|
||||
std::vector<unsigned char> bad = {0, 1, 2, 3};
|
||||
|
||||
ASSERT_THROW(swap_endianness_u64(bad), std::length_error);
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
bool test_merkle_gadget(
|
||||
bool enforce_a,
|
||||
bool enforce_b,
|
||||
bool write_root_first
|
||||
)
|
||||
{
|
||||
protoboard<FieldT> pb;
|
||||
digest_variable<FieldT> root(pb, 256, "root");
|
||||
pb.set_input_sizes(256);
|
||||
|
||||
digest_variable<FieldT> commitment1(pb, 256, "commitment1");
|
||||
digest_variable<FieldT> commitment2(pb, 256, "commitment2");
|
||||
|
||||
pb_variable<FieldT> commitment1_read;
|
||||
commitment1_read.allocate(pb);
|
||||
pb_variable<FieldT> commitment2_read;
|
||||
commitment2_read.allocate(pb);
|
||||
|
||||
merkle_tree_gadget<FieldT> mgadget1(pb, commitment1, root, commitment1_read);
|
||||
merkle_tree_gadget<FieldT> mgadget2(pb, commitment2, root, commitment2_read);
|
||||
|
||||
commitment1.generate_r1cs_constraints();
|
||||
commitment2.generate_r1cs_constraints();
|
||||
root.generate_r1cs_constraints();
|
||||
mgadget1.generate_r1cs_constraints();
|
||||
mgadget2.generate_r1cs_constraints();
|
||||
|
||||
SproutMerkleTree tree;
|
||||
uint256 commitment1_data = uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c");
|
||||
uint256 commitment2_data = uint256S("59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7");
|
||||
tree.append(commitment1_data);
|
||||
auto wit1 = tree.witness();
|
||||
tree.append(commitment2_data);
|
||||
wit1.append(commitment2_data);
|
||||
auto wit2 = tree.witness();
|
||||
auto expected_root = tree.root();
|
||||
tree.append(uint256S("3e243c8798678570bb8d42616c23a536af44be15c4eef073490c2a44ae5f32c3"));
|
||||
auto unexpected_root = tree.root();
|
||||
tree.append(uint256S("26d9b20c7f1c3d2528bbcd43cd63344b0afd3b6a0a8ebd37ec51cba34907bec7"));
|
||||
auto badwit1 = tree.witness();
|
||||
tree.append(uint256S("02c2467c9cd15e0d150f74cd636505ed675b0b71b66a719f6f52fdb49a5937bb"));
|
||||
auto badwit2 = tree.witness();
|
||||
|
||||
// Perform the test
|
||||
|
||||
pb.val(commitment1_read) = enforce_a ? FieldT::one() : FieldT::zero();
|
||||
pb.val(commitment2_read) = enforce_b ? FieldT::one() : FieldT::zero();
|
||||
|
||||
commitment1.bits.fill_with_bits(pb, uint256_to_bool_vector(commitment1_data));
|
||||
commitment2.bits.fill_with_bits(pb, uint256_to_bool_vector(commitment2_data));
|
||||
|
||||
if (write_root_first) {
|
||||
root.bits.fill_with_bits(pb, uint256_to_bool_vector(expected_root));
|
||||
}
|
||||
|
||||
mgadget1.generate_r1cs_witness(wit1.path());
|
||||
mgadget2.generate_r1cs_witness(wit2.path());
|
||||
|
||||
// Overwrite with our expected root
|
||||
root.bits.fill_with_bits(pb, uint256_to_bool_vector(expected_root));
|
||||
|
||||
return pb.is_satisfied();
|
||||
}
|
||||
|
||||
TEST(circuit, merkle_tree_gadget_weirdness)
|
||||
{
|
||||
/*
|
||||
The merkle tree gadget takes a leaf in the merkle tree (the Note commitment),
|
||||
a merkle tree authentication path, and a root (anchor). It also takes a parameter
|
||||
called read_success, which is used to determine if the commitment actually needs to
|
||||
appear in the tree.
|
||||
|
||||
If two input notes use the same root (which our protocol does) then if `read_success`
|
||||
is disabled on the first note but enabled on the second note (i.e., the first note
|
||||
has value of zero and second note has nonzero value) then there is an edge case in
|
||||
the witnessing behavior. The first witness will accidentally constrain the root to
|
||||
equal null (the default value of the anchor) and the second witness will actually
|
||||
copy the bits, violating the constraint system.
|
||||
|
||||
Notice that this edge case is not in the constraint system but in the witnessing
|
||||
behavior.
|
||||
*/
|
||||
|
||||
typedef Fr<default_r1cs_ppzksnark_pp> FieldT;
|
||||
|
||||
// Test the normal case
|
||||
ASSERT_TRUE(test_merkle_gadget<FieldT>(true, true, false));
|
||||
ASSERT_TRUE(test_merkle_gadget<FieldT>(true, true, true));
|
||||
|
||||
// Test the case where the first commitment is enforced but the second isn't
|
||||
// Works because the first read is performed before the second one
|
||||
ASSERT_TRUE(test_merkle_gadget<FieldT>(true, false, false));
|
||||
ASSERT_TRUE(test_merkle_gadget<FieldT>(true, false, true));
|
||||
|
||||
// Test the case where the first commitment isn't enforced but the second is
|
||||
// Doesn't work because the first multipacker witnesses the existing root (which
|
||||
// is null)
|
||||
ASSERT_TRUE(!test_merkle_gadget<FieldT>(false, true, false));
|
||||
|
||||
// Test the last again, except this time write the root first.
|
||||
ASSERT_TRUE(test_merkle_gadget<FieldT>(false, true, true));
|
||||
}
|
|
@ -26,17 +26,11 @@
|
|||
#include "zcash/IncrementalMerkleTree.hpp"
|
||||
#include "zcash/util.h"
|
||||
|
||||
#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
|
||||
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
|
||||
#include <libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp>
|
||||
#include <libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "json_test_vectors.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace libsnark;
|
||||
|
||||
template<>
|
||||
void expect_deser_same(const SproutTestingWitness& expected)
|
||||
|
@ -58,8 +52,7 @@ void test_tree(
|
|||
UniValue root_tests,
|
||||
UniValue ser_tests,
|
||||
UniValue witness_ser_tests,
|
||||
UniValue path_tests,
|
||||
bool libsnark_test
|
||||
UniValue path_tests
|
||||
)
|
||||
{
|
||||
size_t witness_ser_i = 0;
|
||||
|
@ -115,55 +108,6 @@ void test_tree(
|
|||
} else {
|
||||
auto path = wit.path();
|
||||
expect_test_vector(path_tests[path_i++], path);
|
||||
|
||||
if (libsnark_test) {
|
||||
typedef Fr<default_r1cs_ppzksnark_pp> FieldT;
|
||||
|
||||
protoboard<FieldT> pb;
|
||||
pb_variable_array<FieldT> positions;
|
||||
digest_variable<FieldT> commitment(pb, 256, "commitment");
|
||||
digest_variable<FieldT> root(pb, 256, "root");
|
||||
positions.allocate(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "pos");
|
||||
merkle_authentication_path_variable<FieldT, sha256_two_to_one_hash_gadget<FieldT>> authvars(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "auth");
|
||||
merkle_tree_check_read_gadget<FieldT, sha256_two_to_one_hash_gadget<FieldT>> auth(
|
||||
pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, positions, commitment, root, authvars, ONE, "path"
|
||||
);
|
||||
commitment.generate_r1cs_constraints();
|
||||
root.generate_r1cs_constraints();
|
||||
authvars.generate_r1cs_constraints();
|
||||
auth.generate_r1cs_constraints();
|
||||
|
||||
std::vector<bool> commitment_bv;
|
||||
{
|
||||
uint256 witnessed_commitment = wit.element();
|
||||
std::vector<unsigned char> commitment_v(witnessed_commitment.begin(), witnessed_commitment.end());
|
||||
commitment_bv = convertBytesVectorToVector(commitment_v);
|
||||
}
|
||||
|
||||
size_t path_index = convertVectorToInt(path.index);
|
||||
|
||||
commitment.bits.fill_with_bits(pb, bit_vector(commitment_bv));
|
||||
positions.fill_with_bits_of_uint64(pb, path_index);
|
||||
|
||||
authvars.generate_r1cs_witness(path_index, path.authentication_path);
|
||||
auth.generate_r1cs_witness();
|
||||
|
||||
std::vector<bool> root_bv;
|
||||
{
|
||||
uint256 witroot = wit.root();
|
||||
std::vector<unsigned char> root_v(witroot.begin(), witroot.end());
|
||||
root_bv = convertBytesVectorToVector(root_v);
|
||||
}
|
||||
|
||||
root.bits.fill_with_bits(pb, bit_vector(root_bv));
|
||||
|
||||
ASSERT_TRUE(pb.is_satisfied());
|
||||
|
||||
root_bv[0] = !root_bv[0];
|
||||
root.bits.fill_with_bits(pb, bit_vector(root_bv));
|
||||
|
||||
ASSERT_TRUE(!pb.is_satisfied());
|
||||
}
|
||||
}
|
||||
|
||||
// Check witness serialization
|
||||
|
@ -200,8 +144,7 @@ TEST(merkletree, vectors) {
|
|||
root_tests,
|
||||
ser_tests,
|
||||
witness_ser_tests,
|
||||
path_tests,
|
||||
true
|
||||
path_tests
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -217,8 +160,7 @@ TEST(merkletree, SaplingVectors) {
|
|||
root_tests,
|
||||
ser_tests,
|
||||
witness_ser_tests,
|
||||
path_tests,
|
||||
false
|
||||
path_tests
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,702 +0,0 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include "zcash/Proof.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
|
||||
#include <libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp>
|
||||
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
typedef libsnark::default_r1cs_ppzksnark_pp curve_pp;
|
||||
typedef libsnark::default_r1cs_ppzksnark_pp::G1_type curve_G1;
|
||||
typedef libsnark::default_r1cs_ppzksnark_pp::G2_type curve_G2;
|
||||
typedef libsnark::default_r1cs_ppzksnark_pp::GT_type curve_GT;
|
||||
typedef libsnark::default_r1cs_ppzksnark_pp::Fp_type curve_Fr;
|
||||
typedef libsnark::default_r1cs_ppzksnark_pp::Fq_type curve_Fq;
|
||||
typedef libsnark::default_r1cs_ppzksnark_pp::Fqe_type curve_Fq2;
|
||||
|
||||
#include "streams.h"
|
||||
#include "version.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
TEST(proofs, g1_pairing_at_infinity)
|
||||
{
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
auto r1 = curve_G1::random_element();
|
||||
auto r2 = curve_G2::random_element();
|
||||
ASSERT_TRUE(
|
||||
curve_pp::reduced_pairing(curve_G1::zero(), r2) ==
|
||||
curve_GT::one()
|
||||
);
|
||||
ASSERT_TRUE(
|
||||
curve_pp::final_exponentiation(
|
||||
curve_pp::double_miller_loop(
|
||||
curve_pp::precompute_G1(curve_G1::zero()),
|
||||
curve_pp::precompute_G2(r2),
|
||||
curve_pp::precompute_G1(curve_G1::zero()),
|
||||
curve_pp::precompute_G2(r2)
|
||||
)
|
||||
) ==
|
||||
curve_GT::one()
|
||||
);
|
||||
ASSERT_TRUE(
|
||||
curve_pp::final_exponentiation(
|
||||
curve_pp::double_miller_loop(
|
||||
curve_pp::precompute_G1(r1),
|
||||
curve_pp::precompute_G2(r2),
|
||||
curve_pp::precompute_G1(curve_G1::zero()),
|
||||
curve_pp::precompute_G2(r2)
|
||||
)
|
||||
) ==
|
||||
curve_pp::reduced_pairing(r1, r2)
|
||||
);
|
||||
ASSERT_TRUE(
|
||||
curve_pp::final_exponentiation(
|
||||
curve_pp::double_miller_loop(
|
||||
curve_pp::precompute_G1(curve_G1::zero()),
|
||||
curve_pp::precompute_G2(r2),
|
||||
curve_pp::precompute_G1(r1),
|
||||
curve_pp::precompute_G2(r2)
|
||||
)
|
||||
) ==
|
||||
curve_pp::reduced_pairing(r1, r2)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(proofs, g2_subgroup_check)
|
||||
{
|
||||
// all G2 elements are order r
|
||||
ASSERT_TRUE(libsnark::alt_bn128_modulus_r * curve_G2::random_element() == curve_G2::zero());
|
||||
|
||||
// but that doesn't mean all elements that satisfy the curve equation are in G2...
|
||||
curve_G2 p = curve_G2::one();
|
||||
|
||||
while (1) {
|
||||
// This will construct an order r(2q-r) point with high probability
|
||||
p.X = curve_Fq2::random_element();
|
||||
try {
|
||||
p.Y = ((p.X.squared() * p.X) + libsnark::alt_bn128_twist_coeff_b).sqrt();
|
||||
break;
|
||||
} catch(...) {}
|
||||
}
|
||||
|
||||
ASSERT_TRUE(p.is_well_formed()); // it's on the curve
|
||||
ASSERT_TRUE(libsnark::alt_bn128_modulus_r * p != curve_G2::zero()); // but not the order r subgroup..
|
||||
|
||||
{
|
||||
// libsnark unfortunately doesn't check, and the pairing will complete
|
||||
auto e = curve_Fr("149");
|
||||
auto a = curve_pp::reduced_pairing(curve_G1::one(), p);
|
||||
auto b = curve_pp::reduced_pairing(e * curve_G1::one(), p);
|
||||
|
||||
// though it will not preserve bilinearity
|
||||
ASSERT_TRUE((a^e) != b);
|
||||
}
|
||||
|
||||
{
|
||||
// so, our decompression API should not allow you to decompress G2 elements of that form!
|
||||
CompressedG2 badp(p);
|
||||
try {
|
||||
auto newp = badp.to_libsnark_g2<curve_G2>();
|
||||
FAIL() << "Expected std::runtime_error";
|
||||
} catch (std::runtime_error const & err) {
|
||||
EXPECT_EQ(err.what(), std::string("point is not in G2"));
|
||||
} catch(...) {
|
||||
FAIL() << "Expected std::runtime_error";
|
||||
}
|
||||
}
|
||||
|
||||
// educational purposes: showing that E'(Fp2) is of order r(2q-r),
|
||||
// by multiplying our random point in E' by (2q-r) = (q + q - r) to
|
||||
// get an element in G2
|
||||
{
|
||||
auto p1 = libsnark::alt_bn128_modulus_q * p;
|
||||
p1 = p1 + p1;
|
||||
p1 = p1 - (libsnark::alt_bn128_modulus_r * p);
|
||||
|
||||
ASSERT_TRUE(p1.is_well_formed());
|
||||
ASSERT_TRUE(libsnark::alt_bn128_modulus_r * p1 == curve_G2::zero());
|
||||
|
||||
CompressedG2 goodp(p1);
|
||||
auto newp = goodp.to_libsnark_g2<curve_G2>();
|
||||
|
||||
ASSERT_TRUE(newp == p1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(proofs, sqrt_zero)
|
||||
{
|
||||
ASSERT_TRUE(curve_Fq::zero() == curve_Fq::zero().sqrt());
|
||||
ASSERT_TRUE(curve_Fq2::zero() == curve_Fq2::zero().sqrt());
|
||||
}
|
||||
|
||||
TEST(proofs, sqrt_fq)
|
||||
{
|
||||
// Poor man's PRNG
|
||||
curve_Fq acc = curve_Fq("348957923485290374852379485") ^ 1000;
|
||||
|
||||
size_t quadratic_residues = 0;
|
||||
size_t quadratic_nonresidues = 0;
|
||||
|
||||
for (size_t i = 1; i < 1000; i++) {
|
||||
try {
|
||||
acc += curve_Fq("45634563456") ^ i;
|
||||
|
||||
curve_Fq x = acc.sqrt();
|
||||
ASSERT_TRUE((x*x) == acc);
|
||||
quadratic_residues += 1;
|
||||
} catch (std::runtime_error &e) {
|
||||
quadratic_nonresidues += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Half of all nonzero elements in Fp are quadratic residues
|
||||
ASSERT_TRUE(quadratic_residues == 511);
|
||||
ASSERT_TRUE(quadratic_nonresidues == 488);
|
||||
|
||||
for (size_t i = 0; i < 1000; i++) {
|
||||
curve_Fq x = curve_Fq::random_element();
|
||||
curve_Fq x2 = x * x;
|
||||
|
||||
ASSERT_TRUE((x2.sqrt() == x) || (x2.sqrt() == -x));
|
||||
}
|
||||
|
||||
// Test vectors
|
||||
ASSERT_TRUE(
|
||||
curve_Fq("5204065062716160319596273903996315000119019512886596366359652578430118331601")
|
||||
==
|
||||
curve_Fq("348579348568").sqrt()
|
||||
);
|
||||
ASSERT_THROW(curve_Fq("348579348569").sqrt(), std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(proofs, sqrt_fq2)
|
||||
{
|
||||
curve_Fq2 acc = curve_Fq2(
|
||||
curve_Fq("3456293840592348059238409578239048769348760238476029347885092384059238459834") ^ 1000,
|
||||
curve_Fq("2394578084760439457823945729347502374590283479582739485723945729384759823745") ^ 1000
|
||||
);
|
||||
|
||||
size_t quadratic_residues = 0;
|
||||
size_t quadratic_nonresidues = 0;
|
||||
|
||||
for (size_t i = 1; i < 1000; i++) {
|
||||
try {
|
||||
acc = acc + curve_Fq2(
|
||||
curve_Fq("5204065062716160319596273903996315000119019512886596366359652578430118331601") ^ i,
|
||||
curve_Fq("348957923485290374852379485348957923485290374852379485348957923485290374852") ^ i
|
||||
);
|
||||
|
||||
curve_Fq2 x = acc.sqrt();
|
||||
ASSERT_TRUE((x*x) == acc);
|
||||
quadratic_residues += 1;
|
||||
} catch (std::runtime_error &e) {
|
||||
quadratic_nonresidues += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Half of all nonzero elements in Fp^k are quadratic residues as long
|
||||
// as p != 2
|
||||
ASSERT_TRUE(quadratic_residues == 505);
|
||||
ASSERT_TRUE(quadratic_nonresidues == 494);
|
||||
|
||||
for (size_t i = 0; i < 1000; i++) {
|
||||
curve_Fq2 x = curve_Fq2::random_element();
|
||||
curve_Fq2 x2 = x * x;
|
||||
|
||||
ASSERT_TRUE((x2.sqrt() == x) || (x2.sqrt() == -x));
|
||||
}
|
||||
|
||||
// Test vectors
|
||||
ASSERT_THROW(curve_Fq2(
|
||||
curve_Fq("2"),
|
||||
curve_Fq("1")
|
||||
).sqrt(), std::runtime_error);
|
||||
|
||||
ASSERT_THROW(curve_Fq2(
|
||||
curve_Fq("3345897230485723946872934576923485762803457692345760237495682347502347589473"),
|
||||
curve_Fq("1234912378405347958234756902345768290345762348957605678245967234857634857676")
|
||||
).sqrt(), std::runtime_error);
|
||||
|
||||
curve_Fq2 x = curve_Fq2(
|
||||
curve_Fq("12844195307879678418043983815760255909500142247603239203345049921980497041944"),
|
||||
curve_Fq("7476417578426924565731404322659619974551724117137577781074613937423560117731")
|
||||
);
|
||||
|
||||
curve_Fq2 nx = -x;
|
||||
|
||||
curve_Fq2 x2 = curve_Fq2(
|
||||
curve_Fq("3345897230485723946872934576923485762803457692345760237495682347502347589474"),
|
||||
curve_Fq("1234912378405347958234756902345768290345762348957605678245967234857634857676")
|
||||
);
|
||||
|
||||
ASSERT_TRUE(x == x2.sqrt());
|
||||
ASSERT_TRUE(nx == -x2.sqrt());
|
||||
ASSERT_TRUE(x*x == x2);
|
||||
ASSERT_TRUE(nx*nx == x2);
|
||||
}
|
||||
|
||||
TEST(proofs, size_is_expected)
|
||||
{
|
||||
PHGRProof p;
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << p;
|
||||
|
||||
ASSERT_EQ(ss.size(), 296);
|
||||
}
|
||||
|
||||
TEST(proofs, fq_serializes_properly)
|
||||
{
|
||||
for (size_t i = 0; i < 1000; i++) {
|
||||
curve_Fq e = curve_Fq::random_element();
|
||||
|
||||
Fq e2(e);
|
||||
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << e2;
|
||||
|
||||
Fq e3;
|
||||
ss >> e3;
|
||||
|
||||
curve_Fq e4 = e3.to_libsnark_fq<curve_Fq>();
|
||||
|
||||
ASSERT_TRUE(e == e4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(proofs, fq2_serializes_properly)
|
||||
{
|
||||
for (size_t i = 0; i < 1000; i++) {
|
||||
curve_Fq2 e = curve_Fq2::random_element();
|
||||
|
||||
Fq2 e2(e);
|
||||
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << e2;
|
||||
|
||||
Fq2 e3;
|
||||
ss >> e3;
|
||||
|
||||
curve_Fq2 e4 = e3.to_libsnark_fq2<curve_Fq2>();
|
||||
|
||||
ASSERT_TRUE(e == e4);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T deserialize_tv(std::string s)
|
||||
{
|
||||
T e;
|
||||
CDataStream ss(ParseHex(s), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> e;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
curve_Fq deserialize_fq(std::string s)
|
||||
{
|
||||
return deserialize_tv<Fq>(s).to_libsnark_fq<curve_Fq>();
|
||||
}
|
||||
|
||||
curve_Fq2 deserialize_fq2(std::string s)
|
||||
{
|
||||
return deserialize_tv<Fq2>(s).to_libsnark_fq2<curve_Fq2>();
|
||||
}
|
||||
|
||||
TEST(proofs, fq_valid)
|
||||
{
|
||||
curve_Fq e = deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46");
|
||||
|
||||
ASSERT_TRUE(e == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"));
|
||||
ASSERT_TRUE(e != curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208581"));
|
||||
|
||||
curve_Fq e2 = deserialize_fq("30644e72e131a029b75045b68181585d97816a916871ca8d3c208c16d87cfd46");
|
||||
|
||||
ASSERT_TRUE(e2 == curve_Fq("21888242871839275222221885816603420866962577604863418715751138068690288573766"));
|
||||
}
|
||||
|
||||
TEST(proofs, fq_invalid)
|
||||
{
|
||||
// Should not be able to deserialize the modulus
|
||||
ASSERT_THROW(
|
||||
deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"),
|
||||
std::logic_error
|
||||
);
|
||||
|
||||
// Should not be able to deserialize the modulus plus one
|
||||
ASSERT_THROW(
|
||||
deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd48"),
|
||||
std::logic_error
|
||||
);
|
||||
|
||||
// Should not be able to deserialize a ridiculously out of bound int
|
||||
ASSERT_THROW(
|
||||
deserialize_fq("ff644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"),
|
||||
std::logic_error
|
||||
);
|
||||
}
|
||||
|
||||
TEST(proofs, fq2_valid)
|
||||
{
|
||||
// (q - 1) * q + q
|
||||
curve_Fq2 e = deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0");
|
||||
ASSERT_TRUE(e.c0 == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"));
|
||||
ASSERT_TRUE(e.c1 == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"));
|
||||
|
||||
curve_Fq2 e2 = deserialize_fq2("000000000000000000000000000000000000000000000000010245be1c91e3186bbbe1c430a93fcfc5aada4ab10c3492f70eea97a91c7b29554db55acffa34d2");
|
||||
ASSERT_TRUE(e2.c0 == curve_Fq("238769481237490823"));
|
||||
ASSERT_TRUE(e2.c1 == curve_Fq("384579238459723485"));
|
||||
|
||||
curve_Fq2 e3 = deserialize_fq2("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
|
||||
ASSERT_TRUE(e3.c0 == curve_Fq("0"));
|
||||
ASSERT_TRUE(e3.c1 == curve_Fq("0"));
|
||||
|
||||
curve_Fq2 e4 = deserialize_fq2("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
|
||||
ASSERT_TRUE(e4.c0 == curve_Fq("1"));
|
||||
ASSERT_TRUE(e4.c1 == curve_Fq("0"));
|
||||
}
|
||||
|
||||
TEST(proofs, fq2_invalid)
|
||||
{
|
||||
// (q - 1) * q + q is invalid
|
||||
ASSERT_THROW(
|
||||
deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b1"),
|
||||
std::logic_error
|
||||
);
|
||||
|
||||
// q * q + (q - 1) is invalid
|
||||
ASSERT_THROW(
|
||||
deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d34cced085b43e2f202a05e52ef18233a3d8371be725c8b8e7774e4b8ffda66f7"),
|
||||
std::logic_error
|
||||
);
|
||||
|
||||
// Ridiculously out of bounds
|
||||
ASSERT_THROW(
|
||||
deserialize_fq2("0fffc4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0"),
|
||||
std::logic_error
|
||||
);
|
||||
ASSERT_THROW(
|
||||
deserialize_fq2("ffffffff763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0"),
|
||||
std::logic_error
|
||||
);
|
||||
}
|
||||
|
||||
TEST(proofs, g1_serializes_properly)
|
||||
{
|
||||
// Cannot serialize zero
|
||||
{
|
||||
ASSERT_THROW({CompressedG1 g = CompressedG1(curve_G1::zero());}, std::domain_error);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 1000; i++) {
|
||||
curve_G1 e = curve_G1::random_element();
|
||||
|
||||
CompressedG1 e2(e);
|
||||
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << e2;
|
||||
|
||||
CompressedG1 e3;
|
||||
ss >> e3;
|
||||
|
||||
ASSERT_TRUE(e2 == e3);
|
||||
|
||||
curve_G1 e4 = e3.to_libsnark_g1<curve_G1>();
|
||||
|
||||
ASSERT_TRUE(e == e4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(proofs, g2_serializes_properly)
|
||||
{
|
||||
// Cannot serialize zero
|
||||
{
|
||||
ASSERT_THROW({CompressedG2 g = CompressedG2(curve_G2::zero());}, std::domain_error);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 1000; i++) {
|
||||
curve_G2 e = curve_G2::random_element();
|
||||
|
||||
CompressedG2 e2(e);
|
||||
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << e2;
|
||||
|
||||
CompressedG2 e3;
|
||||
ss >> e3;
|
||||
|
||||
ASSERT_TRUE(e2 == e3);
|
||||
|
||||
curve_G2 e4 = e3.to_libsnark_g2<curve_G2>();
|
||||
|
||||
ASSERT_TRUE(e == e4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(proofs, zksnark_serializes_properly)
|
||||
{
|
||||
auto example = libsnark::generate_r1cs_example_with_field_input<curve_Fr>(250, 4);
|
||||
example.constraint_system.swap_AB_if_beneficial();
|
||||
auto kp = libsnark::r1cs_ppzksnark_generator<curve_pp>(example.constraint_system);
|
||||
auto vkprecomp = libsnark::r1cs_ppzksnark_verifier_process_vk(kp.vk);
|
||||
|
||||
for (size_t i = 0; i < 20; i++) {
|
||||
auto badproof = PHGRProof::random_invalid();
|
||||
auto proof = badproof.to_libsnark_proof<libsnark::r1cs_ppzksnark_proof<curve_pp>>();
|
||||
|
||||
auto verifierEnabled = ProofVerifier::Strict();
|
||||
auto verifierDisabled = ProofVerifier::Disabled();
|
||||
// This verifier should catch the bad proof
|
||||
ASSERT_FALSE(verifierEnabled.check(
|
||||
kp.vk,
|
||||
vkprecomp,
|
||||
example.primary_input,
|
||||
proof
|
||||
));
|
||||
// This verifier won't!
|
||||
ASSERT_TRUE(verifierDisabled.check(
|
||||
kp.vk,
|
||||
vkprecomp,
|
||||
example.primary_input,
|
||||
proof
|
||||
));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 20; i++) {
|
||||
auto proof = libsnark::r1cs_ppzksnark_prover<curve_pp>(
|
||||
kp.pk,
|
||||
example.primary_input,
|
||||
example.auxiliary_input,
|
||||
example.constraint_system
|
||||
);
|
||||
|
||||
{
|
||||
auto verifierEnabled = ProofVerifier::Strict();
|
||||
auto verifierDisabled = ProofVerifier::Disabled();
|
||||
ASSERT_TRUE(verifierEnabled.check(
|
||||
kp.vk,
|
||||
vkprecomp,
|
||||
example.primary_input,
|
||||
proof
|
||||
));
|
||||
ASSERT_TRUE(verifierDisabled.check(
|
||||
kp.vk,
|
||||
vkprecomp,
|
||||
example.primary_input,
|
||||
proof
|
||||
));
|
||||
}
|
||||
|
||||
ASSERT_TRUE(libsnark::r1cs_ppzksnark_verifier_strong_IC<curve_pp>(
|
||||
kp.vk,
|
||||
example.primary_input,
|
||||
proof
|
||||
));
|
||||
|
||||
PHGRProof compressed_proof_0(proof);
|
||||
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << compressed_proof_0;
|
||||
|
||||
PHGRProof compressed_proof_1;
|
||||
ss >> compressed_proof_1;
|
||||
|
||||
ASSERT_TRUE(compressed_proof_0 == compressed_proof_1);
|
||||
|
||||
auto newproof = compressed_proof_1.to_libsnark_proof<libsnark::r1cs_ppzksnark_proof<curve_pp>>();
|
||||
|
||||
ASSERT_TRUE(proof == newproof);
|
||||
ASSERT_TRUE(libsnark::r1cs_ppzksnark_verifier_strong_IC<curve_pp>(
|
||||
kp.vk,
|
||||
example.primary_input,
|
||||
newproof
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(proofs, g1_deserialization)
|
||||
{
|
||||
CompressedG1 g;
|
||||
curve_G1 expected;
|
||||
|
||||
// Valid G1 element.
|
||||
{
|
||||
CDataStream ss(ParseHex("0230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> g;
|
||||
|
||||
expected.X = curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");
|
||||
expected.Y = curve_Fq("3969792565221544645472939191694882283483352126195956956354061729942568608776");
|
||||
expected.Z = curve_Fq::one();
|
||||
|
||||
ASSERT_TRUE(g.to_libsnark_g1<curve_G1>() == expected);
|
||||
}
|
||||
|
||||
// Its negation.
|
||||
{
|
||||
CDataStream ss(ParseHex("0330644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> g;
|
||||
|
||||
expected.X = curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");
|
||||
expected.Y = curve_Fq("3969792565221544645472939191694882283483352126195956956354061729942568608776");
|
||||
expected.Z = curve_Fq::one();
|
||||
|
||||
ASSERT_TRUE(g.to_libsnark_g1<curve_G1>() == -expected);
|
||||
}
|
||||
|
||||
// Invalid leading bytes
|
||||
{
|
||||
CDataStream ss(ParseHex("ff30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
||||
ASSERT_THROW(ss >> g, std::ios_base::failure);
|
||||
}
|
||||
|
||||
// Invalid point
|
||||
{
|
||||
CDataStream ss(ParseHex("0208c6d2adffacbc8438f09f321874ea66e2fcc29f8dcfec2caefa21ec8c96a77c"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> g;
|
||||
|
||||
ASSERT_THROW(g.to_libsnark_g1<curve_G1>(), std::runtime_error);
|
||||
}
|
||||
|
||||
// Point with out of bounds Fq
|
||||
{
|
||||
CDataStream ss(ParseHex("02ffc6d2adffacbc8438f09f321874ea66e2fcc29f8dcfec2caefa21ec8c96a77c"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> g;
|
||||
|
||||
ASSERT_THROW(g.to_libsnark_g1<curve_G1>(), std::logic_error);
|
||||
}
|
||||
|
||||
// Randomly produce valid G1 representations and fail/succeed to
|
||||
// turn them into G1 points based on whether they are valid.
|
||||
for (size_t i = 0; i < 5000; i++) {
|
||||
curve_Fq e = curve_Fq::random_element();
|
||||
CDataStream ss(ParseHex("02"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << Fq(e);
|
||||
CompressedG1 g;
|
||||
ss >> g;
|
||||
|
||||
try {
|
||||
curve_G1 g_real = g.to_libsnark_g1<curve_G1>();
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(proofs, g2_deserialization)
|
||||
{
|
||||
CompressedG2 g;
|
||||
curve_G2 expected = curve_G2::random_element();
|
||||
|
||||
// Valid G2 point
|
||||
{
|
||||
CDataStream ss(ParseHex("0a023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> g;
|
||||
|
||||
expected.X = curve_Fq2(
|
||||
curve_Fq("5923585509243758863255447226263146374209884951848029582715967108651637186684"),
|
||||
curve_Fq("5336385337059958111259504403491065820971993066694750945459110579338490853570")
|
||||
);
|
||||
expected.Y = curve_Fq2(
|
||||
curve_Fq("10374495865873200088116930399159835104695426846400310764827677226300185211748"),
|
||||
curve_Fq("5256529835065685814318509161957442385362539991735248614869838648137856366932")
|
||||
);
|
||||
expected.Z = curve_Fq2::one();
|
||||
|
||||
ASSERT_TRUE(g.to_libsnark_g2<curve_G2>() == expected);
|
||||
}
|
||||
|
||||
// Its negation
|
||||
{
|
||||
CDataStream ss(ParseHex("0b023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> g;
|
||||
|
||||
expected.X = curve_Fq2(
|
||||
curve_Fq("5923585509243758863255447226263146374209884951848029582715967108651637186684"),
|
||||
curve_Fq("5336385337059958111259504403491065820971993066694750945459110579338490853570")
|
||||
);
|
||||
expected.Y = curve_Fq2(
|
||||
curve_Fq("10374495865873200088116930399159835104695426846400310764827677226300185211748"),
|
||||
curve_Fq("5256529835065685814318509161957442385362539991735248614869838648137856366932")
|
||||
);
|
||||
expected.Z = curve_Fq2::one();
|
||||
|
||||
ASSERT_TRUE(g.to_libsnark_g2<curve_G2>() == -expected);
|
||||
}
|
||||
|
||||
// Invalid leading bytes
|
||||
{
|
||||
CDataStream ss(ParseHex("ff023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
||||
ASSERT_THROW(ss >> g, std::ios_base::failure);
|
||||
}
|
||||
|
||||
|
||||
// Invalid point
|
||||
{
|
||||
CDataStream ss(ParseHex("0b023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984b"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> g;
|
||||
|
||||
ASSERT_THROW(g.to_libsnark_g2<curve_G2>(), std::runtime_error);
|
||||
}
|
||||
|
||||
// Point with out of bounds Fq2
|
||||
{
|
||||
CDataStream ss(ParseHex("0a0f3aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> g;
|
||||
|
||||
ASSERT_THROW(g.to_libsnark_g2<curve_G2>(), std::logic_error);
|
||||
}
|
||||
|
||||
// Randomly produce valid G2 representations and fail/succeed to
|
||||
// turn them into G2 points based on whether they are valid.
|
||||
for (size_t i = 0; i < 5000; i++) {
|
||||
curve_Fq2 e = curve_Fq2::random_element();
|
||||
CDataStream ss(ParseHex("0a"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << Fq2(e);
|
||||
CompressedG2 g;
|
||||
ss >> g;
|
||||
|
||||
try {
|
||||
curve_G2 g_real = g.to_libsnark_g2<curve_G2>();
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "json_test_vectors.h"
|
||||
#include "test/data/g1_compressed.json.h"
|
||||
|
||||
TEST(proofs, g1_test_vectors)
|
||||
{
|
||||
UniValue v = read_json(std::string(json_tests::g1_compressed, json_tests::g1_compressed + sizeof(json_tests::g1_compressed)));
|
||||
|
||||
curve_G1 e = curve_Fr("34958239045823") * curve_G1::one();
|
||||
for (size_t i = 0; i < 10000; i++) {
|
||||
e = (curve_Fr("34958239045823") ^ i) * e;
|
||||
auto expected = CompressedG1(e);
|
||||
|
||||
expect_test_vector(v[i], expected);
|
||||
ASSERT_TRUE(expected.to_libsnark_g1<curve_G1>() == e);
|
||||
}
|
||||
}
|
||||
|
||||
#include "test/data/g2_compressed.json.h"
|
||||
|
||||
TEST(proofs, g2_test_vectors)
|
||||
{
|
||||
UniValue v = read_json(std::string(json_tests::g2_compressed, json_tests::g2_compressed + sizeof(json_tests::g2_compressed)));
|
||||
|
||||
curve_G2 e = curve_Fr("34958239045823") * curve_G2::one();
|
||||
for (size_t i = 0; i < 10000; i++) {
|
||||
e = (curve_Fr("34958239045823") ^ i) * e;
|
||||
auto expected = CompressedG2(e);
|
||||
|
||||
expect_test_vector(v[i], expected);
|
||||
ASSERT_TRUE(expected.to_libsnark_g2<curve_G2>() == e);
|
||||
}
|
||||
}
|
22
src/init.cpp
22
src/init.cpp
|
@ -59,8 +59,6 @@
|
|||
#include <boost/thread.hpp>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#include <libsnark/common/profiling.hpp>
|
||||
|
||||
#if ENABLE_ZMQ
|
||||
#include "zmq/zmqnotificationinterface.h"
|
||||
#endif
|
||||
|
@ -527,7 +525,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||
strUsage += HelpMessageOpt("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT));
|
||||
}
|
||||
|
||||
// Disabled until we can lock notes and also tune performance of libsnark which by default uses multiple threads
|
||||
// Disabled until we can lock notes and also tune performance of the prover which by default uses multiple threads
|
||||
//strUsage += HelpMessageOpt("-rpcasyncthreads=<n>", strprintf(_("Set the number of threads to service Async RPC calls (default: %d)"), 1));
|
||||
|
||||
if (mode == HMM_BITCOIND) {
|
||||
|
@ -687,15 +685,11 @@ static void ZC_LoadParams(
|
|||
struct timeval tv_start, tv_end;
|
||||
float elapsed;
|
||||
|
||||
boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key";
|
||||
boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
|
||||
boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
|
||||
boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
|
||||
boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params";
|
||||
|
||||
if (!(
|
||||
boost::filesystem::exists(pk_path) &&
|
||||
boost::filesystem::exists(vk_path) &&
|
||||
boost::filesystem::exists(sapling_spend) &&
|
||||
boost::filesystem::exists(sapling_output) &&
|
||||
boost::filesystem::exists(sprout_groth16)
|
||||
|
@ -710,14 +704,7 @@ static void ZC_LoadParams(
|
|||
return;
|
||||
}
|
||||
|
||||
LogPrintf("Loading verifying key from %s\n", vk_path.string().c_str());
|
||||
gettimeofday(&tv_start, 0);
|
||||
|
||||
pzcashParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
|
||||
|
||||
gettimeofday(&tv_end, 0);
|
||||
elapsed = float(tv_end.tv_sec-tv_start.tv_sec) + (tv_end.tv_usec-tv_start.tv_usec)/float(1000000);
|
||||
LogPrintf("Loaded verifying key in %fs seconds.\n", elapsed);
|
||||
pzcashParams = ZCJoinSplit::Prepared();
|
||||
|
||||
static_assert(
|
||||
sizeof(boost::filesystem::path::value_type) == sizeof(codeunit),
|
||||
|
@ -1228,11 +1215,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
threadGroup.create_thread(&ThreadShowMetricsScreen);
|
||||
}
|
||||
|
||||
// These must be disabled for now, they are buggy and we probably don't
|
||||
// want any of libsnark's profiling in production anyway.
|
||||
libsnark::inhibit_profiling_info = true;
|
||||
libsnark::inhibit_profiling_counters = true;
|
||||
|
||||
// Initialize Zcash circuit parameters
|
||||
ZC_LoadParams(chainparams);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -167,7 +167,8 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
|||
tx.vShieldedOutput.push_back(odesc);
|
||||
}
|
||||
}
|
||||
if (tx.nVersion >= 2) {
|
||||
// We have removed pre-Sapling Sprout support.
|
||||
if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) {
|
||||
for (int js = 0; js < joinsplits; js++) {
|
||||
JSDescription jsdesc;
|
||||
if (insecure_rand() % 2 == 0) {
|
||||
|
@ -183,12 +184,10 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
|||
jsdesc.randomSeed = GetRandHash();
|
||||
randombytes_buf(jsdesc.ciphertexts[0].begin(), jsdesc.ciphertexts[0].size());
|
||||
randombytes_buf(jsdesc.ciphertexts[1].begin(), jsdesc.ciphertexts[1].size());
|
||||
if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) {
|
||||
{
|
||||
libzcash::GrothProof zkproof;
|
||||
randombytes_buf(zkproof.begin(), zkproof.size());
|
||||
jsdesc.proof = zkproof;
|
||||
} else {
|
||||
jsdesc.proof = libzcash::PHGRProof::random_invalid();
|
||||
}
|
||||
jsdesc.macs[0] = GetRandHash();
|
||||
jsdesc.macs[1] = GetRandHash();
|
||||
|
|
|
@ -37,9 +37,7 @@ extern void noui_connect();
|
|||
|
||||
JoinSplitTestingSetup::JoinSplitTestingSetup()
|
||||
{
|
||||
boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key";
|
||||
boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
|
||||
pzcashParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
|
||||
pzcashParams = ZCJoinSplit::Prepared();
|
||||
|
||||
boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
|
||||
boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
|
||||
|
|
|
@ -2745,7 +2745,7 @@ UniValue zc_benchmark(const UniValue& params, bool fHelp)
|
|||
if (benchmarktype == "sleep") {
|
||||
sample_times.push_back(benchmark_sleep());
|
||||
} else if (benchmarktype == "parameterloading") {
|
||||
sample_times.push_back(benchmark_parameter_loading());
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Pre-Sapling Sprout parameters have been removed");
|
||||
} else if (benchmarktype == "createjoinsplit") {
|
||||
if (params.size() < 3) {
|
||||
sample_times.push_back(benchmark_create_joinsplit());
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
#include <boost/format.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <fstream>
|
||||
#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
|
||||
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
|
||||
#include <libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp>
|
||||
#include <libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp>
|
||||
#include "tinyformat.h"
|
||||
#include "sync.h"
|
||||
#include "amount.h"
|
||||
|
@ -22,123 +18,16 @@
|
|||
#include "streams.h"
|
||||
#include "version.h"
|
||||
|
||||
using namespace libsnark;
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
#include "zcash/circuit/gadget.tcc"
|
||||
|
||||
static CCriticalSection cs_ParamsIO;
|
||||
|
||||
template<typename T>
|
||||
void saveToFile(const std::string path, T& obj) {
|
||||
LOCK(cs_ParamsIO);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << obj;
|
||||
std::ofstream fh;
|
||||
fh.open(path, std::ios::binary);
|
||||
ss.rdbuf()->pubseekpos(0, std::ios_base::out);
|
||||
fh << ss.rdbuf();
|
||||
fh.flush();
|
||||
fh.close();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void loadFromFile(const std::string path, T& objIn) {
|
||||
LOCK(cs_ParamsIO);
|
||||
|
||||
std::stringstream ss;
|
||||
std::ifstream fh(path, std::ios::binary);
|
||||
|
||||
if(!fh.is_open()) {
|
||||
throw std::runtime_error(strprintf("could not load param file at %s", path));
|
||||
}
|
||||
|
||||
ss << fh.rdbuf();
|
||||
fh.close();
|
||||
|
||||
ss.rdbuf()->pubseekpos(0, std::ios_base::in);
|
||||
|
||||
T obj;
|
||||
ss >> obj;
|
||||
|
||||
objIn = std::move(obj);
|
||||
}
|
||||
|
||||
template<size_t NumInputs, size_t NumOutputs>
|
||||
class JoinSplitCircuit : public JoinSplit<NumInputs, NumOutputs> {
|
||||
public:
|
||||
typedef default_r1cs_ppzksnark_pp ppzksnark_ppT;
|
||||
typedef Fr<ppzksnark_ppT> FieldT;
|
||||
|
||||
r1cs_ppzksnark_verification_key<ppzksnark_ppT> vk;
|
||||
r1cs_ppzksnark_processed_verification_key<ppzksnark_ppT> vk_precomp;
|
||||
std::string pkPath;
|
||||
|
||||
JoinSplitCircuit(const std::string vkPath, const std::string pkPath) : pkPath(pkPath) {
|
||||
loadFromFile(vkPath, vk);
|
||||
vk_precomp = r1cs_ppzksnark_verifier_process_vk(vk);
|
||||
}
|
||||
JoinSplitCircuit() {}
|
||||
~JoinSplitCircuit() {}
|
||||
|
||||
static void generate(const std::string r1csPath,
|
||||
const std::string vkPath,
|
||||
const std::string pkPath)
|
||||
{
|
||||
protoboard<FieldT> pb;
|
||||
|
||||
joinsplit_gadget<FieldT, NumInputs, NumOutputs> g(pb);
|
||||
g.generate_r1cs_constraints();
|
||||
|
||||
auto r1cs = pb.get_constraint_system();
|
||||
|
||||
saveToFile(r1csPath, r1cs);
|
||||
|
||||
r1cs_ppzksnark_keypair<ppzksnark_ppT> keypair = r1cs_ppzksnark_generator<ppzksnark_ppT>(r1cs);
|
||||
|
||||
saveToFile(vkPath, keypair.vk);
|
||||
saveToFile(pkPath, keypair.pk);
|
||||
}
|
||||
|
||||
bool verify(
|
||||
const PHGRProof& proof,
|
||||
ProofVerifier& verifier,
|
||||
const uint256& joinSplitPubKey,
|
||||
const uint256& randomSeed,
|
||||
const std::array<uint256, NumInputs>& macs,
|
||||
const std::array<uint256, NumInputs>& nullifiers,
|
||||
const std::array<uint256, NumOutputs>& commitments,
|
||||
uint64_t vpub_old,
|
||||
uint64_t vpub_new,
|
||||
const uint256& rt
|
||||
) {
|
||||
try {
|
||||
auto r1cs_proof = proof.to_libsnark_proof<r1cs_ppzksnark_proof<ppzksnark_ppT>>();
|
||||
|
||||
uint256 h_sig = this->h_sig(randomSeed, nullifiers, joinSplitPubKey);
|
||||
|
||||
auto witness = joinsplit_gadget<FieldT, NumInputs, NumOutputs>::witness_map(
|
||||
rt,
|
||||
h_sig,
|
||||
macs,
|
||||
nullifiers,
|
||||
commitments,
|
||||
vpub_old,
|
||||
vpub_new
|
||||
);
|
||||
|
||||
return verifier.check(
|
||||
vk,
|
||||
vk_precomp,
|
||||
witness,
|
||||
r1cs_proof
|
||||
);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SproutProof prove(
|
||||
bool makeGrothProof,
|
||||
const std::array<JSInput, NumInputs>& inputs,
|
||||
|
@ -326,20 +215,9 @@ public:
|
|||
};
|
||||
|
||||
template<size_t NumInputs, size_t NumOutputs>
|
||||
void JoinSplit<NumInputs, NumOutputs>::Generate(const std::string r1csPath,
|
||||
const std::string vkPath,
|
||||
const std::string pkPath)
|
||||
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Prepared()
|
||||
{
|
||||
initialize_curve_params();
|
||||
JoinSplitCircuit<NumInputs, NumOutputs>::generate(r1csPath, vkPath, pkPath);
|
||||
}
|
||||
|
||||
template<size_t NumInputs, size_t NumOutputs>
|
||||
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Prepared(const std::string vkPath,
|
||||
const std::string pkPath)
|
||||
{
|
||||
initialize_curve_params();
|
||||
return new JoinSplitCircuit<NumInputs, NumOutputs>(vkPath, pkPath);
|
||||
return new JoinSplitCircuit<NumInputs, NumOutputs>();
|
||||
}
|
||||
|
||||
template<size_t NumInputs, size_t NumOutputs>
|
||||
|
|
|
@ -56,11 +56,7 @@ class JoinSplit {
|
|||
public:
|
||||
virtual ~JoinSplit() {}
|
||||
|
||||
static void Generate(const std::string r1csPath,
|
||||
const std::string vkPath,
|
||||
const std::string pkPath);
|
||||
static JoinSplit<NumInputs, NumOutputs>* Prepared(const std::string vkPath,
|
||||
const std::string pkPath);
|
||||
static JoinSplit<NumInputs, NumOutputs>* Prepared();
|
||||
|
||||
static uint256 h_sig(const uint256& randomSeed,
|
||||
const std::array<uint256, NumInputs>& nullifiers,
|
||||
|
@ -90,19 +86,6 @@ public:
|
|||
uint256 *out_esk = nullptr
|
||||
) = 0;
|
||||
|
||||
virtual bool verify(
|
||||
const PHGRProof& proof,
|
||||
ProofVerifier& verifier,
|
||||
const uint256& joinSplitPubKey,
|
||||
const uint256& randomSeed,
|
||||
const std::array<uint256, NumInputs>& hmacs,
|
||||
const std::array<uint256, NumInputs>& nullifiers,
|
||||
const std::array<uint256, NumOutputs>& commitments,
|
||||
uint64_t vpub_old,
|
||||
uint64_t vpub_new,
|
||||
const uint256& rt
|
||||
) = 0;
|
||||
|
||||
protected:
|
||||
JoinSplit() {}
|
||||
};
|
||||
|
|
|
@ -3,249 +3,16 @@
|
|||
#include "crypto/common.h"
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
|
||||
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
|
||||
#include <mutex>
|
||||
|
||||
using namespace libsnark;
|
||||
|
||||
typedef alt_bn128_pp curve_pp;
|
||||
typedef alt_bn128_pp::G1_type curve_G1;
|
||||
typedef alt_bn128_pp::G2_type curve_G2;
|
||||
typedef alt_bn128_pp::GT_type curve_GT;
|
||||
typedef alt_bn128_pp::Fp_type curve_Fr;
|
||||
typedef alt_bn128_pp::Fq_type curve_Fq;
|
||||
typedef alt_bn128_pp::Fqe_type curve_Fq2;
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(mp_limb_t) == 8);
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
// FE2IP as defined in the protocol spec and IEEE Std 1363a-2004.
|
||||
bigint<8> fq2_to_bigint(const curve_Fq2 &e)
|
||||
{
|
||||
auto modq = curve_Fq::field_char();
|
||||
auto c0 = e.c0.as_bigint();
|
||||
auto c1 = e.c1.as_bigint();
|
||||
|
||||
bigint<8> temp = c1 * modq;
|
||||
temp += c0;
|
||||
return temp;
|
||||
}
|
||||
|
||||
// Writes a bigint in big endian
|
||||
template<mp_size_t LIMBS>
|
||||
void write_bigint(base_blob<8 * LIMBS * sizeof(mp_limb_t)> &blob, const bigint<LIMBS> &val)
|
||||
{
|
||||
auto ptr = blob.begin();
|
||||
for (ssize_t i = LIMBS-1; i >= 0; i--, ptr += 8) {
|
||||
WriteBE64(ptr, val.data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Reads a bigint from big endian
|
||||
template<mp_size_t LIMBS>
|
||||
bigint<LIMBS> read_bigint(const base_blob<8 * LIMBS * sizeof(mp_limb_t)> &blob)
|
||||
{
|
||||
bigint<LIMBS> ret;
|
||||
|
||||
auto ptr = blob.begin();
|
||||
|
||||
for (ssize_t i = LIMBS-1; i >= 0; i--, ptr += 8) {
|
||||
ret.data[i] = ReadBE64(ptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<>
|
||||
Fq::Fq(curve_Fq element) : data()
|
||||
{
|
||||
write_bigint<4>(data, element.as_bigint());
|
||||
}
|
||||
|
||||
template<>
|
||||
curve_Fq Fq::to_libsnark_fq() const
|
||||
{
|
||||
auto element_bigint = read_bigint<4>(data);
|
||||
|
||||
// Check that the integer is smaller than the modulus
|
||||
auto modq = curve_Fq::field_char();
|
||||
element_bigint.limit(modq, "element is not in Fq");
|
||||
|
||||
return curve_Fq(element_bigint);
|
||||
}
|
||||
|
||||
template<>
|
||||
Fq2::Fq2(curve_Fq2 element) : data()
|
||||
{
|
||||
write_bigint<8>(data, fq2_to_bigint(element));
|
||||
}
|
||||
|
||||
template<>
|
||||
curve_Fq2 Fq2::to_libsnark_fq2() const
|
||||
{
|
||||
bigint<4> modq = curve_Fq::field_char();
|
||||
bigint<8> combined = read_bigint<8>(data);
|
||||
bigint<5> res;
|
||||
bigint<4> c0;
|
||||
bigint<8>::div_qr(res, c0, combined, modq);
|
||||
bigint<4> c1 = res.shorten(modq, "element is not in Fq2");
|
||||
|
||||
return curve_Fq2(curve_Fq(c0), curve_Fq(c1));
|
||||
}
|
||||
|
||||
template<>
|
||||
CompressedG1::CompressedG1(curve_G1 point)
|
||||
{
|
||||
if (point.is_zero()) {
|
||||
throw std::domain_error("curve point is zero");
|
||||
}
|
||||
|
||||
point.to_affine_coordinates();
|
||||
|
||||
x = Fq(point.X);
|
||||
y_lsb = point.Y.as_bigint().data[0] & 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
curve_G1 CompressedG1::to_libsnark_g1() const
|
||||
{
|
||||
curve_Fq x_coordinate = x.to_libsnark_fq<curve_Fq>();
|
||||
|
||||
// y = +/- sqrt(x^3 + b)
|
||||
auto y_coordinate = ((x_coordinate.squared() * x_coordinate) + alt_bn128_coeff_b).sqrt();
|
||||
|
||||
if ((y_coordinate.as_bigint().data[0] & 1) != y_lsb) {
|
||||
y_coordinate = -y_coordinate;
|
||||
}
|
||||
|
||||
curve_G1 r = curve_G1::one();
|
||||
r.X = x_coordinate;
|
||||
r.Y = y_coordinate;
|
||||
r.Z = curve_Fq::one();
|
||||
|
||||
assert(r.is_well_formed());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template<>
|
||||
CompressedG2::CompressedG2(curve_G2 point)
|
||||
{
|
||||
if (point.is_zero()) {
|
||||
throw std::domain_error("curve point is zero");
|
||||
}
|
||||
|
||||
point.to_affine_coordinates();
|
||||
|
||||
x = Fq2(point.X);
|
||||
y_gt = fq2_to_bigint(point.Y) > fq2_to_bigint(-(point.Y));
|
||||
}
|
||||
|
||||
template<>
|
||||
curve_G2 CompressedG2::to_libsnark_g2() const
|
||||
{
|
||||
auto x_coordinate = x.to_libsnark_fq2<curve_Fq2>();
|
||||
|
||||
// y = +/- sqrt(x^3 + b)
|
||||
auto y_coordinate = ((x_coordinate.squared() * x_coordinate) + alt_bn128_twist_coeff_b).sqrt();
|
||||
auto y_coordinate_neg = -y_coordinate;
|
||||
|
||||
if ((fq2_to_bigint(y_coordinate) > fq2_to_bigint(y_coordinate_neg)) != y_gt) {
|
||||
y_coordinate = y_coordinate_neg;
|
||||
}
|
||||
|
||||
curve_G2 r = curve_G2::one();
|
||||
r.X = x_coordinate;
|
||||
r.Y = y_coordinate;
|
||||
r.Z = curve_Fq2::one();
|
||||
|
||||
assert(r.is_well_formed());
|
||||
|
||||
if (alt_bn128_modulus_r * r != curve_G2::zero()) {
|
||||
throw std::runtime_error("point is not in G2");
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template<>
|
||||
PHGRProof::PHGRProof(const r1cs_ppzksnark_proof<curve_pp> &proof)
|
||||
{
|
||||
g_A = CompressedG1(proof.g_A.g);
|
||||
g_A_prime = CompressedG1(proof.g_A.h);
|
||||
g_B = CompressedG2(proof.g_B.g);
|
||||
g_B_prime = CompressedG1(proof.g_B.h);
|
||||
g_C = CompressedG1(proof.g_C.g);
|
||||
g_C_prime = CompressedG1(proof.g_C.h);
|
||||
g_K = CompressedG1(proof.g_K);
|
||||
g_H = CompressedG1(proof.g_H);
|
||||
}
|
||||
|
||||
template<>
|
||||
r1cs_ppzksnark_proof<curve_pp> PHGRProof::to_libsnark_proof() const
|
||||
{
|
||||
r1cs_ppzksnark_proof<curve_pp> proof;
|
||||
|
||||
proof.g_A.g = g_A.to_libsnark_g1<curve_G1>();
|
||||
proof.g_A.h = g_A_prime.to_libsnark_g1<curve_G1>();
|
||||
proof.g_B.g = g_B.to_libsnark_g2<curve_G2>();
|
||||
proof.g_B.h = g_B_prime.to_libsnark_g1<curve_G1>();
|
||||
proof.g_C.g = g_C.to_libsnark_g1<curve_G1>();
|
||||
proof.g_C.h = g_C_prime.to_libsnark_g1<curve_G1>();
|
||||
proof.g_K = g_K.to_libsnark_g1<curve_G1>();
|
||||
proof.g_H = g_H.to_libsnark_g1<curve_G1>();
|
||||
|
||||
return proof;
|
||||
}
|
||||
|
||||
PHGRProof PHGRProof::random_invalid()
|
||||
{
|
||||
PHGRProof p;
|
||||
p.g_A = curve_G1::random_element();
|
||||
p.g_A_prime = curve_G1::random_element();
|
||||
p.g_B = curve_G2::random_element();
|
||||
p.g_B_prime = curve_G1::random_element();
|
||||
p.g_C = curve_G1::random_element();
|
||||
p.g_C_prime = curve_G1::random_element();
|
||||
|
||||
p.g_K = curve_G1::random_element();
|
||||
p.g_H = curve_G1::random_element();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static std::once_flag init_public_params_once_flag;
|
||||
|
||||
void initialize_curve_params()
|
||||
{
|
||||
std::call_once (init_public_params_once_flag, curve_pp::init_public_params);
|
||||
}
|
||||
|
||||
ProofVerifier ProofVerifier::Strict() {
|
||||
initialize_curve_params();
|
||||
return ProofVerifier(true);
|
||||
}
|
||||
|
||||
ProofVerifier ProofVerifier::Disabled() {
|
||||
initialize_curve_params();
|
||||
return ProofVerifier(false);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool ProofVerifier::check(
|
||||
const r1cs_ppzksnark_verification_key<curve_pp>& vk,
|
||||
const r1cs_ppzksnark_processed_verification_key<curve_pp>& pvk,
|
||||
const r1cs_primary_input<curve_Fr>& primary_input,
|
||||
const r1cs_ppzksnark_proof<curve_pp>& proof
|
||||
)
|
||||
{
|
||||
if (perform_verification) {
|
||||
return r1cs_ppzksnark_online_verifier_strong_IC<curve_pp>(pvk, primary_input, proof);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,12 +16,6 @@ private:
|
|||
public:
|
||||
Fq() : data() { }
|
||||
|
||||
template<typename libsnark_Fq>
|
||||
Fq(libsnark_Fq element);
|
||||
|
||||
template<typename libsnark_Fq>
|
||||
libsnark_Fq to_libsnark_fq() const;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
|
@ -49,12 +43,6 @@ private:
|
|||
public:
|
||||
Fq2() : data() { }
|
||||
|
||||
template<typename libsnark_Fq2>
|
||||
Fq2(libsnark_Fq2 element);
|
||||
|
||||
template<typename libsnark_Fq2>
|
||||
libsnark_Fq2 to_libsnark_fq2() const;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
|
@ -84,12 +72,6 @@ private:
|
|||
public:
|
||||
CompressedG1() : y_lsb(false), x() { }
|
||||
|
||||
template<typename libsnark_G1>
|
||||
CompressedG1(libsnark_G1 point);
|
||||
|
||||
template<typename libsnark_G1>
|
||||
libsnark_G1 to_libsnark_g1() const;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
|
@ -134,12 +116,6 @@ private:
|
|||
public:
|
||||
CompressedG2() : y_gt(false), x() { }
|
||||
|
||||
template<typename libsnark_G2>
|
||||
CompressedG2(libsnark_G2 point);
|
||||
|
||||
template<typename libsnark_G2>
|
||||
libsnark_G2 to_libsnark_g2() const;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
|
@ -190,17 +166,6 @@ private:
|
|||
public:
|
||||
PHGRProof() : g_A(), g_A_prime(), g_B(), g_B_prime(), g_C(), g_C_prime(), g_K(), g_H() { }
|
||||
|
||||
// Produces a compressed proof using a libsnark zkSNARK proof
|
||||
template<typename libsnark_proof>
|
||||
PHGRProof(const libsnark_proof& proof);
|
||||
|
||||
// Produces a libsnark zkSNARK proof out of this proof,
|
||||
// or throws an exception if it is invalid.
|
||||
template<typename libsnark_proof>
|
||||
libsnark_proof to_libsnark_proof() const;
|
||||
|
||||
static PHGRProof random_invalid();
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
|
|
|
@ -91,24 +91,6 @@ double benchmark_sleep()
|
|||
return timer_stop(tv_start);
|
||||
}
|
||||
|
||||
double benchmark_parameter_loading()
|
||||
{
|
||||
// FIXME: this is duplicated with the actual loading code
|
||||
boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key";
|
||||
boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
|
||||
|
||||
struct timeval tv_start;
|
||||
timer_start(tv_start);
|
||||
|
||||
auto newParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
|
||||
|
||||
double ret = timer_stop(tv_start);
|
||||
|
||||
delete newParams;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
double benchmark_create_joinsplit()
|
||||
{
|
||||
uint256 joinSplitPubKey;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
extern double benchmark_sleep();
|
||||
extern double benchmark_parameter_loading();
|
||||
extern double benchmark_create_joinsplit();
|
||||
extern std::vector<double> benchmark_create_joinsplit_threaded(int nThreads);
|
||||
extern double benchmark_solve_equihash();
|
||||
|
|
Loading…
Reference in New Issue