Page MenuHomePhabricator

No OneTemporary

diff --git a/src/script/script.h b/src/script/script.h
index 284490839..723a098e8 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -1,560 +1,561 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 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_SCRIPT_SCRIPT_H
#define BITCOIN_SCRIPT_SCRIPT_H
+#include <attributes.h>
#include <crypto/common.h>
#include <prevector.h>
#include <serialize.h>
#include <cassert>
#include <climits>
#include <cstdint>
#include <cstring>
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>
// Maximum number of bytes pushable to the stack
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
// Maximum number of non-push operations per script
static const int MAX_OPS_PER_SCRIPT = 201;
// Maximum number of public keys per multisig
static const int MAX_PUBKEYS_PER_MULTISIG = 20;
// Maximum script length in bytes
static const int MAX_SCRIPT_SIZE = 10000;
// Maximum number of values on script interpreter stack
static const int MAX_STACK_SIZE = 1000;
// Threshold for nLockTime: below this value it is interpreted as block number,
// otherwise as UNIX timestamp. Thresold is Tue Nov 5 00:53:20 1985 UTC
static const unsigned int LOCKTIME_THRESHOLD = 500000000;
template <typename T> std::vector<uint8_t> ToByteVector(const T &in) {
return std::vector<uint8_t>(in.begin(), in.end());
}
/** Script opcodes */
enum opcodetype {
// push value
OP_0 = 0x00,
OP_FALSE = OP_0,
OP_PUSHDATA1 = 0x4c,
OP_PUSHDATA2 = 0x4d,
OP_PUSHDATA4 = 0x4e,
OP_1NEGATE = 0x4f,
OP_RESERVED = 0x50,
OP_1 = 0x51,
OP_TRUE = OP_1,
OP_2 = 0x52,
OP_3 = 0x53,
OP_4 = 0x54,
OP_5 = 0x55,
OP_6 = 0x56,
OP_7 = 0x57,
OP_8 = 0x58,
OP_9 = 0x59,
OP_10 = 0x5a,
OP_11 = 0x5b,
OP_12 = 0x5c,
OP_13 = 0x5d,
OP_14 = 0x5e,
OP_15 = 0x5f,
OP_16 = 0x60,
// control
OP_NOP = 0x61,
OP_VER = 0x62,
OP_IF = 0x63,
OP_NOTIF = 0x64,
OP_VERIF = 0x65,
OP_VERNOTIF = 0x66,
OP_ELSE = 0x67,
OP_ENDIF = 0x68,
OP_VERIFY = 0x69,
OP_RETURN = 0x6a,
// stack ops
OP_TOALTSTACK = 0x6b,
OP_FROMALTSTACK = 0x6c,
OP_2DROP = 0x6d,
OP_2DUP = 0x6e,
OP_3DUP = 0x6f,
OP_2OVER = 0x70,
OP_2ROT = 0x71,
OP_2SWAP = 0x72,
OP_IFDUP = 0x73,
OP_DEPTH = 0x74,
OP_DROP = 0x75,
OP_DUP = 0x76,
OP_NIP = 0x77,
OP_OVER = 0x78,
OP_PICK = 0x79,
OP_ROLL = 0x7a,
OP_ROT = 0x7b,
OP_SWAP = 0x7c,
OP_TUCK = 0x7d,
// splice ops
OP_CAT = 0x7e,
OP_SPLIT = 0x7f, // after monolith upgrade (May 2018)
OP_NUM2BIN = 0x80, // after monolith upgrade (May 2018)
OP_BIN2NUM = 0x81, // after monolith upgrade (May 2018)
OP_SIZE = 0x82,
// bit logic
OP_INVERT = 0x83,
OP_AND = 0x84,
OP_OR = 0x85,
OP_XOR = 0x86,
OP_EQUAL = 0x87,
OP_EQUALVERIFY = 0x88,
OP_RESERVED1 = 0x89,
OP_RESERVED2 = 0x8a,
// numeric
OP_1ADD = 0x8b,
OP_1SUB = 0x8c,
OP_2MUL = 0x8d,
OP_2DIV = 0x8e,
OP_NEGATE = 0x8f,
OP_ABS = 0x90,
OP_NOT = 0x91,
OP_0NOTEQUAL = 0x92,
OP_ADD = 0x93,
OP_SUB = 0x94,
OP_MUL = 0x95,
OP_DIV = 0x96,
OP_MOD = 0x97,
OP_LSHIFT = 0x98,
OP_RSHIFT = 0x99,
OP_BOOLAND = 0x9a,
OP_BOOLOR = 0x9b,
OP_NUMEQUAL = 0x9c,
OP_NUMEQUALVERIFY = 0x9d,
OP_NUMNOTEQUAL = 0x9e,
OP_LESSTHAN = 0x9f,
OP_GREATERTHAN = 0xa0,
OP_LESSTHANOREQUAL = 0xa1,
OP_GREATERTHANOREQUAL = 0xa2,
OP_MIN = 0xa3,
OP_MAX = 0xa4,
OP_WITHIN = 0xa5,
// crypto
OP_RIPEMD160 = 0xa6,
OP_SHA1 = 0xa7,
OP_SHA256 = 0xa8,
OP_HASH160 = 0xa9,
OP_HASH256 = 0xaa,
OP_CODESEPARATOR = 0xab,
OP_CHECKSIG = 0xac,
OP_CHECKSIGVERIFY = 0xad,
OP_CHECKMULTISIG = 0xae,
OP_CHECKMULTISIGVERIFY = 0xaf,
// expansion
OP_NOP1 = 0xb0,
OP_CHECKLOCKTIMEVERIFY = 0xb1,
OP_NOP2 = OP_CHECKLOCKTIMEVERIFY,
OP_CHECKSEQUENCEVERIFY = 0xb2,
OP_NOP3 = OP_CHECKSEQUENCEVERIFY,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,
OP_NOP7 = 0xb6,
OP_NOP8 = 0xb7,
OP_NOP9 = 0xb8,
OP_NOP10 = 0xb9,
// More crypto
OP_CHECKDATASIG = 0xba,
OP_CHECKDATASIGVERIFY = 0xbb,
// additional byte string operations
OP_REVERSEBYTES = 0xbc,
// The first op_code value after all defined opcodes
FIRST_UNDEFINED_OP_VALUE,
// multi-byte opcodes
OP_PREFIX_BEGIN = 0xf0,
OP_PREFIX_END = 0xf7,
OP_INVALIDOPCODE = 0xff,
};
// Maximum value that an opcode can be
static const unsigned int MAX_OPCODE = FIRST_UNDEFINED_OP_VALUE - 1;
std::string GetOpName(opcodetype opcode);
/**
* Check whether the given stack element data would be minimally pushed using
* the given opcode.
*/
bool CheckMinimalPush(const std::vector<uint8_t> &data, opcodetype opcode);
class scriptnum_error : public std::runtime_error {
public:
explicit scriptnum_error(const std::string &str)
: std::runtime_error(str) {}
};
class CScriptNum {
/**
* Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte
* integers. The semantics are subtle, though: operands must be in the range
* [-2^31 +1...2^31 -1], but results may overflow (and are valid as long as
* they are not used in a subsequent numeric operation). CScriptNum enforces
* those semantics by storing results as an int64 and allowing out-of-range
* values to be returned as a vector of bytes but throwing an exception if
* arithmetic is done or the result is interpreted as an integer.
*/
public:
static const size_t MAXIMUM_ELEMENT_SIZE = 4;
explicit CScriptNum(const int64_t &n) { m_value = n; }
explicit CScriptNum(const std::vector<uint8_t> &vch, bool fRequireMinimal,
const size_t nMaxNumSize = MAXIMUM_ELEMENT_SIZE) {
if (vch.size() > nMaxNumSize) {
throw scriptnum_error("script number overflow");
}
if (fRequireMinimal && !IsMinimallyEncoded(vch, nMaxNumSize)) {
throw scriptnum_error("non-minimally encoded script number");
}
m_value = set_vch(vch);
}
static bool IsMinimallyEncoded(
const std::vector<uint8_t> &vch,
const size_t nMaxNumSize = CScriptNum::MAXIMUM_ELEMENT_SIZE);
static bool MinimallyEncode(std::vector<uint8_t> &data);
inline bool operator==(const int64_t &rhs) const { return m_value == rhs; }
inline bool operator!=(const int64_t &rhs) const { return m_value != rhs; }
inline bool operator<=(const int64_t &rhs) const { return m_value <= rhs; }
inline bool operator<(const int64_t &rhs) const { return m_value < rhs; }
inline bool operator>=(const int64_t &rhs) const { return m_value >= rhs; }
inline bool operator>(const int64_t &rhs) const { return m_value > rhs; }
inline bool operator==(const CScriptNum &rhs) const {
return operator==(rhs.m_value);
}
inline bool operator!=(const CScriptNum &rhs) const {
return operator!=(rhs.m_value);
}
inline bool operator<=(const CScriptNum &rhs) const {
return operator<=(rhs.m_value);
}
inline bool operator<(const CScriptNum &rhs) const {
return operator<(rhs.m_value);
}
inline bool operator>=(const CScriptNum &rhs) const {
return operator>=(rhs.m_value);
}
inline bool operator>(const CScriptNum &rhs) const {
return operator>(rhs.m_value);
}
inline CScriptNum operator+(const int64_t &rhs) const {
return CScriptNum(m_value + rhs);
}
inline CScriptNum operator-(const int64_t &rhs) const {
return CScriptNum(m_value - rhs);
}
inline CScriptNum operator+(const CScriptNum &rhs) const {
return operator+(rhs.m_value);
}
inline CScriptNum operator-(const CScriptNum &rhs) const {
return operator-(rhs.m_value);
}
inline CScriptNum operator/(const int64_t &rhs) const {
return CScriptNum(m_value / rhs);
}
inline CScriptNum operator/(const CScriptNum &rhs) const {
return operator/(rhs.m_value);
}
inline CScriptNum operator%(const int64_t &rhs) const {
return CScriptNum(m_value % rhs);
}
inline CScriptNum operator%(const CScriptNum &rhs) const {
return operator%(rhs.m_value);
}
inline CScriptNum &operator+=(const CScriptNum &rhs) {
return operator+=(rhs.m_value);
}
inline CScriptNum &operator-=(const CScriptNum &rhs) {
return operator-=(rhs.m_value);
}
inline CScriptNum operator&(const int64_t &rhs) const {
return CScriptNum(m_value & rhs);
}
inline CScriptNum operator&(const CScriptNum &rhs) const {
return operator&(rhs.m_value);
}
inline CScriptNum &operator&=(const CScriptNum &rhs) {
return operator&=(rhs.m_value);
}
inline CScriptNum operator-() const {
assert(m_value != std::numeric_limits<int64_t>::min());
return CScriptNum(-m_value);
}
inline CScriptNum &operator=(const int64_t &rhs) {
m_value = rhs;
return *this;
}
inline CScriptNum &operator+=(const int64_t &rhs) {
assert(
rhs == 0 ||
(rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
(rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
m_value += rhs;
return *this;
}
inline CScriptNum &operator-=(const int64_t &rhs) {
assert(
rhs == 0 ||
(rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
(rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
m_value -= rhs;
return *this;
}
inline CScriptNum &operator&=(const int64_t &rhs) {
m_value &= rhs;
return *this;
}
int getint() const {
if (m_value > std::numeric_limits<int>::max()) {
return std::numeric_limits<int>::max();
} else if (m_value < std::numeric_limits<int>::min()) {
return std::numeric_limits<int>::min();
}
return m_value;
}
std::vector<uint8_t> getvch() const { return serialize(m_value); }
static std::vector<uint8_t> serialize(const int64_t &value) {
if (value == 0) {
return {};
}
std::vector<uint8_t> result;
const bool neg = value < 0;
uint64_t absvalue = neg ? ~static_cast<uint64_t>(value) + 1
: static_cast<uint64_t>(value);
while (absvalue) {
result.push_back(absvalue & 0xff);
absvalue >>= 8;
}
// - If the most significant byte is >= 0x80 and the value is positive,
// push a new zero-byte to make the significant byte < 0x80 again.
// - If the most significant byte is >= 0x80 and the value is negative,
// push a new 0x80 byte that will be popped off when converting to an
// integral.
// - If the most significant byte is < 0x80 and the value is negative,
// add 0x80 to it, since it will be subtracted and interpreted as a
// negative when converting to an integral.
if (result.back() & 0x80) {
result.push_back(neg ? 0x80 : 0);
} else if (neg) {
result.back() |= 0x80;
}
return result;
}
private:
static int64_t set_vch(const std::vector<uint8_t> &vch) {
if (vch.empty()) {
return 0;
}
int64_t result = 0;
for (size_t i = 0; i != vch.size(); ++i) {
result |= int64_t(vch[i]) << 8 * i;
}
// If the input vector's most significant byte is 0x80, remove it from
// the result's msb and return a negative.
if (vch.back() & 0x80) {
return -int64_t(result & ~(0x80ULL << (8 * (vch.size() - 1))));
}
return result;
}
int64_t m_value;
};
/**
* We use a prevector for the script to reduce the considerable memory overhead
* of vectors in cases where they normally contain a small number of small
* elements. Tests in October 2015 showed use of this reduced dbcache memory
* usage by 23% and made an initial sync 13% faster.
*/
typedef prevector<28, uint8_t> CScriptBase;
bool GetScriptOp(CScriptBase::const_iterator &pc,
CScriptBase::const_iterator end, opcodetype &opcodeRet,
std::vector<uint8_t> *pvchRet);
/** Serialized script, used inside transaction inputs and outputs */
class CScript : public CScriptBase {
protected:
CScript &push_int64(int64_t n) {
if (n == -1 || (n >= 1 && n <= 16)) {
push_back(n + (OP_1 - 1));
} else if (n == 0) {
push_back(OP_0);
} else {
*this << CScriptNum::serialize(n);
}
return *this;
}
public:
CScript() {}
CScript(const_iterator pbegin, const_iterator pend)
: CScriptBase(pbegin, pend) {}
CScript(std::vector<uint8_t>::const_iterator pbegin,
std::vector<uint8_t>::const_iterator pend)
: CScriptBase(pbegin, pend) {}
CScript(const uint8_t *pbegin, const uint8_t *pend)
: CScriptBase(pbegin, pend) {}
SERIALIZE_METHODS(CScript, obj) { READWRITEAS(CScriptBase, obj); }
explicit CScript(int64_t b) { operator<<(b); }
explicit CScript(opcodetype b) { operator<<(b); }
explicit CScript(const CScriptNum &b) { operator<<(b); }
// delete non-existent constructor to defend against future introduction
// e.g. via prevector
explicit CScript(const std::vector<uint8_t> &b) = delete;
/** Delete non-existent operator to defend against future introduction */
CScript &operator<<(const CScript &b) = delete;
- CScript &operator<<(int64_t b) { return push_int64(b); }
+ CScript &operator<<(int64_t b) LIFETIMEBOUND { return push_int64(b); }
- CScript &operator<<(opcodetype opcode) {
+ CScript &operator<<(opcodetype opcode) LIFETIMEBOUND {
if (opcode < 0 || opcode > 0xff) {
throw std::runtime_error("CScript::operator<<(): invalid opcode");
}
insert(end(), uint8_t(opcode));
return *this;
}
- CScript &operator<<(const CScriptNum &b) {
+ CScript &operator<<(const CScriptNum &b) LIFETIMEBOUND {
*this << b.getvch();
return *this;
}
- CScript &operator<<(const std::vector<uint8_t> &b) {
+ CScript &operator<<(const std::vector<uint8_t> &b) LIFETIMEBOUND {
if (b.size() < OP_PUSHDATA1) {
insert(end(), uint8_t(b.size()));
} else if (b.size() <= 0xff) {
insert(end(), OP_PUSHDATA1);
insert(end(), uint8_t(b.size()));
} else if (b.size() <= 0xffff) {
insert(end(), OP_PUSHDATA2);
uint8_t _data[2];
WriteLE16(_data, b.size());
insert(end(), _data, _data + sizeof(_data));
} else {
insert(end(), OP_PUSHDATA4);
uint8_t _data[4];
WriteLE32(_data, b.size());
insert(end(), _data, _data + sizeof(_data));
}
insert(end(), b.begin(), b.end());
return *this;
}
bool GetOp(const_iterator &pc, opcodetype &opcodeRet,
std::vector<uint8_t> &vchRet) const {
return GetScriptOp(pc, end(), opcodeRet, &vchRet);
}
bool GetOp(const_iterator &pc, opcodetype &opcodeRet) const {
return GetScriptOp(pc, end(), opcodeRet, nullptr);
}
/** Encode/decode small integers: */
static int DecodeOP_N(opcodetype opcode) {
if (opcode == OP_0) {
return 0;
}
assert(opcode >= OP_1 && opcode <= OP_16);
return int(opcode) - int(OP_1 - 1);
}
static opcodetype EncodeOP_N(int n) {
assert(n >= 0 && n <= 16);
if (n == 0) {
return OP_0;
}
return (opcodetype)(OP_1 + n - 1);
}
bool IsPayToScriptHash() const;
bool IsCommitment(const std::vector<uint8_t> &data) const;
bool IsWitnessProgram(int &version, std::vector<uint8_t> &program) const;
bool IsWitnessProgram() const;
/**
* Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it
* consensus-critical).
*/
bool IsPushOnly(const_iterator pc) const;
bool IsPushOnly() const;
/** Check if the script contains valid OP_CODES */
bool HasValidOps() const;
/**
* Returns whether the script is guaranteed to fail at execution, regardless
* of the initial stack. This allows outputs to be pruned instantly when
* entering the UTXO set.
*/
bool IsUnspendable() const {
return (size() > 0 && *begin() == OP_RETURN) ||
(size() > MAX_SCRIPT_SIZE);
}
void clear() {
// The default prevector::clear() does not release memory
CScriptBase::clear();
shrink_to_fit();
}
};
#endif // BITCOIN_SCRIPT_SCRIPT_H
diff --git a/src/validation.h b/src/validation.h
index e6a8d1c19..c0c472ada 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -1,1418 +1,1419 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Copyright (c) 2017-2020 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_VALIDATION_H
#define BITCOIN_VALIDATION_H
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif
#include <attributes.h>
#include <blockfileinfo.h>
#include <blockindexworkcomparator.h>
#include <coins.h>
#include <consensus/amount.h>
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <disconnectresult.h>
#include <flatfile.h>
#include <fs.h>
#include <node/utxo_snapshot.h>
#include <policy/packages.h>
#include <protocol.h> // For CMessageHeader::MessageMagic
#include <script/script_error.h>
#include <script/script_metrics.h>
#include <sync.h>
#include <txdb.h>
#include <txmempool.h> // For CTxMemPool::cs
#include <util/check.h>
#include <util/hasher.h>
#include <util/translation.h>
#include <versionbits.h>
#include <atomic>
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <thread>
#include <utility>
#include <vector>
class BlockValidationState;
class CBlockIndex;
class CBlockTreeDB;
class CBlockUndo;
class CChainParams;
class CChain;
class CChainState;
class CConnman;
class CInv;
class ChainstateManager;
class Config;
class CScriptCheck;
class CTxMemPool;
class CTxUndo;
class DisconnectedBlockTransactions;
struct CCheckpointData;
struct ChainTxData;
struct FlatFilePos;
struct PrecomputedTransactionData;
struct LockPoints;
struct AssumeutxoData;
namespace Consensus {
struct Params;
}
#define MIN_TRANSACTION_SIZE \
(::GetSerializeSize(CTransaction(), PROTOCOL_VERSION))
/** Default for -minrelaytxfee, minimum relay fee for transactions */
static const Amount DEFAULT_MIN_RELAY_TX_FEE_PER_KB(1000 * SATOSHI);
/** Default for -excessutxocharge for transactions transactions */
static const Amount DEFAULT_UTXO_FEE = Amount::zero();
/**
* 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) */
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
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;
static const bool DEFAULT_PEERBLOOMFILTERS = true;
/** Default for -stopatheight */
static const int DEFAULT_STOPATHEIGHT = 0;
/** Default for -maxreorgdepth */
static const int DEFAULT_MAX_REORG_DEPTH = 10;
/**
* Default for -finalizationdelay
* This is the minimum time between a block header reception and the block
* finalization.
* This value should be >> block propagation and validation time
*/
static const int64_t DEFAULT_MIN_FINALIZATION_DELAY = 2 * 60 * 60;
/**
* Block files containing a block-height within MIN_BLOCKS_TO_KEEP of
* ActiveChain().Tip() will not be pruned.
*/
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
static const signed int DEFAULT_CHECKBLOCKS = 6;
static const unsigned int DEFAULT_CHECKLEVEL = 3;
/**
* Require that user allocate at least 550 MiB for block & undo files
* (blk???.dat and rev???.dat)
* At 1MB per block, 288 blocks = 288MB.
* Add 15% for Undo data = 331MB
* Add 20% for Orphan block rate = 397MB
* We want the low water mark after pruning to be at least 397 MB and since we
* prune in full block file chunks, we need the high water mark which triggers
* the prune to be one 128MB block file + added 15% undo data = 147MB greater
* for a total of 545MB
* Setting the target to >= 550 MiB will make it likely we can respect the
* target.
*/
static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
/** Current sync state passed to tip changed callbacks. */
enum class SynchronizationState { INIT_REINDEX, INIT_DOWNLOAD, POST_INIT };
extern RecursiveMutex cs_main;
typedef std::unordered_map<BlockHash, CBlockIndex *, BlockHasher> BlockMap;
extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
extern uint256 g_best_block;
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;
/**
* Block hash whose ancestors we will assume to have valid scripts without
* checking them.
*/
extern BlockHash 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;
class BlockValidationOptions {
private:
uint64_t excessiveBlockSize;
bool checkPoW : 1;
bool checkMerkleRoot : 1;
public:
// Do full validation by default
explicit BlockValidationOptions(const Config &config);
explicit BlockValidationOptions(uint64_t _excessiveBlockSize,
bool _checkPow = true,
bool _checkMerkleRoot = true)
: excessiveBlockSize(_excessiveBlockSize), checkPoW(_checkPow),
checkMerkleRoot(_checkMerkleRoot) {}
BlockValidationOptions withCheckPoW(bool _checkPoW = true) const {
BlockValidationOptions ret = *this;
ret.checkPoW = _checkPoW;
return ret;
}
BlockValidationOptions
withCheckMerkleRoot(bool _checkMerkleRoot = true) const {
BlockValidationOptions ret = *this;
ret.checkMerkleRoot = _checkMerkleRoot;
return ret;
}
bool shouldValidatePoW() const { return checkPoW; }
bool shouldValidateMerkleRoot() const { return checkMerkleRoot; }
uint64_t getExcessiveBlockSize() const { return excessiveBlockSize; }
};
/**
* Unload database information.
*/
void UnloadBlockIndex(CTxMemPool *mempool, ChainstateManager &chainman);
/**
* Run instances of script checking worker threads
*/
void StartScriptCheckWorkerThreads(int threads_num);
/**
* Stop all of the script checking worker threads
*/
void StopScriptCheckWorkerThreads();
/**
* Return transaction from the block at block_index.
* If block_index is not provided, fall back to mempool.
* If mempool is not provided or the tx couldn't be found in mempool, fall back
* to g_txindex.
*
* @param[in] block_index The block to read from disk, or nullptr
* @param[in] mempool If block_index is not provided, look in the
* mempool, if provided
* @param[in] txid The txid
* @param[in] consensusParams The params
* @param[out] hashBlock The hash of block_index, if the tx was found via
* block_index
* @returns The tx if found, otherwise nullptr
*/
CTransactionRef GetTransaction(const CBlockIndex *const block_index,
const CTxMemPool *const mempool,
const TxId &txid,
const Consensus::Params &consensusParams,
BlockHash &hashBlock);
Amount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams);
bool AbortNode(BlockValidationState &state, const std::string &strMessage,
const bilingual_str &userMessage = bilingual_str{});
/**
* Guess verification progress (as a fraction between 0.0=genesis and
* 1.0=current tip).
*/
double GuessVerificationProgress(const ChainTxData &data,
const CBlockIndex *pindex);
/** Prune block files up to a given height */
void PruneBlockFilesManual(CChainState &active_chainstate,
int nManualPruneHeight);
/**
* Validation result for a single transaction mempool acceptance.
*/
struct MempoolAcceptResult {
/** Used to indicate the results of mempool validation. */
enum class ResultType {
//! Fully validated, valid.
VALID,
//! Invalid.
INVALID,
};
const ResultType m_result_type;
const TxValidationState m_state;
// The following fields are only present when m_result_type =
// ResultType::VALID
/** Raw base fees in satoshis. */
const std::optional<Amount> m_base_fees;
static MempoolAcceptResult Failure(TxValidationState state) {
return MempoolAcceptResult(state);
}
static MempoolAcceptResult Success(Amount fees) {
return MempoolAcceptResult(fees);
}
// Private constructors. Use static methods MempoolAcceptResult::Success,
// etc. to construct.
private:
/** Constructor for failure case */
explicit MempoolAcceptResult(TxValidationState state)
: m_result_type(ResultType::INVALID), m_state(state),
m_base_fees(std::nullopt) {
// Can be invalid or error
Assume(!state.IsValid());
}
/** Constructor for success case */
explicit MempoolAcceptResult(Amount fees)
: m_result_type(ResultType::VALID), m_base_fees(fees) {}
};
/**
* Validation result for package mempool acceptance.
*/
struct PackageMempoolAcceptResult {
const PackageValidationState m_state;
/**
* Map from txid to finished MempoolAcceptResults. The client is
* responsible for keeping track of the transaction objects themselves.
* If a result is not present, it means validation was unfinished for that
* transaction. If there was a package-wide error (see result in m_state),
* m_tx_results will be empty.
*/
std::map<const TxId, const MempoolAcceptResult> m_tx_results;
explicit PackageMempoolAcceptResult(
PackageValidationState state,
std::map<const TxId, const MempoolAcceptResult> &&results)
: m_state{state}, m_tx_results(std::move(results)) {}
/**
* Constructor to create a PackageMempoolAcceptResult from a
* MempoolAcceptResult
*/
explicit PackageMempoolAcceptResult(const TxId &txid,
const MempoolAcceptResult &result)
: m_tx_results{{txid, result}} {}
};
/**
* (try to) add transaction to memory pool
*
* @param[in] bypass_limits When true, don't enforce mempool fee limits.
* @param[in] test_accept When true, run validation checks but don't submit
* to mempool.
*/
MempoolAcceptResult
AcceptToMemoryPool(CChainState &active_chainstate, const Config &config,
CTxMemPool &pool, const CTransactionRef &tx,
bool bypass_limits, bool test_accept = false)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Atomically test acceptance of a package. If the package only contains one tx,
* package rules still apply.
*
* @param[in] txns Group of transactions which may be independent or contain
* parent-child dependencies. The transactions must not conflict, with each
* other, i.e. must not spend the same inputs. If any dependencies exist,
* parents must appear anywhere in the list before their children.
* @returns a PackageMempoolAcceptResult which includes a MempoolAcceptResult
* for each transaction. If a transaction fails, validation will exit early
* and some results may be missing.
*/
PackageMempoolAcceptResult
ProcessNewPackage(const Config &config, CChainState &active_chainstate,
CTxMemPool &pool, const Package &txns, bool test_accept)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Simple class for regulating resource usage during CheckInputScripts (and
* CScriptCheck), atomic so as to be compatible with parallel validation.
*/
class CheckInputsLimiter {
protected:
std::atomic<int64_t> remaining;
public:
explicit CheckInputsLimiter(int64_t limit) : remaining(limit) {}
bool consume_and_check(int consumed) {
auto newvalue = (remaining -= consumed);
return newvalue >= 0;
}
bool check() { return remaining >= 0; }
};
class TxSigCheckLimiter : public CheckInputsLimiter {
public:
TxSigCheckLimiter() : CheckInputsLimiter(MAX_TX_SIGCHECKS) {}
// Let's make this bad boy copiable.
TxSigCheckLimiter(const TxSigCheckLimiter &rhs)
: CheckInputsLimiter(rhs.remaining.load()) {}
TxSigCheckLimiter &operator=(const TxSigCheckLimiter &rhs) {
remaining = rhs.remaining.load();
return *this;
}
static TxSigCheckLimiter getDisabled() {
TxSigCheckLimiter txLimiter;
// Historically, there has not been a transaction with more than 20k sig
// checks on testnet or mainnet, so this effectively disable sigchecks.
txLimiter.remaining = 20000;
return txLimiter;
}
};
class ConnectTrace;
/**
* Check whether all of this transaction's input scripts succeed.
*
* This involves ECDSA signature checks so can be computationally intensive.
* This function should only be called after the cheap sanity checks in
* CheckTxInputs passed.
*
* If pvChecks is not nullptr, script checks are pushed onto it instead of being
* performed inline. Any script checks which are not necessary (eg due to script
* execution cache hits) are, obviously, not pushed onto pvChecks/run.
*
* Upon success nSigChecksOut will be filled in with either:
* - correct total for all inputs, or,
* - 0, in the case when checks were pushed onto pvChecks (i.e., a cache miss
* with pvChecks non-null), in which case the total can be found by executing
* pvChecks and adding the results.
*
* Setting sigCacheStore/scriptCacheStore to false will remove elements from the
* corresponding cache which are matched. This is useful for checking blocks
* where we will likely never need the cache entry again.
*
* pLimitSigChecks can be passed to limit the sigchecks count either in parallel
* or serial validation. With pvChecks null (serial validation), breaking the
* pLimitSigChecks limit will abort evaluation early and return false. With
* pvChecks not-null (parallel validation): the cached nSigChecks may itself
* break the limit in which case false is returned, OR, each entry in the
* returned pvChecks must be executed exactly once in order to probe the limit
* accurately.
*/
bool CheckInputScripts(const CTransaction &tx, TxValidationState &state,
const CCoinsViewCache &view, const uint32_t flags,
bool sigCacheStore, bool scriptCacheStore,
const PrecomputedTransactionData &txdata,
int &nSigChecksOut, TxSigCheckLimiter &txLimitSigChecks,
CheckInputsLimiter *pBlockLimitSigChecks,
std::vector<CScriptCheck> *pvChecks)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Handy shortcut to full fledged CheckInputScripts call.
*/
static inline bool
CheckInputScripts(const CTransaction &tx, TxValidationState &state,
const CCoinsViewCache &view, const uint32_t flags,
bool sigCacheStore, bool scriptCacheStore,
const PrecomputedTransactionData &txdata, int &nSigChecksOut)
EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
TxSigCheckLimiter nSigChecksTxLimiter;
return CheckInputScripts(tx, state, view, flags, sigCacheStore,
scriptCacheStore, txdata, nSigChecksOut,
nSigChecksTxLimiter, nullptr, nullptr);
}
/**
* Mark all the coins corresponding to a given transaction inputs as spent.
*/
void SpendCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo,
int nHeight);
/**
* Apply the effects of this transaction on the UTXO set represented by view.
*/
void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo,
int nHeight);
/**
* Test whether the LockPoints height and time are still valid on the current
* chain.
*/
bool TestLockPointValidity(const CChain &active_chain, const LockPoints *lp)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Check if transaction will be BIP68 final in the next block to be created on
* top of tip.
* @param[in] tip Chain tip to check tx sequence locks against.
* For example, the tip of the current active chain.
* @param[in] coins_view Any CCoinsView that provides access to the
* relevant coins for checking sequence locks. For example, it can be a
* CCoinsViewCache that isn't connected to anything but contains all the
* relevant coins, or a CCoinsViewMemPool that is connected to the mempool
* and chainstate UTXO set. In the latter case, the caller is responsible
* for holding the appropriate locks to ensure that calls to GetCoin()
* return correct coins.
* Simulates calling SequenceLocks() with data from the tip passed in.
* Optionally stores in LockPoints the resulting height and time
* calculated and the hash of the block needed for calculation or skips the
* calculation and uses the LockPoints passed in for evaluation. The LockPoints
* should not be considered valid if CheckSequenceLocks returns false.
*
* See consensus/consensus.h for flag definitions.
*/
bool CheckSequenceLocks(CBlockIndex *tip, const CCoinsView &coins_view,
const CTransaction &tx, int flags,
LockPoints *lp = nullptr,
bool useExistingLockPoints = false);
/**
* Closure representing one script verification.
* Note that this stores references to the spending transaction.
*
* Note that if pLimitSigChecks is passed, then failure does not imply that
* scripts have failed.
*/
class CScriptCheck {
private:
CTxOut m_tx_out;
const CTransaction *ptxTo;
unsigned int nIn;
uint32_t nFlags;
bool cacheStore;
ScriptError error;
ScriptExecutionMetrics metrics;
PrecomputedTransactionData txdata;
TxSigCheckLimiter *pTxLimitSigChecks;
CheckInputsLimiter *pBlockLimitSigChecks;
public:
CScriptCheck()
: ptxTo(nullptr), nIn(0), nFlags(0), cacheStore(false),
error(ScriptError::UNKNOWN), txdata(), pTxLimitSigChecks(nullptr),
pBlockLimitSigChecks(nullptr) {}
CScriptCheck(const CTxOut &outIn, const CTransaction &txToIn,
unsigned int nInIn, uint32_t nFlagsIn, bool cacheIn,
const PrecomputedTransactionData &txdataIn,
TxSigCheckLimiter *pTxLimitSigChecksIn = nullptr,
CheckInputsLimiter *pBlockLimitSigChecksIn = nullptr)
: m_tx_out(outIn), ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn),
cacheStore(cacheIn), error(ScriptError::UNKNOWN), txdata(txdataIn),
pTxLimitSigChecks(pTxLimitSigChecksIn),
pBlockLimitSigChecks(pBlockLimitSigChecksIn) {}
bool operator()();
void swap(CScriptCheck &check) {
std::swap(ptxTo, check.ptxTo);
std::swap(m_tx_out, check.m_tx_out);
std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore);
std::swap(error, check.error);
std::swap(metrics, check.metrics);
std::swap(txdata, check.txdata);
std::swap(pTxLimitSigChecks, check.pTxLimitSigChecks);
std::swap(pBlockLimitSigChecks, check.pBlockLimitSigChecks);
}
ScriptError GetScriptError() const { return error; }
ScriptExecutionMetrics GetScriptExecutionMetrics() const { return metrics; }
};
/** Functions for validating blocks and updating the block tree */
/**
* Context-independent validity checks.
*
* Returns true if the provided block is valid (has valid header,
* transactions are valid, block is a valid size, etc.)
*/
bool CheckBlock(const CBlock &block, BlockValidationState &state,
const Consensus::Params &params,
BlockValidationOptions validationOptions);
/**
* This is a variant of ContextualCheckTransaction which computes the contextual
* check for a transaction based on the chain tip.
*
* See consensus/consensus.h for flag definitions.
*/
bool ContextualCheckTransactionForCurrentBlock(
const CBlockIndex *active_chain_tip, const Consensus::Params &params,
const CTransaction &tx, TxValidationState &state, int flags = -1)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Check a block is completely valid from start to finish (only works on top of
* our current best block)
*/
bool TestBlockValidity(BlockValidationState &state, const CChainParams &params,
CChainState &chainstate, const CBlock &block,
CBlockIndex *pindexPrev,
BlockValidationOptions validationOptions)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* RAII wrapper for VerifyDB: Verify consistency of the block and coin
* databases.
*/
class CVerifyDB {
public:
CVerifyDB();
~CVerifyDB();
bool VerifyDB(CChainState &chainstate, const Config &config,
CCoinsView &coinsview, int nCheckLevel, int nCheckDepth)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
};
/** @see CChainState::FlushStateToDisk */
enum class FlushStateMode { NONE, IF_NEEDED, PERIODIC, ALWAYS };
/** Global variable that points to the active CCoinsView (protected by cs_main)
*/
extern std::unique_ptr<CCoinsViewCache> pcoinsTip;
/**
* Maintains a tree of blocks (stored in `m_block_index`) which is consulted
* to determine where the most-work tip is.
*
* This data is used mostly in `CChainState` - information about, e.g.,
* candidate tips is not maintained here.
*/
class BlockManager {
friend CChainState;
private:
/**
* Calculate the block/rev files to delete based on height specified
* by user with RPC command pruneblockchain
*/
void FindFilesToPruneManual(std::set<int> &setFilesToPrune,
int nManualPruneHeight, int chain_tip_height);
/**
* Prune block and undo files (blk???.dat and undo???.dat) so that the disk
* space used is less than a user-defined target. The user sets the target
* (in MB) on the command line or in config file. This will be run on
* startup and whenever new space is allocated in a block or undo file,
* staying below the target. Changing back to unpruned requires a reindex
* (which in this case means the blockchain must be re-downloaded.)
*
* Pruning functions are called from FlushStateToDisk when the global
* fCheckForPruning flag has been set. Block and undo files are deleted in
* lock-step (when blk00003.dat is deleted, so is rev00003.dat.) Pruning
* cannot take place until the longest chain is at least a certain length
* (100000 on mainnet, 1000 on testnet, 1000 on regtest). Pruning will never
* delete a block within a defined distance (currently 288) from the active
* chain's tip. The block index is updated by unsetting HAVE_DATA and
* HAVE_UNDO for any blocks that were stored in the deleted files. A db flag
* records the fact that at least some block files have been pruned.
*
* @param[out] setFilesToPrune The set of file indices that can be
* unlinked will be returned
*/
void FindFilesToPrune(std::set<int> &setFilesToPrune,
uint64_t nPruneAfterHeight, int chain_tip_height,
int prune_height, bool is_ibd);
public:
BlockMap m_block_index GUARDED_BY(cs_main);
/**
* 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 m_block_index 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 m_block_index 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 m_block_index 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;
/**
* All pairs A->B, where A (or one of its ancestors) misses transactions,
* but B has transactions. Pruned nodes may have entries where B is missing
* data.
*/
std::multimap<CBlockIndex *, CBlockIndex *> m_blocks_unlinked;
/**
* Load the blocktree off disk and into memory. Populate certain metadata
* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as
* peripheral collections like setDirtyBlockIndex.
*
* @param[out] block_index_candidates Fill this set with any valid blocks
* for which we've downloaded all transactions.
*/
bool LoadBlockIndex(const Consensus::Params &consensus_params,
CBlockTreeDB &blocktree,
std::set<CBlockIndex *, CBlockIndexWorkComparator>
&block_index_candidates)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Clear all data members. */
void Unload() 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 BlockHash &hash)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
//! Mark one block file as pruned (modify associated database entries)
void PruneOneBlockFile(const int fileNumber)
EXCLUSIVE_LOCKS_REQUIRED(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
* m_block_index.
*/
bool AcceptBlockHeader(const Config &config, const CBlockHeader &block,
BlockValidationState &state, CBlockIndex **ppindex)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CBlockIndex *LookupBlockIndex(const BlockHash &hash) const
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** 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);
//! Returns last CBlockIndex* that is a checkpoint
CBlockIndex *GetLastCheckpoint(const CCheckpointData &data)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Return the spend height, which is one more than the
* inputs.GetBestBlock(). While checking, GetBestBlock() refers to the
* parent block. (protected by cs_main)
* This is also true for mempool checks.
*/
int GetSpendHeight(const CCoinsViewCache &inputs)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
~BlockManager() { Unload(); }
};
/**
* A convenience class for constructing the CCoinsView* hierarchy used
* to facilitate access to the UTXO set.
*
* This class consists of an arrangement of layered CCoinsView objects,
* preferring to store and retrieve coins in memory via `m_cacheview` but
* ultimately falling back on cache misses to the canonical store of UTXOs on
* disk, `m_dbview`.
*/
class CoinsViews {
public:
//! The lowest level of the CoinsViews cache hierarchy sits in a leveldb
//! database on disk. All unspent coins reside in this store.
CCoinsViewDB m_dbview GUARDED_BY(cs_main);
//! This view wraps access to the leveldb instance and handles read errors
//! gracefully.
CCoinsViewErrorCatcher m_catcherview GUARDED_BY(cs_main);
//! This is the top layer of the cache hierarchy - it keeps as many coins in
//! memory as can fit per the dbcache setting.
std::unique_ptr<CCoinsViewCache> m_cacheview GUARDED_BY(cs_main);
//! This constructor initializes CCoinsViewDB and CCoinsViewErrorCatcher
//! instances, but it *does not* create a CCoinsViewCache instance by
//! default. This is done separately because the presence of the cache has
//! implications on whether or not we're allowed to flush the cache's 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);
//! Initialize the CCoinsViewCache member.
void InitCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
};
enum class CoinsCacheSizeState {
//! The coins cache is in immediate need of a flush.
CRITICAL = 2,
//! The cache is at >= 90% capacity.
LARGE = 1,
OK = 0
};
/**
* CChainState stores and provides an API to update our local knowledge of the
* current best chain.
*
* 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).
*
* Anything that is contingent on the current tip of the chain is stored here,
* whereas block information and metadata independent of the current tip is
* kept in `BlockMetadataManager`.
*/
class CChainState {
private:
/**
* the ChainState CriticalSection
* A lock that must be held when modifying this ChainState - held in
* ActivateBestChain()
*/
RecursiveMutex m_cs_chainstate;
/**
* Every received block is assigned a unique and increasing identifier, so
* we know which one to give priority in case of a fork.
* Blocks loaded from disk are assigned id 0, so start the counter at 1.
*/
std::atomic<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;
/**
* 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};
//! mempool that is kept in sync with the chain
CTxMemPool &m_mempool;
const CChainParams &m_params;
//! Manages the UTXO set, which is a reflection of the contents of
//! `m_chain`.
std::unique_ptr<CoinsViews> m_coins_views;
/**
* The best finalized block.
* This block cannot be reorged in any way except by explicit user action.
*/
const CBlockIndex *m_finalizedBlockIndex GUARDED_BY(cs_main) = nullptr;
mutable Mutex cs_avalancheFinalizedBlockIndex;
/**
* The best block via avalanche voting.
* This block cannot be reorged in any way except by explicit user action.
*/
const CBlockIndex *m_avalancheFinalizedBlockIndex
GUARDED_BY(cs_avalancheFinalizedBlockIndex) = nullptr;
public:
//! Reference to a BlockManager instance which itself is shared across all
//! CChainState instances.
BlockManager &m_blockman;
explicit CChainState(
CTxMemPool &mempool, BlockManager &blockman,
std::optional<BlockHash> from_snapshot_blockhash = std::nullopt);
/**
* Initialize the CoinsViews UTXO set database management data structures.
* The in-memory cache is initialized separately.
*
* All parameters forwarded to CoinsViews.
*/
void InitCoinsDB(size_t cache_size_bytes, bool in_memory, bool should_wipe,
std::string leveldb_name = "chainstate");
//! Initialize the in-memory coins cache (to be done after the health of the
//! on-disk database is verified).
void InitCoinsCache(size_t cache_size_bytes)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
//! @returns whether or not the CoinsViews object has been fully initialized
//! and we can
//! safely flush this object to disk.
bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
return m_coins_views && m_coins_views->m_cacheview;
}
//! The current chain of blockheaders we consult and build on.
//! @see CChain, CBlockIndex.
CChain m_chain;
/**
* The blockhash which is the base of the snapshot this chainstate was
* created from.
*
* std::nullopt if this chainstate was not created from a snapshot.
*/
const std::optional<BlockHash> m_from_snapshot_blockhash{};
/**
* 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;
//! @returns A reference to the in-memory cache of the UTXO set.
CCoinsViewCache &CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
assert(m_coins_views->m_cacheview);
return *m_coins_views->m_cacheview.get();
}
//! @returns A reference to the on-disk UTXO set database.
CCoinsViewDB &CoinsDB() { return m_coins_views->m_dbview; }
//! @returns A reference to a wrapped view of the in-memory UTXO set that
//! handles disk read errors gracefully.
CCoinsViewErrorCatcher &CoinsErrorCatcher()
EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
return m_coins_views->m_catcherview;
}
//! Destructs all objects related to accessing the UTXO set.
void ResetCoinsViews() { m_coins_views.reset(); }
//! The cache size of the on-disk coins view.
size_t m_coinsdb_cache_size_bytes{0};
//! The cache size of the in-memory coins view.
size_t m_coinstip_cache_size_bytes{0};
//! Resize the CoinsViews caches dynamically and flush state to disk.
//! @returns true unless an error occurred during the flush.
bool ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** Import blocks from an external file */
void LoadExternalBlockFile(const Config &config, FILE *fileIn,
FlatFilePos *dbp = nullptr);
/**
* 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.
*
* @returns true unless a system error occurred
*/
bool FlushStateToDisk(BlockValidationState &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();
/**
* Find the best known block, and make it the tip of the block chain. 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.
*
* May not be called with cs_main held. May not be called in a
* validationinterface callback.
*
* @returns true unless a system error occurred
*/
bool ActivateBestChain(const Config &config, BlockValidationState &state,
std::shared_ptr<const CBlock> pblock = nullptr)
LOCKS_EXCLUDED(cs_main);
bool AcceptBlock(const Config &config,
const std::shared_ptr<const CBlock> &pblock,
BlockValidationState &state, 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, BlockValidationState &state,
CBlockIndex *pindex, CCoinsViewCache &view,
BlockValidationOptions options, bool fJustCheck = false)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Block disconnection on our pcoinsTip:
bool DisconnectTip(BlockValidationState &state,
DisconnectedBlockTransactions *disconnectpool)
EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
// Manual block validity manipulation:
/**
* Mark a block as precious and reorganize.
*
* May not be called in a validationinterface callback.
*/
bool PreciousBlock(const Config &config, BlockValidationState &state,
CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main);
/** Mark a block as invalid. */
bool InvalidateBlock(const Config &config, BlockValidationState &state,
CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main)
EXCLUSIVE_LOCKS_REQUIRED(!m_cs_chainstate);
/** Park a block. */
bool ParkBlock(const Config &config, BlockValidationState &state,
CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main)
EXCLUSIVE_LOCKS_REQUIRED(!m_cs_chainstate);
/**
* Finalize a block.
* A finalized block can not be reorged in any way.
*/
bool FinalizeBlock(const Config &config, BlockValidationState &state,
CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main)
EXCLUSIVE_LOCKS_REQUIRED(!m_cs_chainstate);
/** Return the currently finalized block index. */
const CBlockIndex *GetFinalizedBlock() const
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Checks if a block is finalized.
*/
bool IsBlockFinalized(const CBlockIndex *pindex) const
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Mark a block as finalized by avalanche.
*/
bool AvalancheFinalizeBlock(CBlockIndex *pindex);
/**
* Checks if a block is finalized by avalanche voting.
*/
bool IsBlockAvalancheFinalized(const CBlockIndex *pindex) const;
/** Remove invalidity status from a block and its descendants. */
void ResetBlockFailureFlags(CBlockIndex *pindex)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
template <typename F>
bool UpdateFlagsForBlock(CBlockIndex *pindexBase, CBlockIndex *pindex, F f)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
template <typename F, typename C, typename AC>
void UpdateFlags(CBlockIndex *pindex, CBlockIndex *&pindexReset, F f,
C fChild, AC fAncestorWasChanged)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Remove parked status from a block and its descendants. */
void UnparkBlockAndChildren(CBlockIndex *pindex)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Remove parked status from a block. */
void UnparkBlock(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Replay blocks that aren't fully applied to the database. */
bool ReplayBlocks();
/**
* Ensures we have a genesis block in the block tree, possibly writing one
* to disk.
*/
bool LoadGenesisBlock();
void PruneBlockIndexCandidates();
void UnloadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Check whether we are doing an initial block download (synchronizing from
* disk or network)
*/
bool IsInitialBlockDownload() const;
/**
* 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();
/** Load the persisted mempool from disk */
void LoadMempool(const Config &config, const ArgsManager &args);
/** Update the chain tip based on database information, i.e. CoinsTip()'s
* best block. */
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
//! Dictates whether we need to flush the cache to disk or not.
//!
//! @return the state of the size of the coins cache.
CoinsCacheSizeState GetCoinsCacheSizeState(const CTxMemPool *tx_pool)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
CoinsCacheSizeState GetCoinsCacheSizeState(
const CTxMemPool *tx_pool, size_t max_coins_cache_size_bytes,
size_t max_mempool_size_bytes) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
std::string ToString() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
private:
bool ActivateBestChainStep(const Config &config,
BlockValidationState &state,
CBlockIndex *pindexMostWork,
const std::shared_ptr<const CBlock> &pblock,
bool &fInvalidFound, ConnectTrace &connectTrace)
EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
bool ConnectTip(const Config &config, BlockValidationState &state,
CBlockIndex *pindexNew,
const std::shared_ptr<const CBlock> &pblock,
ConnectTrace &connectTrace,
DisconnectedBlockTransactions &disconnectpool)
EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
void InvalidBlockFound(CBlockIndex *pindex,
const BlockValidationState &state)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CBlockIndex *FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool MarkBlockAsFinal(BlockValidationState &state,
const CBlockIndex *pindex)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void ReceivedBlockTransactions(const CBlock &block, CBlockIndex *pindexNew,
const FlatFilePos &pos)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &inputs)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void UnparkBlockImpl(CBlockIndex *pindex, bool fClearChildren)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool UnwindBlock(const Config &config, BlockValidationState &state,
CBlockIndex *pindex, bool invalidate)
EXCLUSIVE_LOCKS_REQUIRED(m_cs_chainstate);
void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void CheckForkWarningConditionsOnNewFork(CBlockIndex *pindexNewForkTip)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void InvalidChainFound(CBlockIndex *pindexNew)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
const CBlockIndex *FindBlockToFinalize(CBlockIndex *pindexNew)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
friend ChainstateManager;
};
/**
* Provides an interface for creating and interacting with one or two
* chainstates: an IBD chainstate generated by downloading blocks, and
* an optional snapshot chainstate loaded from a UTXO snapshot. Managed
* chainstates can be maintained at different heights simultaneously.
*
* This class provides abstractions that allow the retrieval of the current
* most-work chainstate ("Active") as well as chainstates which may be in
* background use to validate UTXO snapshots.
*
* Definitions:
*
* *IBD chainstate*: a chainstate whose current state has been "fully"
* validated by the initial block download process.
*
* *Snapshot chainstate*: a chainstate populated by loading in an
* assumeutxo UTXO snapshot.
*
* *Active chainstate*: the chainstate containing the current most-work
* chain. Consulted by most parts of the system (net_processing,
* wallet) as a reflection of the current chain and UTXO set.
* This may either be an IBD chainstate or a snapshot chainstate.
*
* *Background IBD chainstate*: an IBD chainstate for which the
* IBD process is happening in the background while use of the
* active (snapshot) chainstate allows the rest of the system to function.
*
* *Validated chainstate*: the most-work chainstate which has been validated
* locally via initial block download. This will be the snapshot chainstate
* if a snapshot was loaded and all blocks up to the snapshot starting point
* have been downloaded and validated (via background validation), otherwise
* it will be the IBD chainstate.
*/
class ChainstateManager {
private:
//! The chainstate used under normal operation (i.e. "regular" IBD) or, if
//! a snapshot is in use, for background validation.
//!
//! Its contents (including on-disk data) will be deleted *upon shutdown*
//! after background validation of the snapshot has completed. We do not
//! free the chainstate contents immediately after it finishes validation
//! to cautiously avoid a case where some other part of the system is still
//! using this pointer (e.g. net_processing).
//!
//! Once this pointer is set to a corresponding chainstate, it will not
//! be reset until init.cpp:Shutdown().
//!
//! This is especially important when, e.g., calling ActivateBestChain()
//! on all chainstates because we are not able to hold ::cs_main going into
//! that call.
std::unique_ptr<CChainState> m_ibd_chainstate GUARDED_BY(::cs_main);
//! A chainstate initialized on the basis of a UTXO snapshot. If this is
//! non-null, it is always our active chainstate.
//!
//! Once this pointer is set to a corresponding chainstate, it will not
//! be reset until init.cpp:Shutdown().
//!
//! This is especially important when, e.g., calling ActivateBestChain()
//! on all chainstates because we are not able to hold ::cs_main going into
//! that call.
std::unique_ptr<CChainState> m_snapshot_chainstate GUARDED_BY(::cs_main);
//! Points to either the ibd or snapshot chainstate; indicates our
//! most-work chain.
//!
//! Once this pointer is set to a corresponding chainstate, it will not
//! be reset until init.cpp:Shutdown().
//!
//! This is especially important when, e.g., calling ActivateBestChain()
//! on all chainstates because we are not able to hold ::cs_main going into
//! that call.
CChainState *m_active_chainstate GUARDED_BY(::cs_main){nullptr};
//! If true, the assumed-valid chainstate has been fully validated
//! by the background validation chainstate.
bool m_snapshot_validated{false};
//! Internal helper for ActivateSnapshot().
[[nodiscard]] bool
PopulateAndValidateSnapshot(CChainState &snapshot_chainstate,
CAutoFile &coins_file,
const SnapshotMetadata &metadata);
public:
std::thread m_load_block;
//! A single BlockManager instance is shared across each constructed
//! chainstate to avoid duplicating block metadata.
BlockManager m_blockman GUARDED_BY(::cs_main);
//! 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};
//
//! The total number of bytes available for us to use across all leveldb
//! coins databases. This will be split somehow across chainstates.
int64_t m_total_coinsdb_cache{0};
//! Instantiate a new chainstate and assign it based upon whether it is
//! from a snapshot.
//!
//! @param[in] mempool The mempool to pass to the chainstate
// constructor
//! @param[in] snapshot_blockhash If given, signify that this chainstate
//! is based on a snapshot.
- CChainState &InitializeChainstate(
- CTxMemPool &mempool,
- const std::optional<BlockHash> &snapshot_blockhash = std::nullopt)
+ CChainState &
+ InitializeChainstate(CTxMemPool &mempool,
+ const std::optional<BlockHash> &snapshot_blockhash =
+ std::nullopt) LIFETIMEBOUND
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
//! Get all chainstates currently being used.
std::vector<CChainState *> GetAll();
//! Construct and activate a Chainstate on the basis of UTXO snapshot data.
//!
//! Steps:
//!
//! - Initialize an unused CChainState.
//! - Load its `CoinsViews` contents from `coins_file`.
//! - Verify that the hash of the resulting coinsdb matches the expected
//! hash per assumeutxo chain parameters.
//! - Wait for our headers chain to include the base block of the snapshot.
//! - "Fast forward" the tip of the new chainstate to the base of the
//! snapshot, faking nTx* block index data along the way.
//! - Move the new chainstate to `m_snapshot_chainstate` and make it our
//! ActiveChainstate().
[[nodiscard]] bool ActivateSnapshot(CAutoFile &coins_file,
const SnapshotMetadata &metadata,
bool in_memory);
//! The most-work chain.
CChainState &ActiveChainstate() const;
CChain &ActiveChain() const { return ActiveChainstate().m_chain; }
int ActiveHeight() const { return ActiveChain().Height(); }
CBlockIndex *ActiveTip() const { return ActiveChain().Tip(); }
BlockMap &BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
return m_blockman.m_block_index;
}
//! @returns true if a snapshot-based chainstate is in use. Also implies
//! that a background validation chainstate is also in use.
bool IsSnapshotActive() const;
std::optional<BlockHash> SnapshotBlockhash() const;
//! Is there a snapshot in use and has it been fully validated?
bool IsSnapshotValidated() const { return m_snapshot_validated; }
//! @returns true if this chainstate is being used to validate an active
//! snapshot in the background.
bool IsBackgroundIBD(CChainState *chainstate) const;
//! Return the most-work chainstate that has been fully validated.
//!
//! During background validation of a snapshot, this is the IBD chain. After
//! background validation has completed, this is the snapshot chain.
CChainState &ValidatedChainstate() const;
CChain &ValidatedChain() const { return ValidatedChainstate().m_chain; }
CBlockIndex *ValidatedTip() const { return ValidatedChain().Tip(); }
/**
* Process an incoming block. This only returns after the best known valid
* block is made active. Note that it does not, however, guarantee that the
* specific block passed to it has been checked for validity!
*
* If you want to *possibly* get feedback on whether block is valid, you
* must install a CValidationInterface (see validationinterface.h) - this
* will have its BlockChecked method called whenever *any* block completes
* validation.
*
* Note that we guarantee that either the proof-of-work is valid on block,
* or (and possibly also) BlockChecked will have been called.
*
* May not be called in a validationinterface callback.
*
* @param[in] config The global config.
* @param[in] block The block we want to process.
* @param[in] force_processing Process this block even if unrequested;
* used for non-network block sources.
* @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 Config &config,
const std::shared_ptr<const CBlock> &block,
bool force_processing, bool *new_block)
LOCKS_EXCLUDED(cs_main);
/**
* Process incoming block headers.
*
* May not be called in a validationinterface callback.
*
* @param[in] config The config.
* @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[out] ppindex If set, the pointer will be set to point to the
* last new block index object for the given
* headers.
* @return True if block headers were accepted as valid.
*/
bool ProcessNewBlockHeaders(const Config &config,
const std::vector<CBlockHeader> &block,
BlockValidationState &state,
const CBlockIndex **ppindex = nullptr)
LOCKS_EXCLUDED(cs_main);
//! 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);
//! Clear (deconstruct) chainstate data.
void Reset();
//! 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);
Reset();
}
};
/**
* Global variable that points to the active block tree (protected by cs_main)
*/
extern std::unique_ptr<CBlockTreeDB> pblocktree;
extern VersionBitsCache versionbitscache;
/**
* Determine what nVersion a new block should use.
*/
int32_t ComputeBlockVersion(const CBlockIndex *pindexPrev,
const Consensus::Params &params);
/** Dump the mempool to disk. */
bool DumpMempool(const CTxMemPool &pool);
/** Load the mempool from disk. */
bool LoadMempool(const Config &config, CTxMemPool &pool,
CChainState &active_chainstate);
/**
* Return the expected assumeutxo value for a given height, if one exists.
*
* @param[in] height Get the assumeutxo value for this height.
*
* @returns empty if no assumeutxo configuration exists for the given height.
*/
const AssumeutxoData *ExpectedAssumeutxo(const int height,
const CChainParams &params);
#endif // BITCOIN_VALIDATION_H

File Metadata

Mime Type
text/x-diff
Expires
Sun, Apr 27, 10:07 (15 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5573197
Default Alt Text
(73 KB)

Event Timeline