aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/chain.cpp26
-rw-r--r--src/kernel/chain.h19
-rw-r--r--src/kernel/chainstatemanager_opts.h8
-rw-r--r--src/kernel/checks.cpp11
-rw-r--r--src/kernel/checks.h10
-rw-r--r--src/kernel/coinstats.cpp24
-rw-r--r--src/kernel/coinstats.h6
-rw-r--r--src/kernel/mempool_limits.h30
-rw-r--r--src/kernel/mempool_options.h60
-rw-r--r--src/kernel/mempool_persist.cpp189
-rw-r--r--src/kernel/mempool_persist.h28
-rw-r--r--src/kernel/validation_cache_sizes.h20
12 files changed, 413 insertions, 18 deletions
diff --git a/src/kernel/chain.cpp b/src/kernel/chain.cpp
new file mode 100644
index 0000000000..82e77125d7
--- /dev/null
+++ b/src/kernel/chain.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chain.h>
+#include <interfaces/chain.h>
+#include <sync.h>
+#include <uint256.h>
+
+class CBlock;
+
+namespace kernel {
+interfaces::BlockInfo MakeBlockInfo(const CBlockIndex* index, const CBlock* data)
+{
+ interfaces::BlockInfo info{index ? *index->phashBlock : uint256::ZERO};
+ if (index) {
+ info.prev_hash = index->pprev ? index->pprev->phashBlock : nullptr;
+ info.height = index->nHeight;
+ LOCK(::cs_main);
+ info.file_number = index->nFile;
+ info.data_pos = index->nDataPos;
+ }
+ info.data = data;
+ return info;
+}
+} // namespace kernel
diff --git a/src/kernel/chain.h b/src/kernel/chain.h
new file mode 100644
index 0000000000..f0750f8266
--- /dev/null
+++ b/src/kernel/chain.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_KERNEL_CHAIN_H
+#define BITCOIN_KERNEL_CHAIN_H
+
+class CBlock;
+class CBlockIndex;
+namespace interfaces {
+struct BlockInfo;
+} // namespace interfaces
+
+namespace kernel {
+//! Return data from block index.
+interfaces::BlockInfo MakeBlockInfo(const CBlockIndex* block_index, const CBlock* data = nullptr);
+} // namespace kernel
+
+#endif // BITCOIN_KERNEL_CHAIN_H
diff --git a/src/kernel/chainstatemanager_opts.h b/src/kernel/chainstatemanager_opts.h
index 575d94e2e9..520d0e8e75 100644
--- a/src/kernel/chainstatemanager_opts.h
+++ b/src/kernel/chainstatemanager_opts.h
@@ -5,11 +5,15 @@
#ifndef BITCOIN_KERNEL_CHAINSTATEMANAGER_OPTS_H
#define BITCOIN_KERNEL_CHAINSTATEMANAGER_OPTS_H
+#include <util/time.h>
+
#include <cstdint>
#include <functional>
class CChainParams;
+namespace kernel {
+
/**
* An options struct for `ChainstateManager`, more ergonomically referred to as
* `ChainstateManager::Options` due to the using-declaration in
@@ -17,7 +21,9 @@ class CChainParams;
*/
struct ChainstateManagerOpts {
const CChainParams& chainparams;
- const std::function<int64_t()> adjusted_time_callback{nullptr};
+ const std::function<NodeClock::time_point()> adjusted_time_callback{nullptr};
};
+} // namespace kernel
+
#endif // BITCOIN_KERNEL_CHAINSTATEMANAGER_OPTS_H
diff --git a/src/kernel/checks.cpp b/src/kernel/checks.cpp
index 2a1dd3bfa2..4c303c172c 100644
--- a/src/kernel/checks.cpp
+++ b/src/kernel/checks.cpp
@@ -7,21 +7,24 @@
#include <key.h>
#include <random.h>
#include <util/time.h>
+#include <util/translation.h>
+
+#include <memory>
namespace kernel {
-std::optional<SanityCheckError> SanityChecks(const Context&)
+std::optional<bilingual_str> SanityChecks(const Context&)
{
if (!ECC_InitSanityCheck()) {
- return SanityCheckError::ERROR_ECC;
+ return Untranslated("Elliptic curve cryptography sanity check failure. Aborting.");
}
if (!Random_SanityCheck()) {
- return SanityCheckError::ERROR_RANDOM;
+ return Untranslated("OS cryptographic RNG sanity check failure. Aborting.");
}
if (!ChronoSanityCheck()) {
- return SanityCheckError::ERROR_CHRONO;
+ return Untranslated("Clock epoch mismatch. Aborting.");
}
return std::nullopt;
diff --git a/src/kernel/checks.h b/src/kernel/checks.h
index 80b207f607..3eb14824fb 100644
--- a/src/kernel/checks.h
+++ b/src/kernel/checks.h
@@ -7,20 +7,16 @@
#include <optional>
+struct bilingual_str;
+
namespace kernel {
struct Context;
-enum class SanityCheckError {
- ERROR_ECC,
- ERROR_RANDOM,
- ERROR_CHRONO,
-};
-
/**
* Ensure a usable environment with all necessary library support.
*/
-std::optional<SanityCheckError> SanityChecks(const Context&);
+std::optional<bilingual_str> SanityChecks(const Context&);
}
diff --git a/src/kernel/coinstats.cpp b/src/kernel/coinstats.cpp
index f380871627..06a4b8c974 100644
--- a/src/kernel/coinstats.cpp
+++ b/src/kernel/coinstats.cpp
@@ -4,16 +4,32 @@
#include <kernel/coinstats.h>
+#include <chain.h>
#include <coins.h>
#include <crypto/muhash.h>
#include <hash.h>
+#include <node/blockstorage.h>
+#include <primitives/transaction.h>
+#include <script/script.h>
#include <serialize.h>
+#include <span.h>
+#include <streams.h>
+#include <sync.h>
+#include <tinyformat.h>
#include <uint256.h>
+#include <util/check.h>
#include <util/overflow.h>
#include <util/system.h>
#include <validation.h>
+#include <version.h>
+#include <cassert>
+#include <iosfwd>
+#include <iterator>
#include <map>
+#include <memory>
+#include <string>
+#include <utility>
namespace kernel {
@@ -52,7 +68,7 @@ CDataStream TxOutSer(const COutPoint& outpoint, const Coin& coin) {
//! It is also possible, though very unlikely, that a change in this
//! construction could cause a previously invalid (and potentially malicious)
//! UTXO snapshot to be considered valid.
-static void ApplyHash(CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
+static void ApplyHash(HashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
{
for (auto it = outputs.begin(); it != outputs.end(); ++it) {
if (it == outputs.begin()) {
@@ -143,7 +159,7 @@ std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsV
bool success = [&]() -> bool {
switch (hash_type) {
case(CoinStatsHashType::HASH_SERIALIZED): {
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
+ HashWriter ss{};
return ComputeUTXOStats(view, stats, ss, interruption_point);
}
case(CoinStatsHashType::MUHASH): {
@@ -164,7 +180,7 @@ std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsV
}
// The legacy hash serializes the hashBlock
-static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
+static void PrepareHash(HashWriter& ss, const CCoinsStats& stats)
{
ss << stats.hashBlock;
}
@@ -172,7 +188,7 @@ static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
static void PrepareHash(MuHash3072& muhash, CCoinsStats& stats) {}
static void PrepareHash(std::nullptr_t, CCoinsStats& stats) {}
-static void FinalizeHash(CHashWriter& ss, CCoinsStats& stats)
+static void FinalizeHash(HashWriter& ss, CCoinsStats& stats)
{
stats.hashSerialized = ss.GetHash();
}
diff --git a/src/kernel/coinstats.h b/src/kernel/coinstats.h
index a15957233f..b7c1328e93 100644
--- a/src/kernel/coinstats.h
+++ b/src/kernel/coinstats.h
@@ -5,16 +5,18 @@
#ifndef BITCOIN_KERNEL_COINSTATS_H
#define BITCOIN_KERNEL_COINSTATS_H
-#include <chain.h>
-#include <coins.h>
#include <consensus/amount.h>
#include <streams.h>
#include <uint256.h>
#include <cstdint>
#include <functional>
+#include <optional>
class CCoinsView;
+class Coin;
+class COutPoint;
+class CScript;
namespace node {
class BlockManager;
} // namespace node
diff --git a/src/kernel/mempool_limits.h b/src/kernel/mempool_limits.h
new file mode 100644
index 0000000000..e192e7e6cd
--- /dev/null
+++ b/src/kernel/mempool_limits.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_KERNEL_MEMPOOL_LIMITS_H
+#define BITCOIN_KERNEL_MEMPOOL_LIMITS_H
+
+#include <policy/policy.h>
+
+#include <cstdint>
+
+namespace kernel {
+/**
+ * Options struct containing limit options for a CTxMemPool. Default constructor
+ * populates the struct with sane default values which can be modified.
+ *
+ * Most of the time, this struct should be referenced as CTxMemPool::Limits.
+ */
+struct MemPoolLimits {
+ //! The maximum allowed number of transactions in a package including the entry and its ancestors.
+ int64_t ancestor_count{DEFAULT_ANCESTOR_LIMIT};
+ //! The maximum allowed size in virtual bytes of an entry and its ancestors within a package.
+ int64_t ancestor_size_vbytes{DEFAULT_ANCESTOR_SIZE_LIMIT_KVB * 1'000};
+ //! The maximum allowed number of transactions in a package including the entry and its descendants.
+ int64_t descendant_count{DEFAULT_DESCENDANT_LIMIT};
+ //! The maximum allowed size in virtual bytes of an entry and its descendants within a package.
+ int64_t descendant_size_vbytes{DEFAULT_DESCENDANT_SIZE_LIMIT_KVB * 1'000};
+};
+} // namespace kernel
+
+#endif // BITCOIN_KERNEL_MEMPOOL_LIMITS_H
diff --git a/src/kernel/mempool_options.h b/src/kernel/mempool_options.h
new file mode 100644
index 0000000000..dad6f14c39
--- /dev/null
+++ b/src/kernel/mempool_options.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_KERNEL_MEMPOOL_OPTIONS_H
+#define BITCOIN_KERNEL_MEMPOOL_OPTIONS_H
+
+#include <kernel/mempool_limits.h>
+
+#include <policy/feerate.h>
+#include <policy/policy.h>
+#include <script/standard.h>
+
+#include <chrono>
+#include <cstdint>
+#include <optional>
+
+class CBlockPolicyEstimator;
+
+/** Default for -maxmempool, maximum megabytes of mempool memory usage */
+static constexpr unsigned int DEFAULT_MAX_MEMPOOL_SIZE_MB{300};
+/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
+static constexpr unsigned int DEFAULT_MEMPOOL_EXPIRY_HOURS{336};
+/** Default for -mempoolfullrbf, if the transaction replaceability signaling is ignored */
+static constexpr bool DEFAULT_MEMPOOL_FULL_RBF{false};
+
+namespace kernel {
+/**
+ * Options struct containing options for constructing a CTxMemPool. Default
+ * constructor populates the struct with sane default values which can be
+ * modified.
+ *
+ * Most of the time, this struct should be referenced as CTxMemPool::Options.
+ */
+struct MemPoolOptions {
+ /* Used to estimate appropriate transaction fees. */
+ CBlockPolicyEstimator* estimator{nullptr};
+ /* The ratio used to determine how often sanity checks will run. */
+ int check_ratio{0};
+ int64_t max_size_bytes{DEFAULT_MAX_MEMPOOL_SIZE_MB * 1'000'000};
+ std::chrono::seconds expiry{std::chrono::hours{DEFAULT_MEMPOOL_EXPIRY_HOURS}};
+ CFeeRate incremental_relay_feerate{DEFAULT_INCREMENTAL_RELAY_FEE};
+ /** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
+ CFeeRate min_relay_feerate{DEFAULT_MIN_RELAY_TX_FEE};
+ CFeeRate dust_relay_feerate{DUST_RELAY_TX_FEE};
+ /**
+ * A data carrying output is an unspendable output containing data. The script
+ * type is designated as TxoutType::NULL_DATA.
+ *
+ * Maximum size of TxoutType::NULL_DATA scripts that this node considers standard.
+ * If nullopt, any size is nonstandard.
+ */
+ std::optional<unsigned> max_datacarrier_bytes{DEFAULT_ACCEPT_DATACARRIER ? std::optional{MAX_OP_RETURN_RELAY} : std::nullopt};
+ bool permit_bare_multisig{DEFAULT_PERMIT_BAREMULTISIG};
+ bool require_standard{true};
+ bool full_rbf{DEFAULT_MEMPOOL_FULL_RBF};
+ MemPoolLimits limits{};
+};
+} // namespace kernel
+
+#endif // BITCOIN_KERNEL_MEMPOOL_OPTIONS_H
diff --git a/src/kernel/mempool_persist.cpp b/src/kernel/mempool_persist.cpp
new file mode 100644
index 0000000000..a14b2e6163
--- /dev/null
+++ b/src/kernel/mempool_persist.cpp
@@ -0,0 +1,189 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <kernel/mempool_persist.h>
+
+#include <clientversion.h>
+#include <consensus/amount.h>
+#include <fs.h>
+#include <logging.h>
+#include <primitives/transaction.h>
+#include <serialize.h>
+#include <shutdown.h>
+#include <streams.h>
+#include <sync.h>
+#include <txmempool.h>
+#include <uint256.h>
+#include <util/system.h>
+#include <util/time.h>
+#include <validation.h>
+
+#include <chrono>
+#include <cstdint>
+#include <cstdio>
+#include <exception>
+#include <functional>
+#include <map>
+#include <memory>
+#include <set>
+#include <stdexcept>
+#include <utility>
+#include <vector>
+
+using fsbridge::FopenFn;
+
+namespace kernel {
+
+static const uint64_t MEMPOOL_DUMP_VERSION = 1;
+
+bool LoadMempool(CTxMemPool& pool, const fs::path& load_path, Chainstate& active_chainstate, FopenFn mockable_fopen_function)
+{
+ if (load_path.empty()) return false;
+
+ FILE* filestr{mockable_fopen_function(load_path, "rb")};
+ CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
+ if (file.IsNull()) {
+ LogPrintf("Failed to open mempool file from disk. Continuing anyway.\n");
+ return false;
+ }
+
+ int64_t count = 0;
+ int64_t expired = 0;
+ int64_t failed = 0;
+ int64_t already_there = 0;
+ int64_t unbroadcast = 0;
+ auto now = NodeClock::now();
+
+ try {
+ uint64_t version;
+ file >> version;
+ if (version != MEMPOOL_DUMP_VERSION) {
+ return false;
+ }
+ uint64_t num;
+ file >> num;
+ while (num) {
+ --num;
+ CTransactionRef tx;
+ int64_t nTime;
+ int64_t nFeeDelta;
+ file >> tx;
+ file >> nTime;
+ file >> nFeeDelta;
+
+ CAmount amountdelta = nFeeDelta;
+ if (amountdelta) {
+ pool.PrioritiseTransaction(tx->GetHash(), amountdelta);
+ }
+ if (nTime > TicksSinceEpoch<std::chrono::seconds>(now - pool.m_expiry)) {
+ LOCK(cs_main);
+ const auto& accepted = AcceptToMemoryPool(active_chainstate, tx, nTime, /*bypass_limits=*/false, /*test_accept=*/false);
+ if (accepted.m_result_type == MempoolAcceptResult::ResultType::VALID) {
+ ++count;
+ } else {
+ // mempool may contain the transaction already, e.g. from
+ // wallet(s) having loaded it while we were processing
+ // mempool transactions; consider these as valid, instead of
+ // failed, but mark them as 'already there'
+ if (pool.exists(GenTxid::Txid(tx->GetHash()))) {
+ ++already_there;
+ } else {
+ ++failed;
+ }
+ }
+ } else {
+ ++expired;
+ }
+ if (ShutdownRequested())
+ return false;
+ }
+ std::map<uint256, CAmount> mapDeltas;
+ file >> mapDeltas;
+
+ for (const auto& i : mapDeltas) {
+ pool.PrioritiseTransaction(i.first, i.second);
+ }
+
+ std::set<uint256> unbroadcast_txids;
+ file >> unbroadcast_txids;
+ unbroadcast = unbroadcast_txids.size();
+ for (const auto& txid : unbroadcast_txids) {
+ // Ensure transactions were accepted to mempool then add to
+ // unbroadcast set.
+ if (pool.get(txid) != nullptr) pool.AddUnbroadcastTx(txid);
+ }
+ } 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, %i waiting for initial broadcast\n", count, failed, expired, already_there, unbroadcast);
+ return true;
+}
+
+bool DumpMempool(const CTxMemPool& pool, const fs::path& dump_path, FopenFn mockable_fopen_function, bool skip_file_commit)
+{
+ auto start = SteadyClock::now();
+
+ std::map<uint256, CAmount> mapDeltas;
+ std::vector<TxMempoolInfo> vinfo;
+ std::set<uint256> unbroadcast_txids;
+
+ static Mutex dump_mutex;
+ LOCK(dump_mutex);
+
+ {
+ LOCK(pool.cs);
+ for (const auto &i : pool.mapDeltas) {
+ mapDeltas[i.first] = i.second;
+ }
+ vinfo = pool.infoAll();
+ unbroadcast_txids = pool.GetUnbroadcastTxs();
+ }
+
+ auto mid = SteadyClock::now();
+
+ try {
+ FILE* filestr{mockable_fopen_function(dump_path + ".new", "wb")};
+ if (!filestr) {
+ return false;
+ }
+
+ CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
+
+ uint64_t version = MEMPOOL_DUMP_VERSION;
+ file << version;
+
+ file << (uint64_t)vinfo.size();
+ for (const auto& i : vinfo) {
+ file << *(i.tx);
+ file << int64_t{count_seconds(i.m_time)};
+ file << int64_t{i.nFeeDelta};
+ mapDeltas.erase(i.tx->GetHash());
+ }
+
+ file << mapDeltas;
+
+ LogPrintf("Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
+ file << unbroadcast_txids;
+
+ if (!skip_file_commit && !FileCommit(file.Get()))
+ throw std::runtime_error("FileCommit failed");
+ file.fclose();
+ if (!RenameOver(dump_path + ".new", dump_path)) {
+ throw std::runtime_error("Rename failed");
+ }
+ auto last = SteadyClock::now();
+
+ LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n",
+ Ticks<SecondsDouble>(mid - start),
+ Ticks<SecondsDouble>(last - mid));
+ } catch (const std::exception& e) {
+ LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what());
+ return false;
+ }
+ return true;
+}
+
+} // namespace kernel
diff --git a/src/kernel/mempool_persist.h b/src/kernel/mempool_persist.h
new file mode 100644
index 0000000000..ca4917e38b
--- /dev/null
+++ b/src/kernel/mempool_persist.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_KERNEL_MEMPOOL_PERSIST_H
+#define BITCOIN_KERNEL_MEMPOOL_PERSIST_H
+
+#include <fs.h>
+
+class Chainstate;
+class CTxMemPool;
+
+namespace kernel {
+
+/** Dump the mempool to disk. */
+bool DumpMempool(const CTxMemPool& pool, const fs::path& dump_path,
+ fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen,
+ bool skip_file_commit = false);
+
+/** Load the mempool from disk. */
+bool LoadMempool(CTxMemPool& pool, const fs::path& load_path,
+ Chainstate& active_chainstate,
+ fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen);
+
+} // namespace kernel
+
+
+#endif // BITCOIN_KERNEL_MEMPOOL_PERSIST_H
diff --git a/src/kernel/validation_cache_sizes.h b/src/kernel/validation_cache_sizes.h
new file mode 100644
index 0000000000..72e4d1a52c
--- /dev/null
+++ b/src/kernel/validation_cache_sizes.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H
+#define BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H
+
+#include <script/sigcache.h>
+
+#include <cstddef>
+#include <limits>
+
+namespace kernel {
+struct ValidationCacheSizes {
+ size_t signature_cache_bytes{DEFAULT_MAX_SIG_CACHE_BYTES / 2};
+ size_t script_execution_cache_bytes{DEFAULT_MAX_SIG_CACHE_BYTES / 2};
+};
+}
+
+#endif // BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H