Move ProofVerifier out of the libzcash namespace

It needs to be closer to the root of our dependency tree, so that it can
depend on the transaction format. The libzcash compilation unit is
further from the dependency tree root than the transaction format.
This commit is contained in:
Jack Grigg 2020-07-08 13:23:03 +12:00
parent 7e2558d2e2
commit 35765ec9de
21 changed files with 94 additions and 76 deletions

View File

@ -212,6 +212,7 @@ BITCOIN_CORE_H = \
prevector.h \
primitives/block.h \
primitives/transaction.h \
proof_verifier.h \
protocol.h \
pubkey.h \
random.h \
@ -424,6 +425,7 @@ libbitcoin_common_a_SOURCES = \
netbase.cpp \
primitives/block.cpp \
primitives/transaction.cpp \
proof_verifier.cpp \
protocol.cpp \
pubkey.cpp \
scheduler.cpp \
@ -572,7 +574,6 @@ libzcash_a_SOURCES = \
zcash/address/zip32.cpp \
zcash/History.cpp \
zcash/JoinSplit.cpp \
zcash/Proof.cpp \
zcash/Note.cpp \
zcash/prf.cpp \
zcash/util.cpp

View File

@ -1,5 +1,6 @@
#include "consensus/validation.h"
#include "chainparams.h"
#include "proof_verifier.h"
int main (int argc, char *argv[]) {
int retval = 0;
@ -18,7 +19,7 @@ int main (int argc, char *argv[]) {
// valid blocks with shielded transactions will generate a crash.
const CChainParams& chainparams = Params();
auto verifier = libzcash::ProofVerifier::Disabled();
auto verifier = ProofVerifier::Disabled();
CValidationState state;
// We don't check the PoW or Merkle tree root in order to reach more code.
if (!CheckBlock(block, state, chainparams, verifier, false, false)) {

View File

@ -3,6 +3,7 @@
#include "consensus/validation.h"
#include "main.h"
#include "proof_verifier.h"
#include "utiltest.h"
#include "zcash/Proof.hpp"
@ -24,7 +25,7 @@ public:
};
TEST(CheckBlock, VersionTooLow) {
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
CBlock block;
block.nVersion = 1;
@ -61,7 +62,7 @@ TEST(CheckBlock, BlockSproutRejectsBadVersion) {
MockCValidationState state;
CBlockIndex indexPrev {Params().GenesisBlock()};
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1);
EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false));

View File

@ -11,6 +11,7 @@
#include "version.h"
#include "serialize.h"
#include "primitives/transaction.h"
#include "proof_verifier.h"
#include "zcash/JoinSplit.hpp"
#include "zcash/Note.hpp"
#include "zcash/NoteEncryption.hpp"
@ -38,7 +39,7 @@ bool verifySproutProof(
const uint256& joinSplitPubKey
)
{
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
return jsdesc.Verify(verifier, joinSplitPubKey);
}
@ -46,7 +47,7 @@ bool verifySproutProof(
void test_full_api()
{
// Create verification context.
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
// The recipient's information.
SproutSpendingKey recipient_key = SproutSpendingKey::random();

View File

@ -1078,7 +1078,7 @@ bool ContextualCheckTransaction(
bool CheckTransaction(const CTransaction& tx, CValidationState &state,
libzcash::ProofVerifier& verifier)
ProofVerifier& verifier)
{
// Don't count coinbase transactions because mining skews the count
if (!tx.IsCoinBase()) {
@ -1378,7 +1378,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return false;
}
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
if (!CheckTransaction(tx, state, verifier))
return error("AcceptToMemoryPool: CheckTransaction failed");
@ -2646,8 +2646,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
}
}
auto verifier = libzcash::ProofVerifier::Strict();
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
auto verifier = ProofVerifier::Strict();
auto disabledVerifier = ProofVerifier::Disabled();
// Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in
if (!CheckBlock(block, state, chainparams, fExpensiveChecks ? verifier : disabledVerifier, !fJustCheck, !fJustCheck))
@ -3953,7 +3953,7 @@ bool CheckBlockHeader(
bool CheckBlock(const CBlock& block, CValidationState& state,
const CChainParams& chainparams,
libzcash::ProofVerifier& verifier,
ProofVerifier& verifier,
bool fCheckPOW, bool fCheckMerkleRoot)
{
// These are checks that are independent of context.
@ -4232,7 +4232,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
}
// See method docstring for why this is always disabled
auto verifier = libzcash::ProofVerifier::Disabled();
auto verifier = ProofVerifier::Disabled();
if ((!CheckBlock(block, state, chainparams, verifier)) || !ContextualCheckBlock(block, state, chainparams, pindex->pprev)) {
if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
@ -4282,7 +4282,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp)
{
// Preliminary checks
auto verifier = libzcash::ProofVerifier::Disabled();
auto verifier = ProofVerifier::Disabled();
bool checked = CheckBlock(*pblock, state, chainparams, verifier);
{
@ -4320,7 +4320,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
indexDummy.pprev = pindexPrev;
indexDummy.nHeight = pindexPrev->nHeight + 1;
// JoinSplit proofs are verified in ConnectBlock
auto verifier = libzcash::ProofVerifier::Disabled();
auto verifier = ProofVerifier::Disabled();
// NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, fCheckPOW))
@ -4720,7 +4720,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
int nGoodTransactions = 0;
CValidationState state;
// No need to verify JoinSplits twice
auto verifier = libzcash::ProofVerifier::Disabled();
auto verifier = ProofVerifier::Disabled();
for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
{
boost::this_thread::interruption_point();

View File

@ -18,6 +18,7 @@
#include "net.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "proof_verifier.h"
#include "script/script.h"
#include "script/sigcache.h"
#include "script/standard.h"
@ -344,7 +345,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
/** Transaction validation functions */
/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state, libzcash::ProofVerifier& verifier);
bool CheckTransaction(const CTransaction& tx, CValidationState& state, ProofVerifier& verifier);
bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidationState &state);
namespace Consensus {
@ -447,7 +448,7 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state,
bool fCheckPOW = true);
bool CheckBlock(const CBlock& block, CValidationState& state,
const CChainParams& chainparams,
libzcash::ProofVerifier& verifier,
ProofVerifier& verifier,
bool fCheckPOW = true, bool fCheckMerkleRoot = true);
/** Context-dependent validity checks.

View File

@ -75,13 +75,13 @@ JSDescription JSDescription::Randomized(
class SproutProofVerifier : public boost::static_visitor<bool>
{
libzcash::ProofVerifier& verifier;
ProofVerifier& verifier;
const uint256& joinSplitPubKey;
const JSDescription& jsdesc;
public:
SproutProofVerifier(
libzcash::ProofVerifier& verifier,
ProofVerifier& verifier,
const uint256& joinSplitPubKey,
const JSDescription& jsdesc
) : jsdesc(jsdesc), verifier(verifier), joinSplitPubKey(joinSplitPubKey) {}
@ -114,7 +114,7 @@ public:
};
bool JSDescription::Verify(
libzcash::ProofVerifier& verifier,
ProofVerifier& verifier,
const uint256& joinSplitPubKey
) const {
auto pv = SproutProofVerifier(verifier, joinSplitPubKey, *this);

View File

@ -7,6 +7,7 @@
#define BITCOIN_PRIMITIVES_TRANSACTION_H
#include "amount.h"
#include "proof_verifier.h"
#include "random.h"
#include "script/script.h"
#include "serialize.h"
@ -261,7 +262,7 @@ public:
// Verifies that the JoinSplit proof is correct.
bool Verify(
libzcash::ProofVerifier& verifier,
ProofVerifier& verifier,
const uint256& joinSplitPubKey
) const;

13
src/proof_verifier.cpp Normal file
View File

@ -0,0 +1,13 @@
// Copyright (c) 2016-2020 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#include <proof_verifier.h>
ProofVerifier ProofVerifier::Strict() {
return ProofVerifier(true);
}
ProofVerifier ProofVerifier::Disabled() {
return ProofVerifier(false);
}

31
src/proof_verifier.h Normal file
View File

@ -0,0 +1,31 @@
// Copyright (c) 2016-2020 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#ifndef ZCASH_PROOF_VERIFIER_H
#define ZCASH_PROOF_VERIFIER_H
class ProofVerifier {
private:
bool perform_verification;
ProofVerifier(bool perform_verification) : perform_verification(perform_verification) { }
public:
// ProofVerifier should never be copied
ProofVerifier(const ProofVerifier&) = delete;
ProofVerifier& operator=(const ProofVerifier&) = delete;
ProofVerifier(ProofVerifier&&);
ProofVerifier& operator=(ProofVerifier&&);
// Creates a verification context that strictly verifies
// all proofs.
static ProofVerifier Strict();
// Creates a verification context that performs no
// verification, used when avoiding duplicate effort
// such as during reindexing.
static ProofVerifier Disabled();
};
#endif // ZCASH_PROOF_VERIFIER_H

View File

@ -5,6 +5,7 @@
#include "clientversion.h"
#include "consensus/validation.h"
#include "main.h"
#include "proof_verifier.h"
#include "test/test_bitcoin.h"
#include "utiltime.h"
#include "zcash/Proof.hpp"
@ -57,7 +58,7 @@ BOOST_AUTO_TEST_CASE(May15)
// After May 15'th, big blocks are OK:
forkingBlock.nTime = tMay15; // Invalidates PoW
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
BOOST_CHECK(CheckBlock(forkingBlock, state, Params(), verifier, false, false));
}

View File

@ -16,6 +16,7 @@
#include "keystore.h"
#include "main.h"
#include "policy/policy.h"
#include "proof_verifier.h"
#include "script/script.h"
#include "script/script_error.h"
#include "script/sign.h"
@ -108,7 +109,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
UniValue tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
std::string comment("");
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
ScriptError err;
for (size_t idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
@ -196,7 +197,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
UniValue tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
std::string comment("");
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
ScriptError err;
for (size_t idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
@ -278,7 +279,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
CMutableTransaction tx;
stream >> tx;
CValidationState state;
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state, verifier) && state.IsValid(), "Simple deserialized transaction should be valid.");
// Check that duplicate txins fail
@ -369,7 +370,7 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
libzcash::JSOutput(addr, 50)
};
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
{
JSDescription jsdesc(joinSplitPubKey, rt, inputs, outputs, 0, 0);
@ -460,7 +461,7 @@ void test_simple_sapling_invalidity(uint32_t consensusBranchId, CMutableTransact
void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransaction tx)
{
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
{
// Ensure that empty vin/vout remain invalid without
// joinsplits.

View File

@ -5,6 +5,7 @@
#include "transaction_builder.h"
#include "main.h"
#include "proof_verifier.h"
#include "pubkey.h"
#include "rpc/protocol.h"
#include "script/sign.h"
@ -717,7 +718,7 @@ void TransactionBuilder::CreateJSDescription(
&esk); // parameter expects pointer to esk, so pass in address
{
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
if (!jsdesc.Verify(verifier, mtx.joinSplitPubKey)) {
throw std::runtime_error("error verifying joinsplit");
}

View File

@ -15,6 +15,7 @@
#include "miner.h"
#include "net.h"
#include "netbase.h"
#include "proof_verifier.h"
#include "rpc/protocol.h"
#include "rpc/server.h"
#include "script/interpreter.h"
@ -802,7 +803,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
!this->testmode,
&esk); // parameter expects pointer to esk, so pass in address
{
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
if (!(jsdesc.Verify(verifier, joinSplitPubKey_))) {
throw std::runtime_error("error verifying joinsplit");
}

View File

@ -15,6 +15,7 @@
#include "main.h"
#include "net.h"
#include "netbase.h"
#include "proof_verifier.h"
#include "rpc/protocol.h"
#include "rpc/server.h"
#include "timedata.h"
@ -1077,7 +1078,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
!this->testmode,
&esk); // parameter expects pointer to esk, so pass in address
{
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
if (!(jsdesc.Verify(verifier, joinSplitPubKey_))) {
throw std::runtime_error("error verifying joinsplit");
}

View File

@ -15,6 +15,7 @@
#include "main.h"
#include "net.h"
#include "netbase.h"
#include "proof_verifier.h"
#include "rpc/protocol.h"
#include "rpc/server.h"
#include "timedata.h"
@ -318,7 +319,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
!this->testmode,
&esk); // parameter expects pointer to esk, so pass in address
{
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
if (!(jsdesc.Verify(verifier, joinSplitPubKey_))) {
throw std::runtime_error("error verifying joinsplit");
}

View File

@ -12,6 +12,7 @@
#include "main.h"
#include "net.h"
#include "netbase.h"
#include "proof_verifier.h"
#include "rpc/server.h"
#include "timedata.h"
#include "transaction_builder.h"
@ -3122,7 +3123,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
vpub_new);
{
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
assert(jsdesc.Verify(verifier, joinSplitPubKey));
}

View File

@ -8,6 +8,7 @@
#include "consensus/validation.h"
#include "key_io.h"
#include "main.h"
#include "proof_verifier.h"
#include "protocol.h"
#include "serialize.h"
#include "sync.h"
@ -481,7 +482,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
CWalletTx wtx;
ssValue >> wtx;
CValidationState state;
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
if (!(CheckTransaction(wtx, state, verifier) && (wtx.GetHash() == hash) && state.IsValid()))
return false;

View File

@ -1,18 +0,0 @@
#include "Proof.hpp"
#include "crypto/common.h"
#include <boost/static_assert.hpp>
#include <mutex>
namespace libzcash {
ProofVerifier ProofVerifier::Strict() {
return ProofVerifier(true);
}
ProofVerifier ProofVerifier::Disabled() {
return ProofVerifier(false);
}
}

View File

@ -211,29 +211,6 @@ typedef std::array<unsigned char, GROTH_PROOF_SIZE> GrothProof;
// with a PHGRProof. The default however should be GrothProof.
typedef boost::variant<PHGRProof, GrothProof> SproutProof;
class ProofVerifier {
private:
bool perform_verification;
ProofVerifier(bool perform_verification) : perform_verification(perform_verification) { }
public:
// ProofVerifier should never be copied
ProofVerifier(const ProofVerifier&) = delete;
ProofVerifier& operator=(const ProofVerifier&) = delete;
ProofVerifier(ProofVerifier&&);
ProofVerifier& operator=(ProofVerifier&&);
// Creates a verification context that strictly verifies
// all proofs.
static ProofVerifier Strict();
// Creates a verification context that performs no
// verification, used when avoiding duplicate effort
// such as during reindexing.
static ProofVerifier Disabled();
};
}
#endif // ZC_PROOF_H_

View File

@ -19,6 +19,7 @@
#include "miner.h"
#include "policy/policy.h"
#include "pow.h"
#include "proof_verifier.h"
#include "rpc/server.h"
#include "script/sign.h"
#include "sodium.h"
@ -109,7 +110,7 @@ double benchmark_create_joinsplit()
0);
double ret = timer_stop(tv_start);
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
assert(jsdesc.Verify(verifier, joinSplitPubKey));
return ret;
}
@ -140,7 +141,7 @@ double benchmark_verify_joinsplit(const JSDescription &joinsplit)
struct timeval tv_start;
timer_start(tv_start);
uint256 joinSplitPubKey;
auto verifier = libzcash::ProofVerifier::Strict();
auto verifier = ProofVerifier::Strict();
joinsplit.Verify(verifier, joinSplitPubKey);
return timer_stop(tv_start);
}