|
|
|
@ -1457,6 +1457,32 @@ runCommand(std::string strCommand)
@@ -1457,6 +1457,32 @@ runCommand(std::string strCommand)
|
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
uint256 hash = GetHash(); |
|
|
|
@ -1471,32 +1497,50 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
@@ -1471,32 +1497,50 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
|
|
|
|
} |
|
|
|
|
else if (hashPrevBlock == hashBestChain) |
|
|
|
|
{ |
|
|
|
|
// Adding to current best branch
|
|
|
|
|
if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash)) |
|
|
|
|
if (!SetBestChainInner(txdb, pindexNew)) |
|
|
|
|
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(); |
|
|
|
|
InvalidChainFound(pindexNew); |
|
|
|
|
return error("SetBestChain() : ConnectBlock failed"); |
|
|
|
|
vpindexSecondary.push_back(pindexIntermediate); |
|
|
|
|
pindexIntermediate = pindexIntermediate->pprev; |
|
|
|
|
} |
|
|
|
|
if (!txdb.TxnCommit()) |
|
|
|
|
return error("SetBestChain() : TxnCommit failed"); |
|
|
|
|
|
|
|
|
|
// Add to current best branch
|
|
|
|
|
pindexNew->pprev->pnext = pindexNew; |
|
|
|
|
if (!vpindexSecondary.empty()) |
|
|
|
|
printf("Postponing %i reconnects\n", vpindexSecondary.size()); |
|
|
|
|
|
|
|
|
|
// Delete redundant memory transactions
|
|
|
|
|
BOOST_FOREACH(CTransaction& tx, vtx) |
|
|
|
|
tx.RemoveFromMemoryPool(); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// New best branch
|
|
|
|
|
if (!Reorganize(txdb, pindexNew)) |
|
|
|
|
// Switch to new best branch
|
|
|
|
|
if (!Reorganize(txdb, pindexIntermediate)) |
|
|
|
|
{ |
|
|
|
|
txdb.TxnAbort(); |
|
|
|
|
InvalidChainFound(pindexNew); |
|
|
|
|
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)
|
|
|
|
|