Merge branch 'proofverifier-refactor' into zcashconsensus-fixes-base

This commit is contained in:
Jack Grigg 2020-07-17 15:31:30 +12:00
commit 50ef461f31
38 changed files with 243 additions and 352 deletions

View File

@ -215,6 +215,7 @@ BITCOIN_CORE_H = \
prevector.h \ prevector.h \
primitives/block.h \ primitives/block.h \
primitives/transaction.h \ primitives/transaction.h \
proof_verifier.h \
protocol.h \ protocol.h \
pubkey.h \ pubkey.h \
random.h \ random.h \
@ -428,6 +429,7 @@ libbitcoin_common_a_SOURCES = \
netbase.cpp \ netbase.cpp \
primitives/block.cpp \ primitives/block.cpp \
primitives/transaction.cpp \ primitives/transaction.cpp \
proof_verifier.cpp \
protocol.cpp \ protocol.cpp \
pubkey.cpp \ pubkey.cpp \
scheduler.cpp \ scheduler.cpp \
@ -576,7 +578,6 @@ libzcash_a_SOURCES = \
zcash/address/zip32.cpp \ zcash/address/zip32.cpp \
zcash/History.cpp \ zcash/History.cpp \
zcash/JoinSplit.cpp \ zcash/JoinSplit.cpp \
zcash/Proof.cpp \
zcash/Note.cpp \ zcash/Note.cpp \
zcash/prf.cpp \ zcash/prf.cpp \
zcash/util.cpp zcash/util.cpp

View File

@ -7,7 +7,6 @@
#include "key.h" #include "key.h"
#include "main.h" #include "main.h"
#include "util.h" #include "util.h"
#include "zcash/JoinSplit.hpp"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>

View File

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

View File

