55 #include <boost/algorithm/string/replace.hpp>
56 #include <boost/thread.hpp>
62 #error "PIVX cannot be compiled without assertions."
116 static void CheckBlockIndex();
124 struct CBlockIndexWorkComparator {
137 if (pa < pb)
return false;
138 if (pa > pb)
return true;
151 std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
157 Mutex m_cs_chainstate;
160 std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
163 std::vector<CBlockFileInfo> vinfoBlockFile;
164 int nLastBlockFile = 0;
172 uint32_t nBlockSequenceId = 1;
175 std::set<CBlockIndex*> setDirtyBlockIndex;
178 std::set<int> setDirtyFileInfo;
187 if (pindex && chain.
Contains(pindex)) {
251 return IsFinalTx(tx, nBlockHeight, nBlockTime);
259 std::vector<COutPoint> vNoSpendsRemaining;
261 for (
const COutPoint& removed: vNoSpendsRemaining)
282 if (!
Params().GetConsensus().MoneyRange(nMinFee)) {
291 unsigned int K = DEFAULT_SHIELDEDTXFEE_K;
293 if (!
Params().GetConsensus().MoneyRange(nMinFee))
315 std::vector<uint256> vHashUpdate;
326 if ((*it)->IsProRegTx()) {
331 if (!fAddToMempool || (*it)->IsCoinBase() || (*it)->IsCoinStake() ||
337 vHashUpdate.emplace_back((*it)->GetHash());
353 gArgs.
GetArg(
"-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
356 static bool IsCurrentForFeeEstimation()
369 bool* pfMissingInputs, int64_t nAcceptTime,
bool fOverrideMempoolLimit,
bool fRejectAbsurdFee,
bool ignoreFees,
377 return state.
DoS(100,
false, REJECT_INVALID,
"coinbase");
381 return state.
DoS(100,
false, REJECT_INVALID,
"coinstake");
385 return state.
DoS(100,
false, REJECT_INVALID,
"llmqcomm");
388 *pfMissingInputs =
false;
392 return state.
DoS(10,
error(
"%s : Shielded transactions are temporarily disabled for maintenance",
393 __func__), REJECT_INVALID,
"bad-tx-sapling-maintenance");
404 int nextBlockHeight = chainHeight + 1;
407 return error(
"AcceptToMemoryPool: ContextualCheckTransaction failed");
410 if (pool.existsProviderTxConflict(tx)) {
411 return state.
DoS(0,
false, REJECT_DUPLICATE,
"protx-dup");
418 return state.
DoS(0,
false, REJECT_NONSTANDARD,
"non-final");
423 return state.
DoS(0,
false, REJECT_NONSTANDARD, reason);
426 if (pool.exists(hash)) {
427 return state.
Invalid(
false, REJECT_ALREADY_KNOWN,
"txn-already-in-mempool");
434 for (
const auto& in : tx.
vin) {
436 if (pool.mapNextTx.count(outpoint)) {
438 return state.
Invalid(
false, REJECT_CONFLICT,
"txn-mempool-conflict");
445 for (
const auto& sd : tx.
sapData->vShieldedSpend) {
446 if (pool.nullifierExists(sd.nullifier))
447 return state.
Invalid(
false, REJECT_INVALID,
"bad-txns-nullifier-double-spent");
462 for (
size_t out = 0; out < tx.
vout.size(); out++) {
464 bool had_coin_in_cache =
pcoinsTip->HaveCoinInCache(outpoint);
466 if (!had_coin_in_cache) {
467 coins_to_uncache.push_back(outpoint);
469 return state.
Invalid(
false, REJECT_ALREADY_KNOWN,
"txn-already-known");
476 coins_to_uncache.push_back(txin.
prevout);
479 if (pfMissingInputs) {
480 *pfMissingInputs =
true;
488 return state.
Invalid(
error(
"AcceptToMemoryPool: shielded requirements not met"),
489 REJECT_DUPLICATE,
"bad-txns-shielded-requirements-not-met");
506 return state.
Invalid(
false, REJECT_NONSTANDARD,
"bad-txns-nonstandard-inputs");
514 unsigned int nMaxSigOps = MAX_TX_SIGOPS_CURRENT;
516 if(nSigOps > nMaxSigOps)
517 return state.
DoS(0,
false, REJECT_NONSTANDARD,
"bad-txns-too-many-sigops",
false,
518 strprintf(
"%d > %d", nSigOps, nMaxSigOps));
521 CAmount nFees = nValueIn - nValueOut;
522 bool fSpendsCoinbaseOrCoinstake =
false;
529 fSpendsCoinbaseOrCoinstake =
true;
535 fSpendsCoinbaseOrCoinstake, nSigOps);
536 unsigned int nSize = entry.GetTxSize();
541 if (fLimitFree && nFees < txMinFee) {
542 return state.
DoS(0,
false, REJECT_INSUFFICIENTFEE,
"insufficient fee",
false,
548 return state.
DoS(0,
false, REJECT_INSUFFICIENTFEE,
"min relay fee not met");
552 if (fRejectAbsurdFee) {
556 return state.
Invalid(
false, REJECT_HIGHFEE,
"absurdly-high-fee",
562 size_t nLimitAncestors =
gArgs.
GetArg(
"-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
563 size_t nLimitAncestorSize =
gArgs.
GetArg(
"-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000;
564 size_t nLimitDescendants =
gArgs.
GetArg(
"-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
565 size_t nLimitDescendantSize =
gArgs.
GetArg(
"-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
566 std::string errString;
567 if (!pool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
568 return state.
DoS(0,
error(
"%s : %s", __func__, errString), REJECT_NONSTANDARD,
"too-long-mempool-chain",
false);
575 int flags = STANDARD_SCRIPT_VERIFY_FLAGS;
576 if (fCLTVIsActivated)
578 if (exchangeAddrActivated)
596 flags = MANDATORY_SCRIPT_VERIFY_FLAGS;
597 if (fCLTVIsActivated)
599 if (exchangeAddrActivated)
602 return error(
"%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s",
610 bool validForFeeEstimation = IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx);
613 pool.addUnchecked(hash, entry, setAncestors, validForFeeEstimation);
616 if (!fOverrideMempoolLimit) {
618 if (!pool.exists(hash))
619 return state.
DoS(0,
false, REJECT_INSUFFICIENTFEE,
"mempool full");
622 pool.TrimToSize(
gArgs.
GetArg(
"-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
623 if (!pool.exists(tx.
GetHash()))
624 return state.
DoS(0,
false, REJECT_INSUFFICIENTFEE,
"mempool full");
633 bool* pfMissingInputs, int64_t nAcceptTime,
bool fOverrideMempoolLimit,
bool fRejectAbsurdFee,
bool fIgnoreFees)
637 std::vector<COutPoint> coins_to_uncache;
638 bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, fRejectAbsurdFee, fIgnoreFees, coins_to_uncache);
640 for (
const COutPoint& outpoint: coins_to_uncache)
650 bool fLimitFree,
bool* pfMissingInputs,
bool fOverrideMempoolLimit,
651 bool fRejectInsaneFee,
bool ignoreFees)
661 return state.
DoS(100,
error(
"Output not found"));
663 if (index > txPrev->vout.size()) {
664 return state.
DoS(100,
error(
"Output not found, invalid index %d for %s",index, hash.
GetHex()));
666 out = txPrev->vout[index];
690 return error(
"%s: OpenBlockFile failed", __func__);
696 }
catch (
const std::exception& e) {
697 return error(
"%s : Deserialize or I/O error - %s", __func__, e.what());
700 if (txOut->GetHash() != hash)
701 return error(
"%s : txid mismatch", __func__);
718 for (
const auto& tx : block.
vtx) {
742 return error(
"WriteBlockToDisk : OpenBlockFile failed");
749 long fileOutPos = ftell(fileout.
Get());
751 return error(
"WriteBlockToDisk : ftell failed");
752 pos.
nPos = (
unsigned int)fileOutPos;
765 return error(
"ReadBlockFromDisk : OpenBlockFile failed");
770 }
catch (
const std::exception& e) {
771 return error(
"%s : Deserialize or I/O error - %s", __func__, e.what());
777 return error(
"ReadBlockFromDisk : Errors in block header");
791 return error(
"ReadBlockFromDisk(CBlock&, CBlockIndex*) : GetHash() doesn't match index");
799 int nShift = (nBits >> 24) & 0xff;
802 (double)0x0000ffff / (
double)(nBits & 0x00ffffff);
804 while (nShift < 29) {
808 while (nShift > 29) {
822 if (
Params().IsRegTestNet()) {
824 if (nHeight > nLast)
return 10 * COIN;
829 if (isTestnet && nHeight < 201 && nHeight > 1) {
830 return 250000 * COIN;
834 if (nHeight > nLast)
return 10 * COIN;
835 if (nHeight > nZerocoinV2)
return 5 * COIN;
836 if (nHeight > 648000)
return 4.5 * COIN;
837 if (nHeight > 604800)
return 9 * COIN;
838 if (nHeight > 561600)
return 13.5 * COIN;
839 if (nHeight > 518400)
return 18 * COIN;
840 if (nHeight > 475200)
return 22.5 * COIN;
841 if (nHeight > 432000)
return 27 * COIN;
842 if (nHeight > 388800)
return 31.5 * COIN;
843 if (nHeight > 345600)
return 36 * COIN;
844 if (nHeight > 302400)
return 40.5 * COIN;
845 if (nHeight > 151200)
return 45 * COIN;
846 if (nHeight > 86400)
return 225 * COIN;
847 if (nHeight != 1)
return 250 * COIN;
865 static std::atomic<bool> latchToFalse{
false};
867 if (latchToFalse.load(std::memory_order_relaxed))
871 if (latchToFalse.load(std::memory_order_relaxed))
879 LogPrintf(
"Leaving InitialBlockDownload (latching to false)\n");
880 latchToFalse.store(
true, std::memory_order_relaxed);
887 static void AlertNotify(
const std::string& strMessage)
890 std::string strCmd =
gArgs.
GetArg(
"-alertnotify",
"");
891 if (strCmd.empty())
return;
896 std::string singleQuote(
"'");
898 safeStatus = singleQuote+safeStatus+singleQuote;
899 boost::replace_all(strCmd,
"%s", safeStatus);
925 std::string warning = std::string(
"'Warning: Large-work fork detected, forking after block ") +
927 AlertNotify(warning);
932 LogPrintf(
"CheckForkWarningConditions: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n",
938 LogPrintf(
"CheckForkWarningConditions: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n");
953 while (pfork && pfork != plonger) {
955 plonger = plonger->
pprev;
956 if (pfork == plonger)
958 pfork = pfork->
pprev;
978 void static InvalidChainFound(
CBlockIndex* pindexNew)
980 if (!pindexBestInvalid || pindexNew->
nChainWork > pindexBestInvalid->nChainWork)
981 pindexBestInvalid = pindexNew;
983 LogPrintf(
"InvalidChainFound: invalid block=%s height=%d log2_work=%.16f date=%s\n",
989 LogPrintf(
"InvalidChainFound: current best=%s height=%d log2_work=%.16f date=%s\n",
1000 setDirtyBlockIndex.insert(pindex);
1001 setBlockIndexCandidates.erase(pindex);
1002 InvalidChainFound(pindex);
1006 static bool SkipInvalidUTXOS(
int nHeight)
1029 AddCoins(inputs, tx, nHeight,
false, fSkipInvalid);
1035 UpdateCoins(tx, inputs, txundo, nHeight, fSkipInvalid);
1048 return pindexPrev->
nHeight + 1;
1057 return state.
Invalid(
false, 0,
"",
"Inputs unavailable");
1066 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
1074 return state.
Invalid(
false, REJECT_INVALID,
"bad-txns-premature-spend-of-coinbase-coinstake",
1075 strprintf(
"tried to spend coinbase/coinstake at depth %d", nSpendHeight - coin.
nHeight));
1081 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-inputvalues-outofrange");
1089 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-in-belowout",
false,
1095 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-fee-negative");
1098 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-fee-outofrange");
1112 pvChecks->reserve(tx.
vin.size());
1121 if (fScriptChecks) {
1122 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
1136 pvChecks->emplace_back();
1137 check.
swap(pvChecks->back());
1138 }
else if (!check()) {
1139 if (
flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) {
1147 flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &precomTxData);
1168 static bool AbortNode(
const std::string& strMessage,
const std::string& userMessage=
"")
1171 LogPrintf(
"*** %s\n", strMessage);
1173 userMessage.empty() ?
_(
"Error: A fatal internal error occurred, see debug.log for details") : userMessage,
1179 static bool AbortNode(
CValidationState& state,
const std::string& strMessage,
const std::string& userMessage=
"")
1181 AbortNode(strMessage, userMessage);
1182 return state.
Error(strMessage);
1191 if (fileout.IsNull())
1192 return error(
"%s : OpenUndoFile failed", __func__);
1199 long fileOutPos = ftell(fileout.Get());
1201 return error(
"%s : ftell failed", __func__);
1202 pos.
nPos = (
unsigned int)fileOutPos;
1203 fileout << blockundo;
1207 hasher << hashBlock;
1208 hasher << blockundo;
1209 fileout << hasher.GetHash();
1218 if (filein.IsNull())
1219 return error(
"%s : OpenBlockFile failed", __func__);
1225 verifier << hashBlock;
1226 verifier >> blockundo;
1227 filein >> hashChecksum;
1228 }
catch (
const std::exception& e) {
1229 return error(
"%s : Deserialize or I/O error - %s", __func__, e.what());
1233 if (hashChecksum != verifier.GetHash())
1234 return error(
"%s : Checksum mismatch", __func__);
1259 if (view.
HaveCoin(out)) fClean =
false;
1261 if (undo.nHeight == 0) {
1267 undo.nHeight = alternate.
nHeight;
1278 view.
AddCoin(out, std::move(undo), !fClean);
1293 if (fDIP3Active && !fHasBestBlock) {
1294 AbortNode(
"Found EvoDB inconsistency, you must reindex to continue");
1303 error(
"%s: no undo data available", __func__);
1307 error(
"%s: failure reading undo data", __func__);
1311 if (blockUndo.
vtxundo.size() + 1 != block.
vtx.size()) {
1312 error(
"%s: block and undo data inconsistent", __func__);
1321 for (
int i = block.
vtx.size() - 1; i >= 0; i--) {
1334 for (
size_t o = 0; o < tx.
vout.size(); o++) {
1335 if (!tx.
vout[o].scriptPubKey.IsUnspendable() && !tx.
vout[o].IsZerocoinMint()) {
1355 error(
"%s: transaction and undo data inconsistent - txundo.vprevout.siz=%d tx.vin.siz=%d",
1359 for (
unsigned int j = tx.
vin.size(); j-- > 0;) {
1394 void static FlushBlockFile(
bool fFinalize =
false)
1396 LOCK(cs_LastBlockFile);
1398 FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize);
1399 FlatFilePos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize);
1402 status &= BlockFileSeq().
Flush(block_pos_old, fFinalize);
1403 status &= UndoFileSeq().
Flush(undo_pos_old, fFinalize);
1405 AbortNode(
"Flushing block file to disk failed. This is likely the result of an I/O error.");
1416 scriptcheckqueue.Thread();
1419 static int64_t nTimeVerify = 0;
1420 static int64_t nTimeProcessSpecial = 0;
1421 static int64_t nTimeConnect = 0;
1422 static int64_t nTimeIndex = 0;
1423 static int64_t nTimeTotal = 0;
1432 if (!
CheckBlock(block, state, !fJustCheck, !fJustCheck, !fJustCheck)) {
1437 return AbortNode(state,
"Corrupt block found indicating potential hardware failure; shutting down");
1443 return state.
DoS(10,
error(
"%s: conflicting with chainlock", __func__), REJECT_INVALID,
"bad-chainlock");
1458 if (!isV6UpgradeEnforced && isPoSBlock && (block.
vtx[0]->vout.size() != 1 || !block.
vtx[0]->vout[0].IsEmpty()))
1459 return state.
DoS(100,
false, REJECT_INVALID,
"bad-cb-pos",
false,
"coinbase output not empty for proof-of-stake block");
1461 if (pindex->
pprev) {
1462 bool fHasBestBlock =
evoDb->VerifyBestBlock(hashPrevBlock);
1464 if (isV6UpgradeEnforced && !fHasBestBlock) {
1465 return AbortNode(state,
"Found EvoDB inconsistency, you must reindex to continue");
1478 if (!isPoSActive && isPoSBlock)
1479 return state.
DoS(100,
error(
"ConnectBlock() : PoS period not active"),
1480 REJECT_INVALID,
"PoS-early");
1482 if (isPoSActive && !isPoSBlock)
1483 return state.
DoS(100,
error(
"ConnectBlock() : PoW period ended"),
1484 REJECT_INVALID,
"PoW-ended");
1497 return state.
DoS(100,
error(
"%s: turnstile violation in Sapling shielded value pool: val: %d", __func__, *pindex->
nChainSaplingValue),
1498 REJECT_INVALID,
"turnstile-violation-sapling-shielded-pool");
1505 bool fCLTVIsActivated =
false;
1506 bool exchangeAddrActivated =
false;
1507 if (fScriptChecks && pindex->
pprev) {
1517 unsigned int nSigOps = 0;
1519 std::vector<std::pair<uint256, CDiskTxPos> > vPos;
1520 std::vector<std::pair<CBigNum, uint256> > vSpends;
1521 vPos.reserve(block.
vtx.size());
1523 blockundo.
vtxundo.reserve(block.
vtx.size() - 1);
1526 unsigned int nMaxBlockSigOps = MAX_BLOCK_SIGOPS_CURRENT;
1532 std::vector<PrecomputedTransactionData> precomTxData;
1533 precomTxData.reserve(block.
vtx.size());
1536 for (
unsigned int i = 0; i < block.
vtx.size(); i++) {
1539 nInputs += tx.
vin.size();
1541 if (nSigOps > nMaxBlockSigOps)
1542 return state.
DoS(100,
error(
"ConnectBlock() : too many sigops"), REJECT_INVALID,
"bad-blk-sigops");
1545 if (!fInitialBlockDownload && fSaplingMaintenance && tx.
IsShieldedTx()) {
1546 return state.
DoS(100,
error(
"%s : shielded transactions are currently in maintenance mode", __func__));
1557 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-inputs-missingorspent");
1561 return state.
DoS(100,
error(
"%s: spends requirements not met", __func__),
1562 REJECT_INVALID,
"bad-txns-sapling-requirements-not-met");
1568 if (nSigOps > nMaxBlockSigOps)
1569 return state.
DoS(100,
error(
"ConnectBlock() : too many sigops"), REJECT_INVALID,
"bad-blk-sigops");
1574 precomTxData.emplace_back(tx);
1580 nFees += txValueIn - txValueOut;
1581 nValueIn += txValueIn;
1583 std::vector<CScriptCheck> vChecks;
1585 if (fCLTVIsActivated)
1587 if (exchangeAddrActivated)
1590 bool fCacheResults = fJustCheck;
1593 control.Add(vChecks);
1595 nValueOut += txValueOut;
1599 blockundo.
vtxundo.emplace_back();
1601 const bool fSkipInvalid = SkipInvalidUTXOS(pindex->
nHeight);
1607 sapling_tree.
append(outputDescription.
cmu);
1611 vPos.emplace_back(tx.
GetHash(), pos);
1619 if (isV5UpgradeEnforced) {
1623 return state.
DoS(100,
1624 error(
"ConnectBlock(): block's hashFinalSaplingRoot is incorrect (should be Sapling tree root)"),
1625 REJECT_INVALID,
"bad-sapling-root-in-block");
1631 const int64_t nMint = (nValueOut - nValueIn) + nFees;
1634 nTimeConnect += nTime1 - nTimeStart;
1635 LogPrint(
BCLog::BENCHMARK,
" - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (
unsigned)block.
vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.
vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs - 1), nTimeConnect * 0.000001);
1640 nExpectedMint += nFees;
1645 return state.
DoS(100,
error(
"%s: reward pays too much (actual=%s vs limit=%s)",
1647 REJECT_INVALID,
"bad-blk-amount");
1652 if (!fInitialBlockDownload) {
1655 return state.
DoS(0,
false, REJECT_INVALID,
"bad-cb-payee",
false,
"Couldn't find masternode/budget payment");
1665 if (!control.Wait())
1666 return state.
DoS(100,
error(
"%s: CheckQueue failed", __func__), REJECT_INVALID,
"block-validation-failed");
1668 nTimeVerify += nTime2 - nTimeStart;
1669 LogPrint(
BCLog::BENCHMARK,
" - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime2 - nTimeStart), nInputs <= 1 ? 0 : 0.001 * (nTime2 - nTimeStart) / (nInputs - 1), nTimeVerify * 0.000001);
1675 nTimeProcessSpecial += nTime3 - nTime2;
1676 LogPrint(
BCLog::BENCHMARK,
" - Process special tx: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeProcessSpecial * 0.000001);
1687 return error(
"ConnectBlock() : FindUndoPos failed");
1689 return AbortNode(state,
"Failed to write undo data");
1697 setDirtyBlockIndex.insert(pindex);
1701 if (!vSpends.empty() && !
zerocoinDB->WriteCoinSpendBatch(vSpends))
1702 return AbortNode(state,
"Failed to record coin serials to database");
1706 return AbortNode(state,
"Failed to write transaction index");
1713 nTimeIndex += nTime4 - nTime3;
1714 LogPrint(
BCLog::BENCHMARK,
" - Index writing: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeIndex * 0.000001);
1721 if (pindex->
nHeight % 50000 == 0) {
1749 static int64_t nLastWrite = 0;
1750 static int64_t nLastFlush = 0;
1751 static int64_t nLastSetChain = 0;
1755 if (nLastWrite == 0) {
1758 if (nLastFlush == 0) {
1761 if (nLastSetChain == 0) {
1762 nLastSetChain = nNow;
1764 int64_t nMempoolSizeMax =
gArgs.
GetArg(
"-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
1765 int64_t cacheSize =
pcoinsTip->DynamicMemoryUsage();
1766 int64_t nTotalSpace =
nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0);
1770 cacheSize > std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE * 1024 * 1024);
1777 bool fPeriodicWrite = mode ==
FLUSH_STATE_PERIODIC && nNow > nLastWrite + (int64_t)DATABASE_WRITE_INTERVAL * 1000000;
1779 bool fPeriodicFlush = mode ==
FLUSH_STATE_PERIODIC && nNow > nLastFlush + (int64_t)DATABASE_FLUSH_INTERVAL * 1000000;
1781 bool fDoFullFlush = (mode ==
FLUSH_STATE_ALWAYS) || fCacheLarge || fCacheCritical || fEvoDbCacheCritical || fPeriodicFlush;
1783 if (fDoFullFlush || fPeriodicWrite) {
1786 return AbortNode(state,
"Disk space is low!",
_(
"Error: Disk space is low!"));
1792 std::vector<std::pair<int, const CBlockFileInfo*> > vFiles;
1793 vFiles.reserve(setDirtyFileInfo.size());
1794 for (std::set<int>::iterator it = setDirtyFileInfo.begin(); it != setDirtyFileInfo.end(); ) {
1795 vFiles.emplace_back(*it, &vinfoBlockFile[*it]);
1796 setDirtyFileInfo.erase(it++);
1798 std::vector<const CBlockIndex*> vBlocks;
1799 vBlocks.reserve(setDirtyBlockIndex.size());
1800 for (std::set<CBlockIndex*>::iterator it = setDirtyBlockIndex.begin(); it != setDirtyBlockIndex.end(); ) {
1801 vBlocks.push_back(*it);
1802 setDirtyBlockIndex.erase(it++);
1804 if (!
pblocktree->WriteBatchSync(vFiles, nLastBlockFile, vBlocks)) {
1805 return AbortNode(state,
"Files to write to block index database");
1815 if (fDoFullFlush && !
pcoinsTip->GetBestBlock().IsNull()) {
1822 return AbortNode(state,
"Disk space is low!",
_(
"Error: Disk space is low!"));
1826 return AbortNode(state,
"Failed to write to coin database");
1827 if (!
evoDb->CommitRootTransaction()) {
1828 return AbortNode(state,
"Failed to commit EvoDB");
1839 nLastSetChain = nNow;
1842 }
catch (
const std::runtime_error& e) {
1843 return AbortNode(state, std::string(
"System error while flushing: ") + e.what());
1871 assert(pChainTip !=
nullptr);
1872 LogPrintf(
"%s: new best=%s height=%d version=%d log2_work=%.16f tx=%lu date=%s progress=%f cache=%.1fMiB(%utxo) evodb_cache=%.1fMiB\n",
1877 evoDb->GetMemoryUsage() * (1.0 / (1<<20)));
1880 static bool fWarned =
false;
1884 for (
int i = 0; i < 100 && pindex !=
nullptr; i++) {
1887 pindex = pindex->
pprev;
1891 if (nUpgraded > 100 / 2) {
1892 std::string strWarning =
_(
"Warning: This version is obsolete, upgrade required!");
1895 AlertNotify(strWarning);
1917 assert(pindexDelete);
1919 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
1922 return error(
"%s: Failed to read block", __func__);
1927 auto dbTx =
evoDb->BeginTransaction();
1933 bool flushed = view.
Flush();
1942 if (disconnectpool) {
1944 for (
auto it = block.
vtx.rbegin(); it != block.
vtx.rend(); ++it) {
1947 while (disconnectpool->
DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE * 1000) {
1956 if (saplingAnchorBeforeDisconnect != saplingAnchorAfterDisconnect) {
1962 UpdateTip(pindexDelete->
pprev);
1971 if ((
unsigned) pindexDelete->
nHeight >= CACHED_BLOCK_HASHES) {
1980 static int64_t nTimeReadFromDisk = 0;
1981 static int64_t nTimeConnectTotal = 0;
1982 static int64_t nTimeFlush = 0;
1983 static int64_t nTimeChainState = 0;
1984 static int64_t nTimePostConnect = 0;
2040 std::shared_ptr<const CBlock> pthisBlock;
2042 std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
2044 return AbortNode(state,
"Failed to read block");
2045 pthisBlock = pblockNew;
2047 pthisBlock = pblock;
2049 const CBlock& blockConnecting = *pthisBlock;
2053 nTimeReadFromDisk += nTime2 - nTime1;
2055 LogPrint(
BCLog::BENCHMARK,
" - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
2057 auto dbTx =
evoDb->BeginTransaction();
2060 bool rv = ConnectBlock(blockConnecting, state, pindexNew, view,
false);
2064 InvalidBlockFound(pindexNew, state);
2068 nTimeConnectTotal += nTime3 - nTime2;
2069 LogPrint(
BCLog::BENCHMARK,
" - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
2070 bool flushed = view.
Flush();
2075 nTimeFlush += nTime4 - nTime3;
2085 nTimeChainState += nTime5 - nTime4;
2086 LogPrint(
BCLog::BENCHMARK,
" - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
2092 UpdateTip(pindexNew);
2102 nTimePostConnect += nTime6 - nTime5;
2103 nTimeTotal += nTime6 - nTime1;
2104 LogPrint(
BCLog::BENCHMARK,
" - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
2107 connectTrace.BlockConnected(pindexNew, std::move(pthisBlock));
2122 std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexCandidates.rbegin();
2123 if (it == setBlockIndexCandidates.rend())
2131 bool fInvalidAncestor =
false;
2141 if (fFailedChain || fMissingData) {
2143 if (fFailedChain && (pindexBestInvalid ==
nullptr || pindexNew->
nChainWork > pindexBestInvalid->nChainWork))
2144 pindexBestInvalid = pindexNew;
2147 while (pindexTest != pindexFailed) {
2150 }
else if (fMissingData) {
2154 mapBlocksUnlinked.emplace(pindexFailed->
pprev, pindexFailed);
2156 setBlockIndexCandidates.erase(pindexFailed);
2157 pindexFailed = pindexFailed->
pprev;
2159 setBlockIndexCandidates.erase(pindexTest);
2160 fInvalidAncestor =
true;
2163 pindexTest = pindexTest->
pprev;
2165 if (!fInvalidAncestor)
2171 static void PruneBlockIndexCandidates()
2175 std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
2176 while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it,
chainActive.
Tip())) {
2177 setBlockIndexCandidates.erase(it++);
2180 assert(!setBlockIndexCandidates.empty());
2195 bool fBlocksDisconnected =
false;
2198 if (!DisconnectTip(state,
Params(), &disconnectpool)) {
2201 UpdateMempoolForReorg(disconnectpool,
false);
2206 return AbortNode(state,
"Failed to disconnect block; see debug.log for details");
2208 fBlocksDisconnected =
true;
2212 std::vector<CBlockIndex*> vpindexToConnect;
2213 bool fContinue =
true;
2214 int nHeight = pindexFork ? pindexFork->
nHeight : -1;
2215 while (fContinue && nHeight != pindexMostWork->nHeight) {
2218 int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight);
2219 vpindexToConnect.clear();
2220 vpindexToConnect.reserve(nTargetHeight - nHeight);
2222 while (pindexIter && pindexIter->
nHeight != nHeight) {
2223 vpindexToConnect.push_back(pindexIter);
2224 pindexIter = pindexIter->
pprev;
2226 nHeight = nTargetHeight;
2230 if (!ConnectTip(state, pindexConnect, (pindexConnect == pindexMostWork) ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
2234 InvalidChainFound(vpindexToConnect.front());
2237 fInvalidFound =
true;
2244 UpdateMempoolForReorg(disconnectpool,
false);
2248 PruneBlockIndexCandidates();
2258 if (fBlocksDisconnected) {
2261 UpdateMempoolForReorg(disconnectpool,
true);
2292 LOCK(m_cs_chainstate);
2297 boost::this_thread::interruption_point();
2310 bool blocks_connected =
false;
2316 if (pindexMostWork ==
nullptr) {
2317 pindexMostWork = FindMostWorkChain();
2321 if (pindexMostWork ==
nullptr || pindexMostWork ==
chainActive.
Tip()) {
2325 bool fInvalidFound =
false;
2326 std::shared_ptr<const CBlock> nullBlockPtr;
2327 if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->
GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace))
2329 blocks_connected =
true;
2331 if (fInvalidFound) {
2333 pindexMostWork =
nullptr;
2338 assert(trace.pblock && trace.pindex);
2342 if (!blocks_connected)
return true;
2349 if (pindexFork != pindexNewTip) {
2381 setDirtyBlockIndex.insert(pindex);
2382 setBlockIndexCandidates.erase(pindex);
2389 setDirtyBlockIndex.insert(pindexWalk);
2390 setBlockIndexCandidates.erase(pindexWalk);
2393 if (!DisconnectTip(state, chainparams, &disconnectpool)) {
2396 UpdateMempoolForReorg(disconnectpool,
false);
2403 UpdateMempoolForReorg(disconnectpool,
true);
2410 setBlockIndexCandidates.insert(it->second);
2415 InvalidChainFound(pindex);
2423 int nHeight = pindex->
nHeight;
2428 if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
2430 setDirtyBlockIndex.insert(it->second);
2432 setBlockIndexCandidates.insert(it->second);
2434 if (it->second == pindexBestInvalid) {
2436 pindexBestInvalid =
nullptr;
2443 while (pindex !=
nullptr) {
2446 setDirtyBlockIndex.insert(pindex);
2448 pindex = pindex->
pprev;
2469 BlockMap::iterator mi =
mapBlockIndex.emplace(hash, pindexNew).first;
2474 pindexNew->
pprev = pprev;
2494 setDirtyBlockIndex.insert(pindexNew);
2496 if (pindexNew->
pprev) {
2508 pindexNew->
nTx = block.
vtx.size();
2513 for (
const auto& tx : block.
vtx) {
2519 saplingValue += -tx->
sapData->valueBalance;
2530 setDirtyBlockIndex.insert(pindexNew);
2534 std::deque<CBlockIndex*> queue;
2535 queue.push_back(pindexNew);
2538 while (!queue.empty()) {
2547 LOCK(cs_nBlockSequenceId);
2551 setBlockIndexCandidates.insert(pindex);
2553 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex);
2554 while (range.first != range.second) {
2555 std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first;
2556 queue.push_back(it->second);
2558 mapBlocksUnlinked.erase(it);
2563 mapBlocksUnlinked.emplace(pindexNew->
pprev, pindexNew);
2572 LOCK(cs_LastBlockFile);
2574 unsigned int nFile = fKnown ? pos.
nFile : nLastBlockFile;
2575 if (vinfoBlockFile.size() <= nFile) {
2576 vinfoBlockFile.resize(nFile + 1);
2580 while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
2582 if (vinfoBlockFile.size() <= nFile) {
2583 vinfoBlockFile.resize(nFile + 1);
2587 pos.
nPos = vinfoBlockFile[nFile].nSize;
2590 if ((
int)nFile != nLastBlockFile) {
2592 LogPrintf(
"Leaving block file %i: %s\n", nFile, vinfoBlockFile[nFile].ToString());
2594 FlushBlockFile(!fKnown);
2595 nLastBlockFile = nFile;
2598 vinfoBlockFile[nFile].AddBlock(nHeight, nTime);
2600 vinfoBlockFile[nFile].nSize = std::max(pos.
nPos + nAddSize, vinfoBlockFile[nFile].nSize);
2602 vinfoBlockFile[nFile].nSize += nAddSize;
2606 BlockFileSeq().
Allocate(pos, nAddSize, out_of_space);
2608 return AbortNode(
"Disk space is low!",
_(
"Error: Disk space is low!"));
2613 setDirtyFileInfo.insert(nFile);
2621 LOCK(cs_LastBlockFile);
2623 pos.
nPos = vinfoBlockFile[nFile].nUndoSize;
2624 vinfoBlockFile[nFile].nUndoSize += nAddSize;
2625 setDirtyFileInfo.insert(nFile);
2628 UndoFileSeq().
Allocate(pos, nAddSize, out_of_space);
2630 return AbortNode(state,
"Disk space is low!",
_(
"Error: Disk space is low!"));
2645 if (!tx.
vout[1].scriptPubKey.IsPayToColdStakingLOF()) {
2650 const unsigned int outs = tx.
vout.size();
2666 return error(
"%s : read txPrev failed: %s", __func__, tx.
vin[0].prevout.hash.GetHex());
2669 for (
unsigned int i = 1; i < outs-1; i++) amtOut += tx.
vout[i].nValue;
2670 if (amtOut != amtIn)
2671 return error(
"%s: non-free outputs value %d less than required %d", __func__, amtOut, amtIn);
2679 return error(
"%s: superblocks are not enabled", __func__);
2684 return error(
"%s: Wrong cold staking outputs: vout[%d].scriptPubKey (%s) != vout[%d].scriptPubKey (%s) - value: %s",
2692 static unsigned int GetTotalShieldedTxSize(
const CBlock& block)
2694 unsigned int nSizeShielded = 0;
2695 for (
const auto& tx : block.
vtx) {
2698 return nSizeShielded;
2714 return state.
DoS(50,
false, REJECT_INVALID,
"high-hash",
false,
"proof of work failed");
2721 if (fCheckMerkleRoot) {
2725 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txnmrklroot",
true,
"hashMerkleRoot mismatch");
2731 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-duplicate",
true,
"duplicate transaction");
2735 unsigned int nMaxBlockSize = MAX_BLOCK_SIZE_CURRENT;
2737 if (block.
vtx.empty() || block.
vtx.size() > nMaxBlockSize || nBlockSize > nMaxBlockSize)
2738 return state.
DoS(100,
false, REJECT_INVALID,
"bad-blk-length",
false,
"size limits failed");
2741 if (nBlockSize > MAX_BLOCK_SHIELDED_TXES_SIZE && GetTotalShieldedTxSize(block) > MAX_BLOCK_SHIELDED_TXES_SIZE)
2742 return state.
DoS(100,
false, REJECT_INVALID,
"bad-blk-shielded-size",
false,
"shielded size limits failed");
2745 if (block.
vtx.empty() || !block.
vtx[0]->IsCoinBase())
2746 return state.
DoS(100,
false, REJECT_INVALID,
"bad-cb-missing",
false,
"first tx is not coinbase");
2747 for (
unsigned int i = 1; i < block.
vtx.size(); i++)
2748 if (block.
vtx[i]->IsCoinBase())
2749 return state.
DoS(100,
false, REJECT_INVALID,
"bad-cb-multiple",
false,
"more than one coinbase");
2753 if (block.
vtx.empty() || !block.
vtx[1]->IsCoinStake())
2754 return state.
DoS(100,
false, REJECT_INVALID,
"bad-cs-missing",
false,
"second tx is not coinstake");
2755 for (
unsigned int i = 2; i < block.
vtx.size(); i++)
2756 if (block.
vtx[i]->IsCoinStake())
2757 return state.
DoS(100,
false, REJECT_INVALID,
"bad-cs-multiple",
false,
"more than one coinstake");
2761 bool fColdStakingActive =
true;
2771 return state.
Error(
"blk-out-of-order");
2774 nHeight = pindexPrev->
nHeight + 1;
2786 return state.
DoS(0,
false, REJECT_INVALID,
"bad-p2cs-outs",
false,
"invalid cold-stake output");
2793 LogPrintf(
"%s: Masternode/Budget payment checks skipped on sync\n", __func__);
2798 for (
const auto& txIn : block.
vtx) {
2812 unsigned int nSigOps = 0;
2813 for (
const auto& tx : block.
vtx) {
2817 if (nSigOps > nMaxBlockSigOps)
2818 return state.
DoS(100,
error(
"%s : out-of-bounds SigOpCount", __func__),
2819 REJECT_INVALID,
"bad-blk-sigops",
true);
2823 return state.
DoS(100,
error(
"%s : bad proof-of-stake block signature", __func__),
2824 REJECT_INVALID,
"bad-PoS-sig",
true);
2827 if (fCheckPOW && fCheckMerkleRoot && fCheckSig)
2835 if (pindexPrev ==
nullptr)
2836 return error(
"%s : null pindexPrev for block %s", __func__, block.
GetHash().
GetHex());
2844 if (std::abs(n1 - n2) > n1 * 0.5)
2845 return error(
"%s : incorrect proof of work (DGW pre-fork) - %f %f %f at %d", __func__, std::abs(n1 - n2), n1, n2, pindexPrev->
nHeight + 1);
2850 if (block.
nBits != nBitsRequired) {
2859 return error(
"%s : incorrect proof of work at %d", __func__, pindexPrev->
nHeight + 1);
2868 if (
Params().IsRegTestNet())
2872 const int blockHeight = pindexPrev->
nHeight + 1;
2876 return state.
Invalid(
error(
"%s : block timestamp too far in the future", __func__), REJECT_INVALID,
"time-too-new");
2879 if (blockTime <= pindexPrev->MinPastBlockTime())
2880 return state.
DoS(50,
error(
"%s : block timestamp too old", __func__), REJECT_INVALID,
"time-too-old");
2883 if (!
Params().GetConsensus().IsValidBlockTimeStamp(blockTime, blockHeight))
2884 return state.
DoS(100,
error(
"%s : block timestamp mask not valid", __func__), REJECT_INVALID,
"invalid-time-mask");
2901 const uint256& hash = i.second;
2921 const int nHeight = pindexPrev->
nHeight + 1;
2925 int nMaxReorgDepth =
gArgs.
GetArg(
"-maxreorg", DEFAULT_MAX_REORG_DEPTH);
2926 if (chainHeight - nHeight >= nMaxReorgDepth)
2927 return state.
DoS(1,
error(
"%s: forked chain older than max reorganization depth (height %d)", __func__, chainHeight - nHeight));
2935 return state.
DoS(100,
error(
"%s : rejected by checkpoint lock-in at %d", __func__, nHeight),
2936 REJECT_CHECKPOINT,
"checkpoint mismatch");
2939 const CBlockIndex* pcheckpoint = GetLastCheckpoint();
2940 if (pcheckpoint && nHeight < pcheckpoint->nHeight)
2941 return state.
DoS(0,
error(
"%s : forked chain older than last checkpoint (height %d)", __func__, nHeight));
2944 if ((block.
nVersion < 3 && nHeight >= 1) ||
2951 std::string stringErr =
strprintf(
"rejected block version %d at height %d", block.
nVersion, nHeight);
2952 return state.
Invalid(
false, REJECT_OBSOLETE,
"bad-version", stringErr);
2960 const int nHeight = pindexPrev ==
nullptr ? 0 : pindexPrev->
nHeight + 1;
2964 for (
const auto& tx : block.
vtx) {
2972 return state.
DoS(10,
false, REJECT_INVALID,
"bad-txns-nonfinal",
false,
"non-final transaction");
2979 if (block.
vtx[0]->vin[0].scriptSig.size() <
expect.size() ||
2980 !std::equal(
expect.begin(),
expect.end(), block.
vtx[0]->vin[0].scriptSig.begin())) {
2981 return state.
DoS(100,
false, REJECT_INVALID,
"bad-cb-height",
false,
"block height mismatch in coinbase");
2987 if (csTx->vin.size() > 1) {
2988 return state.
DoS(100,
false, REJECT_INVALID,
"bad-cs-multi-inputs",
false,
2989 "invalid multi-inputs coinstake");
2993 for (
size_t i=1; i<csTx->vout.size(); i++ ) {
2994 if (csTx->vout[i].IsEmpty()) {
2995 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-vout-empty");
3009 pindexPrev =
nullptr;
3010 if (block.
GetHash() !=
Params().GetConsensus().hashGenesisBlock) {
3014 "prevblk-not-found");
3028 REJECT_INVALID,
"bad-prevblk");
3047 return state.
Invalid(
error(
"%s : block is marked invalid", __func__), 0,
"duplicate");
3052 if (pindexPrev ==
nullptr && !GetPrevIndex(block, &pindexPrev, state)) {
3060 if (block.
GetHash() !=
Params().GetConsensus().hashGenesisBlock) {
3062 return state.
DoS(10,
error(
"%s: conflicting with chainlock", __func__), REJECT_INVALID,
"bad-chainlock");
3065 if (pindex ==
nullptr)
3066 pindex = AddToBlockIndex(block);
3084 std::unordered_set<COutPoint, SaltedOutpointHasher>& spent_outpoints,
3085 std::set<CBigNum>& spent_serials)
3094 for (
size_t i = 1; i < block.
vtx.size(); i++) {
3097 for (
const CTxIn& in: tx->vin) {
3099 if (isPublicSpend && (!publicZpivActive || v5Active)) {
3100 return state.
DoS(100,
error(
"%s: public zerocoin spend at height %d", __func__, nHeight));
3103 if (isPrivZerocoinSpend && (!zpivActive || publicZpivActive)) {
3104 return state.
DoS(100,
error(
"%s: private zerocoin spend at height %d", __func__, nHeight));
3106 if (isPrivZerocoinSpend || isPublicSpend) {
3108 if (isPublicSpend) {
3113 spend = publicSpend;
3119 if (spent_serials.find(s) != spent_serials.end()) {
3120 return state.
DoS(100,
error(
"%s: serials double spent in the same block", __func__));
3122 spent_serials.insert(s);
3125 if (spent_outpoints.find(in.
prevout) != spent_outpoints.end()) {
3126 return state.
DoS(100,
error(
"%s: inputs double spent in the same block", __func__));
3128 spent_outpoints.insert(in.
prevout);
3139 std::unordered_set<uint256> inblock_txes;
3140 for (
size_t i = 2; i < block.
vtx.size(); i++) {
3142 inblock_txes.insert(block.
vtx[i]->GetHash());
3144 for (
auto it = spent_outpoints.begin(); it != spent_outpoints.end(); ) {
3145 if (inblock_txes.find(it->hash) != inblock_txes.end()) {
3148 if (*it == block.
vtx[1]->vin[0].prevout) {
3149 return state.
DoS(100,
error(
"%s: coinstake input created in the same block", __func__));
3151 it = spent_outpoints.erase(it);
3172 static bool IsUnspentOnFork(std::unordered_set<COutPoint, SaltedOutpointHasher>& outpoints,
3173 const std::set<CBigNum>& serials,
3178 pindexFork = startIndex;
3181 if (++readBlock ==
gArgs.
GetArg(
"-maxreorg", DEFAULT_MAX_REORG_DEPTH)) {
3183 return error(
"%s: forked chain longer than maximum reorg limit", __func__);
3185 if (pindexFork->
pprev ==
nullptr) {
3190 if (outpoints.empty() && serials.empty())
continue;
3199 for (
auto it = bl.
vtx.rbegin(); it != bl.
vtx.rend(); ++it) {
3202 for (
const CTxIn& in: tx->vin) {
3206 if (outpoints.find(in.
prevout) != outpoints.end()) {
3207 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-inputs-spent-fork-post-split");
3212 if (serials.find(s) != serials.end()) {
3213 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-serials-spent-fork-post-split");
3218 const uint256& txid = tx->GetHash();
3219 for (
size_t i = 0; i < tx->vout.size(); i++) {
3238 static bool IsSpentOnActiveChain(std::unordered_set<COutPoint, SaltedOutpointHasher>& outpoints,
const CBlockIndex* pindexFork)
3241 const int height_start = pindexFork->
nHeight + 1;
3245 for (
int height = height_start; height <= height_end && !outpoints.empty(); height++) {
3253 for (
const auto& tx : bl.
vtx) {
3255 for (
const CTxIn& in: tx->vin) {
3262 return outpoints.empty();
3270 CBlockIndex*& pindex = ppindex ? *ppindex : pindexDummy;
3276 if (!GetPrevIndex(block, &pindexPrev, state))
3280 return state.
DoS(100,
false, REJECT_INVALID);
3284 std::string strError;
3286 return state.
DoS(100,
error(
"%s: proof of stake check failed (%s)", __func__, strError));
3302 setDirtyBlockIndex.insert(pindex);
3307 int nHeight = pindex->
nHeight;
3312 bool isBlockFromFork = pindexPrev !=
nullptr &&
chainActive.
Tip() != pindexPrev;
3315 std::unordered_set<COutPoint, SaltedOutpointHasher> spent_outpoints;
3316 std::set<CBigNum> spent_serials;
3317 if (!CheckInBlockDoubleSpends(block, nHeight, state, spent_outpoints, spent_serials)) {
3325 if (isBlockFromFork && !IsUnspentOnFork(spent_outpoints, spent_serials, pindexPrev, state, pindexFork)) {
3328 assert(!isBlockFromFork || pindexFork !=
nullptr);
3333 return error(
"%s: forked chain longer than maximum reorg limit", __func__);
3337 for (
const CBigNum& s : spent_serials) {
3341 if (nHeightTx <= pindexFork->nHeight)
3342 return state.
DoS(100,
error(
"%s: serials double spent on main chain", __func__));
3347 for (
auto it = spent_outpoints.begin(); it != spent_outpoints.end(); ) {
3351 if (isBlockFromFork && (
int) coin.
nHeight > pindexFork->
nHeight) {
3352 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-inputs-created-post-split");
3355 it = spent_outpoints.erase(it);
3358 if (!isBlockFromFork)
3359 return error(
"%s: tx inputs spent/not-available on main chain (%s)", __func__, it->ToString());
3363 if (isBlockFromFork && !spent_outpoints.empty()) {
3374 if (!IsSpentOnActiveChain(spent_outpoints, pindexFork)) {
3375 return state.
DoS(100,
false, REJECT_INVALID,
"bad-txns-inputs-spent-fork-pre-split");
3381 const CTxIn& coinstake_in = coinstake.
vin[0];
3385 return state.
DoS(100,
error(
"%s: main chain ContextualCheckZerocoinSpend failed for tx %s", __func__,
3386 coinstake.
GetHash().
GetHex()), REJECT_INVALID,
"bad-txns-invalid-zpiv");
3399 return error(
"%s : FindBlockPos failed", __func__);
3402 return AbortNode(state,
"Failed to write block");
3404 return error(
"%s : ReceivedBlockTransactions failed", __func__);
3405 }
catch (
const std::runtime_error& e) {
3406 return AbortNode(state, std::string(
"System error: ") + e.what());
3426 return error (
"%s : CheckBlock FAILED for block %s, %s", __func__, pblock->GetHash().GetHex(),
FormatStateMessage(state));
3431 bool ret = AcceptBlock(*pblock, state, &pindex, dbp);
3435 return error(
"%s : AcceptBlock FAILED", __func__);
3442 return error(
"%s : ActivateBestChain failed", __func__);
3444 LogPrintf(
"%s : ACCEPTED Block %ld in %ld milliseconds with size=%d\n", __func__, newHeight,
GetTimeMillis() - nStartTime,
3455 LogPrintf(
"%s : No longer working on chain tip\n", __func__);
3459 return state.
DoS(10,
error(
"%s: conflicting with chainlock", __func__), REJECT_INVALID,
"bad-chainlock");
3464 indexDummy.
pprev = pindexPrev;
3468 auto dbTx =
evoDb->BeginTransaction();
3473 if (!
CheckBlock(block, state, fCheckPOW, fCheckMerkleRoot, fCheckBlockSig))
3477 if (!ConnectBlock(block, state, &indexDummy, viewNew,
true))
3496 return BlockFileSeq().
Open(pos, fReadOnly);
3501 return UndoFileSeq().
Open(pos, fReadOnly);
3506 return BlockFileSeq().
FileName(pos);
3519 return (*mi).second;
3537 boost::this_thread::interruption_point();
3540 std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight;
3542 for (
const std::pair<const uint256, CBlockIndex*>& item :
mapBlockIndex) {
3544 vSortedByHeight.emplace_back(pindex->
nHeight, pindex);
3546 if (pindex->
pprev) {
3550 std::sort(vSortedByHeight.begin(), vSortedByHeight.end());
3551 for (
const std::pair<int, CBlockIndex*>& item : vSortedByHeight) {
3559 if (pindex->
pprev) {
3572 mapBlocksUnlinked.emplace(pindex->
pprev, pindex);
3580 setBlockIndexCandidates.insert(pindex);
3582 pindexBestInvalid = pindex;
3590 pblocktree->ReadLastBlockFile(nLastBlockFile);
3591 vinfoBlockFile.resize(nLastBlockFile + 1);
3592 LogPrintf(
"%s: last block file = %i\n", __func__, nLastBlockFile);
3593 for (
int nFile = 0; nFile <= nLastBlockFile; nFile++) {
3594 pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]);
3596 LogPrintf(
"%s: last block file info: %s\n", __func__, vinfoBlockFile[nLastBlockFile].ToString());
3597 for (
int nFile = nLastBlockFile + 1;
true; nFile++) {
3599 if (
pblocktree->ReadBlockFileInfo(nFile, info)) {
3600 vinfoBlockFile.push_back(info);
3607 LogPrintf(
"Checking all blk files are present...\n");
3608 std::set<int> setBlkDataFiles;
3609 for (
const std::pair<const uint256, CBlockIndex*>& item :
mapBlockIndex) {
3612 setBlkDataFiles.insert(pindex->
nFile);
3615 for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) {
3623 bool fLastShutdownWasPrepared =
true;
3624 pblocktree->ReadFlag(
"shutdown", fLastShutdownWasPrepared);
3625 LogPrintf(
"%s: Last shutdown was prepared: %s\n", __func__, fLastShutdownWasPrepared);
3628 bool fReindexing =
false;
3634 LogPrintf(
"LoadBlockIndexDB(): transaction index %s\n",
fTxIndex ?
"enabled" :
"disabled");
3651 LogPrintf(
"%s: Connecting genesis block...\n", __func__);
3665 PruneBlockIndexCandidates();
3669 LogPrintf(
"Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
3695 auto dbTx =
evoDb->BeginTransaction();
3698 if (nCheckDepth <= 0)
3699 nCheckDepth = 1000000000;
3700 if (nCheckDepth > chainHeight)
3701 nCheckDepth = chainHeight;
3702 nCheckLevel = std::max(0, std::min(4, nCheckLevel));
3703 LogPrintf(
"Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
3707 int nGoodTransactions = 0;
3709 LogPrintf(
"[0%%]...");
3712 boost::this_thread::interruption_point();
3713 int percentageDone = std::max(1, std::min(99, (
int)(((
double)(
chainActive.
Height() - pindex->
nHeight)) / (
double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
3714 if (reportDone < percentageDone/10) {
3716 LogPrintf(
"[%d%%]...", percentageDone);
3717 reportDone = percentageDone/10;
3720 if (pindex->
nHeight < chainHeight - nCheckDepth)
3727 if (nCheckLevel >= 1 && !
CheckBlock(block, state))
3730 if (nCheckLevel >= 2 && pindex) {
3743 return error(
"%s: *** irrecoverable inconsistency in block data at %d, hash=%s", __func__,
3746 pindexState = pindex->
pprev;
3748 nGoodTransactions = 0;
3749 pindexFailure = pindex;
3751 nGoodTransactions += block.
vtx.size();
3758 return error(
"%s: *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", __func__, chainHeight - pindexFailure->
nHeight + 1, nGoodTransactions);
3761 if (nCheckLevel >= 4) {
3764 boost::this_thread::interruption_point();
3765 uiInterface.
ShowProgress(
_(
"Verifying blocks..."), std::max(1, std::min(99, 100 - (
int)(((
double)(chainHeight - pindex->
nHeight)) / (
double)nCheckDepth * 50))));
3770 if (!ConnectBlock(block, state, pindex, coins,
false))
3774 LogPrintf(
"[DONE].\n");
3775 LogPrintf(
"No coin database inconsistencies in last %i blocks (%i transactions)\n", chainHeight - pindexState->
nHeight, nGoodTransactions);
3791 const bool fSkipInvalid = SkipInvalidUTXOS(pindex->
nHeight);
3794 if (!tx->IsCoinBase()) {
3795 for (
const CTxIn &txin : tx->vin) {
3796 inputs.SpendCoin(txin.
prevout);
3806 return error(
"%s: Special tx processing failed for block %s with %s",
3820 if (hashHeads.empty())
return true;
3821 if (hashHeads.size() != 2)
return error(
"%s: unknown inconsistent state", __func__);
3824 LogPrintf(
"Replaying blocks\n");
3832 return error(
"%s: reorganization to unknown block requested", __func__);
3835 if (!hashHeads[1].IsNull()) {
3838 return error(
"%s: reorganization from unknown block requested", __func__);
3841 assert(pindexFork !=
nullptr);
3845 while (pindexOld != pindexFork) {
3861 pindexOld = pindexOld->
pprev;
3865 int nForkHeight = pindexFork ? pindexFork->
nHeight : 0;
3866 for (
int nHeight = nForkHeight + 1; nHeight <= pindexNew->
nHeight; ++nHeight) {
3869 if (!RollforwardBlock(pindex, cache, params))
return false;
3885 setBlockIndexCandidates.clear();
3887 pindexBestInvalid =
nullptr;
3890 mapBlocksUnlinked.clear();
3891 vinfoBlockFile.clear();
3893 nBlockSequenceId = 1;
3894 setDirtyBlockIndex.clear();
3895 setDirtyFileInfo.clear();
3898 delete entry.second;
3909 if (!LoadBlockIndexDB(strError))
3921 LogPrintf(
"Initializing databases...\n");
3948 return error(
"%s: FindBlockPos failed", __func__);
3950 return error(
"%s: writing genesis block to disk failed", __func__);
3953 return error(
"%s: genesis block not accepted", __func__);
3954 }
catch (
const std::runtime_error& e) {
3955 return error(
"%s: failed to write genesis block: %s", __func__, e.what());
3965 static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
3975 CBufferedFile blkdat(fileIn, 2 * MAX_BLOCK_SIZE_CURRENT, MAX_BLOCK_SIZE_CURRENT + 8,
SER_DISK, CLIENT_VERSION);
3976 uint64_t nRewind = blkdat.
GetPos();
3977 while (!blkdat.
eof()) {
3978 boost::this_thread::interruption_point();
3983 unsigned int nSize = 0;
3988 nRewind = blkdat.
GetPos()+1;
3994 if (nSize < 80 || nSize > MAX_BLOCK_SIZE_CURRENT)
3996 }
catch (
const std::exception&) {
4002 uint64_t nBlockPos = blkdat.
GetPos();
4004 dbp->
nPos = nBlockPos;
4005 blkdat.
SetLimit(nBlockPos + nSize);
4006 blkdat.
SetPos(nBlockPos);
4009 nRewind = blkdat.
GetPos();
4029 std::shared_ptr<const CBlock> block_ptr = std::make_shared<const CBlock>(block);
4037 }
else if (hash !=
Params().GetConsensus().hashGenesisBlock && pindex->
nHeight % 1000 == 0) {
4042 std::deque<uint256> queue;
4043 queue.push_back(hash);
4044 while (!queue.empty()) {
4047 std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
4048 while (range.first != range.second) {
4049 std::multimap<uint256, FlatFilePos>::iterator it = range.first;
4053 std::shared_ptr<const CBlock> block_ptr = std::make_shared<const CBlock>(block);
4056 queue.emplace_back(block.
GetHash());
4060 mapBlocksUnknownParent.erase(it);
4063 }
catch (
const std::exception& e) {
4064 LogPrintf(
"%s : Deserialize or I/O error - %s\n", __func__, e.what());
4067 }
catch (
const std::runtime_error& e) {
4068 AbortNode(std::string(
"System error: ") + e.what());
4071 LogPrintf(
"Loaded %i blocks from external file in %dms\n", nLoaded,
GetTimeMillis() - nStart);
4075 void static CheckBlockIndex()
4092 std::multimap<CBlockIndex*, CBlockIndex*> forward;
4094 forward.emplace(entry.second->pprev, entry.second);
4099 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(
nullptr);
4101 rangeGenesis.first++;
4102 assert(rangeGenesis.first == rangeGenesis.second);
4113 CBlockIndex* pindexFirstNotScriptsValid =
nullptr;
4114 while (pindex !=
nullptr) {
4123 if (pindex->
pprev ==
nullptr) {
4133 assert((pindexFirstMissing !=
nullptr) == (pindex->
nChainTx == 0));
4134 assert(pindex->
nHeight == nHeight);
4137 assert(pindexFirstNotTreeValid ==
nullptr);
4141 if (pindexFirstInvalid ==
nullptr) {
4145 if (!CBlockIndexWorkComparator()(pindex,
chainActive.
Tip()) && pindexFirstMissing ==
nullptr) {
4146 if (pindexFirstInvalid ==
nullptr) {
4147 assert(setBlockIndexCandidates.count(pindex));
4150 assert(setBlockIndexCandidates.count(pindex) == 0);
4153 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> rangeUnlinked = mapBlocksUnlinked.equal_range(pindex->
pprev);
4154 bool foundInUnlinked =
false;
4155 while (rangeUnlinked.first != rangeUnlinked.second) {
4156 assert(rangeUnlinked.first->first == pindex->
pprev);
4157 if (rangeUnlinked.first->second == pindex) {
4158 foundInUnlinked =
true;
4161 rangeUnlinked.first++;
4164 if (pindexFirstInvalid ==
nullptr) {
4165 assert(foundInUnlinked);
4168 assert(!foundInUnlinked);
4174 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = forward.equal_range(pindex);
4175 if (range.first != range.second) {
4177 pindex = range.first->second;
4186 if (pindex == pindexFirstInvalid) pindexFirstInvalid =
nullptr;
4187 if (pindex == pindexFirstMissing) pindexFirstMissing =
nullptr;
4188 if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid =
nullptr;
4189 if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid =
nullptr;
4190 if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid =
nullptr;
4194 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> rangePar = forward.equal_range(pindexPar);
4195 while (rangePar.first->second != pindex) {
4196 assert(rangePar.first != rangePar.second);
4201 if (rangePar.first != rangePar.second) {
4203 pindex = rangePar.first->second;
4215 assert(nNodes == forward.size());
4230 return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT;
4232 return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT;
4242 return &vinfoBlockFile.at(n);
4245 static const uint64_t MEMPOOL_DUMP_VERSION = 1;
4249 int64_t nExpiryTimeout =
gArgs.
GetArg(
"-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
4250 FILE* filestr =
fopen((
GetDataDir() /
"mempool.dat").
string().c_str(),
"r");
4253 LogPrintf(
"Failed to open mempool file from disk. Continuing anyway.\n");
4258 int64_t skipped = 0;
4265 if (version != MEMPOOL_DUMP_VERSION) {
4278 CAmount amountdelta = nFeeDelta;
4283 if (nTime + nExpiryTimeout > nNow) {
4297 std::map<uint256, CAmount> mapDeltas;
4300 for (
const auto& i : mapDeltas) {
4303 }
catch (
const std::exception& e) {
4304 LogPrintf(
"Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
4308 LogPrintf(
"Imported mempool transactions from disk: %i successes, %i failed, %i expired\n", count, failed, skipped);
4316 std::map<uint256, CAmount> mapDeltas;
4317 std::vector<TxMempoolInfo> vinfo;
4319 static Mutex dump_mutex;
4325 mapDeltas[i.first] = i.second;
4333 FILE* filestr =
fopen((
GetDataDir() /
"mempool.dat.new").
string().c_str(),
"w");
4340 uint64_t version = MEMPOOL_DUMP_VERSION;
4343 file << (uint64_t)vinfo.size();
4344 for (
const auto& i : vinfo) {
4346 file << (int64_t)i.nTime;
4347 file << (int64_t)i.nFeeDelta;
4348 mapDeltas.erase(i.tx->GetHash());
4353 throw std::runtime_error(
"FileCommit failed");
4356 throw std::runtime_error(
"Rename failed");
4359 LogPrintf(
"Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*0.000001, (last-mid)*0.000001);
4360 }
catch (
const std::exception& e) {
4361 LogPrintf(
"Failed to dump mempool: %s. Continuing anyway.\n", e.what());
4376 delete (*it1).second;
int64_t CAmount
Amount in PIV (Can be negative)
bool CheckBlockSignature(const CBlock &block)
CBudgetManager g_budgetman
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends.
@ BLOCK_VALID_MASK
All validity bits.
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
@ BLOCK_HAVE_UNDO
full block available in blk*.dat
@ BLOCK_FAILED_CHILD
stage after last reached validness failed
@ BLOCK_FAILED_MASK
descends from failed block
const CChainParams & Params()
Return the currently selected parameters.
std::map< int, uint256 > MapCheckpoints
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void setBlockHash(const uint256 &_hash)
BlockStateCatcher & get() const
Non-refcounted RAII wrapper for FILE*.
FILE * Get() const
Get wrapped FILE* without transfer of ownership.
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
static const std::string MAIN
Chain name strings.
uint64_t nTimeFirst
earliest time of block in file
uint64_t nTimeLast
latest time of block in file
std::string ToString() const
unsigned int nHeightFirst
lowest height of block in file
unsigned int nHeightLast
highest height of block in file
unsigned int nBlocks
number of blocks stored in file
unsigned int nSize
number of used bytes of block file
std::vector< CTransactionRef > vtx
bool IsProofOfStake() const
bool IsProofOfWork() const
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool RaiseValidity(enum BlockStatus nUpTo)
Raise the validity level of this block index entry.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
void BuildSkip()
Build the skiplist pointer for this entry.
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
int nFile
Which # file this block is stored in (blk?????.dat)
FlatFilePos GetBlockPos() const
void SetNewStakeModifier()
int64_t MaxFutureBlockTime() const
uint32_t nSequenceId
(memory only) Sequential id assigned to distinguish order in which blocks are received.
unsigned int nTimeMax
(memory only) Maximum nTime in the chain upto and including this block.
unsigned int nUndoPos
Byte offset within rev?????.dat where this block's undo data is stored.
uint256 GetBlockHash() const
int64_t GetBlockTime() const
void SetChainSaplingValue()
int64_t GetMedianTimePast() const
CAmount nSaplingValue
Change in value held by the Sapling circuit over this block.
CBlockIndex * pskip
pointer to the index of some further predecessor of this block
unsigned int nTx
Number of transactions in this block.
uint256 hashFinalSaplingRoot
FlatFilePos GetUndoPos() const
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const
Check whether this block index entry is valid up to the passed validity level.
int32_t nVersion
block header
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
uint32_t nStatus
Verification status of this block. See enum BlockStatus.
unsigned int nDataPos
Byte offset within blk?????.dat where this block's data is stored.
Optional< CAmount > nChainSaplingValue
(memory only) Total value held by the Sapling circuit up to and including this block.
unsigned int nChainTx
(memory only) Number of transactions in the chain up to and including this block.
const uint256 * phashBlock
pointer to the hash of the block, if any. memory is owned by this CBlockIndex
Undo information for a CBlock.
std::vector< CTxUndo > vtxundo
void RemoveByFeeTxId(const uint256 &feeTxId)
void SetBestHeight(int height)
bool IsBudgetPaymentBlock(int nBlockHeight) const
Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to deserialize from.
bool SetLimit(uint64_t nPos=std::numeric_limits< uint64_t >::max())
prevent reading beyond a certain position no argument removes the limit
bool SetPos(uint64_t nPos)
rewind to a given reading position
An in-memory indexed chain of blocks.
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockLocator GetLocator(const CBlockIndex *pindex=nullptr) const
Return a CBlockLocator that refers to a block in this chain (by default the tip).
int Height() const
Return the maximal height in the chain.
const CBlockIndex * FindFork(const CBlockIndex *pindex) const
Find the last common block between this chain and a block index entry.
void SetTip(CBlockIndex *pindex)
Set/initialize a chain with a given tip.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the PIVX system.
std::string NetworkIDString() const
Return the network string.
const CMessageHeader::MessageStartChars & MessageStart() const
virtual const CCheckpointData & Checkpoints() const =0
const Consensus::Params & GetConsensus() const
const CBlock & GenesisBlock() const
RAII-style controller object for a CCheckQueue that guarantees the passed queue is finished before co...
Queue for verifications that have to be performed.
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
boost::signals2::signal< bool(const std::string &message, const std::string &caption, unsigned int style), boost::signals2::last_value< bool > > ThreadSafeMessageBox
Show message box.
boost::signals2::signal< void()> NotifyAlertChanged
New, updated or cancelled alert.
boost::signals2::signal< void(bool fInitialDownload, const CBlockIndex *newTip)> NotifyBlockTip
New block has been accepted.
void SetBackend(CCoinsView &viewIn)
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
CAmount GetValueIn(const CTransaction &tx) const
Amount of pivx coming in to a transaction Note that lightweight clients may not know anything besides...
bool HaveInputs(const CTransaction &tx) const
Check whether all prevouts of the transaction are present in the UTXO set represented by this view.
void SetNullifiers(const CTransaction &tx, bool spent)
void PushAnchor(const Tree &tree)
void PopAnchor(const uint256 &rt)
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool potential_overwrite)
Add a coin.
bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const override
Retrieve the tree (Sapling) at a particular anchored root in the chain.
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
uint256 GetBestAnchor() const override
Get the current "tip" or the latest anchored tree root in the chain.
void SetBestBlock(const uint256 &hashBlock)
bool Flush()
Push the modifications applied to this cache to its base.
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
bool HaveShieldedRequirements(const CTransaction &tx) const
Check whether all sapling spend requirements (anchors/nullifiers) are satisfied.
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether we have data for a given outpoint.
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to a Coin in the cache, or a pruned one if not found.
Abstract view on the open txout dataset.
virtual std::vector< uint256 > GetHeadBlocks() const
Retrieve the range of blocks that may have been only partially written.
CCoinsView that brings transactions from a memorypool into view.
Fee rate in PIV per kilobyte: CAmount / kB.
CAmount GetFee(size_t size) const
Reads data from an underlying stream, while hashing the read data.
A writer stream (for serialization) that computes a 256-bit hash.
void SetBestChain(const CBlockLocator &)
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)
void AcceptedBlockHeader(const CBlockIndex *pindexNew)
void BlockChecked(const CBlock &, const CValidationState &)
void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const uint256 &blockHash, int nBlockHeight, int64_t blockTime)
void TransactionAddedToMempool(const CTransactionRef &ptxn)
void BlockConnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
void CheckSpentCollaterals(const std::vector< CTransactionRef > &vtx)
Check all transactions in a block, for spent masternode collateral outpoints (marking them as spent)
void CacheBlockHash(const CBlockIndex *pindex)
void SetBestHeight(int height)
void UncacheBlockHash(const CBlockIndex *pindex)
void Update(const CAmount &_nSupply, int _nHeight)
An outpoint - a combination of a transaction hash and an index n into its vout.
Closure representing one script verification Note that this stores references to the spending transac...
ScriptError GetScriptError() const
void swap(CScriptCheck &check)
PrecomputedTransactionData * precomTxData
const CTransaction * ptxTo
Serialized script, used inside transaction inputs and outputs.
int64_t GetSporkValue(SporkId nSporkID)
bool IsSporkActive(SporkId nSporkID)
The basic transaction that is broadcasted on the network and contained in blocks.
bool HasZerocoinSpendInputs() const
bool IsQuorumCommitmentTx() const
bool IsShieldedTx() const
SigVersion GetRequiredSigVersion() const
const uint256 & GetHash() const
CAmount GetShieldedValueIn() const
unsigned int GetTotalSize() const
CAmount GetValueOut() const
Optional< SaplingTxData > sapData
std::vector< CTxOut > vout
An input of a transaction.
bool IsZerocoinSpend() const
bool IsZerocoinPublicSpend() const
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void PrioritiseTransaction(const uint256 &hash, const CAmount &nFeeDelta)
Affect CreateNewBlock prioritisation of transactions.
void removeWithAnchor(const uint256 &invalidRoot)
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason=MemPoolRemovalReason::UNKNOWN)
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
CTransactionRef get(const uint256 &hash) const
int Expire(int64_t time)
Expire all transaction (and their dependencies) in the mempool older than time.
void AddTransactionsUpdated(unsigned int n)
void removeProTxReferences(const uint256 &proTxHash, MemPoolRemovalReason reason)
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
std::map< uint256, CAmount > mapDeltas
void UpdateTransactionsFromBlock(const std::vector< uint256 > &hashesToUpdate)
When adding transactions from a disconnected block back to the mempool, new mempool entries may have ...
bool exists(uint256 hash) const
std::set< txiter, CompareIteratorByHash > setEntries
void check(const CCoinsViewCache *pcoins) const
If sanity-checking is turned on, check makes sure the pool is consistent (does not contain two transa...
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags)
void TrimToSize(size_t sizelimit, std::vector< COutPoint > *pvNoSpendsRemaining=nullptr)
Remove transactions from the mempool until its dynamic size is <= sizelimit.
void removeForBlock(const std::vector< CTransactionRef > &vtx, unsigned int nBlockHeight)
Called when a block is connected.
void ApplyDelta(const uint256 &hash, CAmount &nFeeDelta) const
An output of a transaction.
Undo information for a CTransaction.
std::vector< Coin > vprevout
Capture information about block/transaction validation.
unsigned int GetRejectCode() const
bool Invalid(bool ret=false, unsigned int _chRejectCode=0, const std::string &_strRejectReason="", const std::string &_strDebugMessage="")
bool DoS(int level, bool ret=false, unsigned int chRejectCodeIn=0, std::string strRejectReasonIn="", bool corruptionIn=false, const std::string &strDebugMessageIn="")
std::string GetRejectReason() const
bool Error(std::string strRejectReasonIn="")
bool CorruptionPossible() const
std::string GetDebugMessage() const
bool VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
bool fCoinStake
whether the containing transaction was a coinstake
CTxOut out
unspent transaction output
bool fCoinBase
whether the containing transaction was a coinbase
uint32_t nHeight
at which height the containing transaction was included in the active block chain
Used to track blocks whose transactions were applied to the UTXO state as a part of a single Activate...
std::vector< PerBlockConnectTrace > blocksConnected
std::vector< PerBlockConnectTrace > & GetBlocksConnected()
void BlockConnected(CBlockIndex *pindex, std::shared_ptr< const CBlock > pblock)
FlatFileSeq represents a sequence of numbered files storing raw data.
fs::path FileName(const FlatFilePos &pos) const
Get the name of the file at the given position.
size_t Allocate(const FlatFilePos &pos, size_t add_size, bool &out_of_space)
Allocate additional space in a file after the given starting position.
bool Flush(const FlatFilePos &pos, bool finalize=false)
Commit a file to disk, and optionally truncate off extra pre-allocated bytes if final.
FILE * Open(const FlatFilePos &pos, bool read_only=false)
Open a handle to the file at the given position.
A shielded output to a transaction.
uint256 cmu
The u-coordinate of the note commitment for the output note.
std::string ToString() const
std::string GetHex() const
static libzcash::PedersenHash empty_root()
The complete proof needed to spend a zerocoin.
const CBigNum & getCoinSerialNumber() const
void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight, bool check, bool fSkipInvalid)
Utility function to add all of a transaction's outputs to a cache.
const Coin & AccessByTxid(const CCoinsViewCache &view, const uint256 &txid)
Utility function to find any unspent output with a given txid.
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
std::unique_ptr< CEvoDB > evoDb
CClientUIInterface uiInterface
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, unsigned int flags, const BaseSignatureChecker &checker, SigVersion sigversion, ScriptError *serror)
@ SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY
@ SCRIPT_VERIFY_EXCHANGEADDR
bool CheckProofOfStake(const CBlock &block, std::string &strError, const CBlockIndex *pindexPrev)
#define LogPrint(category,...)
bool IsBlockValueValid(int nHeight, CAmount &nExpectedValue, CAmount nMinted, CAmount &nBudgetAmt)
bool IsCoinbaseValueValid(const CTransactionRef &tx, CAmount nBudgetAmt, CValidationState &_state)
Check coinbase output value for blocks after v6.0 enforcement.
bool IsBlockPayeeValid(const CBlock &block, const CBlockIndex *pindexPrev)
CMasternodeMan mnodeman
Masternode manager.
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
bool CheckBlock(int nHeight, const uint256 &hash, bool fMatchesCheckpoint)
Returns true if block passes checkpoint checks.
int GetTotalBlocksEstimate()
Return conservative estimate of total number of blocks, 0 if unknown.
double GuessVerificationProgress(const CBlockIndex *pindex, bool fSigchecks)
Guess how far we are in the verification process at the given block index.
bool CheckTxInputs(const CTransaction &tx, CValidationState &state, const CCoinsViewCache &inputs, int nSpendHeight)
libzerocoin::CoinSpend TxInToZerocoinSpend(const CTxIn &txin)
void CleanCoinSpendsCache()
bool ParseZerocoinPublicSpend(const CTxIn &txIn, const CTransaction &tx, CValidationState &state, PublicCoinSpend &publicSpend)
FILE * fopen(const fs::path &p, const char *mode)
std::set< COutPoint > setInvalidOutPoints
std::unique_ptr< CChainLocksHandler > chainLocksHandler
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
bool AreInputsStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs)
Check for standard transaction types.
bool IsStandardTx(const CTransactionRef &tx, int nBlockHeight, std::string &reason)
Check for standard transaction types.
bool CheckProofOfWork(uint256 hash, unsigned int nBits)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
arith_uint256 GetBlockProof(const CBlockIndex &block)
unsigned int GetNextWorkRequired(const CBlockIndex *pindexLast, const CBlockHeader *pblock)
reverse_range< T > reverse_iterate(T &x)
const char * ScriptErrorString(const ScriptError serror)
unsigned int GetSerializeSize(const std::array< T, N > &item)
array
unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 byt...
bool UndoSpecialTxsInBlock(const CBlock &block, const CBlockIndex *pindex)
bool CheckSpecialTx(const CTransaction &tx, const CBlockIndex *pindexPrev, const CCoinsViewCache *view, CValidationState &state)
Payload validity checks (including duplicate unique properties against list at pindexPrev)
bool CheckSpecialTxNoContext(const CTransaction &tx, CValidationState &state)
bool ProcessSpecialTxsInBlock(const CBlock &block, const CBlockIndex *pindex, const CCoinsViewCache *view, CValidationState &state, bool fJustCheck)
CSporkManager sporkManager
@ SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2
@ SPORK_13_ENABLE_SUPERBLOCKS
@ SPORK_19_COLDSTAKING_MAINTENANCE
@ SPORK_20_SAPLING_MAINTENANCE
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
const MapCheckpoints * mapCheckpoints
int nActivationHeight
Height of the first block for which the new consensus rules will be active.
Parameters that influence chain consensus.
CAmount nNewMNBlockReward
int64_t nPivxBadBlockTime
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]
libzerocoin::ZerocoinParams * Zerocoin_Params(bool useModulusV1) const
unsigned int nPivxBadBlockBits
bool MoneyRange(const CAmount &nValue) const
int height_last_ZC_AccumCheckpoint
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const
Returns true if the given network upgrade is active as of the given block height.
int height_last_invalid_UTXO
void removeEntry(indexed_disconnected_transactions::index< insertion_order >::type::iterator entry)
indexed_disconnected_transactions queuedTx
void removeForBlock(const std::vector< CTransactionRef > &vtx)
size_t DynamicMemoryUsage() const
void addTransaction(const CTransactionRef &tx)
std::shared_ptr< const CBlock > pblock
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define AssertLockHeld(cs)
bool RenameOver(fs::path src, fs::path dest)
const fs::path & GetDataDir(bool fNetSpecific)
bool CheckDiskSpace(const fs::path &dir, uint64_t additional_bytes)
const fs::path & GetBlocksDir()
void runCommand(std::string strCommand)
bool FileCommit(FILE *file)
bool error(const char *fmt, const Args &... args)
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a Optional result.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
TierTwoSyncState g_tiertwo_sync_state
int64_t GetAdjustedTime()
std::shared_ptr< const CTransaction > CTransactionRef
bool IsFinalTx(const CTransactionRef &tx, int nBlockHeight, int64_t nBlockTime)
Check if transaction is final and can be included in a block with the specified height and time.
bool CheckTransaction(const CTransaction &tx, CValidationState &state, bool fColdStakingActive)
Transaction validation functions.
bool ContextualCheckTransaction(const CTransactionRef &tx, CValidationState &state, const CChainParams &chainparams, int nHeight, bool isMined, bool fIBD)
Context-dependent validity checks.
unsigned int GetLegacySigOpCount(const CTransaction &tx)
Count ECDSA signature operations the old-fashioned (pre-0.6) way.
unsigned int GetP2SHSigOpCount(const CTransaction &tx, const CCoinsViewCache &inputs)
Count ECDSA signature operations in pay-to-script-hash inputs.
@ REORG
Removed in size limiting.
const uint256 UINT256_ZERO
constant uint256 instances
bool NetworkUpgradeActive(int nHeight, const Consensus::Params ¶ms, Consensus::UpgradeIndex idx)
Returns true if the given network upgrade is active as of the given block height.
std::string FormatStateMessage(const CValidationState &state)
Convert CValidationState to a human-readable message for logging.
std::string FormatMoney(const CAmount &n, bool fPlus)
Money parsing/formatting utilities.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
int64_t GetTimeMicros()
Returns the system time (not mockable)
int64_t GetTimeMillis()
Returns the system time (not mockable)
std::string FormatISO8601Date(int64_t nTime)
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
double ConvertBitsToDouble(unsigned int nBits)
DisconnectResult DisconnectBlock(CBlock &block, const CBlockIndex *pindex, CCoinsViewCache &view)
Undo the effects of this block (with given index) on the UTXO set represented by coins.
void CheckForkWarningConditionsOnNewFork(CBlockIndex *pindexNewForkTip)
void FlushStateToDisk()
Flush all state, indexes and buffers to disk.
bool AcceptToMemoryPoolWithTime(CTxMemPool &pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool *pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, bool fRejectAbsurdFee, bool fIgnoreFees)
(try to) add transaction to memory pool with a specified acceptance time
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
int ActiveProtocol()
See whether the protocol update is enforced for connected nodes.
std::unique_ptr< CBlockTreeDB > pblocktree
Global variable that points to the active block tree (protected by cs_main)
std::unique_ptr< CZerocoinDB > zerocoinDB
Global variable that points to the zerocoin database (protected by cs_main)
std::condition_variable g_best_block_cv
bool ReceivedBlockTransactions(const CBlock &block, CValidationState &state, CBlockIndex *pindexNew, const FlatFilePos &pos)
Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS).
bool ContextualCheckBlockHeader(const CBlockHeader &block, CValidationState &state, CBlockIndex *const pindexPrev)
Context-dependent validity checks.
bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, uint256 &hashBlock, bool fAllowSlow, CBlockIndex *blockIndex)
Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock.
CAmount GetShieldedTxMinFee(const CTransaction &tx)
Return the minimum fee for a shielded tx.
std::unique_ptr< CSporkDB > pSporkDB
Global variable that points to the spork database (protected by cs_main)
bool CheckFinalTx(const CTransactionRef &tx, int flags)
Check if transaction will be final in the next block to be created.
bool CheckInputs(const CTransaction &tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData &precomTxData, std::vector< CScriptCheck > *pvChecks)
Check transaction inputs, and make sure any pay-to-script-hash transactions are evaluating IsStandard...
bool LoadBlockIndex(std::string &strError)
Load the block tree and coins database from disk, initializing state if we're running with -reindex.
int ApplyTxInUndo(Coin &&undo, CCoinsViewCache &view, const COutPoint &out)
Restore the UTXO in a Coin at a given COutPoint.
bool DumpMempool(const CTxMemPool &pool)
Dump the mempool to disk.
bool WriteBlockToDisk(const CBlock &block, FlatFilePos &pos)
Functions for disk access for blocks.
CTxMemPool mempool(::minRelayTxFee)
bool LoadMempool(CTxMemPool &pool)
Load the mempool from disk.
CFeeRate minRelayTxFee
Fees smaller than this (in upiv) are considered zero fee (for relaying, mining and transaction creati...
bool CheckWork(const CBlock &block, const CBlockIndex *const pindexPrev)
CScript COINBASE_FLAGS
Constant stuff for coinbase transactions we create:
bool IsInitialBlockDownload()
Check whether we are doing an initial block download (synchronizing from disk or network)
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &pblock, const FlatFilePos *dbp)
Process an incoming block.
void LimitMempoolSize(CTxMemPool &pool, size_t limit, unsigned long age)
bool ActivateBestChain(CValidationState &state, std::shared_ptr< const CBlock > pblock)
Make the best chain active, in multiple steps.
class CMainCleanup instance_of_cmaincleanup
void CheckForkWarningConditions()
std::unique_ptr< CCoinsViewCache > pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
int64_t g_best_block_time
CBlockFileInfo * GetBlockFileInfo(size_t n)
Get block file info entry for one block file.
int64_t GetMasternodePayment(int nHeight)
CAmount GetBlockValue(int nHeight)
std::atomic< bool > fImporting
bool AcceptBlockHeader(const CBlock &block, CValidationState &state, CBlockIndex **ppindex, CBlockIndex *pindexPrev)
bool ReconsiderBlock(CValidationState &state, CBlockIndex *pindex)
Remove invalidity status from a block and its descendants.
bool CheckBlockTime(const CBlockHeader &block, CValidationState &state, CBlockIndex *const pindexPrev)
std::map< uint256, int64_t > mapRejectedBlocks
void ThreadScriptCheck()
Run an instance of the script checking thread.
FILE * OpenUndoFile(const FlatFilePos &pos, bool fReadOnly)
Open an undo file (rev?????.dat)
bool AcceptToMemoryPool(CTxMemPool &pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool *pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectInsaneFee, bool ignoreFees)
(try to) add transaction to memory pool
fs::path GetBlockPosFilename(const FlatFilePos &pos)
Translation to a filesystem path.
CBlockIndex * pindexBestForkBase
bool LoadChainTip(const CChainParams &chainparams)
Update the chain tip based on database information.
FILE * OpenBlockFile(const FlatFilePos &pos, bool fReadOnly)
Open a block file (blk?????.dat)
bool GetOutput(const uint256 &hash, unsigned int index, CValidationState &state, CTxOut &out)
Retrieve an output (from memory pool, or from disk, if possible)
bool CheckBlock(const CBlock &block, CValidationState &state, bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig)
Functions for validating blocks and updating the block tree.
RecursiveMutex cs_main
Global state.
CBlockIndex * pindexBestForkTip
std::unique_ptr< CCoinsViewDB > pcoinsdbview
Global variable that points to the coins database (protected by cs_main)
CBlockIndex * InsertBlockIndex(const uint256 &hash)
Create a new block index entry for a given block hash.
bool LoadExternalBlockFile(FILE *fileIn, FlatFilePos *dbp)
Import blocks from an external file.
void UnloadBlockIndex()
Unload database information.
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos)
CAmount GetMinRelayFee(const CTransaction &tx, const CTxMemPool &pool, unsigned int nBytes)
CBlockIndex * pindexBestHeader
Best header we've seen so far (used for getheaders queries' starting points).
bool ReplayBlocks(const CChainParams ¶ms, CCoinsView *view)
Replay blocks that aren't fully applied to the database.
PrevBlockMap mapPrevBlockIndex
bool FindBlockPos(CValidationState &state, FlatFilePos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown=false)
CBlockIndex * GetChainTip()
Return a reliable pointer (in mapBlockIndex) to the chain's tip index.
std::atomic< bool > fReindex
int GetSpendHeight(const CCoinsViewCache &inputs)
Return the spend height, which is one more than the inputs.GetBestBlock().
bool CheckColdStakeFreeOutput(const CTransaction &tx, const int nHeight)
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
bool TestBlockValidity(CValidationState &state, const CBlock &block, CBlockIndex *const pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckBlockSig)
Check a block is completely valid from start to finish (only works on top of our current best block,...
bool InvalidateBlock(CValidationState &state, const CChainParams &chainparams, CBlockIndex *pindex)
Mark a block as invalid.
std::unique_ptr< AccumulatorCache > accumulatorCache
In-memory cache for the zerocoin accumulators.
bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize)
bool ContextualCheckBlock(const CBlock &block, CValidationState &state, CBlockIndex *const pindexPrev)
CBlockIndex * FindForkInGlobalIndex(const CChain &chain, const CBlockLocator &locator)
Find the last common block between the parameter chain and a locator.
void UpdateCoins(const CTransaction &tx, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, bool fSkipInvalid)
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::unordered_map< uint256, CBlockIndex *, BlockHasher > BlockMap
std::unordered_multimap< uint256, CBlockIndex *, BlockHasher > PrevBlockMap
void CacheAccChecksum(const CBlockIndex *pindex, bool fWrite)
bool DisconnectZerocoinTx(const CTransaction &tx)
CMainSignals & GetMainSignals()
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...
void SetfLargeWorkInvalidChainFound(bool flag)
void SetfLargeWorkForkFound(bool flag)
bool GetfLargeWorkForkFound()
void SetMiscWarning(const std::string &strWarning)
bool ParseAndValidateZerocoinSpends(const Consensus::Params &consensus, const CTransaction &tx, int chainHeight, CValidationState &state, std::vector< std::pair< CBigNum, uint256 >> &vSpendsRet)
bool IsSerialInBlockchain(const CBigNum &bnSerial, int &nHeightTx)
bool ContextualCheckZerocoinSpend(const CTransaction &tx, const libzerocoin::CoinSpend *spend, int nHeight)