From 03a72e47231aa492b32b3acbbc3b084dc29d0487 Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Mon, 23 Dec 2019 20:19:04 +0200 Subject: [PATCH] Make bench working Add hash comparison Signed-off-by: Anthony Fieroni --- src/bench/block_assemble.cpp | 18 +++++++++-- src/bench/checkblock.cpp | 63 +++++++++++++++++++++++++++--------- src/bench/merkle_root.cpp | 19 ++++++++--- src/consensus/merkle.cpp | 6 +++- src/init.cpp | 14 ++++---- 5 files changed, 90 insertions(+), 30 deletions(-) diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp index bc99b8cdc..20b177483 100644 --- a/src/bench/block_assemble.cpp +++ b/src/bench/block_assemble.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,7 @@ static CTxIn MineBlock(const CScript& coinbase_scriptPubKey) { auto block = PrepareBlock(coinbase_scriptPubKey); - while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { + while (!CheckProofOfWork(block->GetPoWHash(), block->nBits, Params().GetConsensus())) { ++block->nNonce; assert(block->nNonce); } @@ -72,18 +73,29 @@ static void AssembleBlock(benchmark::State& state) boost::thread_group thread_group; CScheduler scheduler; { + delete ::pclaimTrie; + const CChainParams& chainparams = Params(); + auto &consensus = chainparams.GetConsensus(); ::pblocktree.reset(new CBlockTreeDB(1 << 20, true)); ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); ::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); + ::pclaimTrie = new CClaimTrie(1 << 25, true, 0, GetDataDir().string(), + consensus.nNormalizedNameForkHeight, + consensus.nMinRemovalWorkaroundHeight, + consensus.nMaxRemovalWorkaroundHeight, + consensus.nOriginalClaimExpirationTime, + consensus.nExtendedClaimExpirationTime, + consensus.nExtendedClaimExpirationForkHeight, + consensus.nAllClaimsInMerkleForkHeight, 1); - const CChainParams& chainparams = Params(); thread_group.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler)); GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); LoadGenesisBlock(chainparams); CValidationState state; ActivateBestChain(state, chainparams); assert(::chainActive.Tip() != nullptr); - const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())}; + const_cast(consensus.nWitnessForkHeight) = ::chainActive.Height(); + const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), consensus)}; assert(witness_enabled); } diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp index acbb72257..1aa71addb 100644 --- a/src/bench/checkblock.cpp +++ b/src/bench/checkblock.cpp @@ -9,9 +9,50 @@ #include #include + +/* Don't use raw bitcoin blocks namespace block_bench { #include } // namespace block_bench +*/ + +CDataStream getTestBlockStream() +{ + static CBlock block; + static CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + if (block.IsNull()) { + block.nVersion = 5; + block.hashPrevBlock = uint256S("e8fc54d1e6581fceaaf64cc8afeedb9c4ba1eb2349eaf638f1fc41e331869dee"); + block.hashMerkleRoot = uint256S("a926580973e1204aa179a4c536023c69212ce00b56dc85d3516488f3c51dd022"); + block.hashClaimTrie = uint256S("7bae80d60b09031265f8a9f6282e4b9653764fadfac2c8b4c1f416c972b58814"); + block.nTime = 1545050539; + block.nBits = 0x207fffff; + block.nNonce = 128913; + block.vtx.resize(60); + uint256 prevHash; + for (int i = 0; i < 60; ++i) { + CMutableTransaction tx; + tx.nVersion = 5; + tx.nLockTime = 0; + tx.vin.resize(1); + tx.vout.resize(1); + if (!prevHash.IsNull()) { + tx.vin[0].prevout.hash = prevHash; + tx.vin[0].prevout.n = 0; + } + tx.vin[0].scriptSig = CScript() << OP_0 << OP_0; + tx.vin[0].nSequence = std::numeric_limits::max(); + tx.vout[0].scriptPubKey = CScript(); + tx.vout[0].nValue = 0; + prevHash = tx.GetHash(); + block.vtx[i] = MakeTransactionRef(std::move(tx)); + } + stream << block; + char a = '\0'; + stream.write(&a, 1); // Prevent compaction + } + return stream; +} // These are the two major time-sinks which happen after we have fully received // a block off the wire, but before we can relay the block on to peers using @@ -19,33 +60,25 @@ namespace block_bench { static void DeserializeBlockTest(benchmark::State& state) { - CDataStream stream((const char*)block_bench::block413567, - (const char*)&block_bench::block413567[sizeof(block_bench::block413567)], - SER_NETWORK, PROTOCOL_VERSION); - char a = '\0'; - stream.write(&a, 1); // Prevent compaction - + auto stream = getTestBlockStream(); + const auto size = stream.size() - 1; while (state.KeepRunning()) { CBlock block; stream >> block; - assert(stream.Rewind(sizeof(block_bench::block413567))); + assert(stream.Rewind(size)); } } static void DeserializeAndCheckBlockTest(benchmark::State& state) { - CDataStream stream((const char*)block_bench::block413567, - (const char*)&block_bench::block413567[sizeof(block_bench::block413567)], - SER_NETWORK, PROTOCOL_VERSION); - char a = '\0'; - stream.write(&a, 1); // Prevent compaction - - const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); + auto stream = getTestBlockStream(); + const auto size = stream.size() - 1; + const auto chainParams = CreateChainParams(CBaseChainParams::REGTEST); while (state.KeepRunning()) { CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here stream >> block; - assert(stream.Rewind(sizeof(block_bench::block413567))); + assert(stream.Rewind(size)); CValidationState validationState; assert(CheckBlock(block, validationState, chainParams->GetConsensus())); diff --git a/src/bench/merkle_root.cpp b/src/bench/merkle_root.cpp index bdb2bdbe3..9d834a537 100644 --- a/src/bench/merkle_root.cpp +++ b/src/bench/merkle_root.cpp @@ -4,11 +4,13 @@ #include -#include -#include +#include #include +#include +#include +#include -static void MerkleRoot(benchmark::State& state) +static void MerkleRootUni(benchmark::State& state) { FastRandomContext rng(true); std::vector leaves; @@ -18,9 +20,18 @@ static void MerkleRoot(benchmark::State& state) } while (state.KeepRunning()) { bool mutation = false; - uint256 hash = ComputeMerkleRoot(std::vector(leaves), &mutation); + uint256 hash = ComputeMerkleRoot(leaves, &mutation); leaves[mutation] = hash; } } +static void MerkleRoot(benchmark::State& state) +{ + sha256n_way = [](std::vector& hashes) { + SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2); + }; + MerkleRootUni(state); +} + BENCHMARK(MerkleRoot, 800); +BENCHMARK(MerkleRootUni, 800); diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 2a87a936b..449ee8b7e 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -6,6 +6,9 @@ #include #include +#include +#include + /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind that the following merkle tree algorithm has a serious flaw related to @@ -42,6 +45,7 @@ root. */ +extern std::function&)> sha256n_way; uint256 ComputeMerkleRoot(std::vector hashes, bool* mutated) { bool mutation = false; @@ -54,7 +58,7 @@ uint256 ComputeMerkleRoot(std::vector hashes, bool* mutated) { if (hashes.size() & 1) { hashes.push_back(hashes.back()); } - SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2); + sha256n_way(hashes); hashes.resize(hashes.size() / 2); } if (mutated) *mutated = mutation; diff --git a/src/init.cpp b/src/init.cpp index bb0fc9967..d9f307886 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1454,6 +1454,13 @@ bool AppInitMain() pblocktree.reset(); pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReindex)); + // use faster N way hash function + // NOTE: it assumes memory is continuous + // that means uint256 itself should use std::array or raw pointer + sha256n_way = [](std::vector& hashes) { + SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2); + }; + if (fReindex) { pblocktree->WriteReindexing(true); //If we're reindexing in prune mode, wipe away unusable block files and all undo data files @@ -1535,13 +1542,6 @@ bool AppInitMain() assert(chainActive.Tip() != nullptr); } - // use faster N way hash function - // NOTE: it assumes memory is continuous - // that means uint256 itself should use std::array or raw pointer - sha256n_way = [](std::vector& hashes) { - SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2); - }; - auto tip = chainActive.Tip(); if (tip && !CClaimTrieCache(pclaimTrie).validateDb(tip->nHeight, tip->hashClaimTrie)) { strLoadError = _("Error validating the claim trie from disk");