Skip to content
Permalink
Browse files

Cache PoW hashes in CBlockHeader and CBlock objects

  • Loading branch information
solardiz committed Mar 30, 2019
1 parent 20c7ba3 commit a73d69465c8884e6289ecbdec58331e8fdc0376a
Showing with 59 additions and 7 deletions.
  1. +2 −2 src/main.cpp
  2. +22 −2 src/primitives/block.cpp
  3. +35 −3 src/primitives/block.h
@@ -1712,7 +1712,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
}

// Check the header
if (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus()))
if (!CheckProofOfWork(block.GetPoWHash_cached(), block.nBits, Params().GetConsensus()))
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());

return true;
@@ -3497,7 +3497,7 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
REJECT_INVALID, "version-too-low");

// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus()))
if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash_cached(), block.nBits, Params().GetConsensus()))
return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),
REJECT_INVALID, "high-hash");

@@ -10,19 +10,20 @@

#include "yespower/yespower.h"
#include "streams.h"
#include "sync.h"
#include "version.h"

#include "hash.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
#include "crypto/common.h"

uint256 CBlockHeader::GetHash() const
uint256 CBlockHeaderUncached::GetHash() const
{
return SerializeHash(*this);
}

uint256 CBlockHeader::GetPoWHash() const
uint256 CBlockHeaderUncached::GetPoWHash() const
{
static const yespower_params_t params = {
.version = YESPOWER_1_0,
@@ -41,6 +42,25 @@ uint256 CBlockHeader::GetPoWHash() const
return hash;
}

uint256 CBlockHeader::GetPoWHash_cached() const
{
uint256 block_hash = GetHash();
LOCK(cache_lock);
if (cache_init) {
if (block_hash != cache_block_hash) {
fprintf(stderr, "Error: CBlockHeader: block hash changed unexpectedly\n");
exit(1);
}
//printf("HIT block_hash = %s PoW_hash = %s\n", cache_block_hash.ToString().c_str(), cache_PoW_hash.ToString().c_str());

This comment has been minimized.

Copy link
@growlot

growlot Mar 31, 2019

Member

If it passed your test, I would like you to remove it.

} else {
cache_PoW_hash = GetPoWHash();
cache_block_hash = block_hash;
cache_init = true;
//printf("MISS block_hash = %s PoW_hash = %s\n", cache_block_hash.ToString().c_str(), cache_PoW_hash.ToString().c_str());

This comment has been minimized.

Copy link
@growlot

growlot Mar 31, 2019

Member

If it passed your test, I would like you to remove it.

This comment has been minimized.

Copy link
@solardiz

solardiz Mar 31, 2019

Author Collaborator

Yes, the caching as currently committed passed my tests using those printf's - there are no repeated MISS'es for the same hash values, but rather there's one MISS followed by some HITs for each hash value (usually one MISS and three HITs). However, I'd like to keep the commented-out printf's in there as I intend to reuse them when I retest the cache after future code changes.

This comment has been minimized.

Copy link
@solardiz

solardiz Dec 22, 2019

Author Collaborator

Since this commit is now referenced from a couple of other Bitcoin/Zcash fork projects, I need to clarify: my comment about "no repeated MISS'es for the same hash values" is for testing along with commit 3c80dac. Without that other commit, there would be some cache misses here. In other words, on its own this commit implements partial caching, and the other commit completes it - thus, other projects should want to import both commits.

}
return cache_PoW_hash;
}

uint256 CBlock::BuildMerkleTree(bool* fMutated) const
{
/* WARNING! If you're reading this because you're learning about crypto
@@ -10,6 +10,7 @@

#include "primitives/transaction.h"
#include "serialize.h"
#include "sync.h"
#include "uint256.h"

/** Nodes collect new transactions into a block, hash them into a hash tree,
@@ -19,7 +20,7 @@
* in the block is a special one that creates a new coin owned by the creator
* of the block.
*/
class CBlockHeader
class CBlockHeaderUncached
{
public:
// header
@@ -33,7 +34,7 @@ class CBlockHeader
uint32_t nBits;
uint256 nNonce;

CBlockHeader()
CBlockHeaderUncached()
{
SetNull();
}
@@ -53,7 +54,7 @@ class CBlockHeader

void SetNull()
{
nVersion = CBlockHeader::CURRENT_VERSION;
nVersion = CBlockHeaderUncached::CURRENT_VERSION;
hashPrevBlock.SetNull();
hashMerkleRoot.SetNull();
hashFinalSaplingRoot.SetNull();
@@ -77,6 +78,37 @@ class CBlockHeader
};


class CBlockHeader : public CBlockHeaderUncached
{
public:
CBlockHeader()
{
cache_init = false;
}

CBlockHeader(const CBlockHeader& header)
{
*this = header;
}

CBlockHeader& operator=(const CBlockHeader& header)
{
*(CBlockHeaderUncached*)this = (CBlockHeaderUncached)header;
cache_init = header.cache_init;
cache_block_hash = header.cache_block_hash;
cache_PoW_hash = header.cache_PoW_hash;
return *this;
}

uint256 GetPoWHash_cached() const;

private:
mutable CCriticalSection cache_lock;
mutable bool cache_init;
mutable uint256 cache_block_hash, cache_PoW_hash;
};


class CBlock : public CBlockHeader
{
public:

0 comments on commit a73d694

Please sign in to comment.
You can’t perform that action at this time.