aboutsummaryrefslogtreecommitdiff
path: root/src/validation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/validation.cpp')
-rw-r--r--src/validation.cpp226
1 files changed, 120 insertions, 106 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index 4a6c4066f..1b9e98275 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -16,6 +16,7 @@
#include <consensus/validation.h>
#include <cuckoocache.h>
#include <hash.h>
+#include <index/txindex.h>
#include <init.h>
#include <policy/fees.h>
#include <policy/policy.h>
@@ -142,7 +143,7 @@ private:
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
* instead of putting things in this set.
*/
- std::set<CBlockIndex*> g_failed_blocks;
+ std::set<CBlockIndex*> m_failed_blocks;
public:
CChain chainActive;
@@ -154,6 +155,10 @@ public:
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock);
+ /**
+ * If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
+ * that it doesn't descend from an invalid block, and then add it to mapBlockIndex.
+ */
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex);
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock);
@@ -185,6 +190,11 @@ private:
CBlockIndex* AddToBlockIndex(const CBlockHeader& block);
/** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex(const uint256& hash);
+ /**
+ * Make various assertions about the state of the block index.
+ *
+ * By default this only executes fully when using the Regtest chain; see: fCheckBlockIndex.
+ */
void CheckBlockIndex(const Consensus::Params& consensusParams);
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state);
@@ -202,12 +212,12 @@ CCriticalSection cs_main;
BlockMap& mapBlockIndex = g_chainstate.mapBlockIndex;
CChain& chainActive = g_chainstate.chainActive;
CBlockIndex *pindexBestHeader = nullptr;
-CWaitableCriticalSection csBestBlock;
-CConditionVariable cvBlockChange;
+CWaitableCriticalSection g_best_block_mutex;
+CConditionVariable g_best_block_cv;
+uint256 g_best_block;
int nScriptCheckThreads = 0;
std::atomic_bool fImporting(false);
std::atomic_bool fReindex(false);
-bool fTxIndex = false;
bool fHavePruned = false;
bool fPruneMode = false;
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
@@ -263,7 +273,8 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
{
AssertLockHeld(cs_main);
- // Find the first block the caller has in the main chain
+ // Find the latest block common to locator and chain - we expect that
+ // locator.vHave is sorted descending by height.
for (const uint256& hash : locator.vHave) {
CBlockIndex* pindex = LookupBlockIndex(hash);
if (pindex) {
@@ -352,7 +363,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
CBlockIndex* tip = chainActive.Tip();
assert(tip != nullptr);
-
+
CBlockIndex index;
index.pprev = tip;
// CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
@@ -718,7 +729,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// No transactions are allowed below minRelayTxFee except from disconnected blocks
if (!bypass_limits && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) {
- return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met");
+ return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met", false, strprintf("%d < %d", nModifiedFees, ::minRelayTxFee.GetFee(nSize)));
}
if (nAbsurdFee && nFees > nAbsurdFee)
@@ -1017,28 +1028,8 @@ bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus
return true;
}
- if (fTxIndex) {
- CDiskTxPos postx;
- if (pblocktree->ReadTxIndex(hash, postx)) {
- CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
- if (file.IsNull())
- return error("%s: OpenBlockFile failed", __func__);
- CBlockHeader header;
- try {
- file >> header;
- fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
- file >> txOut;
- } catch (const std::exception& e) {
- return error("%s: Deserialize or I/O error - %s", __func__, e.what());
- }
- hashBlock = header.GetHash();
- if (txOut->GetHash() != hash)
- return error("%s: txid mismatch", __func__);
- return true;
- }
-
- // transaction not found in index, nothing more can be done
- return false;
+ if (g_txindex) {
+ return g_txindex->FindTx(hash, hashBlock, txOut);
}
if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it
@@ -1284,7 +1275,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
void CChainState::InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) {
if (!state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
- g_failed_blocks.insert(pindex);
+ m_failed_blocks.insert(pindex);
setDirtyBlockIndex.insert(pindex);
setBlockIndexCandidates.erase(pindex);
InvalidChainFound(pindex);
@@ -1613,22 +1604,27 @@ void static FlushBlockFile(bool fFinalize = false)
LOCK(cs_LastBlockFile);
CDiskBlockPos posOld(nLastBlockFile, 0);
+ bool status = true;
FILE *fileOld = OpenBlockFile(posOld);
if (fileOld) {
if (fFinalize)
- TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize);
- FileCommit(fileOld);
+ status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize);
+ status &= FileCommit(fileOld);
fclose(fileOld);
}
fileOld = OpenUndoFile(posOld);
if (fileOld) {
if (fFinalize)
- TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize);
- FileCommit(fileOld);
+ status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize);
+ status &= FileCommit(fileOld);
fclose(fileOld);
}
+
+ if (!status) {
+ AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error.");
+ }
}
static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
@@ -1652,26 +1648,6 @@ static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState&
return true;
}
-static bool WriteTxIndexDataForBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex)
-{
- if (!fTxIndex) return true;
-
- CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
- std::vector<std::pair<uint256, CDiskTxPos> > vPos;
- vPos.reserve(block.vtx.size());
- for (const CTransactionRef& tx : block.vtx)
- {
- vPos.push_back(std::make_pair(tx->GetHash(), pos));
- pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION);
- }
-
- if (!pblocktree->WriteTxIndex(vPos)) {
- return AbortNode(state, "Failed to write transaction index");
- }
-
- return true;
-}
-
static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
void ThreadScriptCheck() {
@@ -1724,16 +1700,38 @@ public:
// Protected by cs_main
static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS];
+// 0.13.0 was shipped with a segwit deployment defined for testnet, but not for
+// mainnet. We no longer need to support disabling the segwit deployment
+// except for testing purposes, due to limitations of the functional test
+// environment. See test/functional/p2p-segwit.py.
+static bool IsScriptWitnessEnabled(const Consensus::Params& params)
+{
+ return params.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0;
+}
+
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) {
AssertLockHeld(cs_main);
unsigned int flags = SCRIPT_VERIFY_NONE;
- // Start enforcing P2SH (BIP16)
- if (pindex->nHeight >= consensusparams.BIP16Height) {
+ // BIP16 didn't become active until Apr 1 2012 (on mainnet, and
+ // retroactively applied to testnet)
+ // However, only one historical block violated the P2SH rules (on both
+ // mainnet and testnet), so for simplicity, always leave P2SH
+ // on except for the one violating block.
+ if (consensusparams.BIP16Exception.IsNull() || // no bip16 exception on this chain
+ pindex->phashBlock == nullptr || // this is a new candidate block, eg from TestBlockValidity()
+ *pindex->phashBlock != consensusparams.BIP16Exception) // this block isn't the historical exception
+ {
flags |= SCRIPT_VERIFY_P2SH;
}
+ // Enforce WITNESS rules whenever P2SH is in effect (and the segwit
+ // deployment is defined).
+ if (flags & SCRIPT_VERIFY_P2SH && IsScriptWitnessEnabled(consensusparams)) {
+ flags |= SCRIPT_VERIFY_WITNESS;
+ }
+
// Start enforcing the DERSIG (BIP66) rule
if (pindex->nHeight >= consensusparams.BIP66Height) {
flags |= SCRIPT_VERIFY_DERSIG;
@@ -1749,9 +1747,7 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
}
- // Start enforcing WITNESS rules using versionbits logic.
- if (IsWitnessEnabled(pindex->pprev, consensusparams)) {
- flags |= SCRIPT_VERIFY_WITNESS;
+ if (IsNullDummyEnabled(pindex->pprev, consensusparams)) {
flags |= SCRIPT_VERIFY_NULLDUMMY;
}
@@ -2043,9 +2039,6 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
setDirtyBlockIndex.insert(pindex);
}
- if (!WriteTxIndexDataForBlock(block, state, pindex))
- return false;
-
assert(pindex->phashBlock);
// add this block to the view's block chain
view.SetBestBlock(pindex->GetBlockHash());
@@ -2064,19 +2057,21 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
* The caches and indexes are flushed depending on the mode we're called with
* if they're too large, if it's been a while since the last write,
* or always and in all cases if we're in prune mode and are deleting files.
+ *
+ * If FlushStateMode::NONE is used, then FlushStateToDisk(...) won't do anything
+ * besides checking if we need to prune.
*/
bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight) {
int64_t nMempoolUsage = mempool.DynamicMemoryUsage();
LOCK(cs_main);
static int64_t nLastWrite = 0;
static int64_t nLastFlush = 0;
- static int64_t nLastSetChain = 0;
std::set<int> setFilesToPrune;
- bool fFlushForPrune = false;
- bool fDoFullFlush = false;
- int64_t nNow = 0;
+ bool full_flush_completed = false;
try {
{
+ bool fFlushForPrune = false;
+ bool fDoFullFlush = false;
LOCK(cs_LastBlockFile);
if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) {
if (nManualPruneHeight > 0) {
@@ -2093,7 +2088,7 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
}
}
}
- nNow = GetTimeMicros();
+ int64_t nNow = GetTimeMicros();
// Avoid writing/flushing immediately after startup.
if (nLastWrite == 0) {
nLastWrite = nNow;
@@ -2101,9 +2096,6 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
if (nLastFlush == 0) {
nLastFlush = nNow;
}
- if (nLastSetChain == 0) {
- nLastSetChain = nNow;
- }
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
int64_t cacheSize = pcoinsTip->DynamicMemoryUsage();
int64_t nTotalSpace = nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0);
@@ -2160,12 +2152,12 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
if (!pcoinsTip->Flush())
return AbortNode(state, "Failed to write to coin database");
nLastFlush = nNow;
+ full_flush_completed = true;
}
}
- if (fDoFullFlush || ((mode == FlushStateMode::ALWAYS || mode == FlushStateMode::PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000)) {
+ if (full_flush_completed) {
// Update best block in wallet (so we can detect restored wallets).
- GetMainSignals().SetBestChain(chainActive.GetLocator());
- nLastSetChain = nNow;
+ GetMainSignals().ChainStateFlushed(chainActive.GetLocator());
}
} catch (const std::runtime_error& e) {
return AbortNode(state, std::string("System error while flushing: ") + e.what());
@@ -2176,14 +2168,18 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
void FlushStateToDisk() {
CValidationState state;
const CChainParams& chainparams = Params();
- FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS);
+ if (!FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS)) {
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ }
}
void PruneAndFlush() {
CValidationState state;
fCheckForPruning = true;
const CChainParams& chainparams = Params();
- FlushStateToDisk(chainparams, state, FlushStateMode::NONE);
+ if (!FlushStateToDisk(chainparams, state, FlushStateMode::NONE)) {
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ }
}
static void DoWarning(const std::string& strWarning)
@@ -2201,7 +2197,11 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
// New best block
mempool.AddTransactionsUpdated(1);
- cvBlockChange.notify_all();
+ {
+ WaitableLock lock(g_best_block_mutex);
+ g_best_block = pindexNew->GetBlockHash();
+ g_best_block_cv.notify_all();
+ }
std::vector<std::string> warningMessages;
if (!IsInitialBlockDownload())
@@ -2616,6 +2616,10 @@ static void NotifyHeaderTip() {
* Make the best chain active, in multiple steps. The result is either failure
* or an activated best chain. pblock is either nullptr or a pointer to a block
* that is already loaded (to avoid loading it again from disk).
+ *
+ * ActivateBestChain is split into steps (see ActivateBestChainStep) so that
+ * we avoid holding cs_main for an extended period of time; the length of this
+ * call may be quite long during reindexing or a substantial reorg.
*/
bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) {
// Note that while we're often called here from ProcessNewBlock, this is
@@ -2669,18 +2673,17 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
assert(trace.pblock && trace.pindex);
GetMainSignals().BlockConnected(trace.pblock, trace.pindex, trace.conflictedTxs);
}
- }
- // When we reach this point, we switched to a new tip (stored in pindexNewTip).
-
- // Notifications/callbacks that can run without cs_main
- // Notify external listeners about the new tip.
- GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
+ // Notify external listeners about the new tip.
+ // Enqueue while holding cs_main to ensure that UpdatedBlockTip is called in the order in which blocks are connected
+ GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
- // Always notify the UI if a new block tip was connected
- if (pindexFork != pindexNewTip) {
- uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
+ // Always notify the UI if a new block tip was connected
+ if (pindexFork != pindexNewTip) {
+ uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
+ }
}
+ // When we reach this point, we switched to a new tip (stored in pindexNewTip).
if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown();
@@ -2775,7 +2778,7 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
setBlockIndexCandidates.erase(pindex);
- g_failed_blocks.insert(pindex);
+ m_failed_blocks.insert(pindex);
// DisconnectTip will add transactions to disconnectpool; try to add these
// back to the mempool.
@@ -2821,7 +2824,7 @@ bool CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
// Reset invalid block marker if it was pointing to one of those.
pindexBestInvalid = nullptr;
}
- g_failed_blocks.erase(it->second);
+ m_failed_blocks.erase(it->second);
}
it++;
}
@@ -3091,6 +3094,12 @@ bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& pa
return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == ThresholdState::ACTIVE);
}
+bool IsNullDummyEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
+{
+ LOCK(cs_main);
+ return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == ThresholdState::ACTIVE);
+}
+
// Compute at which vout of the block's coinbase transaction the witness
// commitment occurs, or -1 if not found.
static int GetWitnessCommitmentIndex(const CBlock& block)
@@ -3314,8 +3323,11 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
+ // If the previous block index isn't valid, determine if it descends from any block which
+ // has been found invalid (g_failed_blocks), then mark pindexPrev and any blocks
+ // between them as failed.
if (!pindexPrev->IsValid(BLOCK_VALID_SCRIPTS)) {
- for (const CBlockIndex* failedit : g_failed_blocks) {
+ for (const CBlockIndex* failedit : m_failed_blocks) {
if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) {
assert(failedit->nStatus & BLOCK_FAILED_VALID);
CBlockIndex* invalid_walk = pindexPrev;
@@ -3454,8 +3466,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
return AbortNode(state, std::string("System error: ") + e.what());
}
- if (fCheckForPruning)
- FlushStateToDisk(chainparams, state, FlushStateMode::NONE); // we just allocated more disk space for block files
+ FlushStateToDisk(chainparams, state, FlushStateMode::NONE);
CheckBlockIndex(chainparams.GetConsensus());
@@ -3482,7 +3493,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
}
if (!ret) {
GetMainSignals().BlockChecked(*pblock, state);
- return error("%s: AcceptBlock FAILED (%s)", __func__, state.GetDebugMessage());
+ return error("%s: AcceptBlock FAILED (%s)", __func__, FormatStateMessage(state));
}
}
@@ -3490,7 +3501,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
CValidationState state; // Only used to report errors, not invalidity - ignore it
if (!g_chainstate.ActivateBestChain(state, chainparams, pblock))
- return error("%s: ActivateBestChain failed", __func__);
+ return error("%s: ActivateBestChain failed (%s)", __func__, FormatStateMessage(state));
return true;
}
@@ -3608,7 +3619,9 @@ void PruneBlockFilesManual(int nManualPruneHeight)
{
CValidationState state;
const CChainParams& chainparams = Params();
- FlushStateToDisk(chainparams, state, FlushStateMode::NONE, nManualPruneHeight);
+ if (!FlushStateToDisk(chainparams, state, FlushStateMode::NONE, nManualPruneHeight)) {
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ }
}
/**
@@ -3843,10 +3856,6 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams)
pblocktree->ReadReindexing(fReindexing);
if(fReindexing) fReindex = true;
- // Check whether we have a transaction index
- pblocktree->ReadFlag("txindex", fTxIndex);
- LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled");
-
return true;
}
@@ -3862,6 +3871,7 @@ bool LoadChainTip(const CChainParams& chainparams)
LogPrintf("%s: Connecting genesis block...\n", __func__);
CValidationState state;
if (!ActivateBestChain(state, chainparams)) {
+ LogPrintf("%s: failed to activate chain (%s)\n", __func__, FormatStateMessage(state));
return false;
}
}
@@ -3976,7 +3986,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
if (!g_chainstate.ConnectBlock(block, state, pindex, coins, chainparams))
- return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
+ return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state));
}
}
@@ -4084,6 +4094,9 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
int nHeight = 1;
while (nHeight <= chainActive.Height()) {
+ // Although SCRIPT_VERIFY_WITNESS is now generally enforced on all
+ // blocks in ConnectBlock, we don't need to go back and
+ // re-download/re-verify blocks from before segwit actually activated.
if (IsWitnessEnabled(chainActive[nHeight - 1], params.GetConsensus()) && !(chainActive[nHeight]->nStatus & BLOCK_OPT_WITNESS)) {
break;
}
@@ -4103,11 +4116,13 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
break;
}
if (!DisconnectTip(state, params, nullptr)) {
- return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight);
+ return error("RewindBlockIndex: unable to disconnect block at height %i (%s)", pindex->nHeight, FormatStateMessage(state));
}
// Occasionally flush state to disk.
- if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC))
+ if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC)) {
+ LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state));
return false;
+ }
}
// Reduce validity flag and have-data flags.
@@ -4173,6 +4188,7 @@ bool RewindBlockIndex(const CChainParams& params) {
// it'll get called a bunch real soon.
CValidationState state;
if (!FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) {
+ LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state));
return false;
}
}
@@ -4182,7 +4198,7 @@ bool RewindBlockIndex(const CChainParams& params) {
void CChainState::UnloadBlockIndex() {
nBlockSequenceId = 1;
- g_failed_blocks.clear();
+ m_failed_blocks.clear();
setBlockIndexCandidates.clear();
}
@@ -4233,9 +4249,6 @@ bool LoadBlockIndex(const CChainParams& chainparams)
// needs_init.
LogPrintf("Initializing databases...\n");
- // Use the provided setting for -txindex in the new database
- fTxIndex = gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX);
- pblocktree->WriteFlag("txindex", fTxIndex);
}
return true;
}
@@ -4259,7 +4272,7 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
CBlockIndex *pindex = AddToBlockIndex(block);
CValidationState state;
if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
- return error("%s: genesis block not accepted", __func__);
+ return error("%s: genesis block not accepted (%s)", __func__, FormatStateMessage(state));
} catch (const std::runtime_error& e) {
return error("%s: failed to write genesis block: %s", __func__, e.what());
}
@@ -4724,7 +4737,8 @@ bool DumpMempool(void)
}
file << mapDeltas;
- FileCommit(file.Get());
+ if (!FileCommit(file.Get()))
+ throw std::runtime_error("FileCommit failed");
file.fclose();
RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat");
int64_t last = GetTimeMicros();