Browse Source

Isolate verification to a `ProofVerifier` context object that allows verification behavior to be tuned by the caller.

pull/4/head
Sean Bowe 8 years ago
parent
commit
bc59f53722
  1. 5
      src/gtest/test_joinsplit.cpp
  2. 3
      src/main.cpp
  3. 2
      src/primitives/transaction.cpp
  4. 6
      src/primitives/transaction.h
  5. 8
      src/test/transaction_tests.cpp
  6. 7
      src/wallet/asyncrpcoperation_sendmany.cpp
  7. 5
      src/wallet/rpcwallet.cpp
  8. 19
      src/zcash/JoinSplit.cpp
  9. 1
      src/zcash/JoinSplit.hpp
  10. 33
      src/zcash/Proof.cpp
  11. 30
      src/zcash/Proof.hpp
  12. 6
      src/zcbenchmarks.cpp

5
src/gtest/test_joinsplit.cpp

@ -15,6 +15,9 @@ using namespace libzcash;
void test_full_api(ZCJoinSplit* js)
{
// Create verification context.
auto verifier = libzcash::ProofVerifier::Strict();
// The recipient's information.
SpendingKey recipient_key = SpendingKey::random();
PaymentAddress recipient_addr = recipient_key.address();
@ -69,6 +72,7 @@ void test_full_api(ZCJoinSplit* js)
// Verify the transaction:
ASSERT_TRUE(js->verify(
proof,
verifier,
pubKeyHash,
randomSeed,
macs,
@ -143,6 +147,7 @@ void test_full_api(ZCJoinSplit* js)
// Verify the transaction:
ASSERT_TRUE(js->verify(
proof,
verifier,
pubKeyHash,
randomSeed,
macs,

3
src/main.cpp

@ -844,8 +844,9 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return false;
} else {
// Ensure that zk-SNARKs verify
auto verifier = libzcash::ProofVerifier::Strict();
BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
if (!joinsplit.Verify(*pzcashParams, tx.joinSplitPubKey)) {
if (!joinsplit.Verify(*pzcashParams, verifier, tx.joinSplitPubKey)) {
return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"),
REJECT_INVALID, "bad-txns-joinsplit-verification-failed");
}

2
src/primitives/transaction.cpp

@ -70,10 +70,12 @@ JSDescription JSDescription::Randomized(
bool JSDescription::Verify(
ZCJoinSplit& params,
libzcash::ProofVerifier& verifier,
const uint256& pubKeyHash
) const {
return params.verify(
proof,
verifier,
pubKeyHash,
randomSeed,
macs,

6
src/primitives/transaction.h

@ -95,7 +95,11 @@ public:
);
// Verifies that the JoinSplit proof is correct.
bool Verify(ZCJoinSplit& params, const uint256& pubKeyHash) const;
bool Verify(
ZCJoinSplit& params,
libzcash::ProofVerifier& verifier,
const uint256& pubKeyHash
) const;
// Returns the calculated h_sig
uint256 h_sig(ZCJoinSplit& params, const uint256& pubKeyHash) const;

8
src/test/transaction_tests.cpp

@ -341,9 +341,11 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
libzcash::JSOutput(addr, 50)
};
auto verifier = libzcash::ProofVerifier::Strict();
{
JSDescription jsdesc(*p, pubKeyHash, rt, inputs, outputs, 0, 0);
BOOST_CHECK(jsdesc.Verify(*p, pubKeyHash));
BOOST_CHECK(jsdesc.Verify(*p, verifier, pubKeyHash));
CDataStream ss(SER_DISK, CLIENT_VERSION);
ss << jsdesc;
@ -352,7 +354,7 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
ss >> jsdesc_deserialized;
BOOST_CHECK(jsdesc_deserialized == jsdesc);
BOOST_CHECK(jsdesc_deserialized.Verify(*p, pubKeyHash));
BOOST_CHECK(jsdesc_deserialized.Verify(*p, verifier, pubKeyHash));
}
{
@ -365,7 +367,7 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
// Ensure that it won't verify if the root is changed.
auto test = JSDescription(*p, pubKeyHash, rt, inputs, outputs, 0, 0);
test.anchor = GetRandHash();
BOOST_CHECK(!test.Verify(*p, pubKeyHash));
BOOST_CHECK(!test.Verify(*p, verifier, pubKeyHash));
}
}

7
src/wallet/asyncrpcoperation_sendmany.cpp

@ -926,8 +926,11 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
info.vpub_new,
!this->testmode);
if (!(jsdesc.Verify(*pzcashParams, joinSplitPubKey_))) {
throw std::runtime_error("error verifying joinsplit");
{
auto verifier = libzcash::ProofVerifier::Strict();
if (!(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey_))) {
throw std::runtime_error("error verifying joinsplit");
}
}
mtx.vjoinsplit.push_back(jsdesc);

5
src/wallet/rpcwallet.cpp

@ -2707,7 +2707,10 @@ Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp)
vpub_old,
vpub_new);
assert(jsdesc.Verify(*pzcashParams, joinSplitPubKey));
{
auto verifier = libzcash::ProofVerifier::Strict();
assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey));
}
mtx.vjoinsplit.push_back(jsdesc);

