Merge remote-tracking branch 'zcash/master' into rebase2
# Conflicts: # .travis.yml # Makefile.am # README.md # configure.ac # depends/Makefile # depends/builders/darwin.mk # depends/funcs.mk # depends/hosts/darwin.mk # depends/packages/googlemock.mk # depends/packages/googletest.mk # depends/packages/libsnark.mk # depends/packages/libsodium.mk # depends/packages/packages.mk # depends/packages/rust.mk # src/Makefile.am # src/Makefile.gtest.include # src/chainparams.cpp # src/chainparams.h # src/checkpoints.h # src/clientversion.h # src/coins.cpp # src/consensus/consensus.h # src/gtest/test_mempool.cpp # src/httprpc.cpp # src/init.cpp # src/komodo-tx.cpp # src/main.cpp # src/miner.cpp # src/policy/fees.cpp # src/policy/fees.h # src/rpcmining.cpp # src/rpcrawtransaction.cpp # src/rpcserver.cpp # src/test/policyestimator_tests.cpp # src/test/rpc_wallet_tests.cpp # src/test/transaction_tests.cpp # src/txdb.cpp # src/txmempool.cpp # src/wallet/asyncrpcoperation_sendmany.cpp # src/wallet/rpcwallet.cpp # src/wallet/wallet.cpp # src/wallet/wallet.h # src/zcash/CreateJoinSplit.cpp # zcutil/build.sh
This commit is contained in:
@@ -6,7 +6,10 @@
|
||||
#include "data/tx_valid.json.h"
|
||||
#include "test/test_bitcoin.h"
|
||||
|
||||
#include "init.h"
|
||||
#include "clientversion.h"
|
||||
#include "checkqueue.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "core_io.h"
|
||||
#include "key.h"
|
||||
@@ -14,6 +17,7 @@
|
||||
#include "main.h"
|
||||
#include "script/script.h"
|
||||
#include "script/script_error.h"
|
||||
#include "script/sign.h"
|
||||
#include "primitives/transaction.h"
|
||||
|
||||
#include "sodium.h"
|
||||
@@ -42,7 +46,6 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of
|
||||
(string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE)
|
||||
(string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH)
|
||||
(string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC)
|
||||
(string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG)
|
||||
(string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S)
|
||||
(string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY)
|
||||
(string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA)
|
||||
@@ -86,10 +89,12 @@ string FormatScriptFlags(unsigned int flags)
|
||||
return ret.substr(0, ret.size() - 1);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(transaction_tests, BasicTestingSetup)
|
||||
BOOST_FIXTURE_TEST_SUITE(transaction_tests, JoinSplitTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
// Read tests from test/data/tx_valid.json
|
||||
// Format is an array of arrays
|
||||
// Inner arrays are either [ "comment" ]
|
||||
@@ -98,6 +103,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
//
|
||||
// verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
|
||||
UniValue tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
|
||||
std::string comment("");
|
||||
|
||||
auto verifier = libzcash::ProofVerifier::Strict();
|
||||
ScriptError err;
|
||||
@@ -108,7 +114,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
{
|
||||
if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
BOOST_ERROR("Bad test: " << strTest << comment);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -133,7 +139,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
}
|
||||
if (!fValid)
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
BOOST_ERROR("Bad test: " << strTest << comment);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -143,29 +149,40 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
stream >> tx;
|
||||
|
||||
CValidationState state;
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state, verifier), strTest);
|
||||
BOOST_CHECK(state.IsValid());
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state, verifier), strTest + comment);
|
||||
BOOST_CHECK_MESSAGE(state.IsValid(), comment);
|
||||
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
BOOST_ERROR("Bad test: " << strTest << comment);
|
||||
break;
|
||||
}
|
||||
|
||||
CAmount amount = 0;
|
||||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||
verify_flags, TransactionSignatureChecker(&tx, i), &err),
|
||||
strTest);
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), consensusBranchId, &err),
|
||||
strTest + comment);
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err) + comment);
|
||||
}
|
||||
|
||||
comment = "";
|
||||
}
|
||||
else if (test.size() == 1)
|
||||
{
|
||||
comment += "\n# ";
|
||||
comment += test[0].write();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
// Read tests from test/data/tx_invalid.json
|
||||
// Format is an array of arrays
|
||||
// Inner arrays are either [ "comment" ]
|
||||
@@ -174,6 +191,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
//
|
||||
// verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
|
||||
UniValue tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
|
||||
std::string comment("");
|
||||
|
||||
auto verifier = libzcash::ProofVerifier::Strict();
|
||||
ScriptError err;
|
||||
@@ -184,7 +202,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
{
|
||||
if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
BOOST_ERROR("Bad test: " << strTest << comment);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -209,7 +227,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
}
|
||||
if (!fValid)
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
BOOST_ERROR("Bad test: " << strTest << comment);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -221,20 +239,29 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
CValidationState state;
|
||||
fValid = CheckTransaction(tx, state, verifier) && state.IsValid();
|
||||
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
for (unsigned int i = 0; i < tx.vin.size() && fValid; i++)
|
||||
{
|
||||
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
BOOST_ERROR("Bad test: " << strTest << comment);
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||
CAmount amount = 0;
|
||||
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||
verify_flags, TransactionSignatureChecker(&tx, i), &err);
|
||||
verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), consensusBranchId, &err);
|
||||
}
|
||||
BOOST_CHECK_MESSAGE(!fValid, strTest);
|
||||
BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
BOOST_CHECK_MESSAGE(!fValid, strTest + comment);
|
||||
BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err) + comment);
|
||||
|
||||
comment = "";
|
||||
}
|
||||
else if (test.size() == 1)
|
||||
{
|
||||
comment += "\n# ";
|
||||
comment += test[0].write();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,9 +338,6 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
|
||||
// Also, it's generally libzcash's job to ensure the
|
||||
// integrity of the scheme through its own tests.
|
||||
|
||||
// construct the r1cs keypair
|
||||
auto p = ZCJoinSplit::Generate();
|
||||
|
||||
// construct a merkle tree
|
||||
ZCIncrementalMerkleTree merkleTree;
|
||||
|
||||
@@ -347,8 +371,8 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
|
||||
auto verifier = libzcash::ProofVerifier::Strict();
|
||||
|
||||
{
|
||||
JSDescription jsdesc(*p, pubKeyHash, rt, inputs, outputs, 0, 0);
|
||||
BOOST_CHECK(jsdesc.Verify(*p, verifier, pubKeyHash));
|
||||
JSDescription jsdesc(*pzcashParams, pubKeyHash, rt, inputs, outputs, 0, 0);
|
||||
BOOST_CHECK(jsdesc.Verify(*pzcashParams, verifier, pubKeyHash));
|
||||
|
||||
CDataStream ss(SER_DISK, CLIENT_VERSION);
|
||||
ss << jsdesc;
|
||||
@@ -357,25 +381,26 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
|
||||
ss >> jsdesc_deserialized;
|
||||
|
||||
BOOST_CHECK(jsdesc_deserialized == jsdesc);
|
||||
BOOST_CHECK(jsdesc_deserialized.Verify(*p, verifier, pubKeyHash));
|
||||
BOOST_CHECK(jsdesc_deserialized.Verify(*pzcashParams, verifier, pubKeyHash));
|
||||
}
|
||||
|
||||
{
|
||||
// Ensure that the balance equation is working.
|
||||
BOOST_CHECK_THROW(JSDescription(*p, pubKeyHash, rt, inputs, outputs, 10, 0), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(JSDescription(*p, pubKeyHash, rt, inputs, outputs, 0, 10), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(JSDescription(*pzcashParams, pubKeyHash, rt, inputs, outputs, 10, 0), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(JSDescription(*pzcashParams, pubKeyHash, rt, inputs, outputs, 0, 10), std::invalid_argument);
|
||||
}
|
||||
|
||||
{
|
||||
// Ensure that it won't verify if the root is changed.
|
||||
auto test = JSDescription(*p, pubKeyHash, rt, inputs, outputs, 0, 0);
|
||||
auto test = JSDescription(*pzcashParams, pubKeyHash, rt, inputs, outputs, 0, 0);
|
||||
test.anchor = GetRandHash();
|
||||
BOOST_CHECK(!test.Verify(*p, verifier, pubKeyHash));
|
||||
BOOST_CHECK(!test.Verify(*pzcashParams, verifier, pubKeyHash));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
auto verifier = libzcash::ProofVerifier::Strict();
|
||||
CMutableTransaction tx;
|
||||
tx.nVersion = 2;
|
||||
@@ -403,13 +428,14 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
|
||||
jsdesc->nullifiers[0] = GetRandHash();
|
||||
jsdesc->nullifiers[1] = GetRandHash();
|
||||
|
||||
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
|
||||
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
||||
BOOST_CHECK(!ContextualCheckTransaction(newTx, state, 0, 100));
|
||||
BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature");
|
||||
|
||||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(newTx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
assert(crypto_sign_detached(&newTx.joinSplitSig[0], NULL,
|
||||
dataToBeSigned.begin(), 32,
|
||||
@@ -417,6 +443,7 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
|
||||
) == 0);
|
||||
|
||||
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
||||
BOOST_CHECK(ContextualCheckTransaction(newTx, state, 0, 100));
|
||||
}
|
||||
{
|
||||
// Ensure that values within the joinsplit are well-formed.
|
||||
@@ -506,6 +533,8 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_Get)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
CBasicKeyStore keystore;
|
||||
CCoinsView coinsDummy;
|
||||
CCoinsViewCache coins(&coinsDummy);
|
||||
@@ -525,17 +554,99 @@ BOOST_AUTO_TEST_CASE(test_Get)
|
||||
t1.vout.resize(2);
|
||||
t1.vout[0].nValue = 90*CENT;
|
||||
t1.vout[0].scriptPubKey << OP_1;
|
||||
int64_t interest;
|
||||
BOOST_CHECK(AreInputsStandard(t1, coins));
|
||||
BOOST_CHECK_EQUAL(coins.GetValueIn(0,&interest,t1,0), (50+21+22)*CENT);
|
||||
BOOST_CHECK(AreInputsStandard(t1, coins, consensusBranchId));
|
||||
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
|
||||
|
||||
// Adding extra junk to the scriptSig should make it non-standard:
|
||||
t1.vin[0].scriptSig << OP_11;
|
||||
BOOST_CHECK(!AreInputsStandard(t1, coins));
|
||||
BOOST_CHECK(!AreInputsStandard(t1, coins, consensusBranchId));
|
||||
|
||||
// ... as should not having enough:
|
||||
t1.vin[0].scriptSig = CScript();
|
||||
BOOST_CHECK(!AreInputsStandard(t1, coins));
|
||||
BOOST_CHECK(!AreInputsStandard(t1, coins, consensusBranchId));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_big_overwinter_transaction) {
|
||||
uint32_t consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_OVERWINTER].nBranchId;
|
||||
CMutableTransaction mtx;
|
||||
mtx.fOverwintered = true;
|
||||
mtx.nVersion = 3;
|
||||
mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
|
||||
|
||||
CKey key;
|
||||
key.MakeNewKey(false);
|
||||
CBasicKeyStore keystore;
|
||||
keystore.AddKeyPubKey(key, key.GetPubKey());
|
||||
CKeyID hash = key.GetPubKey().GetID();
|
||||
CScript scriptPubKey = GetScriptForDestination(hash);
|
||||
|
||||
vector<int> sigHashes;
|
||||
sigHashes.push_back(SIGHASH_NONE | SIGHASH_ANYONECANPAY);
|
||||
sigHashes.push_back(SIGHASH_SINGLE | SIGHASH_ANYONECANPAY);
|
||||
sigHashes.push_back(SIGHASH_ALL | SIGHASH_ANYONECANPAY);
|
||||
sigHashes.push_back(SIGHASH_NONE);
|
||||
sigHashes.push_back(SIGHASH_SINGLE);
|
||||
sigHashes.push_back(SIGHASH_ALL);
|
||||
|
||||
// create a big transaction of 4500 inputs signed by the same key
|
||||
for(uint32_t ij = 0; ij < 4500; ij++) {
|
||||
uint32_t i = mtx.vin.size();
|
||||
uint256 prevId;
|
||||
prevId.SetHex("0000000000000000000000000000000000000000000000000000000000000100");
|
||||
COutPoint outpoint(prevId, i);
|
||||
|
||||
mtx.vin.resize(mtx.vin.size() + 1);
|
||||
mtx.vin[i].prevout = outpoint;
|
||||
mtx.vin[i].scriptSig = CScript();
|
||||
|
||||
mtx.vout.resize(mtx.vout.size() + 1);
|
||||
mtx.vout[i].nValue = 1000;
|
||||
mtx.vout[i].scriptPubKey = CScript() << OP_1;
|
||||
}
|
||||
|
||||
// sign all inputs
|
||||
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
||||
bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, sigHashes.at(i % sigHashes.size()), consensusBranchId);
|
||||
assert(hashSigned);
|
||||
}
|
||||
|
||||
CTransaction tx;
|
||||
CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssout << mtx;
|
||||
ssout >> tx;
|
||||
|
||||
// check all inputs concurrently, with the cache
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
boost::thread_group threadGroup;
|
||||
CCheckQueue<CScriptCheck> scriptcheckqueue(128);
|
||||
CCheckQueueControl<CScriptCheck> control(&scriptcheckqueue);
|
||||
|
||||
for (int i=0; i<20; i++)
|
||||
threadGroup.create_thread(boost::bind(&CCheckQueue<CScriptCheck>::Thread, boost::ref(scriptcheckqueue)));
|
||||
|
||||
CCoins coins;
|
||||
coins.nVersion = 1;
|
||||
coins.fCoinBase = false;
|
||||
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
||||
CTxOut txout;
|
||||
txout.nValue = 1000;
|
||||
txout.scriptPubKey = scriptPubKey;
|
||||
coins.vout.push_back(txout);
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
||||
std::vector<CScriptCheck> vChecks;
|
||||
CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH, false, consensusBranchId, &txdata);
|
||||
vChecks.push_back(CScriptCheck());
|
||||
check.swap(vChecks.back());
|
||||
control.Add(vChecks);
|
||||
}
|
||||
|
||||
bool controlCheck = control.Wait();
|
||||
assert(controlCheck);
|
||||
|
||||
threadGroup.interrupt_all();
|
||||
threadGroup.join_all();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||
|
||||
Reference in New Issue
Block a user