Make bench working

Add hash comparison

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
Anthony Fieroni 2019-12-23 20:19:04 +02:00 committed by Brannon King
parent e53590bb8c
commit 03a72e4723
5 changed files with 90 additions and 30 deletions

View file

@ -13,6 +13,7 @@
#include <scheduler.h> #include <scheduler.h>
#include <txdb.h> #include <txdb.h>
#include <txmempool.h> #include <txmempool.h>
#include <util.h>
#include <utiltime.h> #include <utiltime.h>
#include <validation.h> #include <validation.h>
#include <validationinterface.h> #include <validationinterface.h>
@ -40,7 +41,7 @@ static CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
{ {
auto block = PrepareBlock(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; ++block->nNonce;
assert(block->nNonce); assert(block->nNonce);
} }
@ -72,18 +73,29 @@ static void AssembleBlock(benchmark::State& state)
boost::thread_group thread_group; boost::thread_group thread_group;
CScheduler scheduler; CScheduler scheduler;
{ {
delete ::pclaimTrie;
const CChainParams& chainparams = Params();
auto &consensus = chainparams.GetConsensus();
::pblocktree.reset(new CBlockTreeDB(1 << 20, true)); ::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); ::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)); thread_group.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
LoadGenesisBlock(chainparams); LoadGenesisBlock(chainparams);
CValidationState state; CValidationState state;
ActivateBestChain(state, chainparams); ActivateBestChain(state, chainparams);
assert(::chainActive.Tip() != nullptr); assert(::chainActive.Tip() != nullptr);
const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())}; const_cast<int&>(consensus.nWitnessForkHeight) = ::chainActive.Height();
const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), consensus)};
assert(witness_enabled); assert(witness_enabled);
} }

View file

@ -9,9 +9,50 @@
#include <streams.h> #include <streams.h>
#include <consensus/validation.h> #include <consensus/validation.h>
/* Don't use raw bitcoin blocks
namespace block_bench { namespace block_bench {
#include <bench/data/block413567.raw.h> #include <bench/data/block413567.raw.h>
} // namespace block_bench } // 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<unsigned int>::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 // 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 // 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) static void DeserializeBlockTest(benchmark::State& state)
{ {
CDataStream stream((const char*)block_bench::block413567, auto stream = getTestBlockStream();
(const char*)&block_bench::block413567[sizeof(block_bench::block413567)], const auto size = stream.size() - 1;
SER_NETWORK, PROTOCOL_VERSION);
char a = '\0';
stream.write(&a, 1); // Prevent compaction
while (state.KeepRunning()) { while (state.KeepRunning()) {
CBlock block; CBlock block;
stream >> block; stream >> block;
assert(stream.Rewind(sizeof(block_bench::block413567))); assert(stream.Rewind(size));
} }
} }
static void DeserializeAndCheckBlockTest(benchmark::State& state) static void DeserializeAndCheckBlockTest(benchmark::State& state)
{ {
CDataStream stream((const char*)block_bench::block413567, auto stream = getTestBlockStream();
(const char*)&block_bench::block413567[sizeof(block_bench::block413567)], const auto size = stream.size() - 1;
SER_NETWORK, PROTOCOL_VERSION); const auto chainParams = CreateChainParams(CBaseChainParams::REGTEST);
char a = '\0';
stream.write(&a, 1); // Prevent compaction
const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
while (state.KeepRunning()) { while (state.KeepRunning()) {
CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
stream >> block; stream >> block;
assert(stream.Rewind(sizeof(block_bench::block413567))); assert(stream.Rewind(size));
CValidationState validationState; CValidationState validationState;
assert(CheckBlock(block, validationState, chainParams->GetConsensus())); assert(CheckBlock(block, validationState, chainParams->GetConsensus()));

View file

@ -4,11 +4,13 @@
#include <bench/bench.h> #include <bench/bench.h>
#include <uint256.h> #include <claimtrie/hashes.h>
#include <random.h>
#include <consensus/merkle.h> #include <consensus/merkle.h>
#include <crypto/sha256.h>
#include <random.h>
#include <uint256.h>
static void MerkleRoot(benchmark::State& state) static void MerkleRootUni(benchmark::State& state)
{ {
FastRandomContext rng(true); FastRandomContext rng(true);
std::vector<uint256> leaves; std::vector<uint256> leaves;
@ -18,9 +20,18 @@ static void MerkleRoot(benchmark::State& state)
} }
while (state.KeepRunning()) { while (state.KeepRunning()) {
bool mutation = false; bool mutation = false;
uint256 hash = ComputeMerkleRoot(std::vector<uint256>(leaves), &mutation); uint256 hash = ComputeMerkleRoot(leaves, &mutation);
leaves[mutation] = hash; leaves[mutation] = hash;
} }
} }
static void MerkleRoot(benchmark::State& state)
{
sha256n_way = [](std::vector<uint256>& hashes) {
SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2);
};
MerkleRootUni(state);
}
BENCHMARK(MerkleRoot, 800); BENCHMARK(MerkleRoot, 800);
BENCHMARK(MerkleRootUni, 800);

View file

@ -6,6 +6,9 @@
#include <hash.h> #include <hash.h>
#include <utilstrencodings.h> #include <utilstrencodings.h>
#include <functional>
#include <vector>
/* WARNING! If you're reading this because you're learning about crypto /* 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 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 that the following merkle tree algorithm has a serious flaw related to
@ -42,6 +45,7 @@
root. root.
*/ */
extern std::function<void(std::vector<uint256>&)> sha256n_way;
uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated) { uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated) {
bool mutation = false; bool mutation = false;
@ -54,7 +58,7 @@ uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated) {
if (hashes.size() & 1) { if (hashes.size() & 1) {
hashes.push_back(hashes.back()); hashes.push_back(hashes.back());
} }
SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2); sha256n_way(hashes);
hashes.resize(hashes.size() / 2); hashes.resize(hashes.size() / 2);
} }
if (mutated) *mutated = mutation; if (mutated) *mutated = mutation;

View file

@ -1454,6 +1454,13 @@ bool AppInitMain()
pblocktree.reset(); pblocktree.reset();
pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReindex)); 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<uint256>& hashes) {
SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2);
};
if (fReindex) { if (fReindex) {
pblocktree->WriteReindexing(true); pblocktree->WriteReindexing(true);
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files //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); 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<uint256>& hashes) {
SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2);
};
auto tip = chainActive.Tip(); auto tip = chainActive.Tip();
if (tip && !CClaimTrieCache(pclaimTrie).validateDb(tip->nHeight, tip->hashClaimTrie)) { if (tip && !CClaimTrieCache(pclaimTrie).validateDb(tip->nHeight, tip->hashClaimTrie)) {
strLoadError = _("Error validating the claim trie from disk"); strLoadError = _("Error validating the claim trie from disk");