Add a benchmark for calling ConnectBlock on a block with many inputs
Requires placing block-107134.tar.gz (containing the block, and a fake CoinsDB containing its inputs) into the base directory of the repository. This can be generated using qa/zcash/create_benchmark_archive.py (see the script for usage details). To facilitate generation of the fake CoinsDB, an additional field 'valueZat' has been added to 'getrawtransaction' containing the integer number of zatoshis instead of a decimal number of ZEC. Closes #2355.
This commit is contained in:
@@ -137,6 +137,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
||||
const CTxOut& txout = tx.vout[i];
|
||||
UniValue out(UniValue::VOBJ);
|
||||
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
|
||||
out.push_back(Pair("valueZat", txout.nValue));
|
||||
out.push_back(Pair("n", (int64_t)i));
|
||||
UniValue o(UniValue::VOBJ);
|
||||
ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
|
||||
|
||||
@@ -65,6 +65,9 @@ void static BatchWriteHashBestAnchor(CLevelDBBatch &batch, const uint256 &hash)
|
||||
batch.Write(DB_BEST_ANCHOR, hash);
|
||||
}
|
||||
|
||||
CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe) {
|
||||
}
|
||||
|
||||
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ class CCoinsViewDB : public CCoinsView
|
||||
{
|
||||
protected:
|
||||
CLevelDBWrapper db;
|
||||
CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
||||
public:
|
||||
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
||||
|
||||
|
||||
@@ -2589,6 +2589,11 @@ UniValue zc_benchmark(const UniValue& params, bool fHelp)
|
||||
} else if (benchmarktype == "incnotewitnesses") {
|
||||
int nTxs = params[2].get_int();
|
||||
sample_times.push_back(benchmark_increment_note_witnesses(nTxs));
|
||||
} else if (benchmarktype == "connectblockslow") {
|
||||
if (Params().NetworkIDString() != "regtest") {
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
|
||||
}
|
||||
sample_times.push_back(benchmark_connectblock_slow());
|
||||
} else {
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <cstdio>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
@@ -9,6 +11,7 @@
|
||||
#include "primitives/transaction.h"
|
||||
#include "base58.h"
|
||||
#include "crypto/equihash.h"
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "main.h"
|
||||
@@ -17,6 +20,7 @@
|
||||
#include "script/sign.h"
|
||||
#include "sodium.h"
|
||||
#include "streams.h"
|
||||
#include "txdb.h"
|
||||
#include "utiltest.h"
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
@@ -322,3 +326,82 @@ double benchmark_increment_note_witnesses(size_t nTxs)
|
||||
return timer_stop(tv_start);
|
||||
}
|
||||
|
||||
// Fake the input of a given block
|
||||
class FakeCoinsViewDB : public CCoinsViewDB {
|
||||
uint256 hash;
|
||||
ZCIncrementalMerkleTree t;
|
||||
|
||||
public:
|
||||
FakeCoinsViewDB(std::string dbName, uint256& hash) : CCoinsViewDB(dbName, 100, false, false), hash(hash) {}
|
||||
|
||||
bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const {
|
||||
if (rt == t.root()) {
|
||||
tree = t;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetNullifier(const uint256 &nf) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint256 GetBestBlock() const {
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint256 GetBestAnchor() const {
|
||||
return t.root();
|
||||
}
|
||||
|
||||
bool BatchWrite(CCoinsMap &mapCoins,
|
||||
const uint256 &hashBlock,
|
||||
const uint256 &hashAnchor,
|
||||
CAnchorsMap &mapAnchors,
|
||||
CNullifiersMap &mapNullifiers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetStats(CCoinsStats &stats) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
double benchmark_connectblock_slow()
|
||||
{
|
||||
// Test for issue 2017-05-01.a
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
CBlock block;
|
||||
FILE* fp = fopen((GetDataDir() / "benchmark/block-107134.dat").string().c_str(), "rb");
|
||||
if (!fp) throw new std::runtime_error("Failed to open block data file");
|
||||
CAutoFile blkFile(fp, SER_DISK, CLIENT_VERSION);
|
||||
blkFile >> block;
|
||||
blkFile.fclose();
|
||||
|
||||
// Fake its inputs
|
||||
auto hashPrev = uint256S("00000000159a41f468e22135942a567781c3f3dc7ad62257993eb3c69c3f95ef");
|
||||
FakeCoinsViewDB fakeDB("benchmark/block-107134-inputs", hashPrev);
|
||||
CCoinsViewCache view(&fakeDB);
|
||||
|
||||
// Fake the chain
|
||||
CBlockIndex index(block);
|
||||
index.nHeight = 107134;
|
||||
CBlockIndex indexPrev;
|
||||
indexPrev.phashBlock = &hashPrev;
|
||||
indexPrev.nHeight = index.nHeight - 1;
|
||||
index.pprev = &indexPrev;
|
||||
mapBlockIndex.insert(std::make_pair(hashPrev, &indexPrev));
|
||||
|
||||
CValidationState state;
|
||||
struct timeval tv_start;
|
||||
timer_start(tv_start);
|
||||
assert(ConnectBlock(block, state, &index, view, true));
|
||||
auto duration = timer_stop(tv_start);
|
||||
|
||||
// Undo alterations to global state
|
||||
mapBlockIndex.erase(hashPrev);
|
||||
SelectParamsFromCommandLine();
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,5 +15,6 @@ extern double benchmark_verify_equihash();
|
||||
extern double benchmark_large_tx();
|
||||
extern double benchmark_try_decrypt_notes(size_t nAddrs);
|
||||
extern double benchmark_increment_note_witnesses(size_t nTxs);
|
||||
extern double benchmark_connectblock_slow();
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user