X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=1b56cead3c631f1cd6f657db5c5c1a2391976afc;hb=d68dcf741e088d8d7033521aa1a1e5e87d9dd283;hp=20aa069a79310042e232b064762c254fde2a3f4f;hpb=336ba312a6ddc08f40ce456bfd09f0711bdc78dc;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index 20aa069..1b56cea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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) } 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 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)