aboutsummaryrefslogtreecommitdiff
path: root/src/validation.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/validation.h')
-rw-r--r--src/validation.h235
1 files changed, 199 insertions, 36 deletions
diff --git a/src/validation.h b/src/validation.h
index 4ef82ee2c7..638229952d 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -21,6 +21,7 @@
#include <versionbits.h>
#include <algorithm>
+#include <atomic>
#include <exception>
#include <map>
#include <memory>
@@ -30,10 +31,10 @@
#include <utility>
#include <vector>
-#include <atomic>
-
+class CChainState;
class CBlockIndex;
class CBlockTreeDB;
+class CBlockUndo;
class CChainParams;
class CCoinsViewDB;
class CInv;
@@ -44,6 +45,7 @@ class CTxMemPool;
class CValidationState;
struct ChainTxData;
+struct DisconnectedBlockTransactions;
struct PrecomputedTransactionData;
struct LockPoints;
@@ -53,12 +55,6 @@ static const bool DEFAULT_WHITELISTRELAY = true;
static const bool DEFAULT_WHITELISTFORCERELAY = false;
/** Default for -minrelaytxfee, minimum relay fee for transactions */
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
-//! -maxtxfee default
-static const CAmount DEFAULT_TRANSACTION_MAXFEE = COIN / 10;
-//! Discourage users to set fees higher than this amount (in satoshis) per kB
-static const CAmount HIGH_TX_FEE_PER_KB = COIN / 100;
-//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
-static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB;
/** Default for -limitancestorcount, max number of in-mempool ancestors */
static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25;
/** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */
@@ -114,15 +110,12 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
/** Maximum age of our tip in seconds for us to be considered current for fee estimation */
static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
-/** Default for -permitbaremultisig */
-static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
+static const char* const DEFAULT_BLOCKFILTERINDEX = "0";
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
/** Default for -persistmempool */
static const bool DEFAULT_PERSIST_MEMPOOL = true;
-/** Default for -mempoolreplacement */
-static const bool DEFAULT_ENABLE_REPLACEMENT = true;
/** Default for using fee filter */
static const bool DEFAULT_FEEFILTER = true;
@@ -149,28 +142,22 @@ extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool;
-extern std::atomic_bool g_is_mempool_loaded;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap& mapBlockIndex GUARDED_BY(cs_main);
-extern const std::string strMessageMagic;
extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
extern uint256 g_best_block;
extern std::atomic_bool fImporting;
extern std::atomic_bool fReindex;
extern int nScriptCheckThreads;
-extern bool fIsBareMultisigStd;
extern bool fRequireStandard;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
extern size_t nCoinCacheUsage;
/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
extern CFeeRate minRelayTxFee;
-/** Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendrawtransaction) */
-extern CAmount maxTxFee;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
extern int64_t nMaxTipAge;
-extern bool fEnableReplacement;
/** Block hash whose ancestors we will assume to have valid scripts without checking them. */
extern uint256 hashAssumeValid;
@@ -188,7 +175,7 @@ extern bool fHavePruned;
extern bool fPruneMode;
/** Number of MiB of block files that we're trying to stay below. */
extern uint64_t nPruneTarget;
-/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */
+/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ::ChainActive().Tip() will not be pruned. */
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
/** Minimum blocks required to signal NODE_NETWORK_LIMITED */
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
@@ -258,9 +245,7 @@ bool LoadChainTip(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_m
/** Unload database information */
void UnloadBlockIndex();
/** Run an instance of the script checking thread */
-void ThreadScriptCheck();
-/** Check whether we are doing an initial block download (synchronizing from disk or network) */
-bool IsInitialBlockDownload();
+void ThreadScriptCheck(int worker_num);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, const CBlockIndex* const blockIndex = nullptr);
/**
@@ -288,10 +273,6 @@ void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
*/
void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune);
-/** Flush all state, indexes and buffers to disk. */
-void FlushStateToDisk();
-/** Prune block files and flush state to disk. */
-void PruneAndFlush();
/** Prune block files up to a given height */
void PruneBlockFilesManual(int nManualPruneHeight);
@@ -301,9 +282,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
bool bypass_limits, const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/** Convert CValidationState to a human-readable message for logging */
-std::string FormatStateMessage(const CValidationState &state);
-
/** Get the BIP9 state for a given deployment at the current tip. */
ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos);
@@ -391,6 +369,8 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start);
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start);
+bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
+
/** Functions for validating blocks and updating the block tree */
/** Context-independent validity checks */
@@ -406,7 +386,7 @@ bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& pa
bool IsNullDummyEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
-bool RewindBlockIndex(const CChainParams& params);
+bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
/** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
@@ -425,7 +405,7 @@ public:
/** Replay blocks that aren't fully applied to the database. */
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
-inline CBlockIndex* LookupBlockIndex(const uint256& hash)
+inline CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
BlockMap::const_iterator it = mapBlockIndex.find(hash);
@@ -435,6 +415,186 @@ inline CBlockIndex* LookupBlockIndex(const uint256& hash)
/** Find the last common block between the parameter chain and a locator. */
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+enum DisconnectResult
+{
+ DISCONNECT_OK, // All good.
+ DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
+ DISCONNECT_FAILED // Something else went wrong.
+};
+
+class ConnectTrace;
+
+/** @see CChainState::FlushStateToDisk */
+enum class FlushStateMode {
+ NONE,
+ IF_NEEDED,
+ PERIODIC,
+ ALWAYS
+};
+
+struct CBlockIndexWorkComparator
+{
+ bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const;
+};
+
+/**
+ * CChainState stores and provides an API to update our local knowledge of the
+ * current best chain and header tree.
+ *
+ * It generally provides access to the current block tree, as well as functions
+ * to provide new data, which it will appropriately validate and incorporate in
+ * its state as necessary.
+ *
+ * Eventually, the API here is targeted at being exposed externally as a
+ * consumable libconsensus library, so any functions added must only call
+ * other class member functions, pure functions in other parts of the consensus
+ * library, callbacks via the validation interface, or read/write-to-disk
+ * functions (eventually this will also be via callbacks).
+ */
+class CChainState {
+private:
+ /**
+ * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
+ * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be
+ * missing the data for the block.
+ */
+ std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
+
+ /**
+ * Every received block is assigned a unique and increasing identifier, so we
+ * know which one to give priority in case of a fork.
+ */
+ CCriticalSection cs_nBlockSequenceId;
+ /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
+ int32_t nBlockSequenceId = 1;
+ /** Decreasing counter (used by subsequent preciousblock calls). */
+ int32_t nBlockReverseSequenceId = -1;
+ /** chainwork for the last block that preciousblock has been applied to. */
+ arith_uint256 nLastPreciousChainwork = 0;
+
+ /** In order to efficiently track invalidity of headers, we keep the set of
+ * blocks which we tried to connect and found to be invalid here (ie which
+ * were set to BLOCK_FAILED_VALID since the last restart). We can then
+ * walk this set and check if a new header is a descendant of something in
+ * this set, preventing us from having to walk mapBlockIndex when we try
+ * to connect a bad block and fail.
+ *
+ * While this is more complicated than marking everything which descends
+ * from an invalid block as invalid at the time we discover it to be
+ * invalid, doing so would require walking all of mapBlockIndex to find all
+ * descendants. Since this case should be very rare, keeping track of all
+ * BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
+ * well.
+ *
+ * Because we already walk mapBlockIndex in height-order at startup, we go
+ * ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
+ * instead of putting things in this set.
+ */
+ std::set<CBlockIndex*> m_failed_blocks;
+
+ /**
+ * the ChainState CriticalSection
+ * A lock that must be held when modifying this ChainState - held in ActivateBestChain()
+ */
+ CCriticalSection m_cs_chainstate;
+
+ /**
+ * Whether this chainstate is undergoing initial block download.
+ *
+ * Mutable because we need to be able to mark IsInitialBlockDownload()
+ * const, which latches this for caching purposes.
+ */
+ mutable std::atomic<bool> m_cached_finished_ibd{false};
+
+public:
+ //! The current chain of blockheaders we consult and build on.
+ //! @see CChain, CBlockIndex.
+ CChain m_chain;
+ BlockMap mapBlockIndex GUARDED_BY(cs_main);
+ std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
+ CBlockIndex *pindexBestInvalid = nullptr;
+
+ bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ /**
+ * Update the on-disk chain state.
+ * 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 FlushStateToDisk(
+ const CChainParams& chainparams,
+ CValidationState &state,
+ FlushStateMode mode,
+ int nManualPruneHeight = 0);
+
+ //! Unconditionally flush all changes to disk.
+ void ForceFlushStateToDisk();
+
+ //! Prune blockfiles from the disk if necessary and then flush chainstate changes
+ //! if we pruned.
+ void PruneAndFlush();
+
+ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) LOCKS_EXCLUDED(cs_main);
+
+ /**
+ * 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) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ // Block (dis)connection on a given view:
+ DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
+ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
+ CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ // Block disconnection on our pcoinsTip:
+ bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ // Manual block validity manipulation:
+ bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
+ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
+ void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
+ bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
+ bool LoadGenesisBlock(const CChainParams& chainparams);
+
+ void PruneBlockIndexCandidates();
+
+ void UnloadBlockIndex();
+
+ /** Check whether we are doing an initial block download (synchronizing from disk or network) */
+ bool IsInitialBlockDownload() const;
+
+private:
+ bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ /** Create a new block index entry for a given block hash */
+ CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ /**
+ * 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) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ //! Mark a block as not having block data
+ void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+};
+
/** Mark a block as precious and reorganize.
*
* May not be called in a
@@ -443,13 +603,16 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main);
/** Mark a block as invalid. */
-bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
/** Remove invalidity status from a block and its descendants. */
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/** The currently-connected chain of blocks (protected by cs_main). */
-extern CChain& chainActive;
+/** @returns the most-work valid chainstate. */
+CChainState& ChainstateActive();
+
+/** @returns the most-work chain. */
+CChain& ChainActive();
/** Global variable that points to the coins database (protected by cs_main) */
extern std::unique_ptr<CCoinsViewDB> pcoinsdbview;
@@ -486,10 +649,10 @@ static const unsigned int REJECT_HIGHFEE = 0x100;
CBlockFileInfo* GetBlockFileInfo(size_t n);
/** Dump the mempool to disk. */
-bool DumpMempool();
+bool DumpMempool(const CTxMemPool& pool);
/** Load the mempool from disk. */
-bool LoadMempool();
+bool LoadMempool(CTxMemPool& pool);
//! Check whether the block associated with this index entry is pruned or not.
inline bool IsBlockPruned(const CBlockIndex* pblockindex)