Make validatelargetx test more accurate, reduce block size limit to 1MB for now.

This commit is contained in:
Sean Bowe
2016-07-06 12:07:50 -06:00
parent 2ba9641767
commit 9c45b501ad
5 changed files with 51 additions and 170 deletions

View File

@@ -32,19 +32,6 @@ function zcashd_massif_start {
ZCASHD_PID=$! 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 { function zcashd_massif_stop {
zcash_rpc stop > /dev/null zcash_rpc stop > /dev/null
wait $ZCASHD_PID wait $ZCASHD_PID
@@ -59,19 +46,6 @@ function zcashd_valgrind_start {
ZCASHD_PID=$! 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 { function zcashd_valgrind_stop {
zcash_rpc stop > /dev/null zcash_rpc stop > /dev/null
wait $ZCASHD_PID wait $ZCASHD_PID
@@ -102,13 +76,8 @@ case "$1" in
verifyequihash) verifyequihash)
zcash_rpc zcbenchmark verifyequihash 1000 zcash_rpc zcbenchmark verifyequihash 1000
;; ;;
createlargetx)
zcashd_generate
zcash_rpc zcbenchmark createlargetx 10
;;
validatelargetx) validatelargetx)
zcashd_generate zcash_rpc zcbenchmark validatelargetx 5
zcash_rpc zcbenchmark validatelargetx 2
;; ;;
*) *)
zcashd_stop zcashd_stop
@@ -118,13 +87,7 @@ case "$1" in
zcashd_stop zcashd_stop
;; ;;
memory) memory)
case "$2" in zcashd_massif_start
createlargetx|validatelargetx)
zcashd_massif_start_chain
;;
*)
zcashd_massif_start
esac
case "$2" in case "$2" in
sleep) sleep)
zcash_rpc zcbenchmark sleep 1 zcash_rpc zcbenchmark sleep 1
@@ -144,12 +107,6 @@ case "$1" in
verifyequihash) verifyequihash)
zcash_rpc zcbenchmark verifyequihash 1 zcash_rpc zcbenchmark verifyequihash 1
;; ;;
createlargetx)
zcash_rpc zcbenchmark validatelargetx 1
;;
validatelargetx)
zcash_rpc zcbenchmark validatelargetx 1
;;
*) *)
zcashd_massif_stop zcashd_massif_stop
echo "Bad arguments." echo "Bad arguments."
@@ -159,13 +116,7 @@ case "$1" in
rm -f massif.out rm -f massif.out
;; ;;
valgrind) valgrind)
case "$2" in zcashd_valgrind_start
createlargetx|validatelargetx)
zcashd_valgrind_start_chain
;;
*)
zcashd_valgrind_start
esac
case "$2" in case "$2" in
sleep) sleep)
zcash_rpc zcbenchmark sleep 1 zcash_rpc zcbenchmark sleep 1
@@ -185,12 +136,6 @@ case "$1" in
verifyequihash) verifyequihash)
zcash_rpc zcbenchmark verifyequihash 1 zcash_rpc zcbenchmark verifyequihash 1
;; ;;
createlargetx)
zcash_rpc zcbenchmark validatelargetx 1
;;
validatelargetx)
zcash_rpc zcbenchmark validatelargetx 1
;;
*) *)
zcashd_valgrind_stop zcashd_valgrind_stop
echo "Bad arguments." echo "Bad arguments."

View File

@@ -7,7 +7,7 @@
#define BITCOIN_CONSENSUS_CONSENSUS_H #define BITCOIN_CONSENSUS_CONSENSUS_H
/** The maximum allowed size for a serialized block, in bytes (network rule) */ /** 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) */ /** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = 20000; static const unsigned int MAX_BLOCK_SIGOPS = 20000;
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */

View File

