Merge pull request #2971 from PastaPastaPasta/backports-0.15-pr13-p2
Backports 0.15 pr13 p2
This commit is contained in:
commit
d8df05b955
@ -91,10 +91,11 @@ int dashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int
|
||||
if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen)
|
||||
return set_error(err, dashconsensus_ERR_TX_SIZE_MISMATCH);
|
||||
|
||||
// Regardless of the verification result, the tx did not error.
|
||||
set_error(err, dashconsensus_ERR_OK);
|
||||
// Regardless of the verification result, the tx did not error.
|
||||
set_error(err, dashconsensus_ERR_OK);
|
||||
|
||||
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn), NULL);
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn, txdata), NULL);
|
||||
} catch (const std::exception&) {
|
||||
return set_error(err, dashconsensus_ERR_TX_DESERIALIZE); // Error deserializing
|
||||
}
|
||||
|
@ -1117,9 +1117,40 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
uint256 GetPrevoutHash(const CTransaction& txTo) {
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
|
||||
ss << txTo.vin[n].prevout;
|
||||
}
|
||||
return ss.GetHash();
|
||||
}
|
||||
|
||||
uint256 GetSequenceHash(const CTransaction& txTo) {
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
|
||||
ss << txTo.vin[n].nSequence;
|
||||
}
|
||||
return ss.GetHash();
|
||||
}
|
||||
|
||||
uint256 GetOutputsHash(const CTransaction& txTo) {
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (unsigned int n = 0; n < txTo.vout.size(); n++) {
|
||||
ss << txTo.vout[n];
|
||||
}
|
||||
return ss.GetHash();
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
|
||||
PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
|
||||
{
|
||||
hashPrevouts = GetPrevoutHash(txTo);
|
||||
hashSequence = GetSequenceHash(txTo);
|
||||
hashOutputs = GetOutputsHash(txTo);
|
||||
}
|
||||
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const PrecomputedTransactionData* cache)
|
||||
{
|
||||
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
if (nIn >= txTo.vin.size()) {
|
||||
@ -1162,7 +1193,7 @@ bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vch
|
||||
int nHashType = vchSig.back();
|
||||
vchSig.pop_back();
|
||||
|
||||
uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
|
||||
uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, this->txdata);
|
||||
|
||||
if (!VerifySignature(vchSig, pubkey, sighash))
|
||||
return false;
|
||||
|
@ -94,7 +94,14 @@ enum
|
||||
|
||||
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
|
||||
|
||||
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
struct PrecomputedTransactionData
|
||||
{
|
||||
uint256 hashPrevouts, hashSequence, hashOutputs;
|
||||
|
||||
PrecomputedTransactionData(const CTransaction& tx);
|
||||
};
|
||||
|
||||
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const PrecomputedTransactionData* cache = NULL);
|
||||
|
||||
class BaseSignatureChecker
|
||||
{
|
||||
@ -122,12 +129,14 @@ class TransactionSignatureChecker : public BaseSignatureChecker
|
||||
private:
|
||||
const CTransaction* txTo;
|
||||
unsigned int nIn;
|
||||
const PrecomputedTransactionData* txdata;
|
||||
|
||||
protected:
|
||||
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||
|
||||
public:
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn), txdata(NULL) {}
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), txdata(&txdataIn) {}
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const override;
|
||||
bool CheckLockTime(const CScriptNum& nLockTime) const override;
|
||||
bool CheckSequence(const CScriptNum& nSequence) const override;
|
||||
|
@ -46,7 +46,7 @@ private:
|
||||
bool store;
|
||||
|
||||
public:
|
||||
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn), store(storeIn) {}
|
||||
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, PrecomputedTransactionData& txdataIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn, txdataIn), store(storeIn) {}
|
||||
|
||||
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const override;
|
||||
};
|
||||
|
@ -104,19 +104,21 @@ BOOST_AUTO_TEST_CASE(sign)
|
||||
}
|
||||
// All of the above should be OK, and the txTos have valid signatures
|
||||
// Check to make sure signature verification fails if we use the wrong ScriptSig:
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
PrecomputedTransactionData txdata(txTo[i]);
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
CScript sigSave = txTo[i].vin[0].scriptSig;
|
||||
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
|
||||
const CTxOut& output = txFrom.vout[txTo[i].vin[0].prevout.n];
|
||||
bool sigOK = CScriptCheck(output.scriptPubKey, output.nValue, txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)();
|
||||
bool sigOK = CScriptCheck(output.scriptPubKey, output.nValue, txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
|
||||
if (i == j)
|
||||
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
|
||||
else
|
||||
BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
|
||||
txTo[i].vin[0].scriptSig = sigSave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(norecurse)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "test/test_dash.h"
|
||||
|
||||
#include "clientversion.h"
|
||||
#include "checkqueue.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "core_io.h"
|
||||
#include "key.h"
|
||||
@ -139,6 +140,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
|
||||
BOOST_CHECK(state.IsValid());
|
||||
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
|
||||
@ -149,7 +151,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
|
||||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||
verify_flags, TransactionSignatureChecker(&tx, i), &err),
|
||||
verify_flags, TransactionSignatureChecker(&tx, i, txdata), &err),
|
||||
strTest);
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
}
|
||||
@ -214,6 +216,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
CValidationState state;
|
||||
fValid = CheckTransaction(tx, state) && state.IsValid();
|
||||
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
for (unsigned int i = 0; i < tx.vin.size() && fValid; i++)
|
||||
{
|
||||
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
|
||||
@ -224,7 +227,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
|
||||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||
verify_flags, TransactionSignatureChecker(&tx, i), &err);
|
||||
verify_flags, TransactionSignatureChecker(&tx, i, txdata), &err);
|
||||
}
|
||||
BOOST_CHECK_MESSAGE(!fValid, strTest);
|
||||
BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
@ -206,8 +206,11 @@ enum FlushStateMode {
|
||||
};
|
||||
|
||||
// See definition for documentation
|
||||
bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0);
|
||||
void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight);
|
||||
static bool FlushStateToDisk(const CChainParams& chainParams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0);
|
||||
static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight);
|
||||
static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
|
||||
static bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = NULL);
|
||||
static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
|
||||
|
||||
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
|
||||
{
|
||||
@ -425,7 +428,6 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
|
||||
return EvaluateSequenceLocks(index, lockPair);
|
||||
}
|
||||
|
||||
|
||||
unsigned int GetLegacySigOpCount(const CTransaction& tx)
|
||||
{
|
||||
unsigned int nSigOps = 0;
|
||||
@ -574,7 +576,7 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state,
|
||||
return true;
|
||||
}
|
||||
|
||||
void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
|
||||
static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
|
||||
int expired = pool.Expire(GetTime() - age);
|
||||
if (expired != 0) {
|
||||
LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired);
|
||||
@ -607,7 +609,7 @@ static bool IsCurrentForFeeEstimation()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree,
|
||||
static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree,
|
||||
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit,
|
||||
const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache, bool fDryRun)
|
||||
{
|
||||
@ -833,7 +835,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||
|
||||
// Check against previous transactions
|
||||
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
||||
if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true))
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata))
|
||||
return false; // state filled in by CheckInputs
|
||||
|
||||
// Check again against just the consensus-critical mandatory script
|
||||
@ -845,7 +848,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||
// There is a similar check in CreateNewBlock() to prevent creating
|
||||
// invalid blocks, however allowing such transactions into the mempool
|
||||
// can be exploited as a DoS attack.
|
||||
if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true))
|
||||
if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata))
|
||||
{
|
||||
return error("%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s",
|
||||
__func__, hash.ToString(), FormatStateMessage(state));
|
||||
@ -883,12 +886,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
|
||||
/** (try to) add transaction to memory pool with a specified acceptance time **/
|
||||
static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
|
||||
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit,
|
||||
const CAmount nAbsurdFee, bool fDryRun)
|
||||
{
|
||||
std::vector<COutPoint> coins_to_uncache;
|
||||
bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, fDryRun);
|
||||
bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, fDryRun);
|
||||
if (!res || fDryRun) {
|
||||
if(!res) LogPrint(BCLog::MEMPOOL, "%s: %s %s (%s)\n", __func__, tx->GetHash().ToString(), state.GetRejectReason(), state.GetDebugMessage());
|
||||
BOOST_FOREACH(const COutPoint& hashTx, coins_to_uncache)
|
||||
@ -896,14 +900,15 @@ bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const
|
||||
}
|
||||
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
|
||||
CValidationState stateDummy;
|
||||
FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC);
|
||||
FlushStateToDisk(chainparams, stateDummy, FLUSH_STATE_PERIODIC);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
|
||||
bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee, bool fDryRun)
|
||||
{
|
||||
return AcceptToMemoryPoolWithTime(pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), fOverrideMempoolLimit, nAbsurdFee, fDryRun);
|
||||
const CChainParams& chainparams = Params();
|
||||
return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), fOverrideMempoolLimit, nAbsurdFee, fDryRun);
|
||||
}
|
||||
|
||||
bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &hashes)
|
||||
@ -1024,7 +1029,7 @@ bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus
|
||||
// CBlock and CBlockIndex
|
||||
//
|
||||
|
||||
bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
|
||||
static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
|
||||
{
|
||||
// Open history file to append
|
||||
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
|
||||
@ -1202,7 +1207,7 @@ bool IsInitialBlockDownload()
|
||||
|
||||
CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
|
||||
|
||||
void CheckForkWarningConditions()
|
||||
static void CheckForkWarningConditions()
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
// Before we get past initial download, we cannot reliably alert about forks
|
||||
@ -1250,7 +1255,7 @@ void CheckForkWarningConditions()
|
||||
}
|
||||
}
|
||||
|
||||
void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
|
||||
static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
// If we are on a fork that is sufficiently large, set a warning flag
|
||||
@ -1332,7 +1337,8 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
|
||||
|
||||
bool CScriptCheck::operator()() {
|
||||
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
|
||||
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) {
|
||||
PrecomputedTransactionData txdata(*ptxTo);
|
||||
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, txdata, cacheStore), &error)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -1391,7 +1397,12 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
|
||||
}
|
||||
}// namespace Consensus
|
||||
|
||||
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks)
|
||||
/**
|
||||
* Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
|
||||
* This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
|
||||
* instead of being performed inline.
|
||||
*/
|
||||
static bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks)
|
||||
{
|
||||
if (!tx.IsCoinBase())
|
||||
{
|
||||
@ -1425,7 +1436,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
|
||||
const CAmount amount = coin.out.nValue;
|
||||
|
||||
// Verify signature
|
||||
CScriptCheck check(scriptPubKey, amount, tx, i, flags, cacheStore);
|
||||
CScriptCheck check(scriptPubKey, amount, tx, i, flags, cacheStore, &txdata);
|
||||
if (pvChecks) {
|
||||
pvChecks->push_back(CScriptCheck());
|
||||
check.swap(pvChecks->back());
|
||||
@ -1438,7 +1449,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
|
||||
// avoid splitting the network between upgraded and
|
||||
// non-upgraded nodes.
|
||||
CScriptCheck check2(scriptPubKey, amount, tx, i,
|
||||
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore);
|
||||
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &txdata);
|
||||
if (check2())
|
||||
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
|
||||
}
|
||||
@ -1767,7 +1778,7 @@ void static FlushBlockFile(bool fFinalize = false)
|
||||
}
|
||||
}
|
||||
|
||||
bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
|
||||
static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
|
||||
|
||||
static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
|
||||
|
||||
@ -2016,6 +2027,9 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
|
||||
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
|
||||
|
||||
std::vector<PrecomputedTransactionData> txdata;
|
||||
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
|
||||
|
||||
bool fDIP0001Active_context = pindex->nHeight >= Params().GetConsensus().DIP0001Height;
|
||||
|
||||
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
||||
@ -2029,6 +2043,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
|
||||
return state.DoS(100, error("ConnectBlock(): too many sigops"),
|
||||
REJECT_INVALID, "bad-blk-sigops");
|
||||
|
||||
txdata.emplace_back(tx);
|
||||
if (!tx.IsCoinBase())
|
||||
{
|
||||
if (!view.HaveInputs(tx))
|
||||
@ -2103,7 +2118,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
|
||||
|
||||
std::vector<CScriptCheck> vChecks;
|
||||
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
|
||||
if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, nScriptCheckThreads ? &vChecks : NULL))
|
||||
if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : NULL))
|
||||
return error("ConnectBlock(): CheckInputs on %s failed with %s",
|
||||
tx.GetHash().ToString(), FormatStateMessage(state));
|
||||
control.Add(vChecks);
|
||||
@ -2317,9 +2332,8 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
|
||||
* 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.
|
||||
*/
|
||||
bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight) {
|
||||
bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight) {
|
||||
int64_t nMempoolUsage = mempool.DynamicMemoryUsage();
|
||||
const CChainParams& chainparams = Params();
|
||||
LOCK2(cs_main, cs_LastBlockFile);
|
||||
static int64_t nLastWrite = 0;
|
||||
static int64_t nLastFlush = 0;
|
||||
@ -2426,13 +2440,15 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int n
|
||||
|
||||
void FlushStateToDisk() {
|
||||
CValidationState state;
|
||||
FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
|
||||
const CChainParams& chainparams = Params();
|
||||
FlushStateToDisk(chainparams, state, FLUSH_STATE_ALWAYS);
|
||||
}
|
||||
|
||||
void PruneAndFlush() {
|
||||
CValidationState state;
|
||||
fCheckForPruning = true;
|
||||
FlushStateToDisk(state, FLUSH_STATE_NONE);
|
||||
const CChainParams& chainparams = Params();
|
||||
FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE);
|
||||
}
|
||||
|
||||
/** Update chainActive and related internal data structures. */
|
||||
@ -2521,7 +2537,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
|
||||
}
|
||||
LogPrint(BCLog::BENCHMARK, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
|
||||
// Write the chain state to disk, if necessary.
|
||||
if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
|
||||
if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED))
|
||||
return false;
|
||||
// Resurrect mempool transactions from the disconnected block.
|
||||
std::vector<uint256> vHashUpdate;
|
||||
@ -2665,7 +2681,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
|
||||
int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
|
||||
LogPrint(BCLog::BENCHMARK, " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001);
|
||||
// Write the chain state to disk, if necessary.
|
||||
if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
|
||||
if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED))
|
||||
return false;
|
||||
int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
|
||||
LogPrint(BCLog::BENCHMARK, " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
|
||||
@ -2965,7 +2981,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
|
||||
CheckBlockIndex(chainparams.GetConsensus());
|
||||
|
||||
// Write changes periodically to disk, after relay.
|
||||
if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) {
|
||||
if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_PERIODIC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3085,7 +3101,7 @@ bool ResetBlockFailureFlags(CBlockIndex *pindex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CBlockIndex* AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus = BLOCK_VALID_TREE)
|
||||
static CBlockIndex* AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus = BLOCK_VALID_TREE)
|
||||
{
|
||||
// Check for duplicate
|
||||
uint256 hash = block.GetHash();
|
||||
@ -3176,7 +3192,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
|
||||
static bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
|
||||
{
|
||||
LOCK(cs_LastBlockFile);
|
||||
|
||||
@ -3233,7 +3249,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
|
||||
static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
|
||||
{
|
||||
pos.nFile = nFile;
|
||||
|
||||
@ -3264,7 +3280,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW)
|
||||
static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true)
|
||||
{
|
||||
// Check proof of work matches claimed amount
|
||||
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
|
||||
@ -3359,7 +3375,10 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
|
||||
/** Context-dependent validity checks.
|
||||
* By "context", we mean only the previous block headers, but not the UTXO
|
||||
* set; UTXO-related validity checks are done in ConnectBlock(). */
|
||||
static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
|
||||
{
|
||||
assert(pindexPrev != NULL);
|
||||
const int nHeight = pindexPrev->nHeight + 1;
|
||||
@ -3396,7 +3415,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
|
||||
static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
|
||||
{
|
||||
const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
|
||||
|
||||
@ -3616,7 +3635,7 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation
|
||||
}
|
||||
|
||||
if (fCheckForPruning)
|
||||
FlushStateToDisk(state, FLUSH_STATE_NONE); // we just allocated more disk space for block files
|
||||
FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); // we just allocated more disk space for block files
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -3696,7 +3715,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
|
||||
*/
|
||||
|
||||
/* Calculate the amount of disk space the block & undo files currently use */
|
||||
uint64_t CalculateCurrentUsage()
|
||||
static uint64_t CalculateCurrentUsage()
|
||||
{
|
||||
uint64_t retval = 0;
|
||||
BOOST_FOREACH(const CBlockFileInfo &file, vinfoBlockFile) {
|
||||
@ -3749,7 +3768,7 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
|
||||
}
|
||||
|
||||
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
|
||||
void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight)
|
||||
static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight)
|
||||
{
|
||||
assert(fPruneMode && nManualPruneHeight > 0);
|
||||
|
||||
@ -3774,11 +3793,26 @@ void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeig
|
||||
void PruneBlockFilesManual(int nManualPruneHeight)
|
||||
{
|
||||
CValidationState state;
|
||||
FlushStateToDisk(state, FLUSH_STATE_NONE, nManualPruneHeight);
|
||||
const CChainParams& chainparams = Params();
|
||||
FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE, nManualPruneHeight);
|
||||
}
|
||||
|
||||
/* Calculate the block/rev files that should be deleted to remain under target*/
|
||||
void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
|
||||
{
|
||||
LOCK2(cs_main, cs_LastBlockFile);
|
||||
if (chainActive.Tip() == NULL || nPruneTarget == 0) {
|
||||
@ -3836,7 +3870,7 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes)
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
|
||||
static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
|
||||
{
|
||||
if (pos.IsNull())
|
||||
return NULL;
|
||||
@ -3863,7 +3897,8 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) {
|
||||
return OpenDiskFile(pos, "blk", fReadOnly);
|
||||
}
|
||||
|
||||
FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
|
||||
/** Open an undo file (rev?????.dat) */
|
||||
static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
|
||||
return OpenDiskFile(pos, "rev", fReadOnly);
|
||||
}
|
||||
|
||||
@ -4222,7 +4257,7 @@ bool InitBlockIndex(const CChainParams& chainparams)
|
||||
}
|
||||
|
||||
// Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
|
||||
return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
|
||||
return FlushStateToDisk(chainparams, state, FLUSH_STATE_ALWAYS);
|
||||
} catch (const std::runtime_error& e) {
|
||||
return error("%s: failed to initialize block database: %s", __func__, e.what());
|
||||
}
|
||||
@ -4563,6 +4598,7 @@ bool LoadMempool(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
const CChainParams& chainparams = Params();
|
||||
int64_t nExpiryTimeout = GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
|
||||
FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb");
|
||||
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
|
||||
@ -4599,7 +4635,7 @@ bool LoadMempool(void)
|
||||
CValidationState state;
|
||||
if (nTime + nExpiryTimeout > nNow) {
|
||||
LOCK(cs_main);
|
||||
AcceptToMemoryPoolWithTime(mempool, state, tx, true, NULL, nTime);
|
||||
AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, true, NULL, nTime, NULL, false, 0);
|
||||
if (state.IsValid()) {
|
||||
++count;
|
||||
} else {
|
||||
|
@ -45,6 +45,7 @@ class CBlockPolicyEstimator;
|
||||
class CTxMemPool;
|
||||
class CValidationInterface;
|
||||
class CValidationState;
|
||||
class PrecomputedTransactionData;
|
||||
struct ChainTxData;
|
||||
|
||||
struct LockPoints;
|
||||
@ -232,7 +233,7 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 945 * 1024 * 1024;
|
||||
*
|
||||
* Note that we guarantee that either the proof-of-work is valid on pblock, or
|
||||
* (and possibly also) BlockChecked will have been called.
|
||||
*
|
||||
*
|
||||
* Call without cs_main held.
|
||||
*
|
||||
* @param[in] pblock The block we want to process.
|
||||
@ -258,8 +259,6 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationS
|
||||
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
|
||||
/** Open a block file (blk?????.dat) */
|
||||
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
|
||||
/** Open an undo file (rev?????.dat) */
|
||||
FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
|
||||
/** Translation to a filesystem path */
|
||||
fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix);
|
||||
/** Import blocks from an external file */
|
||||
@ -294,23 +293,6 @@ CAmount GetMasternodePayment(int nHeight, CAmount blockValue);
|
||||
/** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */
|
||||
double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Mark one block file as pruned.
|
||||
*/
|
||||
@ -335,11 +317,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||
bool* pfMissingInputs, bool fOverrideMempoolLimit=false,
|
||||
const CAmount nAbsurdFee=0, bool fDryRun=false);
|
||||
|
||||
/** (try to) add transaction to memory pool with a specified acceptance time **/
|
||||
bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
|
||||
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit=false,
|
||||
const CAmount nAbsurdFee=0, bool fDryRun=false);
|
||||
|
||||
bool GetUTXOCoin(const COutPoint& outpoint, Coin& coin);
|
||||
int GetUTXOHeight(const COutPoint& outpoint);
|
||||
int GetUTXOConfirmations(const COutPoint& outpoint);
|
||||
@ -362,7 +339,7 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
|
||||
|
||||
/**
|
||||
* Count ECDSA signature operations in pay-to-script-hash inputs.
|
||||
*
|
||||
*
|
||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
* @return maximum number of sigops required to validate this transaction's inputs
|
||||
* @see CTransaction::FetchInputs
|
||||
@ -370,14 +347,6 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
|
||||
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||
|
||||
|
||||
/**
|
||||
* Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
|
||||
* This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
|
||||
* instead of being performed inline.
|
||||
*/
|
||||
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks,
|
||||
unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL);
|
||||
|
||||
/** Apply the effects of this transaction on the UTXO set represented by view */
|
||||
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
|
||||
|
||||
@ -449,12 +418,13 @@ private:
|
||||
unsigned int nFlags;
|
||||
bool cacheStore;
|
||||
ScriptError error;
|
||||
PrecomputedTransactionData *txdata;
|
||||
|
||||
public:
|
||||
CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
|
||||
CScriptCheck(const CScript& scriptPubKeyIn, const CAmount amountIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
|
||||
CScriptCheck(const CScript& scriptPubKeyIn, const CAmount amountIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
|
||||
scriptPubKey(scriptPubKeyIn),
|
||||
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
|
||||
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }
|
||||
|
||||
bool operator()();
|
||||
|
||||
@ -465,6 +435,7 @@ public:
|
||||
std::swap(nFlags, check.nFlags);
|
||||
std::swap(cacheStore, check.cacheStore);
|
||||
std::swap(error, check.error);
|
||||
std::swap(txdata, check.txdata);
|
||||
}
|
||||
|
||||
ScriptError GetScriptError() const { return error; }
|
||||
@ -479,7 +450,6 @@ bool GetAddressUnspent(uint160 addressHash, int type,
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs);
|
||||
|
||||
/** Functions for disk access for blocks */
|
||||
bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart);
|
||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
|
||||
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
|
||||
|
||||
@ -490,15 +460,8 @@ bool DisconnectBlocks(int blocks);
|
||||
void ReprocessBlocks(int nBlocks);
|
||||
|
||||
/** Context-independent validity checks */
|
||||
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true);
|
||||
bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
|
||||
/** Context-dependent validity checks.
|
||||
* By "context", we mean only the previous block headers, but not the UTXO
|
||||
* set; UTXO-related validity checks are done in ConnectBlock(). */
|
||||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime);
|
||||
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex *pindexPrev);
|
||||
|
||||
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
|
||||
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user