19
src/zcash/JoinSplit.cpp

@ -5,7 +5,6 @@
#include "zcash/util.h"
#include <memory>
#include <mutex>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
@ -25,8 +24,6 @@ namespace libzcash {
#include "zcash/circuit/gadget.tcc"
std::once_flag init_public_params_once_flag;
CCriticalSection cs_ParamsIO;
CCriticalSection cs_LoadKeys;
@ -80,10 +77,6 @@ public:
JoinSplitCircuit() {}
~JoinSplitCircuit() {}
static void initialize() {
std::call_once (init_public_params_once_flag, ppzksnark_ppT::init_public_params);
}
void setProvingKeyPath(std::string path) {
pkPath = path;
}
@ -151,6 +144,7 @@ public:
bool verify(
const ZCProof& proof,
ProofVerifier& verifier,
const uint256& pubKeyHash,
const uint256& randomSeed,
const boost::array<uint256, NumInputs>& macs,
@ -179,7 +173,12 @@ public:
vpub_new
);
return r1cs_ppzksnark_online_verifier_strong_IC<ppzksnark_ppT>(*vk_precomp, witness, r1cs_proof);
return verifier.check(
*vk,
*vk_precomp,
witness,
r1cs_proof
);
} catch (...) {
return false;
}
@ -358,7 +357,7 @@ public:
template<size_t NumInputs, size_t NumOutputs>
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Generate()
{
JoinSplitCircuit<NumInputs, NumOutputs>::initialize();
initialize_curve_params();
auto js = new JoinSplitCircuit<NumInputs, NumOutputs>();
js->generate();
@ -368,7 +367,7 @@ JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Generate()
template<size_t NumInputs, size_t NumOutputs>
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Unopened()
{
JoinSplitCircuit<NumInputs, NumOutputs>::initialize();
initialize_curve_params();
return new JoinSplitCircuit<NumInputs, NumOutputs>();
}

1
src/zcash/JoinSplit.hpp

@ -83,6 +83,7 @@ public:
virtual bool verify(
const ZCProof& proof,
ProofVerifier& verifier,
const uint256& pubKeyHash,
const uint256& randomSeed,
const boost::array<uint256, NumInputs>& hmacs,

33
src/zcash/Proof.cpp

@ -1,6 +1,7 @@
#include "Proof.hpp"
#include <boost/static_assert.hpp>
#include <mutex>
#include "crypto/common.h"
#include "libsnark/common/default_types/r1cs_ppzksnark_pp.hpp"
@ -211,4 +212,36 @@ ZCProof ZCProof::random_invalid()
return p;
}
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::Dummy() {
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;
}
}
}

30
src/zcash/Proof.hpp

@ -235,6 +235,36 @@ public:
}
};
void initialize_curve_params();
class ProofVerifier {
private:
bool perform_verification;
ProofVerifier(bool perform_verification) : perform_verification(perform_verification) { }
public:
// Creates a verification context that strictly verifies
// all proofs using libsnark's API.
static ProofVerifier Strict();
// Creates a dummy verification context that performs
// no verification, used when avoiding duplicate effort
// such as during reindexing.
static ProofVerifier Dummy();
template <typename VerificationKey,
typename ProcessedVerificationKey,
typename PrimaryInput,
typename Proof
>
bool check(
const VerificationKey& vk,
const ProcessedVerificationKey& pvk,
const PrimaryInput& pi,
const Proof& p
);
};
}

6
src/zcbenchmarks.cpp

@ -89,7 +89,8 @@ double benchmark_create_joinsplit()
0);
double ret = timer_stop(tv_start);
assert(jsdesc.Verify(*pzcashParams, pubKeyHash));
auto verifier = libzcash::ProofVerifier::Strict();
assert(jsdesc.Verify(*pzcashParams, verifier, pubKeyHash));
return ret;
}
@ -98,7 +99,8 @@ double benchmark_verify_joinsplit(const JSDescription &joinsplit)
struct timeval tv_start;
timer_start(tv_start);
uint256 pubKeyHash;
joinsplit.Verify(*pzcashParams, pubKeyHash);
auto verifier = libzcash::ProofVerifier::Strict();
joinsplit.Verify(*pzcashParams, verifier, pubKeyHash);
return timer_stop(tv_start);
}

Loading…
Cancel
Save