@@ -2419,10 +2419,8 @@ Value zc_benchmark(const json_spirit::Array& params, bool fHelp)
sample_times.push_back(benchmark_solve_equihash()); sample_times.push_back(benchmark_solve_equihash());
} else if (benchmarktype == "verifyequihash") { } else if (benchmarktype == "verifyequihash") {
sample_times.push_back(benchmark_verify_equihash()); sample_times.push_back(benchmark_verify_equihash());
} else if (benchmarktype == "createlargetx") {
sample_times.push_back(benchmark_large_tx(false));
} else if (benchmarktype == "validatelargetx") { } else if (benchmarktype == "validatelargetx") {
sample_times.push_back(benchmark_large_tx(true)); sample_times.push_back(benchmark_large_tx());
} else { } else {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype"); throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
} }

View File

@@ -132,123 +132,61 @@ double benchmark_verify_equihash()
return timer_stop(); return timer_stop();
} }
double benchmark_large_tx(bool testValidate) double benchmark_large_tx()
{ {
// Note that the transaction size is checked against the splitting // Number of inputs in the spending transaction that we will simulate
// transaction, not the merging one. Thus we are assuming that transactions const size_t NUM_INPUTS = 5550;
// 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;
std::vector<COutput> vCoins; // Create priv/pub key
pwalletMain->AvailableCoins(vCoins, true); 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 // The "original" transaction that the spending transaction will spend
CMutableTransaction mtx; // from.
mtx.vin.resize(1); CMutableTransaction m_orig_tx;
mtx.vin[0].prevout.hash = vCoins[0].tx->GetHash(); m_orig_tx.vout.resize(1);
mtx.vin[0].prevout.n = 0; m_orig_tx.vout[0].nValue = 1000000;
mtx.vout.resize(1); CScript prevPubKey = GetScriptForDestination(pub.GetID());
mtx.vout[0].scriptPubKey = vCoins[0].tx->vout[0].scriptPubKey; m_orig_tx.vout[0].scriptPubKey = prevPubKey;
mtx.vout[0].nValue = 1000;
SignSignature(*pwalletMain, *vCoins[0].tx, mtx, 0);
// 1a) While the transaction is smaller than the maximum: auto orig_tx = CTransaction(m_orig_tx);
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;
tx = mtx; CMutableTransaction spending_tx;
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); 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 // Sign for all the inputs
SignSignature(*pwalletMain, *vCoins[0].tx, mtx, 0); for (size_t i = 0; i < NUM_INPUTS; i++) {
uint256 hash = mtx.GetHash(); SignSignature(tempKeystore, prevPubKey, spending_tx, i, SIGHASH_ALL);
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<std::vector<unsigned int>> 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);
} }
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(); timer_start();
for (size_t i = 0; i < NUM_INPUTS; i++) {
// 3) Create a transaction that merges all of the inputs ScriptError serror = SCRIPT_ERR_OK;
CMutableTransaction mtx2; assert(VerifyScript(spending_tx.vin[i].scriptSig,
mtx2.vin.resize(mtx.vout.size()); prevPubKey,
mtx2.vout.resize(1); STANDARD_SCRIPT_VERIFY_FLAGS,
mtx2.vout[0].scriptPubKey = vCoins[0].tx->vout[0].scriptPubKey; MutableTransactionSignatureChecker(&spending_tx, i),
mtx2.vout[0].nValue = 0; &serror));
for (int i = 0; i < mtx2.vin.size(); i++) {
mtx2.vin[i].prevout.hash = hash;
mtx2.vin[i].prevout.n = i;
} }
return timer_stop();
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;
} }

View File

@@ -10,6 +10,6 @@ extern double benchmark_create_joinsplit();
extern double benchmark_solve_equihash(); extern double benchmark_solve_equihash();
extern double benchmark_verify_joinsplit(const CPourTx &joinsplit); extern double benchmark_verify_joinsplit(const CPourTx &joinsplit);
extern double benchmark_verify_equihash(); extern double benchmark_verify_equihash();
extern double benchmark_large_tx(bool testValidate); extern double benchmark_large_tx();
#endif #endif