aboutsummaryrefslogtreecommitdiff
path: root/src/validation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/validation.cpp')
-rw-r--r--src/validation.cpp118
1 files changed, 77 insertions, 41 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index 75952e975e..0d57900670 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -196,8 +196,8 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
std::unique_ptr<CBlockTreeDB> pblocktree;
// See definition for documentation
-static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight);
-static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
+static void FindFilesToPruneManual(ChainstateManager& chainman, std::set<int>& setFilesToPrune, int nManualPruneHeight);
+static void FindFilesToPrune(ChainstateManager& chainman, std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = nullptr);
static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly = false);
static FlatFileSeq BlockFileSeq();
@@ -1656,14 +1656,15 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex)
}
/** Abort with a message */
+// TODO: AbortNode() should take bilingual_str userMessage parameter.
static bool AbortNode(const std::string& strMessage, const std::string& userMessage = "", unsigned int prefix = 0)
{
SetMiscWarning(strMessage);
LogPrintf("*** %s\n", strMessage);
if (!userMessage.empty()) {
- uiInterface.ThreadSafeMessageBox(userMessage, "", CClientUIInterface::MSG_ERROR | prefix);
+ uiInterface.ThreadSafeMessageBox(Untranslated(userMessage), "", CClientUIInterface::MSG_ERROR | prefix);
} else {
- uiInterface.ThreadSafeMessageBox(_("Error: A fatal internal error occurred, see debug.log for details").translated, "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MSG_NOPREFIX);
+ uiInterface.ThreadSafeMessageBox(_("Error: A fatal internal error occurred, see debug.log for details"), "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MSG_NOPREFIX);
}
StartShutdown();
return false;
@@ -2284,13 +2285,13 @@ bool CChainState::FlushStateToDisk(
LOCK(cs_LastBlockFile);
if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) {
if (nManualPruneHeight > 0) {
- LOG_TIME_MILLIS("find files to prune (manual)", BCLog::BENCH);
+ LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune (manual)", BCLog::BENCH);
- FindFilesToPruneManual(setFilesToPrune, nManualPruneHeight);
+ FindFilesToPruneManual(g_chainman, setFilesToPrune, nManualPruneHeight);
} else {
- LOG_TIME_MILLIS("find files to prune", BCLog::BENCH);
+ LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune", BCLog::BENCH);
- FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight());
+ FindFilesToPrune(g_chainman, setFilesToPrune, chainparams.PruneAfterHeight());
fCheckForPruning = false;
}
if (!setFilesToPrune.empty()) {
@@ -2326,7 +2327,7 @@ bool CChainState::FlushStateToDisk(
return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX);
}
{
- LOG_TIME_MILLIS("write block and undo data to disk", BCLog::BENCH);
+ LOG_TIME_MILLIS_WITH_CATEGORY("write block and undo data to disk", BCLog::BENCH);
// First make sure all block and undo data is flushed to disk.
FlushBlockFile();
@@ -2334,7 +2335,7 @@ bool CChainState::FlushStateToDisk(
// Then update all block file information (which may refer to block and undo files).
{
- LOG_TIME_MILLIS("write block index to disk", BCLog::BENCH);
+ LOG_TIME_MILLIS_WITH_CATEGORY("write block index to disk", BCLog::BENCH);
std::vector<std::pair<int, const CBlockFileInfo*> > vFiles;
vFiles.reserve(setDirtyFileInfo.size());
@@ -2354,7 +2355,7 @@ bool CChainState::FlushStateToDisk(
}
// Finally remove any pruned files
if (fFlushForPrune) {
- LOG_TIME_MILLIS("unlink pruned files", BCLog::BENCH);
+ LOG_TIME_MILLIS_WITH_CATEGORY("unlink pruned files", BCLog::BENCH);
UnlinkPrunedFiles(setFilesToPrune);
}
@@ -2804,6 +2805,13 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
return true;
}
+static SynchronizationState GetSynchronizationState(bool init)
+{
+ if (!init) return SynchronizationState::POST_INIT;
+ if (::fReindex) return SynchronizationState::INIT_REINDEX;
+ return SynchronizationState::INIT_DOWNLOAD;
+}
+
static bool NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
bool fNotify = false;
bool fInitialBlockDownload = false;
@@ -2821,7 +2829,7 @@ static bool NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
}
// Send block tip changed notifications without cs_main
if (fNotify) {
- uiInterface.NotifyHeaderTip(fInitialBlockDownload, pindexHeader);
+ uiInterface.NotifyHeaderTip(GetSynchronizationState(fInitialBlockDownload), pindexHeader);
}
return fNotify;
}
@@ -2910,7 +2918,7 @@ bool CChainState::ActivateBestChain(BlockValidationState &state, const CChainPar
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
// Always notify the UI if a new block tip was connected
- uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
+ uiInterface.NotifyBlockTip(GetSynchronizationState(fInitialDownload), pindexNewTip);
}
}
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
@@ -3101,7 +3109,7 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, const CChainParam
// Only notify about a new block tip if the active chain was modified.
if (pindex_was_in_chain) {
- uiInterface.NotifyBlockTip(IsInitialBlockDownload(), to_mark_failed->pprev);
+ uiInterface.NotifyBlockTip(GetSynchronizationState(IsInitialBlockDownload()), to_mark_failed->pprev);
}
return true;
}
@@ -3391,7 +3399,14 @@ int GetWitnessCommitmentIndex(const CBlock& block)
int commitpos = -1;
if (!block.vtx.empty()) {
for (size_t o = 0; o < block.vtx[0]->vout.size(); o++) {
- if (block.vtx[0]->vout[o].scriptPubKey.size() >= 38 && block.vtx[0]->vout[o].scriptPubKey[0] == OP_RETURN && block.vtx[0]->vout[o].scriptPubKey[1] == 0x24 && block.vtx[0]->vout[o].scriptPubKey[2] == 0xaa && block.vtx[0]->vout[o].scriptPubKey[3] == 0x21 && block.vtx[0]->vout[o].scriptPubKey[4] == 0xa9 && block.vtx[0]->vout[o].scriptPubKey[5] == 0xed) {
+ const CTxOut& vout = block.vtx[0]->vout[o];
+ if (vout.scriptPubKey.size() >= MINIMUM_WITNESS_COMMITMENT &&
+ vout.scriptPubKey[0] == OP_RETURN &&
+ vout.scriptPubKey[1] == 0x24 &&
+ vout.scriptPubKey[2] == 0xaa &&
+ vout.scriptPubKey[3] == 0x21 &&
+ vout.scriptPubKey[4] == 0xa9 &&
+ vout.scriptPubKey[5] == 0xed) {
commitpos = o;
}
}
@@ -3422,7 +3437,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
CHash256().Write(witnessroot.begin(), 32).Write(ret.data(), 32).Finalize(witnessroot.begin());
CTxOut out;
out.nValue = 0;
- out.scriptPubKey.resize(38);
+ out.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT);
out.scriptPubKey[0] = OP_RETURN;
out.scriptPubKey[1] = 0x24;
out.scriptPubKey[2] = 0xaa;
@@ -3681,13 +3696,14 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
}
// Exposed wrapper for AcceptBlockHeader
-bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex)
+bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex)
{
+ AssertLockNotHeld(cs_main);
{
LOCK(cs_main);
for (const CBlockHeader& header : headers) {
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
- bool accepted = g_chainman.m_blockman.AcceptBlockHeader(
+ bool accepted = m_blockman.AcceptBlockHeader(
header, state, chainparams, &pindex);
::ChainstateActive().CheckBlockIndex(chainparams.GetConsensus());
@@ -3809,7 +3825,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
return true;
}
-bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock> pblock, bool fForceProcessing, bool *fNewBlock)
+bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock> pblock, bool fForceProcessing, bool* fNewBlock)
{
AssertLockNotHeld(cs_main);
@@ -3885,12 +3901,12 @@ uint64_t CalculateCurrentUsage()
return retval;
}
-/* Prune a block file (modify associated database entries)*/
-void PruneOneBlockFile(const int fileNumber)
+void ChainstateManager::PruneOneBlockFile(const int fileNumber)
{
+ AssertLockHeld(cs_main);
LOCK(cs_LastBlockFile);
- for (const auto& entry : g_chainman.BlockIndex()) {
+ for (const auto& entry : m_blockman.m_block_index) {
CBlockIndex* pindex = entry.second;
if (pindex->nFile == fileNumber) {
pindex->nStatus &= ~BLOCK_HAVE_DATA;
@@ -3904,12 +3920,12 @@ void PruneOneBlockFile(const int fileNumber)
// to be downloaded again in order to consider its chain, at which
// point it would be considered as a candidate for
// m_blocks_unlinked or setBlockIndexCandidates.
- auto range = g_chainman.m_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
+ auto range = m_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
while (range.first != range.second) {
std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first;
range.first++;
if (_it->second == pindex) {
- g_chainman.m_blockman.m_blocks_unlinked.erase(_it);
+ m_blockman.m_blocks_unlinked.erase(_it);
}
}
}
@@ -3931,7 +3947,7 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
}
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
-static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight)
+static void FindFilesToPruneManual(ChainstateManager& chainman, std::set<int>& setFilesToPrune, int nManualPruneHeight)
{
assert(fPruneMode && nManualPruneHeight > 0);
@@ -3945,7 +3961,7 @@ static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPr
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
if (vinfoBlockFile[fileNumber].nSize == 0 || vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
continue;
- PruneOneBlockFile(fileNumber);
+ chainman.PruneOneBlockFile(fileNumber);
setFilesToPrune.insert(fileNumber);
count++;
}
@@ -3978,7 +3994,7 @@ void PruneBlockFilesManual(int nManualPruneHeight)
*
* @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned
*/
-static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
+static void FindFilesToPrune(ChainstateManager& chainman, std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
{
LOCK2(cs_main, cs_LastBlockFile);
if (::ChainActive().Tip() == nullptr || nPruneTarget == 0) {
@@ -4020,7 +4036,7 @@ static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfte
if (vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
continue;
- PruneOneBlockFile(fileNumber);
+ chainman.PruneOneBlockFile(fileNumber);
// Queue up the files for removal
setFilesToPrune.insert(fileNumber);
nCurrentUsage -= nBytesToPrune;
@@ -4144,9 +4160,9 @@ void BlockManager::Unload() {
m_block_index.clear();
}
-bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+bool static LoadBlockIndexDB(ChainstateManager& chainman, const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- if (!g_chainman.m_blockman.LoadBlockIndex(
+ if (!chainman.m_blockman.LoadBlockIndex(
chainparams.GetConsensus(), *pblocktree,
::ChainstateActive().setBlockIndexCandidates)) {
return false;
@@ -4172,8 +4188,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
// Check presence of blk files
LogPrintf("Checking all blk files are present...\n");
std::set<int> setBlkDataFiles;
- for (const std::pair<const uint256, CBlockIndex*>& item : g_chainman.BlockIndex())
- {
+ for (const std::pair<const uint256, CBlockIndex*>& item : chainman.BlockIndex()) {
CBlockIndex* pindex = item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
setBlkDataFiles.insert(pindex->nFile);
@@ -4590,14 +4605,15 @@ void UnloadBlockIndex()
fHavePruned = false;
}
-bool LoadBlockIndex(const CChainParams& chainparams)
+bool ChainstateManager::LoadBlockIndex(const CChainParams& chainparams)
{
+ AssertLockHeld(cs_main);
// Load block index from databases
bool needs_init = fReindex;
if (!fReindex) {
- bool ret = LoadBlockIndexDB(chainparams);
+ bool ret = LoadBlockIndexDB(*this, chainparams);
if (!ret) return false;
- needs_init = g_chainman.m_blockman.m_block_index.empty();
+ needs_init = m_blockman.m_block_index.empty();
}
if (needs_init) {
@@ -4642,7 +4658,7 @@ bool LoadGenesisBlock(const CChainParams& chainparams)
return ::ChainstateActive().LoadGenesisBlock(chainparams);
}
-bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos *dbp)
+void LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos* dbp)
{
// Map of disk positions for blocks with unknown parent (only used for reindex)
static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
@@ -4654,7 +4670,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFi
CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SERIALIZED_SIZE, MAX_BLOCK_SERIALIZED_SIZE+8, SER_DISK, CLIENT_VERSION);
uint64_t nRewind = blkdat.GetPos();
while (!blkdat.eof()) {
- boost::this_thread::interruption_point();
+ if (ShutdownRequested()) return;
blkdat.SetPos(nRewind);
nRewind++; // start one byte further next time, in case of failure
@@ -4759,9 +4775,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFi
} catch (const std::runtime_error& e) {
AbortNode(std::string("System error: ") + e.what());
}
- if (nLoaded > 0)
- LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart);
- return nLoaded > 0;
+ LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart);
}
void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
@@ -5003,6 +5017,7 @@ bool LoadMempool(CTxMemPool& pool)
int64_t expired = 0;
int64_t failed = 0;
int64_t already_there = 0;
+ int64_t unbroadcast = 0;
int64_t nNow = GetTime();
try {
@@ -5056,12 +5071,27 @@ bool LoadMempool(CTxMemPool& pool)
for (const auto& i : mapDeltas) {
pool.PrioritiseTransaction(i.first, i.second);
}
+
+ // TODO: remove this try except in v0.22
+ try {
+ std::set<uint256> unbroadcast_txids;
+ file >> unbroadcast_txids;
+ unbroadcast = unbroadcast_txids.size();
+
+ for (const auto& txid : unbroadcast_txids) {
+ pool.AddUnbroadcastTx(txid);
+ }
+ } catch (const std::exception&) {
+ // mempool.dat files created prior to v0.21 will not have an
+ // unbroadcast set. No need to log a failure if parsing fails here.
+ }
+
} catch (const std::exception& e) {
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
return false;
}
- LogPrintf("Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there\n", count, failed, expired, already_there);
+ LogPrintf("Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there, %i waiting for initial broadcast\n", count, failed, expired, already_there, unbroadcast);
return true;
}
@@ -5071,6 +5101,7 @@ bool DumpMempool(const CTxMemPool& pool)
std::map<uint256, CAmount> mapDeltas;
std::vector<TxMempoolInfo> vinfo;
+ std::set<uint256> unbroadcast_txids;
static Mutex dump_mutex;
LOCK(dump_mutex);
@@ -5081,6 +5112,7 @@ bool DumpMempool(const CTxMemPool& pool)
mapDeltas[i.first] = i.second;
}
vinfo = pool.infoAll();
+ unbroadcast_txids = pool.GetUnbroadcastTxs();
}
int64_t mid = GetTimeMicros();
@@ -5105,6 +5137,10 @@ bool DumpMempool(const CTxMemPool& pool)
}
file << mapDeltas;
+
+ LogPrintf("Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
+ file << unbroadcast_txids;
+
if (!FileCommit(file.Get()))
throw std::runtime_error("FileCommit failed");
file.fclose();