Merge branch 'proofverifier-refactor' into zcashconsensus-fixes-base
This commit is contained in:
commit
50ef461f31
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
20
src/main.cpp
20
src/main.cpp
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,7 @@
|
||||||
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(
|
||||||
|
|
|
@ -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() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue