|
|
@ -236,9 +236,9 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const { |
|
|
|
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) { return false; } |
|
|
|
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) { return false; } |
|
|
|
bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return false; } |
|
|
|
bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return false; } |
|
|
|
bool CCoinsView::HaveCoins(const uint256 &txid) { return false; } |
|
|
|
bool CCoinsView::HaveCoins(const uint256 &txid) { return false; } |
|
|
|
CBlockIndex *CCoinsView::GetBestBlock() { return NULL; } |
|
|
|
uint256 CCoinsView::GetBestBlock() { return uint256(0); } |
|
|
|
bool CCoinsView::SetBestBlock(CBlockIndex *pindex) { return false; } |
|
|
|
bool CCoinsView::SetBestBlock(const uint256 &hashBlock) { return false; } |
|
|
|
bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { return false; } |
|
|
|
bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) { return false; } |
|
|
|
bool CCoinsView::GetStats(CCoinsStats &stats) { 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::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::SetCoins(const uint256 &txid, const CCoins &coins) { return base->SetCoins(txid, coins); } |
|
|
|
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) { return base->HaveCoins(txid); } |
|
|
|
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) { return base->HaveCoins(txid); } |
|
|
|
CBlockIndex *CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); } |
|
|
|
uint256 CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); } |
|
|
|
bool CCoinsViewBacked::SetBestBlock(CBlockIndex *pindex) { return base->SetBestBlock(pindex); } |
|
|
|
bool CCoinsViewBacked::SetBestBlock(const uint256 &hashBlock) { return base->SetBestBlock(hashBlock); } |
|
|
|
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } |
|
|
|
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); } |
|
|
|
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) { |
|
|
|
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) { |
|
|
|
if (cacheCoins.count(txid)) { |
|
|
|
if (cacheCoins.count(txid)) { |
|
|
@ -293,26 +293,26 @@ bool CCoinsViewCache::HaveCoins(const uint256 &txid) { |
|
|
|
return FetchCoins(txid) != cacheCoins.end(); |
|
|
|
return FetchCoins(txid) != cacheCoins.end(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CBlockIndex *CCoinsViewCache::GetBestBlock() { |
|
|
|
uint256 CCoinsViewCache::GetBestBlock() { |
|
|
|
if (pindexTip == NULL) |
|
|
|
if (hashBlock == uint256(0)) |
|
|
|
pindexTip = base->GetBestBlock(); |
|
|
|
hashBlock = base->GetBestBlock(); |
|
|
|
return pindexTip; |
|
|
|
return hashBlock; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CCoinsViewCache::SetBestBlock(CBlockIndex *pindex) { |
|
|
|
bool CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) { |
|
|
|
pindexTip = pindex; |
|
|
|
hashBlock = hashBlockIn; |
|
|
|
return true; |
|
|
|
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++) |
|
|
|
for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) |
|
|
|
cacheCoins[it->first] = it->second; |
|
|
|
cacheCoins[it->first] = it->second; |
|
|
|
pindexTip = pindex; |
|
|
|
hashBlock = hashBlockIn; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CCoinsViewCache::Flush() { |
|
|
|
bool CCoinsViewCache::Flush() { |
|
|
|
bool fOk = base->BatchWrite(cacheCoins, pindexTip); |
|
|
|
bool fOk = base->BatchWrite(cacheCoins, hashBlock); |
|
|
|
if (fOk) |
|
|
|
if (fOk) |
|
|
|
cacheCoins.clear(); |
|
|
|
cacheCoins.clear(); |
|
|
|
return fOk; |
|
|
|
return fOk; |
|
|
@ -1498,7 +1498,8 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach |
|
|
|
|
|
|
|
|
|
|
|
// While checking, GetBestBlock() refers to the parent block.
|
|
|
|
// While checking, GetBestBlock() refers to the parent block.
|
|
|
|
// This is also true for mempool checks.
|
|
|
|
// 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 nValueIn = 0; |
|
|
|
int64_t nFees = 0; |
|
|
|
int64_t nFees = 0; |
|
|
|
for (unsigned int i = 0; i < tx.vin.size(); i++) |
|
|
|
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) |
|
|
|
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean) |
|
|
|
{ |
|
|
|
{ |
|
|
|
assert(pindex == view.GetBestBlock()); |
|
|
|
assert(pindex->GetBlockHash() == view.GetBestBlock()); |
|
|
|
|
|
|
|
|
|
|
|
if (pfClean) |
|
|
|
if (pfClean) |
|
|
|
*pfClean = false; |
|
|
|
*pfClean = false; |
|
|
@ -1644,7 +1645,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// move best block pointer to prevout block
|
|
|
|
// move best block pointer to prevout block
|
|
|
|
view.SetBestBlock(pindex->pprev); |
|
|
|
view.SetBestBlock(pindex->pprev->GetBlockHash()); |
|
|
|
|
|
|
|
|
|
|
|
if (pfClean) { |
|
|
|
if (pfClean) { |
|
|
|
*pfClean = fClean; |
|
|
|
*pfClean = fClean; |
|
|
@ -1693,12 +1694,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
// verify that the view's current state corresponds to the previous block
|
|
|
|
// 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
|
|
|
|
// Special case for the genesis block, skipping connection of its transactions
|
|
|
|
// (its coinbase is unspendable)
|
|
|
|
// (its coinbase is unspendable)
|
|
|
|
if (block.GetHash() == Params().HashGenesisBlock()) { |
|
|
|
if (block.GetHash() == Params().HashGenesisBlock()) { |
|
|
|
view.SetBestBlock(pindex); |
|
|
|
view.SetBestBlock(pindex->GetBlockHash()); |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1828,7 +1830,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C |
|
|
|
return state.Abort(_("Failed to write transaction index")); |
|
|
|
return state.Abort(_("Failed to write transaction index")); |
|
|
|
|
|
|
|
|
|
|
|
// add this block to the view's block chain
|
|
|
|
// add this block to the view's block chain
|
|
|
|
assert(view.SetBestBlock(pindex)); |
|
|
|
assert(view.SetBestBlock(pindex->GetBlockHash())); |
|
|
|
|
|
|
|
|
|
|
|
// Watch for transactions paying to me
|
|
|
|
// Watch for transactions paying to me
|
|
|
|
for (unsigned int i = 0; i < block.vtx.size(); i++) |
|
|
|
for (unsigned int i = 0; i < block.vtx.size(); i++) |
|
|
@ -1846,7 +1848,9 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew) |
|
|
|
CCoinsViewCache view(*pcoinsTip, true); |
|
|
|
CCoinsViewCache view(*pcoinsTip, true); |
|
|
|
|
|
|
|
|
|
|
|
// Find the fork (typically, there is none)
|
|
|
|
// 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; |
|
|
|
CBlockIndex* plonger = pindexNew; |
|
|
|
while (pfork && pfork != plonger) |
|
|
|
while (pfork && pfork != plonger) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1862,7 +1866,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew) |
|
|
|
|
|
|
|
|
|
|
|
// List of what to disconnect (typically nothing)
|
|
|
|
// List of what to disconnect (typically nothing)
|
|
|
|
vector<CBlockIndex*> vDisconnect; |
|
|
|
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); |
|
|
|
vDisconnect.push_back(pindex); |
|
|
|
|
|
|
|
|
|
|
|
// List of what to connect (typically only pindexNew)
|
|
|
|
// List of what to connect (typically only pindexNew)
|
|
|
@ -2687,9 +2691,10 @@ bool static LoadBlockIndexDB() |
|
|
|
LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled"); |
|
|
|
LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled"); |
|
|
|
|
|
|
|
|
|
|
|
// Load pointer to end of best chain
|
|
|
|
// Load pointer to end of best chain
|
|
|
|
chainActive.SetTip(pcoinsTip->GetBestBlock()); |
|
|
|
std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); |
|
|
|
if (chainActive.Tip() == NULL) |
|
|
|
if (it == mapBlockIndex.end()) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
chainActive.SetTip(it->second); |
|
|
|
LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n", |
|
|
|
LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n", |
|
|
|
chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(), |
|
|
|
chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(), |
|
|
|
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str()); |
|
|
|
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str()); |
|
|
|