@ -1457,6 +1457,32 @@ runCommand(std::string strCommand)
printf ( " runCommand error: system(%s) returned %d \n " , strCommand . c_str ( ) , nErr ) ;
printf ( " runCommand error: system(%s) returned %d \n " , strCommand . c_str ( ) , nErr ) ;
}
}
bool CBlock : : SetBestChainInner ( CTxDB & txdb , CBlockIndex * pindexNew )
{
assert ( pindexNew - > pprev = = pindexBest ) ;
uint256 hash = GetHash ( ) ;
// Adding to current best branch
if ( ! ConnectBlock ( txdb , pindexNew ) | | ! txdb . WriteHashBestChain ( hash ) )
{
txdb . TxnAbort ( ) ;
InvalidChainFound ( pindexNew ) ;
return false ;
}
if ( ! txdb . TxnCommit ( ) )
return error ( " SetBestChain() : TxnCommit failed " ) ;
// Add to current best branch
pindexNew - > pprev - > pnext = pindexNew ;
// Delete redundant memory transactions
BOOST_FOREACH ( CTransaction & tx , vtx )
tx . RemoveFromMemoryPool ( ) ;
return true ;
}
bool CBlock : : SetBestChain ( CTxDB & txdb , CBlockIndex * pindexNew )
bool CBlock : : SetBestChain ( CTxDB & txdb , CBlockIndex * pindexNew )
{
{
uint256 hash = GetHash ( ) ;
uint256 hash = GetHash ( ) ;
@ -1471,32 +1497,50 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
}
}
else if ( hashPrevBlock = = hashBestChain )
else if ( hashPrevBlock = = hashBestChain )
{
{
// Adding to current best branch
if ( ! SetBestChainInner ( txdb , pindexNew ) )
if ( ! ConnectBlock ( txdb , pindexNew ) | | ! txdb . WriteHashBestChain ( hash ) )
return error ( " SetBestChain() : SetBestChainInner failed " ) ;
}
else
{
// the first block in the new chain that will cause it to become the new best chain
CBlockIndex * pindexIntermediate = pindexNew ;
// list of blocks that need to be connected afterwards
std : : vector < CBlockIndex * > vpindexSecondary ;
// Reorganize is costly in terms of db load, as it works in a single db transaction.
// Try to limit how much needs to be done inside
while ( pindexIntermediate - > pprev & & pindexIntermediate - > pprev - > bnChainWork > pindexBest - > bnChainWork )
{
{
txdb . TxnAbort ( ) ;
vpindexSecondary . push_back ( pindexIntermediate ) ;
InvalidChainFound ( pindexNew ) ;
pindexIntermediate = pindexIntermediate - > pprev ;
return error ( " SetBestChain() : ConnectBlock failed " ) ;
}
}
if ( ! txdb . TxnCommit ( ) )
return error ( " SetBestChain() : TxnCommit failed " ) ;
// Add to current best branch
if ( ! vpindexSecondary . empty ( ) )
pindexNew - > pprev - > pnext = pindexNew ;
printf ( " Postponing %i reconnects \n " , vpindexSecondary . size ( ) ) ;
// Delete redundant memory transactions
// Switch to new best branch
BOOST_FOREACH ( CTransaction & tx , vtx )
if ( ! Reorganize ( txdb , pindexIntermediate ) )
tx . RemoveFromMemoryPool ( ) ;
}
else
{
// New best branch
if ( ! Reorganize ( txdb , pindexNew ) )
{
{
txdb . TxnAbort ( ) ;
txdb . TxnAbort ( ) ;
InvalidChainFound ( pindexNew ) ;
InvalidChainFound ( pindexNew ) ;
return error ( " SetBestChain() : Reorganize failed " ) ;
return error ( " SetBestChain() : Reorganize failed " ) ;
}
}
// Connect futher blocks
BOOST_REVERSE_FOREACH ( CBlockIndex * pindex , vpindexSecondary )
{
CBlock block ;
if ( ! block . ReadFromDisk ( pindex ) )
{
printf ( " SetBestChain() : ReadFromDisk failed \n " ) ;
break ;
}
txdb . TxnBegin ( ) ;
// errors now are not fatal, we still did a reorganisation to a new chain in a valid way
if ( ! block . SetBestChainInner ( txdb , pindex ) )
break ;
}
}
}
// Update best block in wallet (so we can detect restored wallets)
// Update best block in wallet (so we can detect restored wallets)