aboutsummaryrefslogtreecommitdiff
path: root/src/validation.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/validation.h')
-rw-r--r--src/validation.h177
1 files changed, 107 insertions, 70 deletions
diff --git a/src/validation.h b/src/validation.h
index 2199de3197..7c0294d1ad 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -13,11 +13,15 @@
#include <arith_uint256.h>
#include <attributes.h>
#include <chain.h>
+#include <chainparams.h>
+#include <kernel/chainstatemanager_opts.h>
#include <consensus/amount.h>
+#include <deploymentstatus.h>
#include <fs.h>
#include <node/blockstorage.h>
#include <policy/feerate.h>
#include <policy/packages.h>
+#include <policy/policy.h>
#include <script/script_error.h>
#include <sync.h>
#include <txdb.h>
@@ -26,6 +30,7 @@
#include <util/check.h>
#include <util/hasher.h>
#include <util/translation.h>
+#include <versionbits.h>
#include <atomic>
#include <map>
@@ -40,7 +45,6 @@
class CChainState;
class CBlockTreeDB;
-class CChainParams;
class CTxMemPool;
class ChainstateManager;
struct ChainTxData;
@@ -51,29 +55,10 @@ struct AssumeutxoData;
namespace node {
class SnapshotMetadata;
} // namespace node
+namespace Consensus {
+struct Params;
+} // namespace Consensus
-/** Default for -minrelaytxfee, minimum relay fee for transactions */
-static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
-/** 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 */
-static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 101;
-/** Default for -limitdescendantcount, max number of in-mempool descendants */
-static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25;
-/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */
-static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101;
-
-// If a package is submitted, it must be within the mempool's ancestor/descendant limits. Since a
-// submitted package must be child-with-unconfirmed-parents (all of the transactions are an ancestor
-// of the child), package limits are ultimately bounded by mempool package limits. Ensure that the
-// defaults reflect this constraint.
-static_assert(DEFAULT_DESCENDANT_LIMIT >= MAX_PACKAGE_COUNT);
-static_assert(DEFAULT_ANCESTOR_LIMIT >= MAX_PACKAGE_COUNT);
-static_assert(DEFAULT_ANCESTOR_SIZE_LIMIT >= MAX_PACKAGE_SIZE);
-static_assert(DEFAULT_DESCENDANT_SIZE_LIMIT >= MAX_PACKAGE_SIZE);
-
-/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
-static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336;
/** Maximum number of dedicated script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 15;
/** -par default (number of script-checking threads, 0 = auto) */
@@ -83,8 +68,6 @@ static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static constexpr bool DEFAULT_COINSTATSINDEX{false};
static const char* const DEFAULT_BLOCKFILTERINDEX = "0";
-/** Default for -persistmempool */
-static const bool DEFAULT_PERSIST_MEMPOOL = true;
/** Default for -stopatheight */
static const int DEFAULT_STOPATHEIGHT = 0;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pruned. */
@@ -109,7 +92,7 @@ enum class SynchronizationState {
};
extern RecursiveMutex cs_main;
-extern Mutex g_best_block_mutex;
+extern GlobalMutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
/** Used to notify getblocktemplate RPC of new tips. */
extern uint256 g_best_block;
@@ -117,11 +100,8 @@ extern uint256 g_best_block;
* False indicates all script checking is done on the main threadMessageHandler thread.
*/
extern bool g_parallel_script_checks;
-extern bool fRequireStandard;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
-/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
-extern CFeeRate minRelayTxFee;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
extern int64_t nMaxTipAge;
@@ -131,14 +111,9 @@ extern uint256 hashAssumeValid;
/** Minimum work we will assume exists on some valid chain. */
extern arith_uint256 nMinimumChainWork;
-/** Best header we've seen so far (used for getheaders queries' starting points). */
-extern CBlockIndex *pindexBestHeader;
-
/** Documentation for argument 'checklevel'. */
extern const std::vector<std::string> CHECKLEVEL_DOC;
-/** Unload database information */
-void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** Run instances of script checking worker threads */
void StartScriptCheckWorkerThreads(int threads_num);
/** Stop all of the script checking worker threads */
@@ -234,11 +209,19 @@ struct PackageMempoolAcceptResult
* was a package-wide error (see result in m_state), m_tx_results will be empty.
*/
std::map<const uint256, const MempoolAcceptResult> m_tx_results;
+ /** Package feerate, defined as the aggregated modified fees divided by the total virtual size
+ * of all transactions in the package. May be unavailable if some inputs were not available or
+ * a transaction failure caused validation to terminate early. */
+ std::optional<CFeeRate> m_package_feerate;
explicit PackageMempoolAcceptResult(PackageValidationState state,
std::map<const uint256, const MempoolAcceptResult>&& results)
: m_state{state}, m_tx_results(std::move(results)) {}
+ explicit PackageMempoolAcceptResult(PackageValidationState state, CFeeRate feerate,
+ std::map<const uint256, const MempoolAcceptResult>&& results)
+ : m_state{state}, m_tx_results(std::move(results)), m_package_feerate{feerate} {}
+
/** Constructor to create a PackageMempoolAcceptResult from a single MempoolAcceptResult */
explicit PackageMempoolAcceptResult(const uint256& wtxid, const MempoolAcceptResult& result)
: m_tx_results{ {wtxid, result} } {}
@@ -325,7 +308,8 @@ public:
bool operator()();
- void swap(CScriptCheck &check) {
+ void swap(CScriptCheck& check) noexcept
+ {
std::swap(ptxTo, check.ptxTo);
std::swap(m_tx_out, check.m_tx_out);
std::swap(nIn, check.nIn);
@@ -339,7 +323,7 @@ public:
};
/** Initializes the script-execution cache */
-void InitScriptExecutionCache();
+[[nodiscard]] bool InitScriptExecutionCache(size_t max_size_bytes);
/** Functions for validating blocks and updating the block tree */
@@ -352,15 +336,10 @@ bool TestBlockValidity(BlockValidationState& state,
CChainState& chainstate,
const CBlock& block,
CBlockIndex* pindexPrev,
+ const std::function<int64_t()>& adjusted_time_callback,
bool fCheckPOW = true,
bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(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);
-
-/** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
-std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
-
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */
class CVerifyDB {
public:
@@ -420,7 +399,7 @@ public:
//! state to disk, which should not be done until the health of the database is verified.
//!
//! All arguments forwarded onto CCoinsViewDB.
- CoinsViews(std::string ldb_name, size_t cache_size_bytes, bool in_memory, bool should_wipe);
+ CoinsViews(fs::path ldb_name, size_t cache_size_bytes, bool in_memory, bool should_wipe);
//! Initialize the CCoinsViewCache member.
void InitCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
@@ -491,6 +470,7 @@ public:
node::BlockManager& m_blockman;
/** Chain parameters for this chainstate */
+ /* TODO: replace with m_chainman.GetParams() */
const CChainParams& m_params;
//! The chainstate manager that owns this chainstate. The reference is
@@ -514,7 +494,7 @@ public:
size_t cache_size_bytes,
bool in_memory,
bool should_wipe,
- std::string leveldb_name = "chainstate");
+ fs::path leveldb_name = "chainstate");
//! Initialize the in-memory coins cache (to be done after the health of the on-disk database
//! is verified).
@@ -594,8 +574,36 @@ public:
bool ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
- /** Import blocks from an external file */
- void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr)
+ /**
+ * Import blocks from an external file
+ *
+ * During reindexing, this function is called for each block file (datadir/blocks/blk?????.dat).
+ * It reads all blocks contained in the given file and attempts to process them (add them to the
+ * block index). The blocks may be out of order within each file and across files. Often this
+ * function reads a block but finds that its parent hasn't been read yet, so the block can't be
+ * processed yet. The function will add an entry to the blocks_with_unknown_parent map (which is
+ * passed as an argument), so that when the block's parent is later read and processed, this
+ * function can re-read the child block from disk and process it.
+ *
+ * Because a block's parent may be in a later file, not just later in the same file, the
+ * blocks_with_unknown_parent map must be passed in and out with each call. It's a multimap,
+ * rather than just a map, because multiple blocks may have the same parent (when chain splits
+ * or stale blocks exist). It maps from parent-hash to child-disk-position.
+ *
+ * This function can also be used to read blocks from user-specified block files using the
+ * -loadblock= option. There's no unknown-parent tracking, so the last two arguments are omitted.
+ *
+ *
+ * @param[in] fileIn FILE handle to file containing blocks to read
+ * @param[in] dbp (optional) Disk block position (only for reindex)
+ * @param[in,out] blocks_with_unknown_parent (optional) Map of disk positions for blocks with
+ * unknown parent, key is parent block hash
+ * (only used for reindex)
+ * */
+ void LoadExternalBlockFile(
+ FILE* fileIn,
+ FlatFilePos* dbp = nullptr,
+ std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent = nullptr)
EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex);
/**
@@ -686,7 +694,7 @@ public:
bool IsInitialBlockDownload() const;
/** Find the last common block of this chain and a locator. */
- CBlockIndex* FindForkInGlobalIndex(const CBlockLocator& locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ const CBlockIndex* FindForkInGlobalIndex(const CBlockLocator& locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Make various assertions about the state of the block index.
@@ -696,7 +704,7 @@ public:
void CheckBlockIndex();
/** Load the persisted mempool from disk */
- void LoadMempool(const ArgsManager& args);
+ void LoadMempool(const fs::path& load_path, fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen);
/** Update the chain tip based on database information, i.e. CoinsTip()'s best block. */
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -826,15 +834,18 @@ private:
//! If true, the assumed-valid chainstate has been fully validated
//! by the background validation chainstate.
- bool m_snapshot_validated{false};
+ bool m_snapshot_validated GUARDED_BY(::cs_main){false};
+
+ CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr};
+
+ const CChainParams m_chainparams;
- CBlockIndex* m_best_invalid;
- friend bool node::BlockManager::LoadBlockIndex(const Consensus::Params&, ChainstateManager&);
+ const std::function<int64_t()> m_adjusted_time_callback;
//! Internal helper for ActivateSnapshot().
[[nodiscard]] bool PopulateAndValidateSnapshot(
CChainState& snapshot_chainstate,
- CAutoFile& coins_file,
+ AutoFile& coins_file,
const node::SnapshotMetadata& metadata);
/**
@@ -844,11 +855,19 @@ private:
bool AcceptBlockHeader(
const CBlockHeader& block,
BlockValidationState& state,
- const CChainParams& chainparams,
CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
friend CChainState;
public:
+ using Options = kernel::ChainstateManagerOpts;
+
+ explicit ChainstateManager(const Options& opts)
+ : m_chainparams{opts.chainparams},
+ m_adjusted_time_callback{Assert(opts.adjusted_time_callback)} {};
+
+ const CChainParams& GetParams() const { return m_chainparams; }
+ const Consensus::Params& GetConsensus() const { return m_chainparams.GetConsensus(); }
+
std::thread m_load_block;
//! A single BlockManager instance is shared across each constructed
//! chainstate to avoid duplicating block metadata.
@@ -875,6 +894,9 @@ public:
*/
std::set<CBlockIndex*> m_failed_blocks;
+ /** Best header we've seen so far (used for getheaders queries' starting points). */
+ CBlockIndex* m_best_header = nullptr;
+
//! The total number of bytes available for us to use across all in-memory
//! coins caches. This will be split somehow across chainstates.
int64_t m_total_coinstip_cache{0};
@@ -912,7 +934,7 @@ public:
//! - Move the new chainstate to `m_snapshot_chainstate` and make it our
//! ChainstateActive().
[[nodiscard]] bool ActivateSnapshot(
- CAutoFile& coins_file, const node::SnapshotMetadata& metadata, bool in_memory);
+ AutoFile& coins_file, const node::SnapshotMetadata& metadata, bool in_memory);
//! The most-work chain.
CChainState& ActiveChainstate() const;
@@ -926,6 +948,11 @@ public:
return m_blockman.m_block_index;
}
+ /**
+ * Track versionbit status
+ */
+ mutable VersionBitsCache m_versionbitscache;
+
//! @returns true if a snapshot-based chainstate is in use. Also implies
//! that a background validation chainstate is also in use.
bool IsSnapshotActive() const;
@@ -933,7 +960,7 @@ public:
std::optional<uint256> SnapshotBlockhash() const;
//! Is there a snapshot in use and has it been fully validated?
- bool IsSnapshotValidated() const { return m_snapshot_validated; }
+ bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { return m_snapshot_validated; }
/**
* Process an incoming block. This only returns after the best known valid
@@ -954,7 +981,7 @@ public:
* @param[out] new_block A boolean which is set to indicate if the block was first received via this call
* @returns If the block was processed, independently of block validity
*/
- bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block) LOCKS_EXCLUDED(cs_main);
+ bool ProcessNewBlock(const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block) LOCKS_EXCLUDED(cs_main);
/**
* Process incoming block headers.
@@ -964,10 +991,9 @@ public:
*
* @param[in] block The block headers themselves
* @param[out] state This may be set to an Error state if any error occurred processing them
- * @param[in] chainparams The params for the chain we want to connect to
* @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
*/
- bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
+ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
/**
* Try to add a transaction to the memory pool.
@@ -981,26 +1007,37 @@ public:
//! Load the block tree and coins database from disk, initializing state if we're running with -reindex
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- //! Unload block index and chain data before shutdown.
- void Unload() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
-
//! Check to see if caches are out of balance and if so, call
//! ResizeCoinsCaches() as needed.
void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
- ~ChainstateManager() {
- LOCK(::cs_main);
- UnloadBlockIndex(/*mempool=*/nullptr, *this);
- }
+ /** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */
+ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev) const;
+
+ /** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
+ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const;
+
+ ~ChainstateManager();
};
-using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
+/** Deployment* info via ChainstateManager */
+template<typename DEP>
+bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const ChainstateManager& chainman, DEP dep)
+{
+ return DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), dep, chainman.m_versionbitscache);
+}
-/** Dump the mempool to disk. */
-bool DumpMempool(const CTxMemPool& pool, FopenFn mockable_fopen_function = fsbridge::fopen, bool skip_file_commit = false);
+template<typename DEP>
+bool DeploymentActiveAt(const CBlockIndex& index, const ChainstateManager& chainman, DEP dep)
+{
+ return DeploymentActiveAt(index, chainman.GetConsensus(), dep, chainman.m_versionbitscache);
+}
-/** Load the mempool from disk. */
-bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mockable_fopen_function = fsbridge::fopen);
+template<typename DEP>
+bool DeploymentEnabled(const ChainstateManager& chainman, DEP dep)
+{
+ return DeploymentEnabled(chainman.GetConsensus(), dep);
+}
/**
* Return the expected assumeutxo value for a given height, if one exists.