Use a uint256 for bnChainWork

Every block index entry currently requires a separately-allocated
CBigNum. By replacing them with uint256, it's just 32 bytes extra
in CBlockIndex itself.

This should save us a few megabytes in RAM, and less allocation
overhead.
This commit is contained in:
Pieter Wuille 2013-03-28 23:51:50 +01:00 committed by Pieter Wuille
parent 2aa462ec30
commit 1657c4bc49
5 changed files with 48 additions and 36 deletions

View File

@ -1,5 +1,5 @@
diff --git a/src/main.cpp b/src/main.cpp diff --git a/contrib/test-patches/bitcoind-comparison.patch b/contrib/test-patches/bitcoind-comparison.patch
index 8c115c2..1e70ff2 100644 index 04a8618..519429a 100644
--- a/src/main.cpp --- a/src/main.cpp
+++ b/src/main.cpp +++ b/src/main.cpp
@@ -31,8 +31,8 @@ CTxMemPool mempool; @@ -31,8 +31,8 @@ CTxMemPool mempool;
@ -12,7 +12,7 @@ index 8c115c2..1e70ff2 100644
+static CBigNum bnProofOfWorkLimit(~uint256(0) >> 1); +static CBigNum bnProofOfWorkLimit(~uint256(0) >> 1);
CBlockIndex* pindexGenesisBlock = NULL; CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1; int nBestHeight = -1;
CBigNum bnBestChainWork = 0; uint256 nBestChainWork = 0;
@@ -1055,7 +1055,7 @@ int64 static GetBlockValue(int nHeight, int64 nFees) @@ -1055,7 +1055,7 @@ int64 static GetBlockValue(int nHeight, int64 nFees)
int64 nSubsidy = 50 * COIN; int64 nSubsidy = 50 * COIN;
@ -22,7 +22,7 @@ index 8c115c2..1e70ff2 100644
return nSubsidy + nFees; return nSubsidy + nFees;
} }
@@ -2706,9 +2706,9 @@ bool InitBlockIndex() { @@ -2736,9 +2736,9 @@ bool InitBlockIndex() {
block.hashPrevBlock = 0; block.hashPrevBlock = 0;
block.hashMerkleRoot = block.BuildMerkleTree(); block.hashMerkleRoot = block.BuildMerkleTree();
block.nVersion = 1; block.nVersion = 1;
@ -35,7 +35,7 @@ index 8c115c2..1e70ff2 100644
if (fTestNet) if (fTestNet)
{ {
@@ -3007,7 +3007,7 @@ bool static AlreadyHave(const CInv& inv) @@ -3024,7 +3024,7 @@ bool static AlreadyHave(const CInv& inv)
// The message start string is designed to be unlikely to occur in normal data. // The message start string is designed to be unlikely to occur in normal data.
// The characters are rarely used upper ASCII, not valid as UTF-8, and produce // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
// a large 4-byte int at any alignment. // a large 4-byte int at any alignment.

View File

@ -222,7 +222,7 @@ public:
BN_mpi2bn(pch, p - pch, this); BN_mpi2bn(pch, p - pch, this);
} }
uint256 getuint256() uint256 getuint256() const
{ {
unsigned int nSize = BN_bn2mpi(this, NULL); unsigned int nSize = BN_bn2mpi(this, NULL);
if (nSize < 4) if (nSize < 4)

View File

@ -35,8 +35,8 @@ uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32); static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
CBlockIndex* pindexGenesisBlock = NULL; CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1; int nBestHeight = -1;
CBigNum bnBestChainWork = 0; uint256 nBestChainWork = 0;
CBigNum bnBestInvalidWork = 0; uint256 nBestInvalidWork = 0;
uint256 hashBestChain = 0; uint256 hashBestChain = 0;
CBlockIndex* pindexBest = NULL; CBlockIndex* pindexBest = NULL;
set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid; // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid; // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed
@ -1191,20 +1191,20 @@ bool IsInitialBlockDownload()
void static InvalidChainFound(CBlockIndex* pindexNew) void static InvalidChainFound(CBlockIndex* pindexNew)
{ {
if (pindexNew->bnChainWork > bnBestInvalidWork) if (pindexNew->nChainWork > nBestInvalidWork)
{ {
bnBestInvalidWork = pindexNew->bnChainWork; nBestInvalidWork = pindexNew->nChainWork;
pblocktree->WriteBestInvalidWork(bnBestInvalidWork); pblocktree->WriteBestInvalidWork(CBigNum(nBestInvalidWork));
uiInterface.NotifyBlocksChanged(); uiInterface.NotifyBlocksChanged();
} }
printf("InvalidChainFound: invalid block=%s height=%d work=%s date=%s\n", printf("InvalidChainFound: invalid block=%s height=%d log2_work=%.8g date=%s\n",
pindexNew->GetBlockHash().ToString().c_str(), pindexNew->nHeight, pindexNew->GetBlockHash().ToString().c_str(), pindexNew->nHeight,
pindexNew->bnChainWork.ToString().c_str(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
pindexNew->GetBlockTime()).c_str()); pindexNew->GetBlockTime()).c_str());
printf("InvalidChainFound: current best=%s height=%d work=%s date=%s\n", printf("InvalidChainFound: current best=%s height=%d log2_work=%.8g date=%s\n",
hashBestChain.ToString().c_str(), nBestHeight, bnBestChainWork.ToString().c_str(), hashBestChain.ToString().c_str(), nBestHeight, log(nBestChainWork.getdouble())/log(2.0),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str()); DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str());
if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6) if (pindexBest && nBestInvalidWork > nBestChainWork + (pindexBest->GetBlockWork() * 6).getuint256())
printf("InvalidChainFound: Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n"); printf("InvalidChainFound: Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
} }
@ -1230,7 +1230,7 @@ bool ConnectBestBlock(CValidationState &state) {
pindexNewBest = *it; pindexNewBest = *it;
} }
if (pindexNewBest == pindexBest || (pindexBest && pindexNewBest->bnChainWork == pindexBest->bnChainWork)) if (pindexNewBest == pindexBest || (pindexBest && pindexNewBest->nChainWork == pindexBest->nChainWork))
return true; // nothing to do return true; // nothing to do
// check ancestry // check ancestry
@ -1250,7 +1250,7 @@ bool ConnectBestBlock(CValidationState &state) {
break; break;
} }
if (pindexBest == NULL || pindexTest->bnChainWork > pindexBest->bnChainWork) if (pindexBest == NULL || pindexTest->nChainWork > pindexBest->nChainWork)
vAttach.push_back(pindexTest); vAttach.push_back(pindexTest);
if (pindexTest->pprev == NULL || pindexTest->pnext != NULL) { if (pindexTest->pprev == NULL || pindexTest->pnext != NULL) {
@ -1858,11 +1858,11 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
pindexBest = pindexNew; pindexBest = pindexNew;
pblockindexFBBHLast = NULL; pblockindexFBBHLast = NULL;
nBestHeight = pindexBest->nHeight; nBestHeight = pindexBest->nHeight;
bnBestChainWork = pindexNew->bnChainWork; nBestChainWork = pindexNew->nChainWork;
nTimeBestReceived = GetTime(); nTimeBestReceived = GetTime();
nTransactionsUpdated++; nTransactionsUpdated++;
printf("SetBestChain: new best=%s height=%d work=%s tx=%lu date=%s progress=%f\n", printf("SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
hashBestChain.ToString().c_str(), nBestHeight, bnBestChainWork.ToString().c_str(), (unsigned long)pindexNew->nChainTx, hashBestChain.ToString().c_str(), nBestHeight, log(nBestChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str(),
Checkpoints::GuessVerificationProgress(pindexBest)); Checkpoints::GuessVerificationProgress(pindexBest));
@ -1915,7 +1915,7 @@ bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
pindexNew->nHeight = pindexNew->pprev->nHeight + 1; pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
} }
pindexNew->nTx = vtx.size(); pindexNew->nTx = vtx.size();
pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork(); pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork().getuint256();
pindexNew->nChainTx = (pindexNew->pprev ? pindexNew->pprev->nChainTx : 0) + pindexNew->nTx; pindexNew->nChainTx = (pindexNew->pprev ? pindexNew->pprev->nChainTx : 0) + pindexNew->nTx;
pindexNew->nFile = pos.nFile; pindexNew->nFile = pos.nFile;
pindexNew->nDataPos = pos.nPos; pindexNew->nDataPos = pos.nPos;
@ -2537,7 +2537,7 @@ bool static LoadBlockIndexDB()
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
// Calculate bnChainWork // Calculate nChainWork
vector<pair<int, CBlockIndex*> > vSortedByHeight; vector<pair<int, CBlockIndex*> > vSortedByHeight;
vSortedByHeight.reserve(mapBlockIndex.size()); vSortedByHeight.reserve(mapBlockIndex.size());
BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
@ -2549,7 +2549,7 @@ bool static LoadBlockIndexDB()
BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
{ {
CBlockIndex* pindex = item.second; CBlockIndex* pindex = item.second;
pindex->bnChainWork = (pindex->pprev ? pindex->pprev->bnChainWork : 0) + pindex->GetBlockWork(); pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + pindex->GetBlockWork().getuint256();
pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx; pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS && !(pindex->nStatus & BLOCK_FAILED_MASK)) if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS && !(pindex->nStatus & BLOCK_FAILED_MASK))
setBlockIndexValid.insert(pindex); setBlockIndexValid.insert(pindex);
@ -2561,8 +2561,10 @@ bool static LoadBlockIndexDB()
if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile)) if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile))
printf("LoadBlockIndexDB(): last block file info: %s\n", infoLastBlockFile.ToString().c_str()); printf("LoadBlockIndexDB(): last block file info: %s\n", infoLastBlockFile.ToString().c_str());
// Load bnBestInvalidWork, OK if it doesn't exist // Load nBestInvalidWork, OK if it doesn't exist
CBigNum bnBestInvalidWork;
pblocktree->ReadBestInvalidWork(bnBestInvalidWork); pblocktree->ReadBestInvalidWork(bnBestInvalidWork);
nBestInvalidWork = bnBestInvalidWork.getuint256();
// Check whether we need to continue reindexing // Check whether we need to continue reindexing
bool fReindexing = false; bool fReindexing = false;
@ -2579,7 +2581,7 @@ bool static LoadBlockIndexDB()
return true; return true;
hashBestChain = pindexBest->GetBlockHash(); hashBestChain = pindexBest->GetBlockHash();
nBestHeight = pindexBest->nHeight; nBestHeight = pindexBest->nHeight;
bnBestChainWork = pindexBest->bnChainWork; nBestChainWork = pindexBest->nChainWork;
// set 'next' pointers in best chain // set 'next' pointers in best chain
CBlockIndex *pindex = pindexBest; CBlockIndex *pindex = pindexBest;
@ -2675,8 +2677,8 @@ void UnloadBlockIndex()
setBlockIndexValid.clear(); setBlockIndexValid.clear();
pindexGenesisBlock = NULL; pindexGenesisBlock = NULL;
nBestHeight = 0; nBestHeight = 0;
bnBestChainWork = 0; nBestChainWork = 0;
bnBestInvalidWork = 0; nBestInvalidWork = 0;
hashBestChain = 0; hashBestChain = 0;
pindexBest = NULL; pindexBest = NULL;
} }
@ -2953,7 +2955,7 @@ string GetWarnings(string strFor)
} }
// Longer invalid proof-of-work chain // Longer invalid proof-of-work chain
if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6) if (pindexBest && nBestInvalidWork > nBestChainWork + (pindexBest->GetBlockWork() * 6).getuint256())
{ {
nPriority = 2000; nPriority = 2000;
strStatusBar = strRPC = _("Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."); strStatusBar = strRPC = _("Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.");

View File

@ -77,8 +77,8 @@ extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
extern uint256 hashGenesisBlock; extern uint256 hashGenesisBlock;
extern CBlockIndex* pindexGenesisBlock; extern CBlockIndex* pindexGenesisBlock;
extern int nBestHeight; extern int nBestHeight;
extern CBigNum bnBestChainWork; extern uint256 nBestChainWork;
extern CBigNum bnBestInvalidWork; extern uint256 nBestInvalidWork;
extern uint256 hashBestChain; extern uint256 hashBestChain;
extern CBlockIndex* pindexBest; extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated; extern unsigned int nTransactionsUpdated;
@ -1619,7 +1619,7 @@ public:
unsigned int nUndoPos; unsigned int nUndoPos;
// (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block // (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
CBigNum bnChainWork; uint256 nChainWork;
// Number of transactions in this block. // Number of transactions in this block.
// Note: in a potential headers-first mode, this number cannot be relied upon // Note: in a potential headers-first mode, this number cannot be relied upon
@ -1648,7 +1648,7 @@ public:
nFile = 0; nFile = 0;
nDataPos = 0; nDataPos = 0;
nUndoPos = 0; nUndoPos = 0;
bnChainWork = 0; nChainWork = 0;
nTx = 0; nTx = 0;
nChainTx = 0; nChainTx = 0;
nStatus = 0; nStatus = 0;
@ -1669,7 +1669,7 @@ public:
nFile = 0; nFile = 0;
nDataPos = 0; nDataPos = 0;
nUndoPos = 0; nUndoPos = 0;
bnChainWork = 0; nChainWork = 0;
nTx = 0; nTx = 0;
nChainTx = 0; nChainTx = 0;
nStatus = 0; nStatus = 0;
@ -1793,8 +1793,8 @@ public:
struct CBlockIndexWorkComparator struct CBlockIndexWorkComparator
{ {
bool operator()(CBlockIndex *pa, CBlockIndex *pb) { bool operator()(CBlockIndex *pa, CBlockIndex *pb) {
if (pa->bnChainWork > pb->bnChainWork) return false; if (pa->nChainWork > pb->nChainWork) return false;
if (pa->bnChainWork < pb->bnChainWork) return true; if (pa->nChainWork < pb->nChainWork) return true;
if (pa->GetBlockHash() < pb->GetBlockHash()) return false; if (pa->GetBlockHash() < pb->GetBlockHash()) return false;
if (pa->GetBlockHash() > pb->GetBlockHash()) return true; if (pa->GetBlockHash() > pb->GetBlockHash()) return true;

View File

@ -55,6 +55,16 @@ public:
return ret; return ret;
} }
double getdouble() const
{
double ret = 0.0;
double fact = 1.0;
for (int i = 0; i < WIDTH; i++) {
ret += fact * pn[i];
fact *= 4294967296.0;
}
return ret;
}
base_uint& operator=(uint64 b) base_uint& operator=(uint64 b)
{ {