@ -2,7 +2,6 @@
#include "crypto/common.h" #include "crypto/common.h"
#include "key.h" #include "key.h"
#include "pubkey.h" #include "pubkey.h"
#include "zcash/JoinSplit.hpp"
#include "util.h" #include "util.h"
#include "librustzcash.h" #include "librustzcash.h"
@ -14,14 +13,10 @@ struct ECCryptoClosure
ECCryptoClosure instance_of_eccryptoclosure; ECCryptoClosure instance_of_eccryptoclosure;
ZCJoinSplit* params;
int main(int argc, char **argv) { int main(int argc, char **argv) {
assert(init_and_check_sodium() != -1); assert(init_and_check_sodium() != -1);
ECC_Start(); ECC_Start();
params = ZCJoinSplit::Prepared();
boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params"; boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params"; boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params";

View File

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

View File

@ -11,8 +11,6 @@
#include <librustzcash.h> #include <librustzcash.h>
extern ZCJoinSplit* params;
TEST(ChecktransactionTests, CheckVpubNotBothNonzero) { TEST(ChecktransactionTests, CheckVpubNotBothNonzero) {
CMutableTransaction tx; CMutableTransaction tx;
tx.nVersion = 2; tx.nVersion = 2;
@ -831,7 +829,7 @@ TEST(ChecktransactionTests, SaplingSproutInputSumsTooLarge) {
std::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap; std::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap;
auto jsdesc = JSDescription::Randomized( auto jsdesc = JSDescription::Randomized(
*params, joinSplitPubKey, rt, joinSplitPubKey, rt,
inputs, outputs, inputs, outputs,
inputMap, outputMap, inputMap, outputMap,
0, 0, false); 0, 0, false);

View File

@ -11,8 +11,6 @@
#include "transaction_builder.h" #include "transaction_builder.h"
#include "utiltest.h" #include "utiltest.h"
extern ZCJoinSplit* params;
TEST(RecursiveDynamicUsageTests, TestTransactionTransparent) TEST(RecursiveDynamicUsageTests, TestTransactionTransparent)
{ {
auto consensusParams = RegtestActivateSapling(); auto consensusParams = RegtestActivateSapling();
@ -40,7 +38,7 @@ TEST(RecursiveDynamicUsageTests, TestTransactionJoinSplit)
auto sproutSk = libzcash::SproutSpendingKey::random(); auto sproutSk = libzcash::SproutSpendingKey::random();
auto wtx = GetValidSproutReceive(*params, sproutSk, 25000, true); auto wtx = GetValidSproutReceive(sproutSk, 25000, true);
// 2 vin + 1 vJoinSplit + 1 vShieldedOutput // 2 vin + 1 vJoinSplit + 1 vShieldedOutput
// 160 + 1856 + 976 // 160 + 1856 + 976
EXPECT_EQ(2992, RecursiveDynamicUsage(wtx)); EXPECT_EQ(2992, RecursiveDynamicUsage(wtx));

View File

@ -11,6 +11,7 @@
#include "version.h" #include "version.h"
#include "serialize.h" #include "serialize.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "proof_verifier.h"
#include "zcash/JoinSplit.hpp" #include "zcash/JoinSplit.hpp"
#include "zcash/Note.hpp" #include "zcash/Note.hpp"
#include "zcash/NoteEncryption.hpp" #include "zcash/NoteEncryption.hpp"
@ -20,12 +21,9 @@
using namespace libzcash; using namespace libzcash;
extern ZCJoinSplit* params;
// Make the Groth proof for a Sprout statement, // Make the Groth proof for a Sprout statement,
// and store the result in a JSDescription object. // and store the result in a JSDescription object.
JSDescription makeSproutProof( JSDescription makeSproutProof(
ZCJoinSplit& js,
const std::array<JSInput, 2>& inputs, const std::array<JSInput, 2>& inputs,
const std::array<JSOutput, 2>& outputs, const std::array<JSOutput, 2>& outputs,
const uint256& joinSplitPubKey, const uint256& joinSplitPubKey,
@ -33,24 +31,23 @@ JSDescription makeSproutProof(
uint64_t vpub_new, uint64_t vpub_new,
const uint256& rt const uint256& rt
){ ){
return JSDescription(js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); return JSDescription(joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new);
} }
bool verifySproutProof( bool verifySproutProof(
ZCJoinSplit& js,
const JSDescription& jsdesc, const JSDescription& jsdesc,
const uint256& joinSplitPubKey const uint256& joinSplitPubKey
) )
{ {
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
return jsdesc.Verify(js, verifier, joinSplitPubKey); return verifier.VerifySprout(jsdesc, joinSplitPubKey);
} }
void test_full_api(ZCJoinSplit* js) void test_full_api()
{ {
// Create verification context. // Create verification context.
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
// The recipient's information. // The recipient's information.
SproutSpendingKey recipient_key = SproutSpendingKey::random(); SproutSpendingKey recipient_key = SproutSpendingKey::random();
@ -81,7 +78,6 @@ void test_full_api(ZCJoinSplit* js)
// Perform the proofs // Perform the proofs
jsdesc = makeSproutProof( jsdesc = makeSproutProof(
*js,
inputs, inputs,
outputs, outputs,
joinSplitPubKey, joinSplitPubKey,
@ -92,14 +88,14 @@ void test_full_api(ZCJoinSplit* js)
} }
// Verify both PHGR and Groth Proof: // Verify both PHGR and Groth Proof:
ASSERT_TRUE(verifySproutProof(*js, jsdesc, joinSplitPubKey)); ASSERT_TRUE(verifySproutProof(jsdesc, joinSplitPubKey));
{ {
SproutMerkleTree tree; SproutMerkleTree tree;
JSDescription jsdesc2; JSDescription jsdesc2;
// Recipient should decrypt // Recipient should decrypt
// Now the recipient should spend the money again // Now the recipient should spend the money again
auto h_sig = js->h_sig(jsdesc.randomSeed, jsdesc.nullifiers, joinSplitPubKey); auto h_sig = ZCJoinSplit::h_sig(jsdesc.randomSeed, jsdesc.nullifiers, joinSplitPubKey);
ZCNoteDecryption decryptor(recipient_key.receiving_key()); ZCNoteDecryption decryptor(recipient_key.receiving_key());
auto note_pt = SproutNotePlaintext::decrypt( auto note_pt = SproutNotePlaintext::decrypt(
@ -143,7 +139,6 @@ void test_full_api(ZCJoinSplit* js)
// Perform the proofs // Perform the proofs
jsdesc2 = makeSproutProof( jsdesc2 = makeSproutProof(
*js,
inputs, inputs,
outputs, outputs,
joinSplitPubKey2, joinSplitPubKey2,
@ -156,14 +151,13 @@ void test_full_api(ZCJoinSplit* js)
// Verify Groth Proof: // Verify Groth Proof:
ASSERT_TRUE(verifySproutProof(*js, jsdesc2, joinSplitPubKey2)); ASSERT_TRUE(verifySproutProof(jsdesc2, joinSplitPubKey2));
} }
} }
// Invokes the API (but does not compute a proof) // Invokes the API (but does not compute a proof)
// to test exceptions // to test exceptions
void invokeAPI( void invokeAPI(
ZCJoinSplit* js,
const std::array<JSInput, 2>& inputs, const std::array<JSInput, 2>& inputs,
const std::array<JSOutput, 2>& outputs, const std::array<JSOutput, 2>& outputs,
uint64_t vpub_old, uint64_t vpub_old,
@ -181,7 +175,7 @@ void invokeAPI(
std::array<SproutNote, 2> output_notes; std::array<SproutNote, 2> output_notes;
// Groth // Groth
SproutProof proof = js->prove( SproutProof proof = ZCJoinSplit::prove(
inputs, inputs,
outputs, outputs,
output_notes, output_notes,
@ -200,7 +194,6 @@ void invokeAPI(
} }
void invokeAPIFailure( void invokeAPIFailure(
ZCJoinSplit* js,
const std::array<JSInput, 2>& inputs, const std::array<JSInput, 2>& inputs,
const std::array<JSOutput, 2>& outputs, const std::array<JSOutput, 2>& outputs,
uint64_t vpub_old, uint64_t vpub_old,
@ -210,7 +203,7 @@ void invokeAPIFailure(
) )
{ {
try { try {
invokeAPI(js, inputs, outputs, vpub_old, vpub_new, rt); invokeAPI(inputs, outputs, vpub_old, vpub_new, rt);
FAIL() << "It worked, when it shouldn't have!"; FAIL() << "It worked, when it shouldn't have!";
} catch(std::invalid_argument const & err) { } catch(std::invalid_argument const & err) {
EXPECT_EQ(err.what(), reason); EXPECT_EQ(err.what(), reason);
@ -327,7 +320,7 @@ TEST(Joinsplit, FullApiTest)
increment_note_witnesses(note5.cm(), witnesses, tree); increment_note_witnesses(note5.cm(), witnesses, tree);
// Should work // Should work
invokeAPI(params, invokeAPI(
{ {
JSInput(), JSInput(),
JSInput() JSInput()
@ -341,7 +334,7 @@ TEST(Joinsplit, FullApiTest)
tree.root()); tree.root());
// lhs > MAX_MONEY // lhs > MAX_MONEY
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(), JSInput(),
JSInput() JSInput()
@ -356,7 +349,7 @@ TEST(Joinsplit, FullApiTest)
"nonsensical vpub_old value"); "nonsensical vpub_old value");
// rhs > MAX_MONEY // rhs > MAX_MONEY
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(), JSInput(),
JSInput() JSInput()
@ -371,7 +364,7 @@ TEST(Joinsplit, FullApiTest)
"nonsensical vpub_new value"); "nonsensical vpub_new value");
// input witness for the wrong element // input witness for the wrong element
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(witnesses[0], note1, sk), JSInput(witnesses[0], note1, sk),
JSInput() JSInput()
@ -387,7 +380,7 @@ TEST(Joinsplit, FullApiTest)
// input witness doesn't match up with // input witness doesn't match up with
// real root // real root
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(witnesses[1], note1, sk), JSInput(witnesses[1], note1, sk),
JSInput() JSInput()
@ -402,7 +395,7 @@ TEST(Joinsplit, FullApiTest)
"joinsplit not anchored to the correct root"); "joinsplit not anchored to the correct root");
// input is in the tree now! this should work // input is in the tree now! this should work
invokeAPI(params, invokeAPI(
{ {
JSInput(witnesses[1], note1, sk), JSInput(witnesses[1], note1, sk),
JSInput() JSInput()
@ -416,7 +409,7 @@ TEST(Joinsplit, FullApiTest)
tree.root()); tree.root());
// Wrong secret key // Wrong secret key
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(witnesses[1], note1, SproutSpendingKey::random()), JSInput(witnesses[1], note1, SproutSpendingKey::random()),
JSInput() JSInput()
@ -431,7 +424,7 @@ TEST(Joinsplit, FullApiTest)
"input note not authorized to spend with given key"); "input note not authorized to spend with given key");
// Absurd input value // Absurd input value
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(witnesses[3], note3, sk), JSInput(witnesses[3], note3, sk),
JSInput() JSInput()
@ -446,7 +439,7 @@ TEST(Joinsplit, FullApiTest)
"nonsensical input note value"); "nonsensical input note value");
// Absurd total input value // Absurd total input value
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(witnesses[4], note4, sk), JSInput(witnesses[4], note4, sk),
JSInput(witnesses[5], note5, sk) JSInput(witnesses[5], note5, sk)
@ -461,7 +454,7 @@ TEST(Joinsplit, FullApiTest)
"nonsensical left hand size of joinsplit balance"); "nonsensical left hand size of joinsplit balance");
// Absurd output value // Absurd output value
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(), JSInput(),
JSInput() JSInput()
@ -476,7 +469,7 @@ TEST(Joinsplit, FullApiTest)
"nonsensical output value"); "nonsensical output value");
// Absurd total output value // Absurd total output value
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(), JSInput(),
JSInput() JSInput()
@ -491,7 +484,7 @@ TEST(Joinsplit, FullApiTest)
"nonsensical right hand side of joinsplit balance"); "nonsensical right hand side of joinsplit balance");
// Absurd total output value // Absurd total output value
invokeAPIFailure(params, invokeAPIFailure(
{ {
JSInput(), JSInput(),
JSInput() JSInput()
@ -506,7 +499,7 @@ TEST(Joinsplit, FullApiTest)
"invalid joinsplit balance"); "invalid joinsplit balance");
} }
test_full_api(params); test_full_api();
} }
TEST(Joinsplit, NotePlaintexts) TEST(Joinsplit, NotePlaintexts)

View File

@ -6,7 +6,6 @@
#include <array> #include <array>
extern ZCJoinSplit* params;
extern int GenZero(int n); extern int GenZero(int n);
extern int GenMax(int n); extern int GenMax(int n);
@ -45,7 +44,7 @@ TEST(Transaction, JSDescriptionRandomized) {
{ {
auto jsdesc = JSDescription::Randomized( auto jsdesc = JSDescription::Randomized(
*params, joinSplitPubKey, rt, joinSplitPubKey, rt,
inputs, outputs, inputs, outputs,
inputMap, outputMap, inputMap, outputMap,
0, 0, false); 0, 0, false);
@ -61,7 +60,7 @@ TEST(Transaction, JSDescriptionRandomized) {
{ {
auto jsdesc = JSDescription::Randomized( auto jsdesc = JSDescription::Randomized(
*params, joinSplitPubKey, rt, joinSplitPubKey, rt,
inputs, outputs, inputs, outputs,
inputMap, outputMap, inputMap, outputMap,
0, 0, false, nullptr, GenZero); 0, 0, false, nullptr, GenZero);
@ -74,7 +73,7 @@ TEST(Transaction, JSDescriptionRandomized) {
{ {
auto jsdesc = JSDescription::Randomized( auto jsdesc = JSDescription::Randomized(
*params, joinSplitPubKey, rt, joinSplitPubKey, rt,
inputs, outputs, inputs, outputs,
inputMap, outputMap, inputMap, outputMap,
0, 0, false, nullptr, GenMax); 0, 0, false, nullptr, GenMax);

View File

@ -13,8 +13,6 @@
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
extern ZCJoinSplit* params;
// Fake an empty view // Fake an empty view
class TransactionBuilderCoinsViewDB : public CCoinsView { class TransactionBuilderCoinsViewDB : public CCoinsView {
public: public:
@ -167,7 +165,7 @@ TEST(TransactionBuilder, SaplingToSprout) {
// - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out // - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out
// - 0.00005 Sapling-ZEC change // - 0.00005 Sapling-ZEC change
// - 0.0001 t-ZEC fee // - 0.0001 t-ZEC fee
auto builder = TransactionBuilder(consensusParams, 2, nullptr, params); auto builder = TransactionBuilder(consensusParams, 2, nullptr);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
builder.AddSproutOutput(sproutAddr, 25000); builder.AddSproutOutput(sproutAddr, 25000);
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -199,8 +197,8 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) {
auto sproutSk = libzcash::SproutSpendingKey::random(); auto sproutSk = libzcash::SproutSpendingKey::random();
auto sproutAddr = sproutSk.address(); auto sproutAddr = sproutSk.address();
auto wtx = GetValidSproutReceive(*params, sproutSk, 25000, true); auto wtx = GetValidSproutReceive(sproutSk, 25000, true);
auto sproutNote = GetSproutNote(*params, sproutSk, wtx, 0, 1); auto sproutNote = GetSproutNote(sproutSk, wtx, 0, 1);
SproutMerkleTree sproutTree; SproutMerkleTree sproutTree;
for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
@ -219,7 +217,7 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) {
// - 0.00005 Sprout-ZEC change // - 0.00005 Sprout-ZEC change
// - 0.00005 Sapling-ZEC out // - 0.00005 Sapling-ZEC out
// - 0.00005 t-ZEC fee // - 0.00005 t-ZEC fee
auto builder = TransactionBuilder(consensusParams, 2, nullptr, params, &view); auto builder = TransactionBuilder(consensusParams, 2, nullptr, &view);
builder.SetFee(5000); builder.SetFee(5000);
builder.AddSproutInput(sproutSk, sproutNote, sproutWitness); builder.AddSproutInput(sproutSk, sproutNote, sproutWitness);
builder.AddSproutOutput(sproutAddr, 6000); builder.AddSproutOutput(sproutAddr, 6000);

View File

@ -7,8 +7,6 @@
#include "transaction_builder.h" #include "transaction_builder.h"
#include "utiltest.h" #include "utiltest.h"
extern ZCJoinSplit* params;
extern bool ReceivedBlockTransactions( extern bool ReceivedBlockTransactions(
const CBlock &block, const CBlock &block,
CValidationState& state, CValidationState& state,
@ -221,14 +219,14 @@ TEST(Validation, ReceivedBlockTransactions) {
// Create a fake genesis block // Create a fake genesis block
CBlock block1; CBlock block1;
block1.vtx.push_back(GetValidSproutReceive(*params, sk, 5, true)); block1.vtx.push_back(GetValidSproutReceive(sk, 5, true));
block1.hashMerkleRoot = block1.BuildMerkleTree(); block1.hashMerkleRoot = block1.BuildMerkleTree();
CBlockIndex fakeIndex1 {block1}; CBlockIndex fakeIndex1 {block1};
// Create a fake child block // Create a fake child block
CBlock block2; CBlock block2;
block2.hashPrevBlock = block1.GetHash(); block2.hashPrevBlock = block1.GetHash();
block2.vtx.push_back(GetValidSproutReceive(*params, sk, 10, true)); block2.vtx.push_back(GetValidSproutReceive(sk, 10, true));
block2.hashMerkleRoot = block2.BuildMerkleTree(); block2.hashMerkleRoot = block2.BuildMerkleTree();
CBlockIndex fakeIndex2 {block2}; CBlockIndex fakeIndex2 {block2};
fakeIndex2.pprev = &fakeIndex1; fakeIndex2.pprev = &fakeIndex1;

View File

@ -75,8 +75,6 @@ using namespace std;
extern void ThreadSendAlert(); extern void ThreadSendAlert();
ZCJoinSplit* pzcashParams = NULL;
bool fFeeEstimatesInitialized = false; bool fFeeEstimatesInitialized = false;
static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false; static const bool DEFAULT_REST_ENABLE = false;
@ -271,8 +269,6 @@ void Shutdown()
delete pwalletMain; delete pwalletMain;
pwalletMain = NULL; pwalletMain = NULL;
#endif #endif
delete pzcashParams;
pzcashParams = NULL;
globalVerifyHandle.reset(); globalVerifyHandle.reset();
ECC_Stop(); ECC_Stop();
LogPrintf("%s: done\n", __func__); LogPrintf("%s: done\n", __func__);
@ -716,8 +712,6 @@ static void ZC_LoadParams(
return; return;
} }
pzcashParams = ZCJoinSplit::Prepared();
static_assert( static_assert(
sizeof(boost::filesystem::path::value_type) == sizeof(codeunit), sizeof(boost::filesystem::path::value_type) == sizeof(codeunit),
"librustzcash not configured correctly"); "librustzcash not configured correctly");

View File

@ -8,8 +8,6 @@
#include <string> #include <string>
#include "zcash/JoinSplit.hpp"
class CScheduler; class CScheduler;
class CWallet; class CWallet;
@ -18,8 +16,6 @@ namespace boost
class thread_group; class thread_group;
} // namespace boost } // namespace boost
extern ZCJoinSplit* pzcashParams;
void StartShutdown(); void StartShutdown();
bool ShutdownRequested(); bool ShutdownRequested();
/** Interrupt threads */ /** Interrupt threads */

View File

@ -1138,7 +1138,7 @@ bool ContextualCheckTransaction(
bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool CheckTransaction(const CTransaction& tx, CValidationState &state,
libzcash::ProofVerifier& verifier) ProofVerifier& verifier)
{ {
// Don't count coinbase transactions because mining skews the count // Don't count coinbase transactions because mining skews the count
if (!tx.IsCoinBase()) { if (!tx.IsCoinBase()) {
@ -1150,7 +1150,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state,
} else { } else {
// Ensure that zk-SNARKs verify // Ensure that zk-SNARKs verify
BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) {
if (!joinsplit.Verify(*pzcashParams, verifier, tx.joinSplitPubKey)) { if (!verifier.VerifySprout(joinsplit, tx.joinSplitPubKey)) {
return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"), return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"),
REJECT_INVALID, "bad-txns-joinsplit-verification-failed"); REJECT_INVALID, "bad-txns-joinsplit-verification-failed");
} }
@ -1438,7 +1438,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return false; return false;
} }
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
if (!CheckTransaction(tx, state, verifier)) if (!CheckTransaction(tx, state, verifier))
return error("AcceptToMemoryPool: CheckTransaction failed"); return error("AcceptToMemoryPool: CheckTransaction failed");
@ -2706,8 +2706,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
} }
} }
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
auto disabledVerifier = libzcash::ProofVerifier::Disabled(); auto disabledVerifier = ProofVerifier::Disabled();
// Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in // 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)) if (!CheckBlock(block, state, chainparams, fExpensiveChecks ? verifier : disabledVerifier, !fJustCheck, !fJustCheck))
@ -3997,7 +3997,7 @@ bool CheckBlockHeader(
bool CheckBlock(const CBlock& block, CValidationState& state, bool CheckBlock(const CBlock& block, CValidationState& state,
const CChainParams& chainparams, const CChainParams& chainparams,
libzcash::ProofVerifier& verifier, ProofVerifier& verifier,
bool fCheckPOW, bool fCheckMerkleRoot) bool fCheckPOW, bool fCheckMerkleRoot)
{ {
// These are checks that are independent of context. // These are checks that are independent of context.
@ -4272,7 +4272,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
} }
// See method docstring for why this is always disabled // 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 ((!CheckBlock(block, state, chainparams, verifier)) || !ContextualCheckBlock(block, state, chainparams, pindex->pprev)) {
if (state.IsInvalid() && !state.CorruptionPossible()) { if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID; pindex->nStatus |= BLOCK_FAILED_VALID;
@ -4322,7 +4322,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) bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp)
{ {
// Preliminary checks // Preliminary checks
auto verifier = libzcash::ProofVerifier::Disabled(); auto verifier = ProofVerifier::Disabled();
bool checked = CheckBlock(*pblock, state, chainparams, verifier); bool checked = CheckBlock(*pblock, state, chainparams, verifier);
{ {
@ -4360,7 +4360,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
indexDummy.pprev = pindexPrev; indexDummy.pprev = pindexPrev;
indexDummy.nHeight = pindexPrev->nHeight + 1; indexDummy.nHeight = pindexPrev->nHeight + 1;
// JoinSplit proofs are verified in ConnectBlock // JoinSplit proofs are verified in ConnectBlock
auto verifier = libzcash::ProofVerifier::Disabled(); auto verifier = ProofVerifier::Disabled();
// NOTE: CheckBlockHeader is called by CheckBlock // NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev)) if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev))
@ -4760,7 +4760,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
int nGoodTransactions = 0; int nGoodTransactions = 0;
CValidationState state; CValidationState state;
// No need to verify JoinSplits twice // 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) for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
{ {
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();

View File

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

View File

@ -9,10 +9,7 @@
#include "tinyformat.h" #include "tinyformat.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
#include "librustzcash.h"
JSDescription::JSDescription( JSDescription::JSDescription(
ZCJoinSplit& params,
const uint256& joinSplitPubKey, const uint256& joinSplitPubKey,
const uint256& anchor, const uint256& anchor,
const std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs, const std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
@ -25,7 +22,7 @@ JSDescription::JSDescription(
{ {
std::array<libzcash::SproutNote, ZC_NUM_JS_OUTPUTS> notes; std::array<libzcash::SproutNote, ZC_NUM_JS_OUTPUTS> notes;
proof = params.prove( proof = ZCJoinSplit::prove(
inputs, inputs,
outputs, outputs,
notes, notes,
@ -45,7 +42,6 @@ JSDescription::JSDescription(
} }
JSDescription JSDescription::Randomized( JSDescription JSDescription::Randomized(
ZCJoinSplit& params,
const uint256& joinSplitPubKey, const uint256& joinSplitPubKey,
const uint256& anchor, const uint256& anchor,
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs, std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
@ -69,63 +65,12 @@ JSDescription JSDescription::Randomized(
MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, gen); MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, gen);
return JSDescription( return JSDescription(
params, joinSplitPubKey, anchor, inputs, outputs, joinSplitPubKey, anchor, inputs, outputs,
vpub_old, vpub_new, computeProof, vpub_old, vpub_new, computeProof,
esk // payment disclosure esk // payment disclosure
); );
} }
class SproutProofVerifier : public boost::static_visitor<bool>
{
ZCJoinSplit& params;
libzcash::ProofVerifier& verifier;
const uint256& joinSplitPubKey;
const JSDescription& jsdesc;
public:
SproutProofVerifier(
ZCJoinSplit& params,
libzcash::ProofVerifier& verifier,
const uint256& joinSplitPubKey,
const JSDescription& jsdesc
) : params(params), jsdesc(jsdesc), verifier(verifier), joinSplitPubKey(joinSplitPubKey) {}
bool operator()(const libzcash::PHGRProof& proof) const
{
// We checkpoint after Sapling activation, so we can skip verification
// for all Sprout proofs.
return true;
}
bool operator()(const libzcash::GrothProof& proof) const
{
uint256 h_sig = ZCJoinSplit::h_sig(jsdesc.randomSeed, jsdesc.nullifiers, joinSplitPubKey);
return librustzcash_sprout_verify(
proof.begin(),
jsdesc.anchor.begin(),
h_sig.begin(),
jsdesc.macs[0].begin(),
jsdesc.macs[1].begin(),
jsdesc.nullifiers[0].begin(),
jsdesc.nullifiers[1].begin(),
jsdesc.commitments[0].begin(),
jsdesc.commitments[1].begin(),
jsdesc.vpub_old,
jsdesc.vpub_new
);
}
};
bool JSDescription::Verify(
ZCJoinSplit& params,
libzcash::ProofVerifier& verifier,
const uint256& joinSplitPubKey
) const {
auto pv = SproutProofVerifier(params, verifier, joinSplitPubKey, *this);
return boost::apply_visitor(pv, proof);
}
uint256 JSDescription::h_sig(const uint256& joinSplitPubKey) const uint256 JSDescription::h_sig(const uint256& joinSplitPubKey) const
{ {
return ZCJoinSplit::h_sig(randomSeed, nullifiers, joinSplitPubKey); return ZCJoinSplit::h_sig(randomSeed, nullifiers, joinSplitPubKey);

View File

@ -235,7 +235,6 @@ public:
JSDescription(): vpub_old(0), vpub_new(0) { } JSDescription(): vpub_old(0), vpub_new(0) { }
JSDescription( JSDescription(
ZCJoinSplit& params,
const uint256& joinSplitPubKey, const uint256& joinSplitPubKey,
const uint256& rt, const uint256& rt,
const std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs, const std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
@ -247,7 +246,6 @@ public:
); );
static JSDescription Randomized( static JSDescription Randomized(
ZCJoinSplit& params,
const uint256& joinSplitPubKey, const uint256& joinSplitPubKey,
const uint256& rt, const uint256& rt,
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs, std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
@ -261,13 +259,6 @@ public:
std::function<int(int)> gen = GetRandInt std::function<int(int)> gen = GetRandInt
); );
// Verifies that the JoinSplit proof is correct.
bool Verify(
ZCJoinSplit& params,
libzcash::ProofVerifier& verifier,
const uint256& joinSplitPubKey
) const;
// Returns the calculated h_sig // Returns the calculated h_sig
uint256 h_sig(const uint256& joinSplitPubKey) const; uint256 h_sig(const uint256& joinSplitPubKey) const;

70
src/proof_verifier.cpp Normal file
View File

@ -0,0 +1,70 @@
// 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>
#include <zcash/JoinSplit.hpp>
#include <boost/variant.hpp>
#include <librustzcash.h>
class SproutProofVerifier : public boost::static_visitor<bool>
{
ProofVerifier& verifier;
const uint256& joinSplitPubKey;
const JSDescription& jsdesc;
public:
SproutProofVerifier(
ProofVerifier& verifier,
const uint256& joinSplitPubKey,
const JSDescription& jsdesc
) : jsdesc(jsdesc), verifier(verifier), joinSplitPubKey(joinSplitPubKey) {}
bool operator()(const libzcash::PHGRProof& proof) const
{
// We checkpoint after Sapling activation, so we can skip verification
// for all Sprout proofs.
return true;
}
bool operator()(const libzcash::GrothProof& proof) const
{
uint256 h_sig = ZCJoinSplit::h_sig(jsdesc.randomSeed, jsdesc.nullifiers, joinSplitPubKey);
return librustzcash_sprout_verify(
proof.begin(),
jsdesc.anchor.begin(),
h_sig.begin(),
jsdesc.macs[0].begin(),
jsdesc.macs[1].begin(),
jsdesc.nullifiers[0].begin(),
jsdesc.nullifiers[1].begin(),
jsdesc.commitments[0].begin(),
jsdesc.commitments[1].begin(),
jsdesc.vpub_old,
jsdesc.vpub_new
);
}
};
ProofVerifier ProofVerifier::Strict() {
return ProofVerifier(true);
}
ProofVerifier ProofVerifier::Disabled() {
return ProofVerifier(false);
}
bool ProofVerifier::VerifySprout(
const JSDescription& jsdesc,
const uint256& joinSplitPubKey
) {
if (!perform_verification) {
return true;
}
auto pv = SproutProofVerifier(*this, joinSplitPubKey, jsdesc);
return boost::apply_visitor(pv, jsdesc.proof);
}

40
src/proof_verifier.h Normal file
View File

@ -0,0 +1,40 @@
// 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
#include <primitives/transaction.h>
#include <uint256.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();
// Verifies that the JoinSplit proof is correct.
bool VerifySprout(
const JSDescription& jsdesc,
const uint256& joinSplitPubKey
);
};
#endif // ZCASH_PROOF_VERIFIER_H

View File

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

View File

@ -32,7 +32,6 @@
#include "librustzcash.h" #include "librustzcash.h"
CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
ZCJoinSplit *pzcashParams;
FastRandomContext insecure_rand_ctx(true); FastRandomContext insecure_rand_ctx(true);
extern bool fPrintToConsole; extern bool fPrintToConsole;
@ -40,8 +39,6 @@ extern void noui_connect();
JoinSplitTestingSetup::JoinSplitTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName) JoinSplitTestingSetup::JoinSplitTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{ {
pzcashParams = ZCJoinSplit::Prepared();
boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params"; boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params"; boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params";
@ -68,7 +65,6 @@ JoinSplitTestingSetup::JoinSplitTestingSetup(const std::string& chainName) : Bas
JoinSplitTestingSetup::~JoinSplitTestingSetup() JoinSplitTestingSetup::~JoinSplitTestingSetup()
{ {
delete pzcashParams;
} }
BasicTestingSetup::BasicTestingSetup(const std::string& chainName) BasicTestingSetup::BasicTestingSetup(const std::string& chainName)

View File

@ -16,6 +16,7 @@
#include "keystore.h" #include "keystore.h"
#include "main.h" #include "main.h"
#include "policy/policy.h" #include "policy/policy.h"
#include "proof_verifier.h"
#include "script/script.h" #include "script/script.h"
#include "script/script_error.h" #include "script/script_error.h"
#include "script/sign.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))); UniValue tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
std::string comment(""); std::string comment("");
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
ScriptError err; ScriptError err;
for (size_t idx = 0; idx < tests.size(); idx++) { for (size_t idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[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))); UniValue tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
std::string comment(""); std::string comment("");
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
ScriptError err; ScriptError err;
for (size_t idx = 0; idx < tests.size(); idx++) { for (size_t idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx]; UniValue test = tests[idx];
@ -278,7 +279,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
CMutableTransaction tx; CMutableTransaction tx;
stream >> tx; stream >> tx;
CValidationState state; 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."); BOOST_CHECK_MESSAGE(CheckTransaction(tx, state, verifier) && state.IsValid(), "Simple deserialized transaction should be valid.");
// Check that duplicate txins fail // Check that duplicate txins fail
@ -369,11 +370,11 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
libzcash::JSOutput(addr, 50) libzcash::JSOutput(addr, 50)
}; };
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
{ {
JSDescription jsdesc(*pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); JSDescription jsdesc(joinSplitPubKey, rt, inputs, outputs, 0, 0);
BOOST_CHECK(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey)); BOOST_CHECK(verifier.VerifySprout(jsdesc, joinSplitPubKey));
CDataStream ss(SER_DISK, CLIENT_VERSION); CDataStream ss(SER_DISK, CLIENT_VERSION);
auto os = WithVersion(&ss, SAPLING_TX_VERSION | 1 << 31); auto os = WithVersion(&ss, SAPLING_TX_VERSION | 1 << 31);
@ -383,20 +384,20 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
os >> jsdesc_deserialized; os >> jsdesc_deserialized;
BOOST_CHECK(jsdesc_deserialized == jsdesc); BOOST_CHECK(jsdesc_deserialized == jsdesc);
BOOST_CHECK(jsdesc_deserialized.Verify(*pzcashParams, verifier, joinSplitPubKey)); BOOST_CHECK(verifier.VerifySprout(jsdesc_deserialized, joinSplitPubKey));
} }
{ {
// Ensure that the balance equation is working. // Ensure that the balance equation is working.
BOOST_CHECK_THROW(JSDescription(*pzcashParams, joinSplitPubKey, rt, inputs, outputs, 10, 0), std::invalid_argument); BOOST_CHECK_THROW(JSDescription(joinSplitPubKey, rt, inputs, outputs, 10, 0), std::invalid_argument);
BOOST_CHECK_THROW(JSDescription(*pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 10), std::invalid_argument); BOOST_CHECK_THROW(JSDescription(joinSplitPubKey, rt, inputs, outputs, 0, 10), std::invalid_argument);
} }
{ {
// Ensure that it won't verify if the root is changed. // Ensure that it won't verify if the root is changed.
auto test = JSDescription(*pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); auto test = JSDescription(joinSplitPubKey, rt, inputs, outputs, 0, 0);
test.anchor = GetRandHash(); test.anchor = GetRandHash();
BOOST_CHECK(!test.Verify(*pzcashParams, verifier, joinSplitPubKey)); BOOST_CHECK(!verifier.VerifySprout(test, joinSplitPubKey));
} }
} }
@ -460,7 +461,7 @@ void test_simple_sapling_invalidity(uint32_t consensusBranchId, CMutableTransact
void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransaction tx) 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 // Ensure that empty vin/vout remain invalid without
// joinsplits. // joinsplits.

View File

@ -5,6 +5,7 @@
#include "transaction_builder.h" #include "transaction_builder.h"
#include "main.h" #include "main.h"
#include "proof_verifier.h"
#include "pubkey.h" #include "pubkey.h"
#include "rpc/protocol.h" #include "rpc/protocol.h"
#include "script/sign.h" #include "script/sign.h"
@ -99,13 +100,11 @@ TransactionBuilder::TransactionBuilder(
const Consensus::Params& consensusParams, const Consensus::Params& consensusParams,
int nHeight, int nHeight,
CKeyStore* keystore, CKeyStore* keystore,
ZCJoinSplit* sproutParams,
CCoinsViewCache* coinsView, CCoinsViewCache* coinsView,
CCriticalSection* cs_coinsView) : CCriticalSection* cs_coinsView) :
consensusParams(consensusParams), consensusParams(consensusParams),
nHeight(nHeight), nHeight(nHeight),
keystore(keystore), keystore(keystore),
sproutParams(sproutParams),
coinsView(coinsView), coinsView(coinsView),
cs_coinsView(cs_coinsView) cs_coinsView(cs_coinsView)
{ {
@ -179,10 +178,6 @@ void TransactionBuilder::AddSproutInput(
libzcash::SproutNote note, libzcash::SproutNote note,
SproutWitness witness) SproutWitness witness)
{ {
if (sproutParams == nullptr) {
throw std::runtime_error("Cannot add Sprout inputs to a TransactionBuilder without Sprout params");
}
// Consistency check: all anchors must equal the first one // Consistency check: all anchors must equal the first one
if (!jsInputs.empty()) { if (!jsInputs.empty()) {
if (jsInputs[0].witness.root() != witness.root()) { if (jsInputs[0].witness.root() != witness.root()) {
@ -198,10 +193,6 @@ void TransactionBuilder::AddSproutOutput(
CAmount value, CAmount value,
std::array<unsigned char, ZC_MEMO_SIZE> memo) std::array<unsigned char, ZC_MEMO_SIZE> memo)
{ {
if (sproutParams == nullptr) {
throw std::runtime_error("Cannot add Sprout outputs to a TransactionBuilder without Sprout params");
}
libzcash::JSOutput jsOutput(to, value); libzcash::JSOutput jsOutput(to, value);
jsOutput.memo = memo; jsOutput.memo = memo;
jsOutputs.push_back(jsOutput); jsOutputs.push_back(jsOutput);
@ -724,7 +715,6 @@ void TransactionBuilder::CreateJSDescription(
// Generate the proof, this can take over a minute. // Generate the proof, this can take over a minute.
assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)); assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION));
JSDescription jsdesc = JSDescription::Randomized( JSDescription jsdesc = JSDescription::Randomized(
*sproutParams,
mtx.joinSplitPubKey, mtx.joinSplitPubKey,
vjsin[0].witness.root(), vjsin[0].witness.root(),
vjsin, vjsin,
@ -737,8 +727,8 @@ void TransactionBuilder::CreateJSDescription(
&esk); // parameter expects pointer to esk, so pass in address &esk); // parameter expects pointer to esk, so pass in address
{ {
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
if (!jsdesc.Verify(*sproutParams, verifier, mtx.joinSplitPubKey)) { if (!verifier.VerifySprout(jsdesc, mtx.joinSplitPubKey)) {
throw std::runtime_error("error verifying joinsplit"); throw std::runtime_error("error verifying joinsplit");
} }
} }

View File

@ -78,7 +78,6 @@ private:
Consensus::Params consensusParams; Consensus::Params consensusParams;
int nHeight; int nHeight;
const CKeyStore* keystore; const CKeyStore* keystore;
ZCJoinSplit* sproutParams;
const CCoinsViewCache* coinsView; const CCoinsViewCache* coinsView;
CCriticalSection* cs_coinsView; CCriticalSection* cs_coinsView;
CMutableTransaction mtx; CMutableTransaction mtx;
@ -100,7 +99,6 @@ public:
const Consensus::Params& consensusParams, const Consensus::Params& consensusParams,
int nHeight, int nHeight,
CKeyStore* keyStore = nullptr, CKeyStore* keyStore = nullptr,
ZCJoinSplit* sproutParams = nullptr,
CCoinsViewCache* coinsView = nullptr, CCoinsViewCache* coinsView = nullptr,
CCriticalSection* cs_coinsView = nullptr); CCriticalSection* cs_coinsView = nullptr);

View File

@ -10,7 +10,7 @@
#include <array> #include <array>
// Sprout // Sprout
CMutableTransaction GetValidSproutReceiveTransaction(ZCJoinSplit& params, CMutableTransaction GetValidSproutReceiveTransaction(
const libzcash::SproutSpendingKey& sk, const libzcash::SproutSpendingKey& sk,
CAmount value, CAmount value,
bool randomInputs, bool randomInputs,
@ -52,7 +52,7 @@ CMutableTransaction GetValidSproutReceiveTransaction(ZCJoinSplit& params,
// Prepare JoinSplits // Prepare JoinSplits
uint256 rt; uint256 rt;
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, JSDescription jsdesc {mtx.joinSplitPubKey, rt,
inputs, outputs, 2*value, 0, false}; inputs, outputs, 2*value, 0, false};
mtx.vJoinSplit.push_back(jsdesc); mtx.vJoinSplit.push_back(jsdesc);
@ -80,22 +80,21 @@ CMutableTransaction GetValidSproutReceiveTransaction(ZCJoinSplit& params,
return mtx; return mtx;
} }
CWalletTx GetValidSproutReceive(ZCJoinSplit& params, CWalletTx GetValidSproutReceive(const libzcash::SproutSpendingKey& sk,
const libzcash::SproutSpendingKey& sk,
CAmount value, CAmount value,
bool randomInputs, bool randomInputs,
uint32_t versionGroupId, /* = SAPLING_VERSION_GROUP_ID */ uint32_t versionGroupId, /* = SAPLING_VERSION_GROUP_ID */
int32_t version /* = SAPLING_TX_VERSION */) int32_t version /* = SAPLING_TX_VERSION */)
{ {
CMutableTransaction mtx = GetValidSproutReceiveTransaction( CMutableTransaction mtx = GetValidSproutReceiveTransaction(
params, sk, value, randomInputs, versionGroupId, version sk, value, randomInputs, versionGroupId, version
); );
CTransaction tx {mtx}; CTransaction tx {mtx};
CWalletTx wtx {NULL, tx}; CWalletTx wtx {NULL, tx};
return wtx; return wtx;
} }
CWalletTx GetInvalidCommitmentSproutReceive(ZCJoinSplit& params, CWalletTx GetInvalidCommitmentSproutReceive(
const libzcash::SproutSpendingKey& sk, const libzcash::SproutSpendingKey& sk,
CAmount value, CAmount value,
bool randomInputs, bool randomInputs,
@ -103,7 +102,7 @@ CWalletTx GetInvalidCommitmentSproutReceive(ZCJoinSplit& params,
int32_t version /* = SAPLING_TX_VERSION */) int32_t version /* = SAPLING_TX_VERSION */)
{ {
CMutableTransaction mtx = GetValidSproutReceiveTransaction( CMutableTransaction mtx = GetValidSproutReceiveTransaction(
params, sk, value, randomInputs, versionGroupId, version sk, value, randomInputs, versionGroupId, version
); );
mtx.vJoinSplit[0].commitments[0] = uint256(); mtx.vJoinSplit[0].commitments[0] = uint256();
mtx.vJoinSplit[0].commitments[1] = uint256(); mtx.vJoinSplit[0].commitments[1] = uint256();
@ -112,8 +111,7 @@ CWalletTx GetInvalidCommitmentSproutReceive(ZCJoinSplit& params,
return wtx; return wtx;
} }
libzcash::SproutNote GetSproutNote(ZCJoinSplit& params, libzcash::SproutNote GetSproutNote(const libzcash::SproutSpendingKey& sk,
const libzcash::SproutSpendingKey& sk,
const CTransaction& tx, size_t js, size_t n) { const CTransaction& tx, size_t js, size_t n) {
ZCNoteDecryption decryptor {sk.receiving_key()}; ZCNoteDecryption decryptor {sk.receiving_key()};
auto hSig = tx.vJoinSplit[js].h_sig(tx.joinSplitPubKey); auto hSig = tx.vJoinSplit[js].h_sig(tx.joinSplitPubKey);
@ -126,8 +124,7 @@ libzcash::SproutNote GetSproutNote(ZCJoinSplit& params,
return note_pt.note(sk.address()); return note_pt.note(sk.address());
} }
CWalletTx GetValidSproutSpend(ZCJoinSplit& params, CWalletTx GetValidSproutSpend(const libzcash::SproutSpendingKey& sk,
const libzcash::SproutSpendingKey& sk,
const libzcash::SproutNote& note, const libzcash::SproutNote& note,
CAmount value) { CAmount value) {
CMutableTransaction mtx; CMutableTransaction mtx;
@ -178,7 +175,7 @@ CWalletTx GetValidSproutSpend(ZCJoinSplit& params,
// Prepare JoinSplits // Prepare JoinSplits
uint256 rt = tree.root(); uint256 rt = tree.root();
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, JSDescription jsdesc {mtx.joinSplitPubKey, rt,
inputs, outputs, 0, value, false}; inputs, outputs, 0, value, false};
mtx.vJoinSplit.push_back(jsdesc); mtx.vJoinSplit.push_back(jsdesc);

View File

@ -8,28 +8,24 @@
#include "key_io.h" #include "key_io.h"
#include "wallet/wallet.h" #include "wallet/wallet.h"
#include "zcash/Address.hpp" #include "zcash/Address.hpp"
#include "zcash/JoinSplit.hpp"
#include "zcash/Note.hpp" #include "zcash/Note.hpp"
#include "zcash/NoteEncryption.hpp" #include "zcash/NoteEncryption.hpp"
// Sprout // Sprout
CWalletTx GetValidSproutReceive(ZCJoinSplit& params, CWalletTx GetValidSproutReceive(const libzcash::SproutSpendingKey& sk,
CAmount value,
bool randomInputs,
uint32_t versionGroupId = SAPLING_VERSION_GROUP_ID,
int32_t version = SAPLING_TX_VERSION);
CWalletTx GetInvalidCommitmentSproutReceive(
const libzcash::SproutSpendingKey& sk, const libzcash::SproutSpendingKey& sk,
CAmount value, CAmount value,
bool randomInputs, bool randomInputs,
uint32_t versionGroupId = SAPLING_VERSION_GROUP_ID, uint32_t versionGroupId = SAPLING_VERSION_GROUP_ID,
int32_t version = SAPLING_TX_VERSION); int32_t version = SAPLING_TX_VERSION);
CWalletTx GetInvalidCommitmentSproutReceive(ZCJoinSplit& params, libzcash::SproutNote GetSproutNote(const libzcash::SproutSpendingKey& sk,
const libzcash::SproutSpendingKey& sk,
CAmount value,
bool randomInputs,
uint32_t versionGroupId = SAPLING_VERSION_GROUP_ID,
int32_t version = SAPLING_TX_VERSION);
libzcash::SproutNote GetSproutNote(ZCJoinSplit& params,
const libzcash::SproutSpendingKey& sk,
const CTransaction& tx, size_t js, size_t n); const CTransaction& tx, size_t js, size_t n);
CWalletTx GetValidSproutSpend(ZCJoinSplit& params, CWalletTx GetValidSproutSpend(const libzcash::SproutSpendingKey& sk,
const libzcash::SproutSpendingKey& sk,
const libzcash::SproutNote& note, const libzcash::SproutNote& note,
CAmount value); CAmount value);

View File

@ -15,6 +15,7 @@
#include "miner.h" #include "miner.h"
#include "net.h" #include "net.h"
#include "netbase.h" #include "netbase.h"
#include "proof_verifier.h"
#include "rpc/protocol.h" #include "rpc/protocol.h"
#include "rpc/server.h" #include "rpc/server.h"
#include "script/interpreter.h" #include "script/interpreter.h"
@ -792,7 +793,6 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)); assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION));
JSDescription jsdesc = JSDescription::Randomized( JSDescription jsdesc = JSDescription::Randomized(
*pzcashParams,
joinSplitPubKey_, joinSplitPubKey_,
anchor, anchor,
inputs, inputs,
@ -804,8 +804,8 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
!this->testmode, !this->testmode,
&esk); // parameter expects pointer to esk, so pass in address &esk); // parameter expects pointer to esk, so pass in address
{ {
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
if (!(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey_))) { if (!(verifier.VerifySprout(jsdesc, joinSplitPubKey_))) {
throw std::runtime_error("error verifying joinsplit"); throw std::runtime_error("error verifying joinsplit");
} }
} }

View File

@ -110,7 +110,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() {
CCoinsViewCache coinsView(pcoinsTip); CCoinsViewCache coinsView(pcoinsTip);
do { do {
CAmount amountToSend = chooseAmount(availableFunds); CAmount amountToSend = chooseAmount(availableFunds);
auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams, &coinsView, &cs_main); auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, &coinsView, &cs_main);
builder.SetExpiryHeight(targetHeight_ + MIGRATION_EXPIRY_DELTA); builder.SetExpiryHeight(targetHeight_ + MIGRATION_EXPIRY_DELTA);
LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), FormatMoney(amountToSend - FEE)); LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), FormatMoney(amountToSend - FEE));
std::vector<SproutNoteEntry> fromNotes; std::vector<SproutNoteEntry> fromNotes;

View File

@ -15,6 +15,7 @@
#include "main.h" #include "main.h"
#include "net.h" #include "net.h"
#include "netbase.h" #include "netbase.h"
#include "proof_verifier.h"
#include "rpc/protocol.h" #include "rpc/protocol.h"
#include "rpc/server.h" #include "rpc/server.h"
#include "timedata.h" #include "timedata.h"
@ -1069,7 +1070,6 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)); assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION));
JSDescription jsdesc = JSDescription::Randomized( JSDescription jsdesc = JSDescription::Randomized(
*pzcashParams,
joinSplitPubKey_, joinSplitPubKey_,
anchor, anchor,
inputs, inputs,
@ -1081,8 +1081,8 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
!this->testmode, !this->testmode,
&esk); // parameter expects pointer to esk, so pass in address &esk); // parameter expects pointer to esk, so pass in address
{ {
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
if (!(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey_))) { if (!(verifier.VerifySprout(jsdesc, joinSplitPubKey_))) {
throw std::runtime_error("error verifying joinsplit"); throw std::runtime_error("error verifying joinsplit");
} }
} }

View File

@ -15,6 +15,7 @@
#include "main.h" #include "main.h"
#include "net.h" #include "net.h"
#include "netbase.h" #include "netbase.h"
#include "proof_verifier.h"
#include "rpc/protocol.h" #include "rpc/protocol.h"
#include "rpc/server.h" #include "rpc/server.h"
#include "timedata.h" #include "timedata.h"
@ -308,7 +309,6 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)); assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION));
JSDescription jsdesc = JSDescription::Randomized( JSDescription jsdesc = JSDescription::Randomized(
*pzcashParams,
joinSplitPubKey_, joinSplitPubKey_,
anchor, anchor,
inputs, inputs,
@ -320,8 +320,8 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
!this->testmode, !this->testmode,
&esk); // parameter expects pointer to esk, so pass in address &esk); // parameter expects pointer to esk, so pass in address
{ {
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
if (!(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey_))) { if (!(verifier.VerifySprout(jsdesc, joinSplitPubKey_))) {
throw std::runtime_error("error verifying joinsplit"); throw std::runtime_error("error verifying joinsplit");
} }
} }

View File

@ -11,7 +11,6 @@
#include "transaction_builder.h" #include "transaction_builder.h"
#include "utiltest.h" #include "utiltest.h"
#include "wallet/wallet.h" #include "wallet/wallet.h"
#include "zcash/JoinSplit.hpp"
#include "zcash/Note.hpp" #include "zcash/Note.hpp"
#include "zcash/NoteEncryption.hpp" #include "zcash/NoteEncryption.hpp"
@ -19,8 +18,6 @@
using ::testing::Return; using ::testing::Return;
extern ZCJoinSplit* params;
ACTION(ThrowLogicError) { ACTION(ThrowLogicError) {
throw std::logic_error("Boom"); throw std::logic_error("Boom");
} }
@ -71,36 +68,6 @@ public:
} }
}; };
CWalletTx GetValidSproutReceive(
const libzcash::SproutSpendingKey& sk,
CAmount value,
bool randomInputs,
int32_t versionGroupId = SAPLING_VERSION_GROUP_ID,
int32_t version = SAPLING_TX_VERSION)
{
return GetValidSproutReceive(*params, sk, value, randomInputs, versionGroupId, version);
}
CWalletTx GetInvalidCommitmentSproutReceive(
const libzcash::SproutSpendingKey& sk,
CAmount value,
bool randomInputs,
int32_t versionGroupId = SAPLING_VERSION_GROUP_ID,
int32_t version = SAPLING_TX_VERSION)
{
return GetInvalidCommitmentSproutReceive(*params, sk, value, randomInputs, versionGroupId, version);
}
libzcash::SproutNote GetSproutNote(const libzcash::SproutSpendingKey& sk,
const CTransaction& tx, size_t js, size_t n) {
return GetSproutNote(*params, sk, tx, js, n);
}
CWalletTx GetValidSproutSpend(const libzcash::SproutSpendingKey& sk,
const libzcash::SproutNote& note, CAmount value) {
return GetValidSproutSpend(*params, sk, note, value);
}
std::vector<SaplingOutPoint> SetSaplingNoteData(CWalletTx& wtx) { std::vector<SaplingOutPoint> SetSaplingNoteData(CWalletTx& wtx) {
mapSaplingNoteData_t saplingNoteData; mapSaplingNoteData_t saplingNoteData;
SaplingOutPoint saplingOutPoint = {wtx.GetHash(), 0}; SaplingOutPoint saplingOutPoint = {wtx.GetHash(), 0};

View File

@ -13,6 +13,7 @@
#include "main.h" #include "main.h"
#include "net.h" #include "net.h"
#include "netbase.h" #include "netbase.h"
#include "proof_verifier.h"
#include "rpc/server.h" #include "rpc/server.h"
#include "timedata.h" #include "timedata.h"
#include "transaction_builder.h" #include "transaction_builder.h"
@ -2761,8 +2762,7 @@ UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp)
uint256 joinSplitPubKey; uint256 joinSplitPubKey;
uint256 anchor = SproutMerkleTree().root(); uint256 anchor = SproutMerkleTree().root();
JSDescription samplejoinsplit(*pzcashParams, JSDescription samplejoinsplit(joinSplitPubKey,
joinSplitPubKey,
anchor, anchor,
{JSInput(), JSInput()}, {JSInput(), JSInput()},
{JSOutput(), JSOutput()}, {JSOutput(), JSOutput()},
@ -3136,8 +3136,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
mtx.joinSplitPubKey = joinSplitPubKey; mtx.joinSplitPubKey = joinSplitPubKey;
JSDescription jsdesc(*pzcashParams, JSDescription jsdesc(joinSplitPubKey,
joinSplitPubKey,
anchor, anchor,
{vjsin[0], vjsin[1]}, {vjsin[0], vjsin[1]},
{vjsout[0], vjsout[1]}, {vjsout[0], vjsout[1]},
@ -3145,8 +3144,8 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
vpub_new); vpub_new);
{ {
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey)); assert(verifier.VerifySprout(jsdesc, joinSplitPubKey));
} }
mtx.vJoinSplit.push_back(jsdesc); mtx.vJoinSplit.push_back(jsdesc);

View File

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

View File

@ -21,13 +21,8 @@
namespace libzcash { namespace libzcash {
template<size_t NumInputs, size_t NumOutputs> template<size_t NumInputs, size_t NumOutputs>
class JoinSplitCircuit : public JoinSplit<NumInputs, NumOutputs> { SproutProof JoinSplit<NumInputs, NumOutputs>::prove(
public:
JoinSplitCircuit() {}
~JoinSplitCircuit() {}
SproutProof prove(
const std::array<JSInput, NumInputs>& inputs, const std::array<JSInput, NumInputs>& inputs,
const std::array<JSOutput, NumOutputs>& outputs, const std::array<JSOutput, NumOutputs>& outputs,
std::array<SproutNote, NumOutputs>& out_notes, std::array<SproutNote, NumOutputs>& out_notes,
@ -96,7 +91,8 @@ public:
out_randomSeed = random_uint256(); out_randomSeed = random_uint256();
// Compute h_sig // Compute h_sig
uint256 h_sig = this->h_sig(out_randomSeed, out_nullifiers, joinSplitPubKey); uint256 h_sig = JoinSplit<NumInputs, NumOutputs>::h_sig(
out_randomSeed, out_nullifiers, joinSplitPubKey);
// Sample phi // Sample phi
uint252 phi = random_uint252(); uint252 phi = random_uint252();
@ -205,13 +201,6 @@ public:
return proof; return proof;
} }
};
template<size_t NumInputs, size_t NumOutputs>
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Prepared()
{
return new JoinSplitCircuit<NumInputs, NumOutputs>();
}
template<size_t NumInputs, size_t NumOutputs> template<size_t NumInputs, size_t NumOutputs>
uint256 JoinSplit<NumInputs, NumOutputs>::h_sig( uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(

View File

@ -15,17 +15,6 @@
namespace libzcash { namespace libzcash {
static constexpr size_t GROTH_PROOF_SIZE = (
48 + // π_A
96 + // π_B
48); // π_C
typedef std::array<unsigned char, GROTH_PROOF_SIZE> GrothProof;
// TODO: Because PHGRProof is listed first, using the default
// constructor for JSDescription() will create a JSDescription
// with a PHGRProof. The default however should be GrothProof.
typedef boost::variant<PHGRProof, GrothProof> SproutProof;
class JSInput { class JSInput {
public: public:
SproutWitness witness; SproutWitness witness;
@ -57,17 +46,13 @@ public:
template<size_t NumInputs, size_t NumOutputs> template<size_t NumInputs, size_t NumOutputs>
class JoinSplit { class JoinSplit {
public: public:
virtual ~JoinSplit() {}
static JoinSplit<NumInputs, NumOutputs>* Prepared();
static uint256 h_sig(const uint256& randomSeed, static uint256 h_sig(const uint256& randomSeed,
const std::array<uint256, NumInputs>& nullifiers, const std::array<uint256, NumInputs>& nullifiers,
const uint256& joinSplitPubKey const uint256& joinSplitPubKey
); );
// Compute nullifiers, macs, note commitments & encryptions, and SNARK proof // Compute nullifiers, macs, note commitments & encryptions, and SNARK proof
virtual SproutProof prove( static SproutProof prove(
const std::array<JSInput, NumInputs>& inputs, const std::array<JSInput, NumInputs>& inputs,
const std::array<JSOutput, NumOutputs>& outputs, const std::array<JSOutput, NumOutputs>& outputs,
std::array<SproutNote, NumOutputs>& out_notes, std::array<SproutNote, NumOutputs>& out_notes,
@ -86,10 +71,7 @@ public:
// Reference as non-const parameter with default value leads to compile error. // Reference as non-const parameter with default value leads to compile error.
// So use pointer for simplicity. // So use pointer for simplicity.
uint256 *out_esk = nullptr uint256 *out_esk = nullptr
) = 0; );
protected:
JoinSplit() {}
}; };
} }

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

@ -200,42 +200,16 @@ public:
} }
}; };
void initialize_curve_params(); static constexpr size_t GROTH_PROOF_SIZE = (
48 + // π_A
96 + // π_B
48); // π_C
class ProofVerifier { typedef std::array<unsigned char, GROTH_PROOF_SIZE> GrothProof;
private: // TODO: Because PHGRProof is listed first, using the default
bool perform_verification; // constructor for JSDescription() will create a JSDescription
// with a PHGRProof. The default however should be GrothProof.
ProofVerifier(bool perform_verification) : perform_verification(perform_verification) { } typedef boost::variant<PHGRProof, GrothProof> SproutProof;
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 using libsnark's API.
static ProofVerifier Strict();
// Creates a verification context that performs no
// verification, used when avoiding duplicate effort
// such as during reindexing.
static ProofVerifier Disabled();
template <typename VerificationKey,
typename ProcessedVerificationKey,
typename PrimaryInput,
typename Proof
>
bool check(
const VerificationKey& vk,
const ProcessedVerificationKey& pvk,
const PrimaryInput& pi,
const Proof& p
);
};
} }

View File

@ -19,6 +19,7 @@
#include "miner.h" #include "miner.h"
#include "policy/policy.h" #include "policy/policy.h"
#include "pow.h" #include "pow.h"
#include "proof_verifier.h"
#include "random.h" #include "random.h"
#include "rpc/server.h" #include "rpc/server.h"
#include "script/sign.h" #include "script/sign.h"
@ -101,8 +102,7 @@ double benchmark_create_joinsplit()
struct timeval tv_start; struct timeval tv_start;
timer_start(tv_start); timer_start(tv_start);
JSDescription jsdesc(*pzcashParams, JSDescription jsdesc(joinSplitPubKey,
joinSplitPubKey,
anchor, anchor,
{JSInput(), JSInput()}, {JSInput(), JSInput()},
{JSOutput(), JSOutput()}, {JSOutput(), JSOutput()},
@ -110,8 +110,8 @@ double benchmark_create_joinsplit()
0); 0);
double ret = timer_stop(tv_start); double ret = timer_stop(tv_start);
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey)); assert(verifier.VerifySprout(jsdesc, joinSplitPubKey));
return ret; return ret;
} }
@ -141,8 +141,8 @@ double benchmark_verify_joinsplit(const JSDescription &joinsplit)
struct timeval tv_start; struct timeval tv_start;
timer_start(tv_start); timer_start(tv_start);
uint256 joinSplitPubKey; uint256 joinSplitPubKey;
auto verifier = libzcash::ProofVerifier::Strict(); auto verifier = ProofVerifier::Strict();
joinsplit.Verify(*pzcashParams, verifier, joinSplitPubKey); verifier.VerifySprout(joinsplit, joinSplitPubKey);
return timer_stop(tv_start); return timer_stop(tv_start);
} }
@ -274,7 +274,7 @@ double benchmark_try_decrypt_sprout_notes(size_t nKeys)
} }
auto sk = libzcash::SproutSpendingKey::random(); auto sk = libzcash::SproutSpendingKey::random();
auto tx = GetValidSproutReceive(*pzcashParams, sk, 10, true); auto tx = GetValidSproutReceive(sk, 10, true);
struct timeval tv_start; struct timeval tv_start;
timer_start(tv_start); timer_start(tv_start);
@ -310,8 +310,8 @@ double benchmark_try_decrypt_sapling_notes(size_t nKeys)
} }
CWalletTx CreateSproutTxWithNoteData(const libzcash::SproutSpendingKey& sk) { CWalletTx CreateSproutTxWithNoteData(const libzcash::SproutSpendingKey& sk) {
auto wtx = GetValidSproutReceive(*pzcashParams, sk, 10, true); auto wtx = GetValidSproutReceive(sk, 10, true);
auto note = GetSproutNote(*pzcashParams, sk, wtx, 0, 1); auto note = GetSproutNote(sk, wtx, 0, 1);
auto nullifier = note.nullifier(sk); auto nullifier = note.nullifier(sk);
mapSproutNoteData_t noteDataMap; mapSproutNoteData_t noteDataMap;