aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPieter Wuille <sipa@ulyssis.org>2013-11-05 02:27:39 +0100
committerPieter Wuille <pieter.wuille@gmail.com>2013-11-10 19:22:53 +0100
commit84674082b0c4cfcdd54fb97a29bc841aa7f691c2 (patch)
tree87fb3462d81b84c0d4a64cb5eca7ab8c64895091 /src
parentf76c122e2eac8ef66f69d142231bd33c88a24c50 (diff)
Make CCoinsView use block hashes instead of indices
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp57
-rw-r--r--src/main.h24
-rw-r--r--src/rpcblockchain.cpp6
-rw-r--r--src/txdb.cpp23
-rw-r--r--src/txdb.h6
5 files changed, 60 insertions, 56 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 2a133b3eae..5b330536fd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -236,9 +236,9 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) { return false; }
bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return false; }
bool CCoinsView::HaveCoins(const uint256 &txid) { return false; }
-CBlockIndex *CCoinsView::GetBestBlock() { return NULL; }
-bool CCoinsView::SetBestBlock(CBlockIndex *pindex) { return false; }
-bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { return false; }
+uint256 CCoinsView::GetBestBlock() { return uint256(0); }
+bool CCoinsView::SetBestBlock(const uint256 &hashBlock) { return false; }
+bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) { return false; }
bool CCoinsView::GetStats(CCoinsStats &stats) { return false; }
@@ -246,13 +246,13 @@ CCoinsViewBacked::CCoinsViewBacked(CCoinsView &viewIn) : base(&viewIn) { }
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) { return base->GetCoins(txid, coins); }
bool CCoinsViewBacked::SetCoins(const uint256 &txid, const CCoins &coins) { return base->SetCoins(txid, coins); }
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) { return base->HaveCoins(txid); }
-CBlockIndex *CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); }
-bool CCoinsViewBacked::SetBestBlock(CBlockIndex *pindex) { return base->SetBestBlock(pindex); }
+uint256 CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); }
+bool CCoinsViewBacked::SetBestBlock(const uint256 &hashBlock) { return base->SetBestBlock(hashBlock); }
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
-bool CCoinsViewBacked::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { return base->BatchWrite(mapCoins, pindex); }
+bool CCoinsViewBacked::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stats); }
-CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), pindexTip(NULL) { }
+CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), hashBlock(0) { }
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) {
if (cacheCoins.count(txid)) {
@@ -293,26 +293,26 @@ bool CCoinsViewCache::HaveCoins(const uint256 &txid) {
return FetchCoins(txid) != cacheCoins.end();
}
-CBlockIndex *CCoinsViewCache::GetBestBlock() {
- if (pindexTip == NULL)
- pindexTip = base->GetBestBlock();
- return pindexTip;
+uint256 CCoinsViewCache::GetBestBlock() {
+ if (hashBlock == uint256(0))
+ hashBlock = base->GetBestBlock();
+ return hashBlock;
}
-bool CCoinsViewCache::SetBestBlock(CBlockIndex *pindex) {
- pindexTip = pindex;
+bool CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
+ hashBlock = hashBlockIn;
return true;
}
-bool CCoinsViewCache::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
+bool CCoinsViewCache::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlockIn) {
for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
cacheCoins[it->first] = it->second;
- pindexTip = pindex;
+ hashBlock = hashBlockIn;
return true;
}
bool CCoinsViewCache::Flush() {
- bool fOk = base->BatchWrite(cacheCoins, pindexTip);
+ bool fOk = base->BatchWrite(cacheCoins, hashBlock);
if (fOk)
cacheCoins.clear();
return fOk;
@@ -1498,7 +1498,8 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
// While checking, GetBestBlock() refers to the parent block.
// This is also true for mempool checks.
- int nSpendHeight = inputs.GetBestBlock()->nHeight + 1;
+ CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second;
+ int nSpendHeight = pindexPrev->nHeight + 1;
int64_t nValueIn = 0;
int64_t nFees = 0;
for (unsigned int i = 0; i < tx.vin.size(); i++)
@@ -1568,7 +1569,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
{
- assert(pindex == view.GetBestBlock());
+ assert(pindex->GetBlockHash() == view.GetBestBlock());
if (pfClean)
*pfClean = false;
@@ -1644,7 +1645,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
}
// move best block pointer to prevout block
- view.SetBestBlock(pindex->pprev);
+ view.SetBestBlock(pindex->pprev->GetBlockHash());
if (pfClean) {
*pfClean = fClean;
@@ -1693,12 +1694,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return false;
// verify that the view's current state corresponds to the previous block
- assert(pindex->pprev == view.GetBestBlock());
+ uint256 hashPrevBlock = pindex->pprev == NULL ? uint256(0) : pindex->pprev->GetBlockHash();
+ assert(hashPrevBlock == view.GetBestBlock());
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
if (block.GetHash() == Params().HashGenesisBlock()) {
- view.SetBestBlock(pindex);
+ view.SetBestBlock(pindex->GetBlockHash());
return true;
}
@@ -1828,7 +1830,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return state.Abort(_("Failed to write transaction index"));
// add this block to the view's block chain
- assert(view.SetBestBlock(pindex));
+ assert(view.SetBestBlock(pindex->GetBlockHash()));
// Watch for transactions paying to me
for (unsigned int i = 0; i < block.vtx.size(); i++)
@@ -1846,7 +1848,9 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
CCoinsViewCache view(*pcoinsTip, true);
// Find the fork (typically, there is none)
- CBlockIndex* pfork = view.GetBestBlock();
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(view.GetBestBlock());
+ CBlockIndex* ptip = (it != mapBlockIndex.end()) ? it->second : NULL;
+ CBlockIndex* pfork = ptip;
CBlockIndex* plonger = pindexNew;
while (pfork && pfork != plonger)
{
@@ -1862,7 +1866,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// List of what to disconnect (typically nothing)
vector<CBlockIndex*> vDisconnect;
- for (CBlockIndex* pindex = view.GetBestBlock(); pindex != pfork; pindex = pindex->pprev)
+ for (CBlockIndex* pindex = ptip; pindex != pfork; pindex = pindex->pprev)
vDisconnect.push_back(pindex);
// List of what to connect (typically only pindexNew)
@@ -2687,9 +2691,10 @@ bool static LoadBlockIndexDB()
LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
// Load pointer to end of best chain
- chainActive.SetTip(pcoinsTip->GetBestBlock());
- if (chainActive.Tip() == NULL)
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
+ if (it == mapBlockIndex.end())
return true;
+ chainActive.SetTip(it->second);
LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str());
diff --git a/src/main.h b/src/main.h
index d717802618..b8db357aed 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1062,14 +1062,14 @@ public:
// This may (but cannot always) return true for fully spent transactions
virtual bool HaveCoins(const uint256 &txid);
- // Retrieve the block index whose state this CCoinsView currently represents
- virtual CBlockIndex *GetBestBlock();
+ // Retrieve the block hash whose state this CCoinsView currently represents
+ virtual uint256 GetBestBlock();
- // Modify the currently active block index
- virtual bool SetBestBlock(CBlockIndex *pindex);
+ // Modify the currently active block hash
+ virtual bool SetBestBlock(const uint256 &hashBlock);
// Do a bulk modification (multiple SetCoins + one SetBestBlock)
- virtual bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
+ virtual bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock);
// Calculate statistics about the unspent transaction output set
virtual bool GetStats(CCoinsStats &stats);
@@ -1089,10 +1089,10 @@ public:
bool GetCoins(const uint256 &txid, CCoins &coins);
bool SetCoins(const uint256 &txid, const CCoins &coins);
bool HaveCoins(const uint256 &txid);
- CBlockIndex *GetBestBlock();
- bool SetBestBlock(CBlockIndex *pindex);
+ uint256 GetBestBlock();
+ bool SetBestBlock(const uint256 &hashBlock);
void SetBackend(CCoinsView &viewIn);
- bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
+ bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock);
bool GetStats(CCoinsStats &stats);
};
@@ -1100,7 +1100,7 @@ public:
class CCoinsViewCache : public CCoinsViewBacked
{
protected:
- CBlockIndex *pindexTip;
+ uint256 hashBlock;
std::map<uint256,CCoins> cacheCoins;
public:
@@ -1110,9 +1110,9 @@ public:
bool GetCoins(const uint256 &txid, CCoins &coins);
bool SetCoins(const uint256 &txid, const CCoins &coins);
bool HaveCoins(const uint256 &txid);
- CBlockIndex *GetBestBlock();
- bool SetBestBlock(CBlockIndex *pindex);
- bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
+ uint256 GetBestBlock();
+ bool SetBestBlock(const uint256 &hashBlock);
+ bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock);
// Return a modifiable reference to a CCoins. Check HaveCoins first.
// Many methods explicitly require a CCoinsViewCache because of this method, to reduce
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 18e213257e..483d8d2e8d 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -245,11 +245,13 @@ Value gettxout(const Array& params, bool fHelp)
if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
return Value::null;
- ret.push_back(Pair("bestblock", pcoinsTip->GetBestBlock()->GetBlockHash().GetHex()));
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
+ CBlockIndex *pindex = it->second;
+ ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
ret.push_back(Pair("confirmations", 0));
else
- ret.push_back(Pair("confirmations", pcoinsTip->GetBestBlock()->nHeight - coins.nHeight + 1));
+ ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
Object o;
ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 3c8b0b7fe1..99deb31404 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -40,30 +40,27 @@ bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
return db.Exists(make_pair('c', txid));
}
-CBlockIndex *CCoinsViewDB::GetBestBlock() {
+uint256 CCoinsViewDB::GetBestBlock() {
uint256 hashBestChain;
if (!db.Read('B', hashBestChain))
- return NULL;
- std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hashBestChain);
- if (it == mapBlockIndex.end())
- return NULL;
- return it->second;
+ return uint256(0);
+ return hashBestChain;
}
-bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) {
+bool CCoinsViewDB::SetBestBlock(const uint256 &hashBlock) {
CLevelDBBatch batch;
- BatchWriteHashBestChain(batch, pindex->GetBlockHash());
+ BatchWriteHashBestChain(batch, hashBlock);
return db.WriteBatch(batch);
}
-bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
+bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) {
LogPrint("coindb", "Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());
CLevelDBBatch batch;
for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
BatchWriteCoins(batch, it->first, it->second);
- if (pindex)
- BatchWriteHashBestChain(batch, pindex->GetBlockHash());
+ if (hashBlock != uint256(0))
+ BatchWriteHashBestChain(batch, hashBlock);
return db.WriteBatch(batch);
}
@@ -115,7 +112,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
pcursor->SeekToFirst();
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- stats.hashBlock = GetBestBlock()->GetBlockHash();
+ stats.hashBlock = GetBestBlock();
ss << stats.hashBlock;
int64_t nTotalAmount = 0;
while (pcursor->Valid()) {
@@ -155,7 +152,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
}
}
delete pcursor;
- stats.nHeight = GetBestBlock()->nHeight;
+ stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
stats.hashSerialized = ss.GetHash();
stats.nTotalAmount = nTotalAmount;
return true;
diff --git a/src/txdb.h b/src/txdb.h
index 8043a595a8..7ce6585d37 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -29,9 +29,9 @@ public:
bool GetCoins(const uint256 &txid, CCoins &coins);
bool SetCoins(const uint256 &txid, const CCoins &coins);
bool HaveCoins(const uint256 &txid);
- CBlockIndex *GetBestBlock();
- bool SetBestBlock(CBlockIndex *pindex);
- bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
+ uint256 GetBestBlock();
+ bool SetBestBlock(const uint256 &hashBlock);
+ bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock);
bool GetStats(CCoinsStats &stats);
};