@ -168,6 +168,7 @@ bool CCoinsView::SetCoins(uint256 txid, const CCoins &coins) { return false; }
@@ -168,6 +168,7 @@ bool CCoinsView::SetCoins(uint256 txid, const CCoins &coins) { return false; }
bool CCoinsView : : HaveCoins ( 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 ; }
CCoinsViewBacked : : CCoinsViewBacked ( CCoinsView & viewIn ) : base ( & viewIn ) { }
bool CCoinsViewBacked : : GetCoins ( uint256 txid , CCoins & coins ) { return base - > GetCoins ( txid , coins ) ; }
@ -176,13 +177,7 @@ bool CCoinsViewBacked::HaveCoins(uint256 txid) { return base->HaveCoins(txid); }
@@ -176,13 +177,7 @@ bool CCoinsViewBacked::HaveCoins(uint256 txid) { return base->HaveCoins(txid); }
CBlockIndex * CCoinsViewBacked : : GetBestBlock ( ) { return base - > GetBestBlock ( ) ; }
bool CCoinsViewBacked : : SetBestBlock ( CBlockIndex * pindex ) { return base - > SetBestBlock ( pindex ) ; }
void CCoinsViewBacked : : SetBackend ( CCoinsView & viewIn ) { base = & viewIn ; }
CCoinsViewDB : : CCoinsViewDB ( CCoinsDB & dbIn ) : db ( dbIn ) { }
bool CCoinsViewDB : : GetCoins ( uint256 txid , CCoins & coins ) { return db . ReadCoins ( txid , coins ) ; }
bool CCoinsViewDB : : SetCoins ( uint256 txid , const CCoins & coins ) { return db . WriteCoins ( txid , coins ) ; }
bool CCoinsViewDB : : HaveCoins ( uint256 txid ) { return db . HaveCoins ( txid ) ; }
CBlockIndex * CCoinsViewDB : : GetBestBlock ( ) { return pindexBest ; }
bool CCoinsViewDB : : SetBestBlock ( CBlockIndex * pindex ) { return db . WriteHashBestChain ( pindex - > GetBlockHash ( ) ) ; }
bool CCoinsViewBacked : : BatchWrite ( const std : : map < uint256 , CCoins > & mapCoins , CBlockIndex * pindex ) { return base - > BatchWrite ( mapCoins , pindex ) ; }
CCoinsViewCache : : CCoinsViewCache ( CCoinsView & baseIn , bool fDummy ) : CCoinsViewBacked ( baseIn ) , pindexTip ( NULL ) { }
@ -218,16 +213,22 @@ bool CCoinsViewCache::SetBestBlock(CBlockIndex *pindex) {
@@ -218,16 +213,22 @@ bool CCoinsViewCache::SetBestBlock(CBlockIndex *pindex) {
return true ;
}
bool CCoinsViewCache : : BatchWrite ( const std : : map < uint256 , CCoins > & mapCoins , CBlockIndex * pindex ) {
for ( std : : map < uint256 , CCoins > : : const_iterator it = mapCoins . begin ( ) ; it ! = mapCoins . end ( ) ; it + + )
cacheCoins [ it - > first ] = it - > second ;
pindexTip = pindex ;
return true ;
}
bool CCoinsViewCache : : Flush ( ) {
for ( std : : map < uint256 , CCoins > : : iterator it = cacheCoins . begin ( ) ; it ! = cacheCoins . end ( ) ; it + + ) {
if ( ! base - > SetCoins ( it - > first , it - > second ) )
return false ;
}
if ( ! base - > SetBestBlock ( pindexTip ) )
return false ;
bool fOk = base - > BatchWrite ( cacheCoins , pindexTip ) ;
if ( fOk )
cacheCoins . clear ( ) ;
pindexTip = NULL ;
return true ;
return fOk ;
}
unsigned int CCoinsViewCache : : GetCacheSize ( ) {
return cacheCoins . size ( ) ;
}
/** CCoinsView that brings transactions from a memorypool into view.
@ -249,7 +250,7 @@ bool CCoinsViewMemPool::HaveCoins(uint256 txid) {
@@ -249,7 +250,7 @@ bool CCoinsViewMemPool::HaveCoins(uint256 txid) {
return mempool . exists ( txid ) | | base - > HaveCoins ( txid ) ;
}
CCoinsViewCache * pcoinsTip = NULL ;
//////////////////////////////////////////////////////////////////////////////
//
@ -450,9 +451,8 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
@@ -450,9 +451,8 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
CBlock blockTmp ;
if ( pblock = = NULL ) {
CCoinsDB coinsdb ( " r " ) ;
CCoins coins ;
if ( coinsdb . Read Coins( GetHash ( ) , coins ) ) {
if ( pcoinsTip - > Get Coins( GetHash ( ) , coins ) ) {
CBlockIndex * pindex = FindBlockByHeight ( coins . nHeight ) ;
if ( pindex ) {
if ( ! blockTmp . ReadFromDisk ( pindex ) )
@ -609,7 +609,7 @@ void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
@@ -609,7 +609,7 @@ void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
}
}
bool CTxMemPool : : accept ( CCoinsDB & coinsdb , C Transaction & tx , bool fCheckInputs ,
bool CTxMemPool : : accept ( CTransaction & tx , bool fCheckInputs ,
bool * pfMissingInputs )
{
if ( pfMissingInputs )
@ -668,9 +668,7 @@ bool CTxMemPool::accept(CCoinsDB& coinsdb, CTransaction &tx, bool fCheckInputs,
@@ -668,9 +668,7 @@ bool CTxMemPool::accept(CCoinsDB& coinsdb, CTransaction &tx, bool fCheckInputs,
if ( fCheckInputs )
{
CCoinsViewDB viewDB ( coinsdb ) ;
CCoinsViewMemPool viewMemPool ( viewDB , mempool ) ;
CCoinsViewCache view ( viewMemPool ) ;
CCoinsViewCache & view = * pcoinsTip ;
// do we already have it?
if ( view . HaveCoins ( hash ) )
@ -758,9 +756,9 @@ bool CTxMemPool::accept(CCoinsDB& coinsdb, CTransaction &tx, bool fCheckInputs,
@@ -758,9 +756,9 @@ bool CTxMemPool::accept(CCoinsDB& coinsdb, CTransaction &tx, bool fCheckInputs,
return true ;
}
bool CTransaction : : AcceptToMemoryPool ( CCoinsDB & coinsdb , bool fCheckInputs , bool * pfMissingInputs )
bool CTransaction : : AcceptToMemoryPool ( bool fCheckInputs , bool * pfMissingInputs )
{
return mempool . accept ( coinsdb , * this , fCheckInputs , pfMissingInputs ) ;
return mempool . accept ( * this , fCheckInputs , pfMissingInputs ) ;
}
bool CTxMemPool : : addUnchecked ( const uint256 & hash , CTransaction & tx )
@ -849,31 +847,24 @@ int CMerkleTx::GetBlocksToMaturity() const
@@ -849,31 +847,24 @@ int CMerkleTx::GetBlocksToMaturity() const
}
bool CMerkleTx : : AcceptToMemoryPool ( CCoinsDB & coinsdb , bool fCheckInputs )
bool CMerkleTx : : AcceptToMemoryPool ( bool fCheckInputs )
{
if ( fClient )
{
if ( ! IsInMainChain ( ) & & ! ClientCheckInputs ( ) )
return false ;
return CTransaction : : AcceptToMemoryPool ( coinsdb , false ) ;
return CTransaction : : AcceptToMemoryPool ( false ) ;
}
else
{
return CTransaction : : AcceptToMemoryPool ( coinsdb , fCheckInputs ) ;
return CTransaction : : AcceptToMemoryPool ( fCheckInputs ) ;
}
}
bool CMerkleTx : : AcceptToMemoryPool ( )
{
CCoinsDB coinsdb ( " r " ) ;
return AcceptToMemoryPool ( coinsdb ) ;
}
bool CWalletTx : : AcceptWalletTransaction ( CCoinsDB & coinsdb , bool fCheckInputs )
bool CWalletTx : : AcceptWalletTransaction ( bool fCheckInputs )
{
{
LOCK ( mempool . cs ) ;
// Add previous supporting transactions first
@ -882,20 +873,15 @@ bool CWalletTx::AcceptWalletTransaction(CCoinsDB& coinsdb, bool fCheckInputs)
@@ -882,20 +873,15 @@ bool CWalletTx::AcceptWalletTransaction(CCoinsDB& coinsdb, bool fCheckInputs)
if ( ! tx . IsCoinBase ( ) )
{
uint256 hash = tx . GetHash ( ) ;
if ( ! mempool . exists ( hash ) & & ! coinsdb . HaveCoins ( hash ) )
tx . AcceptToMemoryPool ( coinsdb , fCheckInputs ) ;
if ( ! mempool . exists ( hash ) & & pcoinsTip - > HaveCoins ( hash ) )
tx . AcceptToMemoryPool ( fCheckInputs ) ;
}
}
return AcceptToMemoryPool ( coinsdb , fCheckInputs ) ;
return AcceptToMemoryPool ( fCheckInputs ) ;
}
return false ;
}
bool CWalletTx : : AcceptWalletTransaction ( )
{
CCoinsDB coinsdb ( " r " ) ;
return AcceptWalletTransaction ( coinsdb ) ;
}
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
bool GetTransaction ( const uint256 & hash , CTransaction & txOut , uint256 & hashBlock , bool fAllowSlow )
@ -915,8 +901,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
@@ -915,8 +901,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
if ( fAllowSlow ) { // use coin database to locate block that contains transaction, and scan it
int nHeight = - 1 ;
{
CCoinsDB coindb ( " r " ) ;
CCoinsViewDB view ( coindb ) ;
CCoinsViewCache & view = * pcoinsTip ;
CCoins coins ;
if ( view . GetCoins ( hash , coins ) )
nHeight = coins . nHeight ;
@ -1565,18 +1550,15 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsView &view, bool fJustCheck
@@ -1565,18 +1550,15 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsView &view, bool fJustCheck
bool CBlock : : SetBestChain ( CBlockIndex * pindexNew )
{
// if this functions exits prematurely, the transaction is aborted
CCoinsDB coinsdb ;
if ( ! coinsdb . TxnBegin ( ) )
return error ( " SetBestChain() : TxnBegin failed " ) ;
CCoinsViewCache & view = * pcoinsTip ;
// special case for attaching the genesis block
// note that no ConnectBlock is called, so its coinbase output is non-spendable
if ( pindexGenesisBlock = = NULL & & pindexNew - > GetBlockHash ( ) = = hashGenesisBlock )
{
coinsdb . WriteHashBestChain ( pindexNew - > GetBlockHash ( ) ) ;
if ( ! coinsdb . TxnCommit ( ) )
return error ( " SetBestChain() : TxnCommit failed " ) ;
view . SetBestBlock ( pindexNew ) ;
if ( ! view . Flush ( ) )
return false ;
pindexGenesisBlock = pindexNew ;
pindexBest = pindexNew ;
hashBestChain = pindexNew - > GetBlockHash ( ) ;
@ -1585,10 +1567,6 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
@@ -1585,10 +1567,6 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
return true ;
}
// create cached view to the coins database
CCoinsViewDB viewDB ( coinsdb ) ;
CCoinsViewCache view ( viewDB ) ;
// Find the fork (typically, there is none)
CBlockIndex * pfork = view . GetBestBlock ( ) ;
CBlockIndex * plonger = pindexNew ;
@ -1625,8 +1603,11 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
@@ -1625,8 +1603,11 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
CBlock block ;
if ( ! block . ReadFromDisk ( pindex ) )
return error ( " SetBestBlock() : ReadFromDisk for disconnect failed " ) ;
if ( ! block . DisconnectBlock ( pindex , view ) )
CCoinsViewCache viewTemp ( view , true ) ;
if ( ! block . DisconnectBlock ( pindex , viewTemp ) )
return error ( " SetBestBlock() : DisconnectBlock % s failed " , pindex->GetBlockHash().ToString().substr(0,20).c_str()) ;
if ( ! viewTemp . Flush ( ) )
return error ( " SetBestBlock() : Cache flush failed after disconnect " ) ;
// Queue memory transactions to resurrect
BOOST_FOREACH ( const CTransaction & tx , block . vtx )
@ -1646,10 +1627,13 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
@@ -1646,10 +1627,13 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
return error ( " SetBestBlock() : ReadFromDisk for connect failed " ) ;
pblock = & block ;
}
if ( ! pblock - > ConnectBlock ( pindex , view ) ) {
CCoinsViewCache viewTemp ( view , true ) ;
if ( ! pblock - > ConnectBlock ( pindex , viewTemp ) ) {
InvalidChainFound ( pindexNew ) ;
return error ( " SetBestBlock() : ConnectBlock % s failed " , pindex->GetBlockHash().ToString().substr(0,20).c_str()) ;
}
if ( ! viewTemp . Flush ( ) )
return error ( " SetBestBlock() : Cache flush failed after connect " ) ;
// Queue memory transactions to delete
BOOST_FOREACH ( const CTransaction & tx , pblock - > vtx )
@ -1657,11 +1641,10 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
@@ -1657,11 +1641,10 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
}
// Make sure it's successfully written to disk before changing memory structure
bool fIsInitialDownload = IsInitialBlockDownload ( ) ;
if ( ! fIsInitialDownload | | view . GetCacheSize ( ) > 5000 )
if ( ! view . Flush ( ) )
return error ( " SetBestBlock() : failed to write coin changes " ) ;
if ( ! coinsdb . TxnCommit ( ) )
return error ( " SetBestBlock() : TxnCommit failed " ) ;
coinsdb . Close ( ) ;
return false ;
// At this point, all changes have been done to the database.
// Proceed by updating the memory structures.
@ -1678,14 +1661,13 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
@@ -1678,14 +1661,13 @@ bool CBlock::SetBestChain(CBlockIndex* pindexNew)
// Resurrect memory transactions that were in the disconnected branch
BOOST_FOREACH ( CTransaction & tx , vResurrect )
tx . AcceptToMemoryPool ( coinsdb , false ) ;
tx . AcceptToMemoryPool ( false ) ;
// Delete redundant memory transactions that are in the connected branch
BOOST_FOREACH ( CTransaction & tx , vDelete )
mempool . remove ( tx ) ;
// Update best block in wallet (so we can detect restored wallets)
bool fIsInitialDownload = IsInitialBlockDownload ( ) ;
if ( ! fIsInitialDownload )
{
const CBlockLocator locator ( pindexNew ) ;
@ -1765,11 +1747,8 @@ bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos)
@@ -1765,11 +1747,8 @@ bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos)
return false ;
// New best
if ( pindexNew - > bnChainWork > bnBestChainWork ) {
if ( ! IsInitialBlockDownload ( ) | | ( pindexNew - > nHeight % 1 ) = = 0 )
if ( ! SetBestChain ( pindexNew ) )
return false ;
}
if ( pindexNew = = pindexBest )
{
@ -2169,11 +2148,9 @@ bool LoadBlockIndex(bool fAllowNew)
@@ -2169,11 +2148,9 @@ bool LoadBlockIndex(bool fAllowNew)
// Load block index
//
CChainDB chaindb ( " cr " ) ;
CCoinsDB coinsdb ( " cr " ) ;
if ( ! LoadBlockIndex ( coinsdb , chaindb ) )
if ( ! LoadBlockIndex ( chaindb ) )
return false ;
chaindb . Close ( ) ;
coinsdb . Close ( ) ;
//
// Init with genesis block
@ -2492,7 +2469,7 @@ string GetWarnings(string strFor)
@@ -2492,7 +2469,7 @@ string GetWarnings(string strFor)
//
bool static AlreadyHave ( CCoinsDB & coinsdb , const CInv & inv )
bool static AlreadyHave ( const CInv & inv )
{
switch ( inv . type )
{
@ -2504,7 +2481,7 @@ bool static AlreadyHave(CCoinsDB &coinsdb, const CInv& inv)
@@ -2504,7 +2481,7 @@ bool static AlreadyHave(CCoinsDB &coinsdb, const CInv& inv)
txInMap = mempool . exists ( inv . hash ) ;
}
return txInMap | | mapOrphanTransactions . count ( inv . hash ) | |
coinsdb . HaveCoins ( inv . hash ) ;
pcoinsTip - > HaveCoins ( inv . hash ) ;
}
case MSG_BLOCK :
return mapBlockIndex . count ( inv . hash ) | |
@ -2748,7 +2725,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
@@ -2748,7 +2725,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
break ;
}
}
CCoinsDB coinsdb ( " r " ) ;
for ( unsigned int nInv = 0 ; nInv < vInv . size ( ) ; nInv + + )
{
const CInv & inv = vInv [ nInv ] ;
@ -2757,7 +2733,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
@@ -2757,7 +2733,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return true ;
pfrom - > AddInventoryKnown ( inv ) ;
bool fAlreadyHave = AlreadyHave ( coinsdb , inv ) ;
bool fAlreadyHave = AlreadyHave ( inv ) ;
if ( fDebug )
printf ( " got inventory: %s %s \n " , inv . ToString ( ) . c_str ( ) , fAlreadyHave ? " have " : " new " ) ;
@ -2929,7 +2905,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
@@ -2929,7 +2905,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vector < uint256 > vWorkQueue ;
vector < uint256 > vEraseQueue ;
CDataStream vMsg ( vRecv ) ;
CCoinsDB coinsdb ( " r " ) ;
CTransaction tx ;
vRecv > > tx ;
@ -2937,7 +2912,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
@@ -2937,7 +2912,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom - > AddInventoryKnown ( inv ) ;
bool fMissingInputs = false ;
if ( tx . AcceptToMemoryPool ( coinsdb , true , & fMissingInputs ) )
if ( tx . AcceptToMemoryPool ( true , & fMissingInputs ) )
{
SyncWithWallets ( tx , NULL , true ) ;
RelayMessage ( inv , vMsg ) ;
@ -2959,7 +2934,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
@@ -2959,7 +2934,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CInv inv ( MSG_TX , tx . GetHash ( ) ) ;
bool fMissingInputs2 = false ;
if ( tx . AcceptToMemoryPool ( coinsdb , true , & fMissingInputs2 ) )
if ( tx . AcceptToMemoryPool ( true , & fMissingInputs2 ) )
{
printf ( " accepted orphan tx %s \n " , inv . hash . ToString ( ) . substr ( 0 , 10 ) . c_str ( ) ) ;
SyncWithWallets ( tx , NULL , true ) ;
@ -3407,11 +3382,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
@@ -3407,11 +3382,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
//
vector < CInv > vGetData ;
int64 nNow = GetTime ( ) * 1000000 ;
CCoinsDB coinsdb ( " r " ) ;
while ( ! pto - > mapAskFor . empty ( ) & & ( * pto - > mapAskFor . begin ( ) ) . first < = nNow )
{
const CInv & inv = ( * pto - > mapAskFor . begin ( ) ) . second ;
if ( ! AlreadyHave ( coinsdb , inv ) )
if ( ! AlreadyHave ( inv ) )
{
if ( fDebugNet )
printf ( " sending getdata: %s \n " , inv . ToString ( ) . c_str ( ) ) ;
@ -3621,9 +3595,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
@@ -3621,9 +3595,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
int64 nFees = 0 ;
{
LOCK2 ( cs_main , mempool . cs ) ;
CCoinsDB coinsdb ( " r " ) ;
CCoinsViewDB viewdb ( coinsdb ) ;
CCoinsViewCache view ( viewdb ) ;
CCoinsViewCache view ( * pcoinsTip , true ) ;
// Priority order to process transactions
list < COrphan > vOrphan ; // list memory doesn't move
@ -3811,7 +3783,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
@@ -3811,7 +3783,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
CBlockIndex indexDummy ( * pblock ) ;
indexDummy . pprev = pindexPrev ;
indexDummy . nHeight = pindexPrev - > nHeight + 1 ;
CCoinsViewCache viewNew ( viewdb ) ;
CCoinsViewCache viewNew ( * pcoinsTip , true ) ;
if ( ! pblock - > ConnectBlock ( & indexDummy , viewNew , true ) )
throw std : : runtime_error ( " CreateNewBlock() : ConnectBlock failed " ) ;
}