diff --git a/qa/zcash/performance-measurements.sh b/qa/zcash/performance-measurements.sh index 849fc511..33213835 100755 --- a/qa/zcash/performance-measurements.sh +++ b/qa/zcash/performance-measurements.sh @@ -32,19 +32,6 @@ function zcashd_massif_start { ZCASHD_PID=$! } -function zcashd_massif_start_chain { - rm -rf "$DATADIR" - mkdir -p "$DATADIR" - rm -f massif.out - ./src/zcashd -regtest -datadir="$DATADIR" -rpcuser=user -rpcpassword=password -rpcport=5983 & - ZCASHD_PID=$! - zcashd_generate - zcash_rpc stop > /dev/null - wait $ZCASHD_PID - valgrind --tool=massif --time-unit=ms --massif-out-file=massif.out ./src/zcashd -regtest -datadir="$DATADIR" -rpcuser=user -rpcpassword=password -rpcport=5983 & - ZCASHD_PID=$! -} - function zcashd_massif_stop { zcash_rpc stop > /dev/null wait $ZCASHD_PID @@ -59,19 +46,6 @@ function zcashd_valgrind_start { ZCASHD_PID=$! } -function zcashd_valgrind_start_chain { - rm -rf "$DATADIR" - mkdir -p "$DATADIR" - rm -f valgrind.out - ./src/zcashd -regtest -datadir="$DATADIR" -rpcuser=user -rpcpassword=password -rpcport=5983 & - ZCASHD_PID=$! - zcashd_generate - zcash_rpc stop > /dev/null - wait $ZCASHD_PID - valgrind --leak-check=yes -v --error-limit=no --log-file="valgrind.out" ./src/zcashd -regtest -datadir="$DATADIR" -rpcuser=user -rpcpassword=password -rpcport=5983 & - ZCASHD_PID=$! -} - function zcashd_valgrind_stop { zcash_rpc stop > /dev/null wait $ZCASHD_PID @@ -102,13 +76,8 @@ case "$1" in verifyequihash) zcash_rpc zcbenchmark verifyequihash 1000 ;; - createlargetx) - zcashd_generate - zcash_rpc zcbenchmark createlargetx 10 - ;; validatelargetx) - zcashd_generate - zcash_rpc zcbenchmark validatelargetx 2 + zcash_rpc zcbenchmark validatelargetx 5 ;; *) zcashd_stop @@ -118,13 +87,7 @@ case "$1" in zcashd_stop ;; memory) - case "$2" in - createlargetx|validatelargetx) - zcashd_massif_start_chain - ;; - *) - zcashd_massif_start - esac + zcashd_massif_start case "$2" in sleep) zcash_rpc zcbenchmark sleep 1 @@ -144,12 +107,6 @@ case "$1" in verifyequihash) zcash_rpc zcbenchmark verifyequihash 1 ;; - createlargetx) - zcash_rpc zcbenchmark validatelargetx 1 - ;; - validatelargetx) - zcash_rpc zcbenchmark validatelargetx 1 - ;; *) zcashd_massif_stop echo "Bad arguments." @@ -159,13 +116,7 @@ case "$1" in rm -f massif.out ;; valgrind) - case "$2" in - createlargetx|validatelargetx) - zcashd_valgrind_start_chain - ;; - *) - zcashd_valgrind_start - esac + zcashd_valgrind_start case "$2" in sleep) zcash_rpc zcbenchmark sleep 1 @@ -185,12 +136,6 @@ case "$1" in verifyequihash) zcash_rpc zcbenchmark verifyequihash 1 ;; - createlargetx) - zcash_rpc zcbenchmark validatelargetx 1 - ;; - validatelargetx) - zcash_rpc zcbenchmark validatelargetx 1 - ;; *) zcashd_valgrind_stop echo "Bad arguments." diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index e7f4e02f..002d9ea6 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -7,7 +7,7 @@ #define BITCOIN_CONSENSUS_CONSENSUS_H /** The maximum allowed size for a serialized block, in bytes (network rule) */ -static const unsigned int MAX_BLOCK_SIZE = 2000000; +static const unsigned int MAX_BLOCK_SIZE = 1000000; /** The maximum allowed number of signature check operations in a block (network rule) */ static const unsigned int MAX_BLOCK_SIGOPS = 20000; /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 14b217ca..d1115cdc 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2419,10 +2419,8 @@ Value zc_benchmark(const json_spirit::Array& params, bool fHelp) sample_times.push_back(benchmark_solve_equihash()); } else if (benchmarktype == "verifyequihash") { sample_times.push_back(benchmark_verify_equihash()); - } else if (benchmarktype == "createlargetx") { - sample_times.push_back(benchmark_large_tx(false)); } else if (benchmarktype == "validatelargetx") { - sample_times.push_back(benchmark_large_tx(true)); + sample_times.push_back(benchmark_large_tx()); } else { throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype"); } diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 185de93a..dd8a91a0 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -132,123 +132,61 @@ double benchmark_verify_equihash() return timer_stop(); } -double benchmark_large_tx(bool testValidate) +double benchmark_large_tx() { - // Note that the transaction size is checked against the splitting - // transaction, not the merging one. Thus we are assuming that transactions - // with 1 input and N outputs are about the same size as transactions with - // N inputs and 1 output. - mapArgs["-blockmaxsize"] = itostr(MAX_BLOCK_SIZE); - int nMaxBlockSize = MAX_BLOCK_SIZE-1000; + // Number of inputs in the spending transaction that we will simulate + const size_t NUM_INPUTS = 5550; - std::vector vCoins; - pwalletMain->AvailableCoins(vCoins, true); + // Create priv/pub key + CKey priv; + priv.MakeNewKey(false); + auto pub = priv.GetPubKey(); + CBasicKeyStore tempKeystore; + tempKeystore.AddKey(priv); - // 1) Create a transaction splitting the first coinbase to many outputs - CMutableTransaction mtx; - mtx.vin.resize(1); - mtx.vin[0].prevout.hash = vCoins[0].tx->GetHash(); - mtx.vin[0].prevout.n = 0; - mtx.vout.resize(1); - mtx.vout[0].scriptPubKey = vCoins[0].tx->vout[0].scriptPubKey; - mtx.vout[0].nValue = 1000; - SignSignature(*pwalletMain, *vCoins[0].tx, mtx, 0); + // The "original" transaction that the spending transaction will spend + // from. + CMutableTransaction m_orig_tx; + m_orig_tx.vout.resize(1); + m_orig_tx.vout[0].nValue = 1000000; + CScript prevPubKey = GetScriptForDestination(pub.GetID()); + m_orig_tx.vout[0].scriptPubKey = prevPubKey; - // 1a) While the transaction is smaller than the maximum: - CTransaction tx {mtx}; - unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); - while (nTxSize < nMaxBlockSize) { - // 1b) Add another output - size_t oldSize = mtx.vout.size(); - mtx.vout.resize(oldSize+1); - mtx.vout[oldSize].scriptPubKey = vCoins[0].tx->vout[0].scriptPubKey; - mtx.vout[oldSize].nValue = 1000; + auto orig_tx = CTransaction(m_orig_tx); - tx = mtx; - nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + CMutableTransaction spending_tx; + auto input_hash = orig_tx.GetHash(); + // Add NUM_INPUTS inputs + for (size_t i = 0; i < NUM_INPUTS; i++) { + spending_tx.vin.emplace_back(input_hash, 0); } - // 1c) Sign the splitting transaction - SignSignature(*pwalletMain, *vCoins[0].tx, mtx, 0); - uint256 hash = mtx.GetHash(); - mempool.clear(); - mempool.addUnchecked(hash, CTxMemPoolEntry(mtx, 11, GetTime(), 111.0, 11)); - - // 2) Mine the splitting transaction into a block - CScript scriptDummy = CScript() << OP_TRUE; - CBlockTemplate* pblocktemplate = CreateNewBlock(scriptDummy); - CBlock *pblock = &pblocktemplate->block; - CBlockIndex* pindexPrev = chainActive.Tip(); - unsigned int nExtraNonce = 0; - IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - - arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - unsigned int n = Params().EquihashN(); - unsigned int k = Params().EquihashK(); - crypto_generichash_blake2b_state eh_state; - EhInitialiseState(n, k, eh_state); - CEquihashInput I{*pblock}; - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << I; - crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); - while (true) { - crypto_generichash_blake2b_state curr_state; - curr_state = eh_state; - crypto_generichash_blake2b_update(&curr_state, - pblock->nNonce.begin(), - pblock->nNonce.size()); - std::set> solns; - EhOptimisedSolve(n, k, curr_state, solns); - for (auto soln : solns) { - pblock->nSolution = soln; - if (UintToArith256(pblock->GetHash()) > hashTarget) { - continue; - } - goto processblock; - } - pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); + // Sign for all the inputs + for (size_t i = 0; i < NUM_INPUTS; i++) { + SignSignature(tempKeystore, prevPubKey, spending_tx, i, SIGHASH_ALL); } -processblock: - CValidationState state; - assert(ProcessNewBlock(state, NULL, pblock, true, NULL)); + // Serialize: + { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << spending_tx; + //std::cout << "SIZE OF SPENDING TX: " << ss.size() << std::endl; + + auto error = MAX_BLOCK_SIZE / 20; // 5% error + assert(ss.size() < MAX_BLOCK_SIZE + error); + assert(ss.size() > MAX_BLOCK_SIZE - error); + } + + // Benchmark signature verification costs: timer_start(); - - // 3) Create a transaction that merges all of the inputs - CMutableTransaction mtx2; - mtx2.vin.resize(mtx.vout.size()); - mtx2.vout.resize(1); - mtx2.vout[0].scriptPubKey = vCoins[0].tx->vout[0].scriptPubKey; - mtx2.vout[0].nValue = 0; - - for (int i = 0; i < mtx2.vin.size(); i++) { - mtx2.vin[i].prevout.hash = hash; - mtx2.vin[i].prevout.n = i; + for (size_t i = 0; i < NUM_INPUTS; i++) { + ScriptError serror = SCRIPT_ERR_OK; + assert(VerifyScript(spending_tx.vin[i].scriptSig, + prevPubKey, + STANDARD_SCRIPT_VERIFY_FLAGS, + MutableTransactionSignatureChecker(&spending_tx, i), + &serror)); } - - for (int i = 0; i < mtx2.vin.size(); i++) { - SignSignature(*pwalletMain, mtx, mtx2, i); - } - - double ret = timer_stop(); - delete pblocktemplate; - if (!testValidate) - return ret; - - hash = mtx2.GetHash(); - mempool.addUnchecked(hash, CTxMemPoolEntry(mtx2, 11, GetTime(), 111.0, 11)); - - // 4) Call CreateNewBlock (which itself calls TestBlockValidity) - pblocktemplate = CreateNewBlock(scriptDummy); - pblock = &pblocktemplate->block; - pindexPrev = chainActive.Tip(); - - // 5) Call TestBlockValidity again under timing - timer_start(); - assert(TestBlockValidity(state, *pblock, pindexPrev, false, false)); - ret = timer_stop(); - delete pblocktemplate; - mempool.clear(); - return ret; + return timer_stop(); } diff --git a/src/zcbenchmarks.h b/src/zcbenchmarks.h index 4540c1f1..e59fff1d 100644 --- a/src/zcbenchmarks.h +++ b/src/zcbenchmarks.h @@ -10,6 +10,6 @@ extern double benchmark_create_joinsplit(); extern double benchmark_solve_equihash(); extern double benchmark_verify_joinsplit(const CPourTx &joinsplit); extern double benchmark_verify_equihash(); -extern double benchmark_large_tx(bool testValidate); +extern double benchmark_large_tx(); #endif