2010-08-29 12:58:15 -04:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2021-12-30 14:36:57 -03:00
// Copyright (c) 2009-2021 The Bitcoin Core developers
2014-11-30 22:39:44 -03:00
// Distributed under the MIT software license, see the accompanying
2012-05-18 10:02:28 -04:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-09 21:57:53 -03:00
# include <validation.h>
2013-08-27 01:51:57 -04:00
2017-11-09 21:57:53 -03:00
# include <arith_uint256.h>
# include <chain.h>
# include <chainparams.h>
# include <checkqueue.h>
2021-09-10 23:29:00 -03:00
# include <consensus/amount.h>
2017-11-09 21:57:53 -03:00
# include <consensus/consensus.h>
# include <consensus/merkle.h>
2019-04-02 14:41:12 -03:00
# include <consensus/tx_check.h>
2017-11-09 21:57:53 -03:00
# include <consensus/tx_verify.h>
# include <consensus/validation.h>
# include <cuckoocache.h>
2019-01-06 16:06:31 -03:00
# include <flatfile.h>
2022-07-13 12:32:43 -04:00
# include <fs.h>
2017-11-09 21:57:53 -03:00
# include <hash.h>
2022-02-16 17:23:11 -03:00
# include <kernel/coinstats.h>
2019-08-21 12:03:39 -04:00
# include <logging.h>
# include <logging/timer.h>
2021-04-02 15:42:05 -03:00
# include <node/blockstorage.h>
2022-06-14 04:38:51 -04:00
# include <node/interface_ui.h>
2021-09-20 07:26:29 -03:00
# include <node/utxo_snapshot.h>
2017-11-09 21:57:53 -03:00
# include <policy/policy.h>
2021-07-27 05:03:49 -04:00
# include <policy/rbf.h>
2019-04-02 15:14:58 -03:00
# include <policy/settings.h>
2017-11-09 21:57:53 -03:00
# include <pow.h>
# include <primitives/block.h>
# include <primitives/transaction.h>
# include <random.h>
# include <reverse_iterator.h>
# include <script/script.h>
# include <script/sigcache.h>
2018-05-16 15:17:40 -04:00
# include <shutdown.h>
2019-07-17 05:40:34 -04:00
# include <signet.h>
2017-11-09 21:57:53 -03:00
# include <tinyformat.h>
# include <txdb.h>
# include <txmempool.h>
2019-03-23 13:41:16 -03:00
# include <uint256.h>
2017-11-09 21:57:53 -03:00
# include <undo.h>
2020-06-08 08:54:23 -04:00
# include <util/check.h> // For NDEBUG compile time check
2021-04-05 16:15:56 -04:00
# include <util/hasher.h>
2018-10-22 19:51:11 -03:00
# include <util/moneystr.h>
2019-04-02 18:03:37 -03:00
# include <util/rbf.h>
2018-10-22 19:51:11 -03:00
# include <util/strencodings.h>
2019-03-19 13:09:27 -03:00
# include <util/system.h>
2022-05-16 14:09:48 -04:00
# include <util/time.h>
2021-05-20 11:53:24 -04:00
# include <util/trace.h>
2019-06-17 03:56:52 -04:00
# include <util/translation.h>
2017-11-09 21:57:53 -03:00
# include <validationinterface.h>
# include <warnings.h>
2013-04-13 02:13:08 -03:00
2021-10-28 17:07:46 -03:00
# include <algorithm>
2022-05-16 14:09:48 -04:00
# include <chrono>
2022-05-05 02:28:29 -04:00
# include <deque>
2021-04-05 13:12:58 -04:00
# include <numeric>
2021-03-15 00:59:05 -03:00
# include <optional>
2018-06-13 14:50:59 -04:00
# include <string>
2013-04-13 02:13:08 -03:00
2022-02-18 00:02:48 -03:00
using kernel : : CCoinsStats ;
using kernel : : CoinStatsHashType ;
2022-02-16 17:23:11 -03:00
using kernel : : ComputeUTXOStats ;
2022-02-18 00:02:48 -03:00
2022-07-13 12:32:43 -04:00
using fsbridge : : FopenFn ;
2021-11-12 12:06:00 -03:00
using node : : BLOCKFILE_CHUNK_SIZE ;
using node : : BlockManager ;
using node : : BlockMap ;
2022-03-15 20:19:58 -03:00
using node : : CBlockIndexHeightOnlyComparator ;
2021-11-12 12:06:00 -03:00
using node : : CBlockIndexWorkComparator ;
2022-03-15 20:19:58 -03:00
using node : : fImporting ;
using node : : fPruneMode ;
using node : : fReindex ;
using node : : nPruneTarget ;
2021-11-12 12:06:00 -03:00
using node : : OpenBlockFile ;
using node : : ReadBlockFromDisk ;
using node : : SnapshotMetadata ;
using node : : UNDOFILE_CHUNK_SIZE ;
using node : : UndoReadFromDisk ;
using node : : UnlinkPrunedFiles ;
2017-05-31 22:42:34 -04:00
# define MICRO 0.000001
# define MILLI 0.001
2019-11-05 16:18:08 -03:00
/** Maximum kilobytes for transactions to store for processing during reorg */
static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE = 20000 ;
2020-05-28 03:00:19 -04:00
/** Time to wait between writing blocks/block index to disk. */
static constexpr std : : chrono : : hours DATABASE_WRITE_INTERVAL { 1 } ;
/** Time to wait between flushing chainstate to disk. */
static constexpr std : : chrono : : hours DATABASE_FLUSH_INTERVAL { 24 } ;
2020-05-28 03:42:06 -04:00
/** Maximum age of our tip for us to be considered current for fee estimation */
static constexpr std : : chrono : : hours MAX_FEE_ESTIMATION_TIP_AGE { 3 } ;
2020-05-30 08:52:47 -04:00
const std : : vector < std : : string > CHECKLEVEL_DOC {
" level 0 reads the blocks from disk " ,
" level 1 verifies block validity " ,
" level 2 verifies undo data " ,
" level 3 checks disconnection of tip blocks " ,
" level 4 tries to reconnect the blocks " ,
" each level includes the checks of the previous levels " ,
} ;
2021-05-13 13:13:08 -04:00
/** The number of blocks to keep below the deepest prune lock.
* There is nothing special about this number . It is higher than what we
* expect to see in regular mainnet reorgs , but not so high that it would
* noticeably interfere with the pruning mechanism .
* */
static constexpr int PRUNE_LOCK_BUFFER { 10 } ;
2019-11-05 16:18:08 -03:00
2018-12-14 19:25:05 -03:00
/**
* Mutex to guard access to validation specific variables , such as reading
* or changing the chainstate .
*
* This may also need to be locked when updating the transaction pool , e . g . on
* AcceptToMemoryPool . See CTxMemPool : : cs comment for details .
*
* The transaction pool has a separate lock to allow reading from it and the
* chainstate at the same time .
*/
RecursiveMutex cs_main ;
2010-08-29 12:58:15 -04:00
2022-04-20 03:10:13 -04:00
GlobalMutex g_best_block_mutex ;
2017-11-03 08:49:16 -03:00
std : : condition_variable g_best_block_cv ;
2018-04-04 01:53:07 -03:00
uint256 g_best_block ;
2019-11-02 18:14:38 -03:00
bool g_parallel_script_checks { false } ;
2015-06-24 00:36:22 -03:00
bool fRequireStandard = true ;
2015-03-13 13:25:34 -03:00
bool fCheckBlockIndex = false ;
2015-11-09 15:16:38 -03:00
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED ;
2015-12-14 09:23:45 -03:00
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE ;
2010-08-29 12:58:15 -04:00
2017-01-06 08:49:59 -03:00
uint256 hashAssumeValid ;
2017-05-07 15:10:19 -03:00
arith_uint256 nMinimumChainWork ;
2016-05-21 05:45:32 -04:00
2022-03-02 02:42:57 -03:00
const CBlockIndex * CChainState : : FindForkInGlobalIndex ( const CBlockLocator & locator ) const
2014-09-02 20:52:01 -04:00
{
2018-01-11 20:32:32 -03:00
AssertLockHeld ( cs_main ) ;
2018-04-11 15:14:45 -03:00
// Find the latest block common to locator and chain - we expect that
// locator.vHave is sorted descending by height.
2017-06-01 21:18:57 -04:00
for ( const uint256 & hash : locator . vHave ) {
2022-03-02 02:42:57 -03:00
const CBlockIndex * pindex { m_blockman . LookupBlockIndex ( hash ) } ;
2018-01-11 21:23:09 -03:00
if ( pindex ) {
2021-11-23 14:07:00 -03:00
if ( m_chain . Contains ( pindex ) ) {
2013-05-07 07:59:29 -04:00
return pindex ;
2021-11-23 14:07:00 -03:00
}
if ( pindex - > GetAncestor ( m_chain . Height ( ) ) = = m_chain . Tip ( ) ) {
return m_chain . Tip ( ) ;
2016-03-18 13:20:12 -03:00
}
2013-05-07 07:59:29 -04:00
}
}
2021-11-23 14:07:00 -03:00
return m_chain . Genesis ( ) ;
2014-05-05 18:54:10 -04:00
}
2021-02-16 16:41:41 -03:00
bool CheckInputScripts ( const CTransaction & tx , TxValidationState & state ,
const CCoinsViewCache & inputs , unsigned int flags , bool cacheSigStore ,
bool cacheFullScriptStore , PrecomputedTransactionData & txdata ,
std : : vector < CScriptCheck > * pvChecks = nullptr )
EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
2016-10-03 11:06:10 -03:00
2022-01-11 11:53:50 -03:00
bool CheckFinalTxAtTip ( const CBlockIndex * active_chain_tip , const CTransaction & tx )
2015-05-25 01:48:33 -03:00
{
AssertLockHeld ( cs_main ) ;
2021-02-22 13:46:21 -03:00
assert ( active_chain_tip ) ; // TODO: Make active_chain_tip a reference
2015-11-03 14:12:36 -03:00
2022-01-11 11:53:50 -03:00
// CheckFinalTxAtTip() uses active_chain_tip.Height()+1 to evaluate
2015-11-03 14:12:36 -03:00
// nLockTime because when IsFinalTx() is called within
2021-06-08 10:57:40 -04:00
// AcceptBlock(), the height of the block *being*
2015-11-03 14:12:36 -03:00
// evaluated is what is used. Thus if we want to know if a
// transaction can be part of the *next* block, we need to call
2021-02-22 13:46:21 -03:00
// IsFinalTx() with one more than active_chain_tip.Height().
2020-09-16 18:17:45 -03:00
const int nBlockHeight = active_chain_tip - > nHeight + 1 ;
2015-11-03 14:12:36 -03:00
2017-09-14 11:59:09 -03:00
// BIP113 requires that time-locked transactions have nLockTime set to
2015-11-13 18:36:54 -03:00
// less than the median time of the previous block they're contained in.
// When the next block is created its previous block will be the current
// chain tip, so we use that to calculate the median time passed to
2022-01-11 13:02:23 -03:00
// IsFinalTx().
const int64_t nBlockTime { active_chain_tip - > GetMedianTimePast ( ) } ;
2015-11-03 14:12:36 -03:00
return IsFinalTx ( tx , nBlockHeight , nBlockTime ) ;
2015-05-25 01:48:33 -03:00
}
2022-01-11 11:53:50 -03:00
bool CheckSequenceLocksAtTip ( CBlockIndex * tip ,
2021-02-11 14:36:20 -03:00
const CCoinsView & coins_view ,
2021-02-08 16:12:12 -03:00
const CTransaction & tx ,
LockPoints * lp ,
bool useExistingLockPoints )
2015-12-07 17:44:16 -03:00
{
2017-08-23 04:47:56 -03:00
assert ( tip ! = nullptr ) ;
2018-04-15 12:22:28 -03:00
2015-12-07 17:44:16 -03:00
CBlockIndex index ;
index . pprev = tip ;
2022-01-11 11:53:50 -03:00
// CheckSequenceLocksAtTip() uses active_chainstate.m_chain.Height()+1 to evaluate
2015-12-07 17:44:16 -03:00
// height based locks because when SequenceLocks() is called within
2016-02-11 17:34:04 -03:00
// ConnectBlock(), the height of the block *being*
// evaluated is what is used.
// Thus if we want to know if a transaction can be part of the
2020-09-16 18:29:10 -03:00
// *next* block, we need to use one more than active_chainstate.m_chain.Height()
2015-12-07 17:44:16 -03:00
index . nHeight = tip - > nHeight + 1 ;
2015-12-04 17:01:22 -03:00
std : : pair < int , int64_t > lockPair ;
if ( useExistingLockPoints ) {
assert ( lp ) ;
lockPair . first = lp - > height ;
lockPair . second = lp - > time ;
}
else {
std : : vector < int > prevheights ;
prevheights . resize ( tx . vin . size ( ) ) ;
for ( size_t txinIndex = 0 ; txinIndex < tx . vin . size ( ) ; txinIndex + + ) {
const CTxIn & txin = tx . vin [ txinIndex ] ;
2017-04-25 15:29:39 -03:00
Coin coin ;
2021-02-11 14:36:20 -03:00
if ( ! coins_view . GetCoin ( txin . prevout , coin ) ) {
2015-12-04 17:01:22 -03:00
return error ( " %s: Missing input " , __func__ ) ;
}
2017-04-25 15:29:39 -03:00
if ( coin . nHeight = = MEMPOOL_HEIGHT ) {
2015-12-04 17:01:22 -03:00
// Assume all mempool transaction confirm in the next block
prevheights [ txinIndex ] = tip - > nHeight + 1 ;
} else {
2017-04-25 15:29:39 -03:00
prevheights [ txinIndex ] = coin . nHeight ;
2015-12-04 17:01:22 -03:00
}
2015-12-07 17:44:16 -03:00
}
2022-01-11 13:02:23 -03:00
lockPair = CalculateSequenceLocks ( tx , STANDARD_LOCKTIME_VERIFY_FLAGS , prevheights , index ) ;
2015-12-04 17:01:22 -03:00
if ( lp ) {
lp - > height = lockPair . first ;
lp - > time = lockPair . second ;
// Also store the hash of the block with the highest height of
// all the blocks which have sequence locked prevouts.
// This hash needs to still be on the chain
// for these LockPoint calculations to be valid
// Note: It is impossible to correctly calculate a maxInputBlock
// if any of the sequence locked inputs depend on unconfirmed txs,
// except in the special case where the relative lock time/height
// is 0, which is equivalent to no sequence lock. Since we assume
// input height of tip+1 for mempool txs and test the resulting
// lockPair from CalculateSequenceLocks against tip+1. We know
// EvaluateSequenceLocks will fail if there was a non-zero sequence
// lock on a mempool input, so we can use the return value of
2022-01-11 11:53:50 -03:00
// CheckSequenceLocksAtTip to indicate the LockPoints validity
2015-12-04 17:01:22 -03:00
int maxInputHeight = 0 ;
2018-06-18 01:58:28 -04:00
for ( const int height : prevheights ) {
2015-12-04 17:01:22 -03:00
// Can ignore mempool inputs since we'll fail if they had non-zero locks
if ( height ! = tip - > nHeight + 1 ) {
maxInputHeight = std : : max ( maxInputHeight , height ) ;
}
}
2019-10-21 14:17:22 -03:00
// tip->GetAncestor(maxInputHeight) should never return a nullptr
// because maxInputHeight is always less than the tip height.
// It would, however, be a bad bug to continue execution, since a
// LockPoints object with the maxInputBlock member set to nullptr
// signifies no relative lock time.
lp - > maxInputBlock = Assert ( tip - > GetAncestor ( maxInputHeight ) ) ;
2015-12-07 17:44:16 -03:00
}
}
return EvaluateSequenceLocks ( index , lockPair ) ;
}
2017-04-11 17:04:37 -03:00
// Returns the script flags which should be checked for a given block
2022-04-14 15:50:53 -04:00
static unsigned int GetBlockScriptFlags ( const CBlockIndex & block_index , const ChainstateManager & chainman ) ;
2017-04-11 17:04:37 -03:00
2021-10-28 15:13:04 -03:00
static void LimitMempoolSize ( CTxMemPool & pool , CCoinsViewCache & coins_cache )
2022-01-27 07:48:19 -03:00
EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main , pool . cs )
2018-12-22 12:33:54 -03:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
AssertLockHeld ( pool . cs ) ;
2021-10-28 15:13:04 -03:00
int expired = pool . Expire ( GetTime < std : : chrono : : seconds > ( ) - pool . m_expiry ) ;
2016-12-25 17:19:40 -03:00
if ( expired ! = 0 ) {
LogPrint ( BCLog : : MEMPOOL , " Expired %i transactions from the memory pool \n " , expired ) ;
}
2015-10-22 15:52:55 -03:00
2017-04-25 15:29:39 -03:00
std : : vector < COutPoint > vNoSpendsRemaining ;
2021-10-28 14:46:19 -03:00
pool . TrimToSize ( pool . m_max_size_bytes , & vNoSpendsRemaining ) ;
2017-06-01 21:18:57 -04:00
for ( const COutPoint & removed : vNoSpendsRemaining )
2020-09-16 17:35:38 -03:00
coins_cache . Uncache ( removed ) ;
2015-10-22 15:52:55 -03:00
}
2020-09-16 17:36:06 -03:00
static bool IsCurrentForFeeEstimation ( CChainState & active_chainstate ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main )
2016-11-11 15:29:13 -03:00
{
AssertLockHeld ( cs_main ) ;
2020-09-16 17:36:06 -03:00
if ( active_chainstate . IsInitialBlockDownload ( ) )
2016-11-11 15:29:13 -03:00
return false ;
2020-09-16 17:36:06 -03:00
if ( active_chainstate . m_chain . Tip ( ) - > GetBlockTime ( ) < count_seconds ( GetTime < std : : chrono : : seconds > ( ) - MAX_FEE_ESTIMATION_TIP_AGE ) )
2016-11-11 15:29:13 -03:00
return false ;
2022-03-18 13:35:52 -03:00
if ( active_chainstate . m_chain . Height ( ) < active_chainstate . m_chainman . m_best_header - > nHeight - 1 ) {
2016-11-11 15:29:13 -03:00
return false ;
2020-12-24 18:18:46 -03:00
}
2016-11-11 15:29:13 -03:00
return true ;
}
2021-07-09 13:06:19 -04:00
void CChainState : : MaybeUpdateMempoolForReorg (
DisconnectedBlockTransactions & disconnectpool ,
bool fAddToMempool )
2016-11-03 15:45:10 -03:00
{
2021-07-09 13:06:19 -04:00
if ( ! m_mempool ) return ;
2016-11-03 15:45:10 -03:00
AssertLockHeld ( cs_main ) ;
2021-07-09 13:06:19 -04:00
AssertLockHeld ( m_mempool - > cs ) ;
2016-11-03 15:45:10 -03:00
std : : vector < uint256 > vHashUpdate ;
// disconnectpool's insertion_order index sorts the entries from
// oldest to newest, but the oldest entry will be the last tx from the
// latest mined block that was disconnected.
// Iterate disconnectpool in reverse, so that we add transactions
// back to the mempool starting with the earliest transaction that had
// been previously seen in a block.
auto it = disconnectpool . queuedTx . get < insertion_order > ( ) . rbegin ( ) ;
while ( it ! = disconnectpool . queuedTx . get < insertion_order > ( ) . rend ( ) ) {
// ignore validation errors in resurrected transactions
2017-09-12 13:30:26 -03:00
if ( ! fAddToMempool | | ( * it ) - > IsCoinBase ( ) | |
2021-12-02 01:50:27 -03:00
AcceptToMemoryPool ( * this , * it , GetTime ( ) ,
/*bypass_limits=*/ true , /*test_accept=*/ false ) . m_result_type ! =
2021-07-09 13:06:19 -04:00
MempoolAcceptResult : : ResultType : : VALID ) {
2016-11-03 15:45:10 -03:00
// If the transaction doesn't make it in to the mempool, remove any
// transactions that depend on it (which would now be orphans).
2021-07-09 13:06:19 -04:00
m_mempool - > removeRecursive ( * * it , MemPoolRemovalReason : : REORG ) ;
2021-10-20 12:41:45 -03:00
} else if ( m_mempool - > exists ( GenTxid : : Txid ( ( * it ) - > GetHash ( ) ) ) ) {
2016-11-03 15:45:10 -03:00
vHashUpdate . push_back ( ( * it ) - > GetHash ( ) ) ;
}
+ + it ;
}
disconnectpool . queuedTx . clear ( ) ;
// AcceptToMemoryPool/addUnchecked all assume that new mempool entries have
// no in-mempool children, which is generally not true when adding
// previously-confirmed transactions back to the mempool.
// UpdateTransactionsFromBlock finds descendants of any transactions in
// the disconnectpool that were added back and cleans up the mempool state.
2022-05-18 14:44:25 -04:00
m_mempool - > UpdateTransactionsFromBlock ( vHashUpdate ) ;
2016-11-03 15:45:10 -03:00
2021-12-03 15:03:16 -03:00
// Predicate to use for filtering transactions in removeForReorg.
// Checks whether the transaction is still final and, if it spends a coinbase output, mature.
// Also updates valid entries' cached LockPoints if needed.
// If false, the tx is still valid and its lockpoints are updated.
// If true, the tx would be invalid in the next block; remove this entry and all of its descendants.
2022-01-11 13:02:23 -03:00
const auto filter_final_and_mature = [ this ] ( CTxMemPool : : txiter it )
2021-09-29 16:52:04 -03:00
EXCLUSIVE_LOCKS_REQUIRED ( m_mempool - > cs , : : cs_main ) {
AssertLockHeld ( m_mempool - > cs ) ;
AssertLockHeld ( : : cs_main ) ;
const CTransaction & tx = it - > GetTx ( ) ;
2021-12-03 15:03:16 -03:00
// The transaction must be final.
2022-01-11 11:53:50 -03:00
if ( ! CheckFinalTxAtTip ( m_chain . Tip ( ) , tx ) ) return true ;
2021-09-29 16:52:04 -03:00
LockPoints lp = it - > GetLockPoints ( ) ;
2021-12-02 08:51:21 -03:00
const bool validLP { TestLockPointValidity ( m_chain , lp ) } ;
2021-09-29 16:52:04 -03:00
CCoinsViewMemPool view_mempool ( & CoinsTip ( ) , * m_mempool ) ;
2022-01-11 11:53:50 -03:00
// CheckSequenceLocksAtTip checks if the transaction will be final in the next block to be
2021-12-03 15:03:16 -03:00
// created on top of the new chain. We use useExistingLockPoints=false so that, instead of
// using the information in lp (which might now refer to a block that no longer exists in
// the chain), it will update lp to contain LockPoints relevant to the new chain.
2022-01-11 11:53:50 -03:00
if ( ! CheckSequenceLocksAtTip ( m_chain . Tip ( ) , view_mempool , tx , & lp , validLP ) ) {
// If CheckSequenceLocksAtTip fails, remove the tx and don't depend on the LockPoints.
2021-12-03 15:03:16 -03:00
return true ;
} else if ( ! validLP ) {
2022-01-11 11:53:50 -03:00
// If CheckSequenceLocksAtTip succeeded, it also updated the LockPoints.
2021-12-03 15:03:16 -03:00
// Now update the mempool entry lockpoints as well.
2022-01-17 07:24:38 -03:00
m_mempool - > mapTx . modify ( it , [ & lp ] ( CTxMemPoolEntry & e ) { e . UpdateLockPoints ( lp ) ; } ) ;
2021-12-03 15:03:16 -03:00
}
// If the transaction spends any coinbase outputs, it must be mature.
if ( it - > GetSpendsCoinbase ( ) ) {
2021-09-29 16:52:04 -03:00
for ( const CTxIn & txin : tx . vin ) {
auto it2 = m_mempool - > mapTx . find ( txin . prevout . hash ) ;
if ( it2 ! = m_mempool - > mapTx . end ( ) )
continue ;
2022-01-19 12:56:25 -03:00
const Coin & coin { CoinsTip ( ) . AccessCoin ( txin . prevout ) } ;
2021-09-29 16:52:04 -03:00
assert ( ! coin . IsSpent ( ) ) ;
2021-12-02 08:47:20 -03:00
const auto mempool_spend_height { m_chain . Tip ( ) - > nHeight + 1 } ;
2022-01-19 12:56:25 -03:00
if ( coin . IsCoinBase ( ) & & mempool_spend_height - coin . nHeight < COINBASE_MATURITY ) {
2021-12-03 15:03:16 -03:00
return true ;
2021-09-29 16:52:04 -03:00
}
}
}
2021-12-03 15:03:16 -03:00
// Transaction is still valid and cached LockPoints are updated.
return false ;
2021-09-29 16:52:04 -03:00
} ;
2016-11-03 15:45:10 -03:00
// We also need to remove any now-immature transactions
2021-12-03 15:03:16 -03:00
m_mempool - > removeForReorg ( m_chain , filter_final_and_mature ) ;
2016-11-03 15:45:10 -03:00
// Re-limit mempool size, in case we added any transactions
2021-10-28 15:13:04 -03:00
LimitMempoolSize ( * m_mempool , this - > CoinsTip ( ) ) ;
2016-11-03 15:45:10 -03:00
}
2021-01-06 18:38:32 -03:00
/**
* Checks to avoid mempool polluting consensus critical paths since cached
* signature and script validity results will be reused if we validate this
* transaction again during block validation .
* */
static bool CheckInputsFromMempoolAndCache ( const CTransaction & tx , TxValidationState & state ,
const CCoinsViewCache & view , const CTxMemPool & pool ,
2020-09-16 17:42:01 -03:00
unsigned int flags , PrecomputedTransactionData & txdata , CCoinsViewCache & coins_tip )
2021-01-06 18:38:32 -03:00
EXCLUSIVE_LOCKS_REQUIRED ( cs_main , pool . cs )
{
2017-06-05 20:46:23 -04:00
AssertLockHeld ( cs_main ) ;
2020-12-30 14:57:00 -03:00
AssertLockHeld ( pool . cs ) ;
2017-06-05 20:46:23 -04:00
assert ( ! tx . IsCoinBase ( ) ) ;
for ( const CTxIn & txin : tx . vin ) {
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
2020-12-30 14:57:00 -03:00
// This coin was checked in PreChecks and MemPoolAccept
// has been holding cs_main since then.
Assume ( ! coin . IsSpent ( ) ) ;
2017-06-05 20:46:23 -04:00
if ( coin . IsSpent ( ) ) return false ;
2021-01-06 18:38:32 -03:00
// If the Coin is available, there are 2 possibilities:
// it is available in our current ChainstateActive UTXO set,
// or it's a UTXO provided by a transaction in our mempool.
// Ensure the scriptPubKeys in Coins from CoinsView are correct.
2017-06-05 20:46:23 -04:00
const CTransactionRef & txFrom = pool . get ( txin . prevout . hash ) ;
if ( txFrom ) {
assert ( txFrom - > GetHash ( ) = = txin . prevout . hash ) ;
assert ( txFrom - > vout . size ( ) > txin . prevout . n ) ;
assert ( txFrom - > vout [ txin . prevout . n ] = = coin . out ) ;
} else {
2020-09-16 17:42:01 -03:00
const Coin & coinFromUTXOSet = coins_tip . AccessCoin ( txin . prevout ) ;
2021-01-06 18:38:32 -03:00
assert ( ! coinFromUTXOSet . IsSpent ( ) ) ;
assert ( coinFromUTXOSet . out = = coin . out ) ;
2017-06-05 20:46:23 -04:00
}
}
2019-08-19 11:55:38 -04:00
// Call CheckInputScripts() to cache signature and script validity against current tip consensus rules.
2021-09-06 12:47:12 -03:00
return CheckInputScripts ( tx , state , view , flags , /* cacheSigStore= */ true , /* cacheFullScriptStore= */ true , txdata ) ;
2017-06-05 20:46:23 -04:00
}
2019-07-10 11:38:03 -04:00
namespace {
class MemPoolAccept
2010-08-29 12:58:15 -04:00
{
2019-07-10 11:38:03 -04:00
public :
2020-09-16 17:53:57 -03:00
explicit MemPoolAccept ( CTxMemPool & mempool , CChainState & active_chainstate ) : m_pool ( mempool ) , m_view ( & m_dummy ) , m_viewmempool ( & active_chainstate . CoinsTip ( ) , m_pool ) , m_active_chainstate ( active_chainstate ) ,
2022-06-06 21:19:50 -04:00
m_limit_ancestors ( m_pool . m_limits . ancestor_count ) ,
m_limit_ancestor_size ( m_pool . m_limits . ancestor_size_vbytes ) ,
m_limit_descendants ( m_pool . m_limits . descendant_count ) ,
m_limit_descendant_size ( m_pool . m_limits . descendant_size_vbytes ) {
2020-09-16 17:53:57 -03:00
}
2019-07-10 11:38:03 -04:00
// We put the arguments we're handed into a struct, so we can pass them
// around easier.
struct ATMPArgs {
const CChainParams & m_chainparams ;
const int64_t m_accept_time ;
const bool m_bypass_limits ;
/*
* Return any outpoints which were not previously present in the coins
* cache , but were added as a result of validating the tx for mempool
* acceptance . This allows the caller to optionally remove the cache
* additions if the associated transaction ends up being rejected by
* the mempool .
*/
std : : vector < COutPoint > & m_coins_to_uncache ;
const bool m_test_accept ;
2021-05-26 13:02:00 -04:00
/** Whether we allow transactions to replace mempool transactions by BIP125 rules. If false,
* any transaction spending the same inputs as a transaction in the mempool is considered
* a conflict . */
2021-07-20 05:41:00 -04:00
const bool m_allow_bip125_replacement ;
2021-07-20 06:07:25 -04:00
/** When true, the mempool will not be trimmed when individual transactions are submitted in
* Finalize ( ) . Instead , limits should be enforced at the end to ensure the package is not
* partially submitted .
*/
const bool m_package_submission ;
2021-07-20 08:26:26 -04:00
/** When true, use package feerates instead of individual transaction feerates for fee-based
* policies such as mempool min fee and min relay fee .
*/
const bool m_package_feerates ;
2021-07-20 05:41:00 -04:00
/** Parameters for single transaction mempool validation. */
static ATMPArgs SingleAccept ( const CChainParams & chainparams , int64_t accept_time ,
bool bypass_limits , std : : vector < COutPoint > & coins_to_uncache ,
bool test_accept ) {
return ATMPArgs { /* m_chainparams */ chainparams ,
/* m_accept_time */ accept_time ,
/* m_bypass_limits */ bypass_limits ,
/* m_coins_to_uncache */ coins_to_uncache ,
/* m_test_accept */ test_accept ,
/* m_allow_bip125_replacement */ true ,
2021-07-20 06:07:25 -04:00
/* m_package_submission */ false ,
2021-07-20 08:26:26 -04:00
/* m_package_feerates */ false ,
2021-07-20 05:41:00 -04:00
} ;
}
/** Parameters for test package mempool validation through testmempoolaccept. */
static ATMPArgs PackageTestAccept ( const CChainParams & chainparams , int64_t accept_time ,
std : : vector < COutPoint > & coins_to_uncache ) {
return ATMPArgs { /* m_chainparams */ chainparams ,
/* m_accept_time */ accept_time ,
/* m_bypass_limits */ false ,
/* m_coins_to_uncache */ coins_to_uncache ,
/* m_test_accept */ true ,
/* m_allow_bip125_replacement */ false ,
2021-07-20 06:07:25 -04:00
/* m_package_submission */ false , // not submitting to mempool
2021-07-20 08:26:26 -04:00
/* m_package_feerates */ false ,
2021-07-20 05:41:00 -04:00
} ;
}
2021-09-22 11:40:22 -03:00
/** Parameters for child-with-unconfirmed-parents package validation. */
static ATMPArgs PackageChildWithParents ( const CChainParams & chainparams , int64_t accept_time ,
std : : vector < COutPoint > & coins_to_uncache ) {
return ATMPArgs { /* m_chainparams */ chainparams ,
/* m_accept_time */ accept_time ,
/* m_bypass_limits */ false ,
/* m_coins_to_uncache */ coins_to_uncache ,
/* m_test_accept */ false ,
/* m_allow_bip125_replacement */ false ,
2021-07-20 06:07:25 -04:00
/* m_package_submission */ true ,
2021-07-20 08:26:26 -04:00
/* m_package_feerates */ true ,
2021-09-22 11:40:22 -03:00
} ;
}
2022-02-21 08:24:33 -03:00
2022-01-25 08:39:03 -03:00
/** Parameters for a single transaction within a package. */
static ATMPArgs SingleInPackageAccept ( const ATMPArgs & package_args ) {
return ATMPArgs { /* m_chainparams */ package_args . m_chainparams ,
/* m_accept_time */ package_args . m_accept_time ,
/* m_bypass_limits */ false ,
/* m_coins_to_uncache */ package_args . m_coins_to_uncache ,
/* m_test_accept */ package_args . m_test_accept ,
/* m_allow_bip125_replacement */ true ,
/* m_package_submission */ false ,
/* m_package_feerates */ false , // only 1 transaction
2021-09-22 11:40:22 -03:00
} ;
}
2022-02-21 08:24:33 -03:00
private :
// Private ctor to avoid exposing details to clients and allowing the possibility of
2021-07-20 05:41:00 -04:00
// mixing up the order of the arguments. Use static functions above instead.
2022-02-21 08:24:33 -03:00
ATMPArgs ( const CChainParams & chainparams ,
int64_t accept_time ,
bool bypass_limits ,
std : : vector < COutPoint > & coins_to_uncache ,
bool test_accept ,
bool allow_bip125_replacement ,
2021-07-20 08:26:26 -04:00
bool package_submission ,
bool package_feerates )
2022-02-21 08:24:33 -03:00
: m_chainparams { chainparams } ,
m_accept_time { accept_time } ,
m_bypass_limits { bypass_limits } ,
m_coins_to_uncache { coins_to_uncache } ,
m_test_accept { test_accept } ,
m_allow_bip125_replacement { allow_bip125_replacement } ,
2021-07-20 08:26:26 -04:00
m_package_submission { package_submission } ,
m_package_feerates { package_feerates }
2022-02-21 08:24:33 -03:00
{
}
2019-07-10 11:38:03 -04:00
} ;
// Single transaction acceptance
2021-01-19 10:29:40 -03:00
MempoolAcceptResult AcceptSingleTransaction ( const CTransactionRef & ptx , ATMPArgs & args ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
2019-07-10 11:38:03 -04:00
2021-04-05 13:12:58 -04:00
/**
2021-07-20 06:07:25 -04:00
* Multiple transaction acceptance . Transactions may or may not be interdependent , but must not
* conflict with each other , and the transactions cannot already be in the mempool . Parents must
* come before children if any dependencies exist .
2021-04-05 13:12:58 -04:00
*/
PackageMempoolAcceptResult AcceptMultipleTransactions ( const std : : vector < CTransactionRef > & txns , ATMPArgs & args ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
2021-09-22 11:40:22 -03:00
/**
* Package ( more specific than just multiple transactions ) acceptance . Package must be a child
* with all of its unconfirmed parents , and topologically sorted .
*/
PackageMempoolAcceptResult AcceptPackage ( const Package & package , ATMPArgs & args ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
2019-07-10 11:38:03 -04:00
private :
// All the intermediate state that gets passed between the various levels
// of checking a given transaction.
struct Workspace {
2020-11-29 15:33:22 -03:00
explicit Workspace ( const CTransactionRef & ptx ) : m_ptx ( ptx ) , m_hash ( ptx - > GetHash ( ) ) { }
2021-11-04 13:23:32 -03:00
/** Txids of mempool transactions that this transaction directly conflicts with. */
2019-07-10 11:38:03 -04:00
std : : set < uint256 > m_conflicts ;
2021-11-04 13:23:32 -03:00
/** Iterators to mempool entries that this transaction directly conflicts with. */
2021-10-28 12:09:33 -03:00
CTxMemPool : : setEntries m_iters_conflicting ;
2021-11-04 13:23:32 -03:00
/** Iterators to all mempool entries that would be replaced by this transaction, including
* those it directly conflicts with and their descendants . */
2019-07-10 11:38:03 -04:00
CTxMemPool : : setEntries m_all_conflicting ;
2021-11-04 13:23:32 -03:00
/** All mempool ancestors of this transaction. */
2019-07-10 11:38:03 -04:00
CTxMemPool : : setEntries m_ancestors ;
2021-11-04 13:23:32 -03:00
/** Mempool entry constructed for this transaction. Constructed in PreChecks() but not
* inserted into the mempool until Finalize ( ) . */
2019-07-10 11:38:03 -04:00
std : : unique_ptr < CTxMemPoolEntry > m_entry ;
2021-11-04 13:23:32 -03:00
/** Pointers to the transactions that have been removed from the mempool and replaced by
* this transaction , used to return to the MemPoolAccept caller . Only populated if
* validation is successful and the original transactions are removed . */
2021-01-19 14:32:20 -03:00
std : : list < CTransactionRef > m_replaced_transactions ;
2019-07-10 11:38:03 -04:00
2021-09-02 08:09:11 -04:00
/** Virtual size of the transaction as used by the mempool, calculated using serialized size
* of the transaction and sigops . */
int64_t m_vsize ;
2021-11-04 13:23:32 -03:00
/** Fees paid by this transaction: total input amounts subtracted by total output amounts. */
2021-02-01 20:34:27 -03:00
CAmount m_base_fees ;
2021-11-04 13:23:32 -03:00
/** Base fees + any fee delta set by the user with prioritisetransaction. */
2019-07-10 11:38:03 -04:00
CAmount m_modified_fees ;
2021-08-20 10:17:49 -04:00
/** Total modified fees of all transactions being replaced. */
CAmount m_conflicting_fees { 0 } ;
/** Total virtual size of all transactions being replaced. */
size_t m_conflicting_size { 0 } ;
2019-07-10 11:38:03 -04:00
const CTransactionRef & m_ptx ;
2021-11-04 13:23:32 -03:00
/** Txid. */
2019-07-10 11:38:03 -04:00
const uint256 & m_hash ;
2021-01-19 14:32:20 -03:00
TxValidationState m_state ;
2021-07-20 06:38:44 -04:00
/** A temporary cache containing serialized transaction data for signature verification.
* Reused across PolicyScriptChecks and ConsensusScriptChecks . */
PrecomputedTransactionData m_precomputed_txdata ;
2019-07-10 11:38:03 -04:00
} ;
// Run the policy checks on a given transaction, excluding any script checks.
// Looks up inputs, calculates feerate, considers replacement, evaluates
// package limits, etc. As this function can be invoked for "free" by a peer,
// only tests that are fast should be done here (to avoid CPU DoS).
bool PreChecks ( ATMPArgs & args , Workspace & ws ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main , m_pool . cs ) ;
2021-08-09 06:56:57 -04:00
// Run checks for mempool replace-by-fee.
bool ReplacementChecks ( Workspace & ws ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main , m_pool . cs ) ;
// Enforce package mempool ancestor/descendant limits (distinct from individual
// ancestor/descendant limits done in PreChecks).
bool PackageMempoolChecks ( const std : : vector < CTransactionRef > & txns ,
PackageValidationState & package_state ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main , m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
// Run the script checks using our policy flags. As this can be slow, we should
// only invoke this on transactions that have otherwise passed policy checks.
2021-07-20 06:38:44 -04:00
bool PolicyScriptChecks ( const ATMPArgs & args , Workspace & ws ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main , m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
// Re-run the script checks, using consensus flags, and try to cache the
// result in the scriptcache. This should be done after
// PolicyScriptChecks(). This requires that all inputs either be in our
// utxo set or in the mempool.
2021-07-20 06:38:44 -04:00
bool ConsensusScriptChecks ( const ATMPArgs & args , Workspace & ws ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main , m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
// Try to add the transaction to the mempool, removing any conflicts first.
// Returns true if the transaction is in the mempool after any size
// limiting is performed, false otherwise.
2021-01-19 14:32:20 -03:00
bool Finalize ( const ATMPArgs & args , Workspace & ws ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main , m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
2021-07-20 06:07:25 -04:00
// Submit all transactions to the mempool and call ConsensusScriptChecks to add to the script
// cache - should only be called after successful validation of all transactions in the package.
2022-01-07 12:45:23 -03:00
// The package may end up partially-submitted after size limiting; returns true if all
2021-07-20 06:07:25 -04:00
// transactions are successfully added to the mempool, false otherwise.
2022-01-07 12:45:23 -03:00
bool SubmitPackage ( const ATMPArgs & args , std : : vector < Workspace > & workspaces , PackageValidationState & package_state ,
std : : map < const uint256 , const MempoolAcceptResult > & results )
2021-07-20 06:07:25 -04:00
EXCLUSIVE_LOCKS_REQUIRED ( cs_main , m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
// Compare a package's feerate against minimum allowed.
2022-01-27 07:48:19 -03:00
bool CheckFeeRate ( size_t package_size , CAmount package_fee , TxValidationState & state ) EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main , m_pool . cs )
2019-07-10 11:38:03 -04:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
AssertLockHeld ( m_pool . cs ) ;
2021-10-28 14:46:19 -03:00
CAmount mempoolRejectFee = m_pool . GetMinFee ( ) . GetFee ( package_size ) ;
2019-07-10 11:38:03 -04:00
if ( mempoolRejectFee > 0 & & package_fee < mempoolRejectFee ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " mempool min fee not met " , strprintf ( " %d < %d " , package_fee , mempoolRejectFee ) ) ;
2019-07-10 11:38:03 -04:00
}
if ( package_fee < : : minRelayTxFee . GetFee ( package_size ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " min relay fee not met " , strprintf ( " %d < %d " , package_fee , : : minRelayTxFee . GetFee ( package_size ) ) ) ;
2019-07-10 11:38:03 -04:00
}
return true ;
}
private :
CTxMemPool & m_pool ;
CCoinsViewCache m_view ;
CCoinsViewMemPool m_viewmempool ;
CCoinsView m_dummy ;
2020-09-16 17:53:57 -03:00
CChainState & m_active_chainstate ;
2019-07-10 11:38:03 -04:00
// The package limits in effect at the time of invocation.
const size_t m_limit_ancestors ;
const size_t m_limit_ancestor_size ;
// These may be modified while evaluating a transaction (eg to account for
// in-mempool conflicts; see below).
size_t m_limit_descendants ;
size_t m_limit_descendant_size ;
2021-10-28 09:25:23 -03:00
/** Whether the transaction(s) would replace any mempool transactions. If so, RBF rules apply. */
bool m_rbf { false } ;
2019-07-10 11:38:03 -04:00
} ;
bool MemPoolAccept : : PreChecks ( ATMPArgs & args , Workspace & ws )
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
const CTransactionRef & ptx = ws . m_ptx ;
const CTransaction & tx = * ws . m_ptx ;
const uint256 & hash = ws . m_hash ;
// Copy/alias what we need out of args
const int64_t nAcceptTime = args . m_accept_time ;
const bool bypass_limits = args . m_bypass_limits ;
std : : vector < COutPoint > & coins_to_uncache = args . m_coins_to_uncache ;
// Alias what we need out of ws
2021-02-01 20:34:27 -03:00
TxValidationState & state = ws . m_state ;
2019-07-10 11:38:03 -04:00
std : : unique_ptr < CTxMemPoolEntry > & entry = ws . m_entry ;
2020-05-16 10:40:17 -04:00
if ( ! CheckTransaction ( tx , state ) ) {
2016-02-24 14:34:37 -03:00
return false ; // state filled in by CheckTransaction
2020-05-16 10:40:17 -04:00
}
2010-09-30 12:23:07 -04:00
2010-08-29 12:58:15 -04:00
// Coinbase is only valid in a block, not as a loose transaction
2012-04-13 18:34:22 -03:00
if ( tx . IsCoinBase ( ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_CONSENSUS , " coinbase " ) ;
2010-09-06 21:12:53 -04:00
2016-07-07 15:49:26 -04:00
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
2017-01-27 05:43:41 -03:00
std : : string reason ;
2018-04-29 20:34:57 -03:00
if ( fRequireStandard & & ! IsStandardTx ( tx , reason ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_NOT_STANDARD , reason ) ;
2016-07-07 15:49:26 -04:00
2018-04-26 16:31:36 -03:00
// Do not work on transactions that are too small.
// A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes.
2019-09-16 13:11:05 -03:00
// Transactions smaller than this are not relayed to mitigate CVE-2017-12842 by not relaying
// 64-byte transactions.
2018-06-22 14:27:18 -04:00
if ( : : GetSerializeSize ( tx , PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS ) < MIN_STANDARD_TX_NONWITNESS_SIZE )
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_NOT_STANDARD , " tx-size-small " ) ;
2018-04-26 16:31:36 -03:00
2014-12-20 19:04:21 -03:00
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
2022-01-11 11:53:50 -03:00
if ( ! CheckFinalTxAtTip ( m_active_chainstate . m_chain . Tip ( ) , tx ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_PREMATURE_SPEND , " non-final " ) ;
2022-01-11 13:02:23 -03:00
}
2014-12-20 19:04:21 -03:00
2021-10-22 07:28:14 -03:00
if ( m_pool . exists ( GenTxid : : Wtxid ( tx . GetWitnessHash ( ) ) ) ) {
2021-06-14 05:18:47 -04:00
// Exact transaction already exists in the mempool.
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_CONFLICT , " txn-already-in-mempool " ) ;
2021-10-22 07:28:14 -03:00
} else if ( m_pool . exists ( GenTxid : : Txid ( tx . GetHash ( ) ) ) ) {
2021-06-14 05:18:47 -04:00
// Transaction with the same non-witness data but different witness (same txid, different
// wtxid) already exists in the mempool.
return state . Invalid ( TxValidationResult : : TX_CONFLICT , " txn-same-nonwitness-data-in-mempool " ) ;
2017-06-01 14:12:59 -04:00
}
2010-08-29 12:58:15 -04:00
// Check for conflicts with in-memory transactions
2017-06-01 21:18:57 -04:00
for ( const CTxIn & txin : tx . vin )
2010-08-29 12:58:15 -04:00
{
2019-07-10 11:38:03 -04:00
const CTransaction * ptxConflicting = m_pool . GetConflictTx ( txin . prevout ) ;
2018-07-29 10:41:42 -04:00
if ( ptxConflicting ) {
2021-05-26 13:02:00 -04:00
if ( ! args . m_allow_bip125_replacement ) {
// Transaction conflicts with a mempool tx, but we're not allowing replacements.
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " bip125-replacement-disallowed " ) ;
}
2021-08-03 06:54:42 -04:00
if ( ! ws . m_conflicts . count ( ptxConflicting - > GetHash ( ) ) )
2015-10-22 15:13:18 -03:00
{
2021-05-13 12:35:33 -04:00
// Transactions that don't explicitly signal replaceability are
// *not* replaceable with the current logic, even if one of their
// unconfirmed ancestors signals replaceability. This diverges
// from BIP125's inherited signaling description (see CVE-2021-31876).
// Applications relying on first-seen mempool behavior should
// check all unconfirmed ancestors; otherwise an opt-in ancestor
// might be replaced, causing removal of this descendant.
2022-04-27 10:25:22 -04:00
//
// If replaceability signaling is ignored due to node setting,
// replacement is always allowed.
if ( ! m_pool . m_full_rbf & & ! SignalsOptInRBF ( * ptxConflicting ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " txn-mempool-conflict " ) ;
2017-06-01 14:12:59 -04:00
}
2015-10-22 15:13:18 -03:00
2021-08-03 06:54:42 -04:00
ws . m_conflicts . insert ( ptxConflicting - > GetHash ( ) ) ;
2015-10-22 15:13:18 -03:00
}
2010-08-29 12:58:15 -04:00
}
}
2019-07-10 11:38:03 -04:00
LockPoints lp ;
m_view . SetBackend ( m_viewmempool ) ;
2019-01-25 18:33:21 -03:00
2020-09-16 17:53:57 -03:00
const CCoinsViewCache & coins_cache = m_active_chainstate . CoinsTip ( ) ;
2019-07-10 11:38:03 -04:00
// do all inputs exist?
for ( const CTxIn & txin : tx . vin ) {
if ( ! coins_cache . HaveCoinInCache ( txin . prevout ) ) {
coins_to_uncache . push_back ( txin . prevout ) ;
}
// Note: this call may add txin.prevout to the coins cache
// (coins_cache.cacheCoins) by way of FetchCoin(). It should be removed
// later (via coins_to_uncache) if this tx turns out to be invalid.
if ( ! m_view . HaveCoin ( txin . prevout ) ) {
// Are inputs missing because we already have the tx?
for ( size_t out = 0 ; out < tx . vout . size ( ) ; out + + ) {
// Optimistically just do efficient check of cache for outputs
if ( coins_cache . HaveCoinInCache ( COutPoint ( hash , out ) ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_CONFLICT , " txn-already-known " ) ;
2017-04-25 15:29:39 -03:00
}
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
}
2019-07-10 11:38:03 -04:00
// Otherwise assume this might be an orphan tx for which we just haven't seen parents yet
2019-04-28 17:26:31 -04:00
return state . Invalid ( TxValidationResult : : TX_MISSING_INPUTS , " bad-txns-inputs-missingorspent " ) ;
2011-10-03 14:05:43 -03:00
}
2019-07-10 11:38:03 -04:00
}
2011-10-03 14:05:43 -03:00
2021-02-01 20:24:30 -03:00
// This is const, but calls into the back end CoinsViews. The CCoinsViewDB at the bottom of the
// hierarchy brings the best block into scope. See CCoinsViewDB::GetBestBlock().
2019-07-10 11:38:03 -04:00
m_view . GetBestBlock ( ) ;
2015-12-07 17:44:16 -03:00
2019-07-10 11:38:03 -04:00
// we have all inputs cached now, so switch back to dummy (to protect
// against bugs where we pull more inputs from disk that miss being added
// to coins_to_uncache)
m_view . SetBackend ( m_dummy ) ;
2016-08-10 22:42:36 -04:00
2021-11-23 14:03:11 -03:00
assert ( m_active_chainstate . m_blockman . LookupBlockIndex ( m_view . GetBestBlock ( ) ) = = m_active_chainstate . m_chain . Tip ( ) ) ;
2019-07-10 11:38:03 -04:00
// Only accept BIP68 sequence locked transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
2021-02-11 14:36:20 -03:00
// Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
// backend was removed, it no longer pulls coins from the mempool.
2022-01-11 11:53:50 -03:00
if ( ! CheckSequenceLocksAtTip ( m_active_chainstate . m_chain . Tip ( ) , m_view , tx , & lp ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_PREMATURE_SPEND , " non-BIP68-final " ) ;
2022-01-11 13:02:23 -03:00
}
2019-07-10 11:38:03 -04:00
2021-11-23 14:03:11 -03:00
// The mempool holds txs for the next block, so pass height+1 to CheckTxInputs
if ( ! Consensus : : CheckTxInputs ( tx , state , m_view , m_active_chainstate . m_chain . Height ( ) + 1 , ws . m_base_fees ) ) {
2020-05-16 10:40:17 -04:00
return false ; // state filled in by CheckTxInputs
2019-07-10 11:38:03 -04:00
}
2012-07-08 13:04:05 -04:00
2021-11-15 06:56:16 -03:00
if ( fRequireStandard & & ! AreInputsStandard ( tx , m_view ) ) {
2020-07-29 11:07:23 -04:00
return state . Invalid ( TxValidationResult : : TX_INPUTS_NOT_STANDARD , " bad-txns-nonstandard-inputs " ) ;
}
2011-10-03 14:05:43 -03:00
2020-10-21 17:45:02 -03:00
// Check for non-standard witnesses.
2019-07-10 11:38:03 -04:00
if ( tx . HasWitness ( ) & & fRequireStandard & & ! IsWitnessStandard ( tx , m_view ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_WITNESS_MUTATED , " bad-witness-nonstandard " ) ;
2016-10-16 12:53:16 -03:00
2019-07-10 11:38:03 -04:00
int64_t nSigOpsCost = GetTransactionSigOpCost ( tx , m_view , STANDARD_SCRIPT_VERIFY_FLAGS ) ;
2012-01-20 19:07:40 -03:00
2021-08-03 06:54:42 -04:00
// ws.m_modified_fees includes any fee deltas from PrioritiseTransaction
ws . m_modified_fees = ws . m_base_fees ;
m_pool . ApplyDelta ( hash , ws . m_modified_fees ) ;
2013-11-11 04:35:14 -03:00
2019-07-10 11:38:03 -04:00
// Keep track of transactions that spend a coinbase, which we re-scan
// during reorgs to ensure COINBASE_MATURITY is still met.
bool fSpendsCoinbase = false ;
for ( const CTxIn & txin : tx . vin ) {
const Coin & coin = m_view . AccessCoin ( txin . prevout ) ;
if ( coin . IsCoinBase ( ) ) {
fSpendsCoinbase = true ;
break ;
2015-10-29 15:06:13 -03:00
}
2019-07-10 11:38:03 -04:00
}
2015-10-29 15:06:13 -03:00
2020-09-16 17:53:57 -03:00
entry . reset ( new CTxMemPoolEntry ( ptx , ws . m_base_fees , nAcceptTime , m_active_chainstate . m_chain . Height ( ) ,
2019-07-10 11:38:03 -04:00
fSpendsCoinbase , nSigOpsCost , lp ) ) ;
2021-09-02 08:09:11 -04:00
ws . m_vsize = entry - > GetTxSize ( ) ;
2012-01-10 22:18:00 -03:00
2019-07-10 11:38:03 -04:00
if ( nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST )
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_NOT_STANDARD , " bad-txns-too-many-sigops " ,
2016-01-03 14:54:50 -03:00
strprintf ( " %d " , nSigOpsCost ) ) ;
2014-02-21 23:41:01 -03:00
2021-07-20 08:26:26 -04:00
// No individual transactions are allowed below minRelayTxFee and mempool min fee except from
// disconnected blocks and transactions in a package. Package transactions will be checked using
// package feerate later.
if ( ! bypass_limits & & ! args . m_package_feerates & & ! CheckFeeRate ( ws . m_vsize , ws . m_modified_fees , state ) ) return false ;
2012-01-10 22:18:00 -03:00
2021-08-03 06:54:42 -04:00
ws . m_iters_conflicting = m_pool . GetIterSet ( ws . m_conflicts ) ;
2019-07-10 11:38:03 -04:00
// Calculate in-mempool ancestors, up to a limit.
2021-08-03 06:54:42 -04:00
if ( ws . m_conflicts . size ( ) = = 1 ) {
2019-07-10 11:38:03 -04:00
// In general, when we receive an RBF transaction with mempool conflicts, we want to know whether we
// would meet the chain limits after the conflicts have been removed. However, there isn't a practical
// way to do this short of calculating the ancestor and descendant sets with an overlay cache of
// changed mempool entries. Due to both implementation and runtime complexity concerns, this isn't
// very realistic, thus we only ensure a limited set of transactions are RBF'able despite mempool
// conflicts here. Importantly, we need to ensure that some transactions which were accepted using
// the below carve-out are able to be RBF'ed, without impacting the security the carve-out provides
// for off-chain contract systems (see link in the comment below).
//
// Specifically, the subset of RBF transactions which we allow despite chain limits are those which
// conflict directly with exactly one other transaction (but may evict children of said transaction),
// and which are not adding any new mempool dependencies. Note that the "no new mempool dependencies"
// check is accomplished later, so we don't bother doing anything about it here, but if BIP 125 is
// amended, we may need to move that check to here instead of removing it wholesale.
//
// Such transactions are clearly not merging any existing packages, so we are only concerned with
// ensuring that (a) no package is growing past the package size (not count) limits and (b) we are
// not allowing something to effectively use the (below) carve-out spot when it shouldn't be allowed
// to.
//
// To check these we first check if we meet the RBF criteria, above, and increment the descendant
// limits by the direct conflict and its descendants (as these are recalculated in
// CalculateMempoolAncestors by assuming the new transaction being added is a new descendant, with no
2019-11-04 06:22:53 -03:00
// removals, of each parent's existing dependent set). The ancestor count limits are unmodified (as
2019-07-10 11:38:03 -04:00
// the ancestor limits should be the same for both our new transaction and any conflicts).
// We don't bother incrementing m_limit_descendants by the full removal count as that limit never comes
// into force here (as we're only adding a single transaction).
2021-10-28 12:09:33 -03:00
assert ( ws . m_iters_conflicting . size ( ) = = 1 ) ;
CTxMemPool : : txiter conflict = * ws . m_iters_conflicting . begin ( ) ;
2019-07-10 11:38:03 -04:00
m_limit_descendants + = 1 ;
m_limit_descendant_size + = conflict - > GetSizeWithDescendants ( ) ;
}
2019-07-11 15:54:17 -04:00
2019-07-10 11:38:03 -04:00
std : : string errString ;
2021-08-03 06:54:42 -04:00
if ( ! m_pool . CalculateMemPoolAncestors ( * entry , ws . m_ancestors , m_limit_ancestors , m_limit_ancestor_size , m_limit_descendants , m_limit_descendant_size , errString ) ) {
ws . m_ancestors . clear ( ) ;
2019-07-10 11:38:03 -04:00
// If CalculateMemPoolAncestors fails second time, we want the original error string.
std : : string dummy_err_string ;
// Contracting/payment channels CPFP carve-out:
// If the new transaction is relatively small (up to 40k weight)
// and has at most one ancestor (ie ancestor limit of 2, including
// the new transaction), allow it if its parent has exactly the
// descendant limit descendants.
//
// This allows protocols which rely on distrusting counterparties
// being able to broadcast descendants of an unconfirmed transaction
// to be secure by simply only having two immediately-spendable
// outputs - one for each counterparty. For more info on the uses for
// this, see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
2021-09-02 08:09:11 -04:00
if ( ws . m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT | |
2021-08-03 06:54:42 -04:00
! m_pool . CalculateMemPoolAncestors ( * entry , ws . m_ancestors , 2 , m_limit_ancestor_size , m_limit_descendants + 1 , m_limit_descendant_size + EXTRA_DESCENDANT_TX_SIZE_LIMIT , dummy_err_string ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " too-long-mempool-chain " , errString ) ;
2015-07-15 15:47:45 -03:00
}
2019-07-10 11:38:03 -04:00
}
2015-07-15 15:47:45 -03:00
2019-07-10 11:38:03 -04:00
// A transaction that spends outputs that would be replaced by it is invalid. Now
// that we have the set of all ancestors we can detect this
2021-08-03 06:54:42 -04:00
// pathological case by making sure ws.m_conflicts and ws.m_ancestors don't
2019-07-10 11:38:03 -04:00
// intersect.
2021-08-03 06:54:42 -04:00
if ( const auto err_string { EntriesAndTxidsDisjoint ( ws . m_ancestors , ws . m_conflicts , hash ) } ) {
2021-08-16 05:40:46 -04:00
// We classify this as a consensus error because a transaction depending on something it
// conflicts with would be inconsistent.
2021-07-27 10:55:25 -04:00
return state . Invalid ( TxValidationResult : : TX_CONSENSUS , " bad-txns-spends-conflicting-tx " , * err_string ) ;
2019-07-10 11:38:03 -04:00
}
2015-10-22 15:13:18 -03:00
2021-08-03 06:54:42 -04:00
m_rbf = ! ws . m_conflicts . empty ( ) ;
2021-08-09 06:56:57 -04:00
return true ;
}
2021-07-27 06:49:34 -04:00
2021-08-09 06:56:57 -04:00
bool MemPoolAccept : : ReplacementChecks ( Workspace & ws )
{
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( m_pool . cs ) ;
2021-07-27 09:23:40 -04:00
2021-08-09 06:56:57 -04:00
const CTransaction & tx = * ws . m_ptx ;
const uint256 & hash = ws . m_hash ;
TxValidationState & state = ws . m_state ;
CFeeRate newFeeRate ( ws . m_modified_fees , ws . m_vsize ) ;
2022-02-10 08:22:18 -03:00
// The replacement transaction must have a higher feerate than its direct conflicts.
// - The motivation for this check is to ensure that the replacement transaction is preferable for
// block-inclusion, compared to what would be removed from the mempool.
// - This logic predates ancestor feerate-based transaction selection, which is why it doesn't
// consider feerates of descendants.
// - Note: Ancestor feerate-based transaction selection has made this comparison insufficient to
// guarantee that this is incentive-compatible for miners, because it is possible for a
// descendant transaction of a direct conflict to pay a higher feerate than the transaction that
// might replace them, under these rules.
2021-08-09 06:56:57 -04:00
if ( const auto err_string { PaysMoreThanConflicts ( ws . m_iters_conflicting , newFeeRate , hash ) } ) {
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " insufficient fee " , * err_string ) ;
}
// Calculate all conflicting entries and enforce BIP125 Rule #5.
if ( const auto err_string { GetEntriesForConflicts ( tx , m_pool , ws . m_iters_conflicting , ws . m_all_conflicting ) } ) {
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY ,
" too many potential replacements " , * err_string ) ;
}
// Enforce BIP125 Rule #2.
if ( const auto err_string { HasNoNewUnconfirmed ( tx , m_pool , ws . m_iters_conflicting ) } ) {
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY ,
" replacement-adds-unconfirmed " , * err_string ) ;
}
// Check if it's economically rational to mine this transaction rather than the ones it
// replaces and pays for its own relay fees. Enforce BIP125 Rules #3 and #4.
for ( CTxMemPool : : txiter it : ws . m_all_conflicting ) {
ws . m_conflicting_fees + = it - > GetModifiedFee ( ) ;
ws . m_conflicting_size + = it - > GetTxSize ( ) ;
}
if ( const auto err_string { PaysForRBF ( ws . m_conflicting_fees , ws . m_modified_fees , ws . m_vsize ,
: : incrementalRelayFee , hash ) } ) {
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " insufficient fee " , * err_string ) ;
2019-07-10 11:38:03 -04:00
}
return true ;
}
2021-08-09 06:56:57 -04:00
bool MemPoolAccept : : PackageMempoolChecks ( const std : : vector < CTransactionRef > & txns ,
PackageValidationState & package_state )
{
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( m_pool . cs ) ;
2021-08-23 11:57:10 -04:00
// CheckPackageLimits expects the package transactions to not already be in the mempool.
assert ( std : : all_of ( txns . cbegin ( ) , txns . cend ( ) , [ this ] ( const auto & tx )
{ return ! m_pool . exists ( GenTxid : : Txid ( tx - > GetHash ( ) ) ) ; } ) ) ;
2021-08-09 06:56:57 -04:00
std : : string err_string ;
if ( ! m_pool . CheckPackageLimits ( txns , m_limit_ancestors , m_limit_ancestor_size , m_limit_descendants ,
m_limit_descendant_size , err_string ) ) {
// This is a package-wide error, separate from an individual transaction error.
return package_state . Invalid ( PackageValidationResult : : PCKG_POLICY , " package-mempool-limits " , err_string ) ;
}
return true ;
}
2021-07-20 06:38:44 -04:00
bool MemPoolAccept : : PolicyScriptChecks ( const ATMPArgs & args , Workspace & ws )
2019-07-10 11:38:03 -04:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
const CTransaction & tx = * ws . m_ptx ;
2021-02-01 20:34:27 -03:00
TxValidationState & state = ws . m_state ;
2019-07-10 11:38:03 -04:00
constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS ;
2019-08-19 12:10:45 -04:00
// Check input scripts and signatures.
2019-07-10 11:38:03 -04:00
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
2021-07-20 06:38:44 -04:00
if ( ! CheckInputScripts ( tx , state , m_view , scriptVerifyFlags , true , false , ws . m_precomputed_txdata ) ) {
2019-07-10 11:38:03 -04:00
// SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we
// need to turn both off, and compare against just turning off CLEANSTACK
// to see if the failure is specifically due to witness validation.
2019-08-19 11:55:38 -04:00
TxValidationState state_dummy ; // Want reported failures to be from first CheckInputScripts
2021-07-20 06:38:44 -04:00
if ( ! tx . HasWitness ( ) & & CheckInputScripts ( tx , state_dummy , m_view , scriptVerifyFlags & ~ ( SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK ) , true , false , ws . m_precomputed_txdata ) & &
! CheckInputScripts ( tx , state_dummy , m_view , scriptVerifyFlags & ~ SCRIPT_VERIFY_CLEANSTACK , true , false , ws . m_precomputed_txdata ) ) {
2019-07-10 11:38:03 -04:00
// Only the witness is missing, so the transaction itself may be fine.
2020-02-07 06:30:41 -03:00
state . Invalid ( TxValidationResult : : TX_WITNESS_STRIPPED ,
2019-09-30 17:25:04 -03:00
state . GetRejectReason ( ) , state . GetDebugMessage ( ) ) ;
2015-10-02 18:20:38 -03:00
}
2019-08-19 11:55:38 -04:00
return false ; // state filled in by CheckInputScripts
2019-07-10 11:38:03 -04:00
}
return true ;
}
2021-07-20 06:38:44 -04:00
bool MemPoolAccept : : ConsensusScriptChecks ( const ATMPArgs & args , Workspace & ws )
2019-07-10 11:38:03 -04:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
const CTransaction & tx = * ws . m_ptx ;
const uint256 & hash = ws . m_hash ;
2021-02-01 20:34:27 -03:00
TxValidationState & state = ws . m_state ;
2019-07-10 11:38:03 -04:00
// Check again against the current block tip's script verification
// flags to cache our script execution flags. This is, of course,
// useless if the next block has different script flags from the
// previous one, but because the cache tracks script flags for us it
// will auto-invalidate and we'll just have a few blocks of extra
// misses on soft-fork activation.
//
// This is also useful in case of bugs in the standard flags that cause
// transactions to pass as valid when they're actually invalid. For
// instance the STRICTENC flag was incorrectly allowing certain
// CHECKSIG NOT scripts to pass, even though they were invalid.
//
// There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks (using TestBlockValidity), however allowing such
// transactions into the mempool can be exploited as a DoS attack.
2022-04-14 15:50:53 -04:00
unsigned int currentBlockScriptVerifyFlags { GetBlockScriptFlags ( * m_active_chainstate . m_chain . Tip ( ) , m_active_chainstate . m_chainman ) } ;
2021-07-20 06:38:44 -04:00
if ( ! CheckInputsFromMempoolAndCache ( tx , state , m_view , m_pool , currentBlockScriptVerifyFlags ,
ws . m_precomputed_txdata , m_active_chainstate . CoinsTip ( ) ) ) {
2021-11-25 07:50:17 -03:00
LogPrintf ( " BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s \n " , hash . ToString ( ) , state . ToString ( ) ) ;
return Assume ( false ) ;
2014-06-26 02:41:44 -04:00
}
2019-07-10 11:38:03 -04:00
return true ;
}
2021-01-19 14:32:20 -03:00
bool MemPoolAccept : : Finalize ( const ATMPArgs & args , Workspace & ws )
2019-07-10 11:38:03 -04:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( m_pool . cs ) ;
2019-07-10 11:38:03 -04:00
const CTransaction & tx = * ws . m_ptx ;
const uint256 & hash = ws . m_hash ;
2021-02-01 20:34:27 -03:00
TxValidationState & state = ws . m_state ;
2019-07-10 11:38:03 -04:00
const bool bypass_limits = args . m_bypass_limits ;
std : : unique_ptr < CTxMemPoolEntry > & entry = ws . m_entry ;
// Remove conflicting transactions from the mempool
2021-08-03 06:54:42 -04:00
for ( CTxMemPool : : txiter it : ws . m_all_conflicting )
2019-07-10 11:38:03 -04:00
{
2020-03-13 07:40:03 -03:00
LogPrint ( BCLog : : MEMPOOL , " replacing tx %s with %s for %s additional fees, %d delta bytes \n " ,
2019-07-10 11:38:03 -04:00
it - > GetTx ( ) . GetHash ( ) . ToString ( ) ,
hash . ToString ( ) ,
2021-08-03 06:54:42 -04:00
FormatMoney ( ws . m_modified_fees - ws . m_conflicting_fees ) ,
( int ) entry - > GetTxSize ( ) - ( int ) ws . m_conflicting_size ) ;
2021-01-19 14:32:20 -03:00
ws . m_replaced_transactions . push_back ( it - > GetSharedTx ( ) ) ;
2019-07-10 11:38:03 -04:00
}
2021-08-03 06:54:42 -04:00
m_pool . RemoveStaged ( ws . m_all_conflicting , false , MemPoolRemovalReason : : REPLACED ) ;
2019-07-10 11:38:03 -04:00
// This transaction should only count for fee estimation if:
// - it's not being re-added during a reorg which bypasses typical mempool fee limits
// - the node is not behind
// - the transaction is not dependent on any other transactions in the mempool
2021-07-20 06:07:25 -04:00
// - it's not part of a package. Since package relay is not currently supported, this
// transaction has not necessarily been accepted to miners' mempools.
bool validForFeeEstimation = ! bypass_limits & & ! args . m_package_submission & & IsCurrentForFeeEstimation ( m_active_chainstate ) & & m_pool . HasNoInputsOf ( tx ) ;
2019-07-10 11:38:03 -04:00
// Store transaction in memory
2021-08-03 06:54:42 -04:00
m_pool . addUnchecked ( * entry , ws . m_ancestors , validForFeeEstimation ) ;
2019-07-10 11:38:03 -04:00
// trim mempool and check if tx was trimmed
2021-07-20 06:07:25 -04:00
// If we are validating a package, don't trim here because we could evict a previous transaction
// in the package. LimitMempoolSize() should be called at the very end to make sure the mempool
// is still within limits and package submission happens atomically.
if ( ! args . m_package_submission & & ! bypass_limits ) {
2021-10-28 15:13:04 -03:00
LimitMempoolSize ( m_pool , m_active_chainstate . CoinsTip ( ) ) ;
2021-10-20 12:41:45 -03:00
if ( ! m_pool . exists ( GenTxid : : Txid ( hash ) ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " mempool full " ) ;
2019-07-10 11:38:03 -04:00
}
return true ;
}
2022-01-07 12:45:23 -03:00
bool MemPoolAccept : : SubmitPackage ( const ATMPArgs & args , std : : vector < Workspace > & workspaces ,
PackageValidationState & package_state ,
std : : map < const uint256 , const MempoolAcceptResult > & results )
2021-07-20 06:07:25 -04:00
{
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( m_pool . cs ) ;
2022-01-07 12:45:23 -03:00
// Sanity check: none of the transactions should be in the mempool, and none of the transactions
// should have a same-txid-different-witness equivalent in the mempool.
assert ( std : : all_of ( workspaces . cbegin ( ) , workspaces . cend ( ) , [ this ] ( const auto & ws ) {
return ! m_pool . exists ( GenTxid : : Txid ( ws . m_ptx - > GetHash ( ) ) ) ; } ) ) ;
2021-07-20 06:07:25 -04:00
bool all_submitted = true ;
// ConsensusScriptChecks adds to the script cache and is therefore consensus-critical;
// CheckInputsFromMempoolAndCache asserts that transactions only spend coins available from the
// mempool or UTXO set. Submit each transaction to the mempool immediately after calling
// ConsensusScriptChecks to make the outputs available for subsequent transactions.
for ( Workspace & ws : workspaces ) {
if ( ! ConsensusScriptChecks ( args , ws ) ) {
results . emplace ( ws . m_ptx - > GetWitnessHash ( ) , MempoolAcceptResult : : Failure ( ws . m_state ) ) ;
// Since PolicyScriptChecks() passed, this should never fail.
2022-04-27 12:30:10 -04:00
Assume ( false ) ;
2022-01-07 13:55:53 -03:00
all_submitted = false ;
package_state . Invalid ( PackageValidationResult : : PCKG_MEMPOOL_ERROR ,
strprintf ( " BUG! PolicyScriptChecks succeeded but ConsensusScriptChecks failed: %s " ,
ws . m_ptx - > GetHash ( ) . ToString ( ) ) ) ;
2021-07-20 06:07:25 -04:00
}
// Re-calculate mempool ancestors to call addUnchecked(). They may have changed since the
// last calculation done in PreChecks, since package ancestors have already been submitted.
2022-01-07 12:45:23 -03:00
std : : string unused_err_string ;
2021-07-20 06:07:25 -04:00
if ( ! m_pool . CalculateMemPoolAncestors ( * ws . m_entry , ws . m_ancestors , m_limit_ancestors ,
m_limit_ancestor_size , m_limit_descendants ,
2022-01-07 12:45:23 -03:00
m_limit_descendant_size , unused_err_string ) ) {
2021-07-20 06:07:25 -04:00
results . emplace ( ws . m_ptx - > GetWitnessHash ( ) , MempoolAcceptResult : : Failure ( ws . m_state ) ) ;
// Since PreChecks() and PackageMempoolChecks() both enforce limits, this should never fail.
2022-04-27 12:30:10 -04:00
Assume ( false ) ;
2022-01-07 13:55:53 -03:00
all_submitted = false ;
package_state . Invalid ( PackageValidationResult : : PCKG_MEMPOOL_ERROR ,
strprintf ( " BUG! Mempool ancestors or descendants were underestimated: %s " ,
ws . m_ptx - > GetHash ( ) . ToString ( ) ) ) ;
2021-07-20 06:07:25 -04:00
}
// If we call LimitMempoolSize() for each individual Finalize(), the mempool will not take
// the transaction's descendant feerate into account because it hasn't seen them yet. Also,
// we risk evicting a transaction that a subsequent package transaction depends on. Instead,
// allow the mempool to temporarily bypass limits, the maximum package size) while
// submitting transactions individually and then trim at the very end.
if ( ! Finalize ( args , ws ) ) {
results . emplace ( ws . m_ptx - > GetWitnessHash ( ) , MempoolAcceptResult : : Failure ( ws . m_state ) ) ;
// Since LimitMempoolSize() won't be called, this should never fail.
2022-04-27 12:30:10 -04:00
Assume ( false ) ;
2022-01-07 13:55:53 -03:00
all_submitted = false ;
package_state . Invalid ( PackageValidationResult : : PCKG_MEMPOOL_ERROR ,
strprintf ( " BUG! Adding to mempool failed: %s " , ws . m_ptx - > GetHash ( ) . ToString ( ) ) ) ;
2021-07-20 06:07:25 -04:00
}
}
// It may or may not be the case that all the transactions made it into the mempool. Regardless,
// make sure we haven't exceeded max mempool size.
2021-10-28 15:13:04 -03:00
LimitMempoolSize ( m_pool , m_active_chainstate . CoinsTip ( ) ) ;
2021-07-20 06:07:25 -04:00
// Find the wtxids of the transactions that made it into the mempool. Allow partial submission,
// but don't report success unless they all made it into the mempool.
for ( Workspace & ws : workspaces ) {
if ( m_pool . exists ( GenTxid : : Wtxid ( ws . m_ptx - > GetWitnessHash ( ) ) ) ) {
results . emplace ( ws . m_ptx - > GetWitnessHash ( ) ,
MempoolAcceptResult : : Success ( std : : move ( ws . m_replaced_transactions ) , ws . m_vsize , ws . m_base_fees ) ) ;
GetMainSignals ( ) . TransactionAddedToMempool ( ws . m_ptx , m_pool . GetAndIncrementSequence ( ) ) ;
} else {
all_submitted = false ;
ws . m_state . Invalid ( TxValidationResult : : TX_MEMPOOL_POLICY , " mempool full " ) ;
results . emplace ( ws . m_ptx - > GetWitnessHash ( ) , MempoolAcceptResult : : Failure ( ws . m_state ) ) ;
}
}
return all_submitted ;
}
2021-01-19 10:29:40 -03:00
MempoolAcceptResult MemPoolAccept : : AcceptSingleTransaction ( const CTransactionRef & ptx , ATMPArgs & args )
2019-07-10 11:38:03 -04:00
{
AssertLockHeld ( cs_main ) ;
LOCK ( m_pool . cs ) ; // mempool "read lock" (held through GetMainSignals().TransactionAddedToMempool())
2021-02-01 20:34:27 -03:00
Workspace ws ( ptx ) ;
2019-07-10 11:38:03 -04:00
2021-05-20 16:22:35 -04:00
if ( ! PreChecks ( args , ws ) ) return MempoolAcceptResult : : Failure ( ws . m_state ) ;
2019-07-10 11:38:03 -04:00
2021-08-09 06:56:57 -04:00
if ( m_rbf & & ! ReplacementChecks ( ws ) ) return MempoolAcceptResult : : Failure ( ws . m_state ) ;
2021-07-20 06:38:44 -04:00
// Perform the inexpensive checks first and avoid hashing and signature verification unless
// those checks pass, to mitigate CPU exhaustion denial-of-service attacks.
if ( ! PolicyScriptChecks ( args , ws ) ) return MempoolAcceptResult : : Failure ( ws . m_state ) ;
2019-07-10 11:38:03 -04:00
2021-07-20 06:38:44 -04:00
if ( ! ConsensusScriptChecks ( args , ws ) ) return MempoolAcceptResult : : Failure ( ws . m_state ) ;
2019-07-10 11:38:03 -04:00
// Tx was accepted, but not added
2021-01-19 10:29:40 -03:00
if ( args . m_test_accept ) {
2021-09-02 08:09:11 -04:00
return MempoolAcceptResult : : Success ( std : : move ( ws . m_replaced_transactions ) , ws . m_vsize , ws . m_base_fees ) ;
2021-01-19 10:29:40 -03:00
}
2019-07-10 11:38:03 -04:00
2021-05-20 16:22:35 -04:00
if ( ! Finalize ( args , ws ) ) return MempoolAcceptResult : : Failure ( ws . m_state ) ;
2019-07-10 11:38:03 -04:00
Add 'sequence' zmq publisher to track all block (dis)connects, mempool deltas
Using the zmq notifications to avoid excessive mempool polling can be difficult
given the current notifications available. It announces all transactions
being added to mempool or included in blocks, but announces no evictions
and gives no indication if the transaction is in the mempool or a block.
Block notifications for zmq are also substandard, in that it only announces
block tips, while all block transactions are still announced.
This commit adds a unified stream which can be used to closely track mempool:
1) getrawmempool to fill out mempool knowledge
2) if txhash is announced, add or remove from set
based on add/remove flag
3) if blockhash is announced, get block txn list,
remove from those transactions local view of mempool
4) if we drop a sequence number, go to (1)
The mempool sequence number starts at the value 1, and
increments each time a transaction enters the mempool,
or is evicted from the mempool for any reason, including
block inclusion. The mempool sequence number is published
via ZMQ for any transaction-related notification.
These features allow for ZMQ/RPC consumer to track mempool
state in a more exacting way, without unnecesarily polling
getrawmempool. See interface_zmq.py::test_mempool_sync for
example usage.
2020-09-04 11:55:58 -04:00
GetMainSignals ( ) . TransactionAddedToMempool ( ptx , m_pool . GetAndIncrementSequence ( ) ) ;
2014-06-26 02:41:44 -04:00
2021-09-02 08:09:11 -04:00
return MempoolAcceptResult : : Success ( std : : move ( ws . m_replaced_transactions ) , ws . m_vsize , ws . m_base_fees ) ;
2014-06-26 02:41:44 -04:00
}
2021-04-05 13:12:58 -04:00
PackageMempoolAcceptResult MemPoolAccept : : AcceptMultipleTransactions ( const std : : vector < CTransactionRef > & txns , ATMPArgs & args )
{
AssertLockHeld ( cs_main ) ;
2021-06-02 11:19:29 -04:00
// These context-free package limits can be done before taking the mempool lock.
2021-04-05 13:12:58 -04:00
PackageValidationState package_state ;
2021-06-02 11:19:29 -04:00
if ( ! CheckPackage ( txns , package_state ) ) return PackageMempoolAcceptResult ( package_state , { } ) ;
2021-04-05 14:13:27 -04:00
2021-04-05 13:12:58 -04:00
std : : vector < Workspace > workspaces { } ;
2021-06-02 11:19:29 -04:00
workspaces . reserve ( txns . size ( ) ) ;
std : : transform ( txns . cbegin ( ) , txns . cend ( ) , std : : back_inserter ( workspaces ) ,
[ ] ( const auto & tx ) { return Workspace ( tx ) ; } ) ;
2021-04-05 13:12:58 -04:00
std : : map < const uint256 , const MempoolAcceptResult > results ;
LOCK ( m_pool . cs ) ;
// Do all PreChecks first and fail fast to avoid running expensive script checks when unnecessary.
for ( Workspace & ws : workspaces ) {
if ( ! PreChecks ( args , ws ) ) {
package_state . Invalid ( PackageValidationResult : : PCKG_TX , " transaction failed " ) ;
// Exit early to avoid doing pointless work. Update the failed tx result; the rest are unfinished.
results . emplace ( ws . m_ptx - > GetWitnessHash ( ) , MempoolAcceptResult : : Failure ( ws . m_state ) ) ;
return PackageMempoolAcceptResult ( package_state , std : : move ( results ) ) ;
}
// Make the coins created by this transaction available for subsequent transactions in the
2021-05-27 03:39:59 -04:00
// package to spend. Since we already checked conflicts in the package and we don't allow
// replacements, we don't need to track the coins spent. Note that this logic will need to be
// updated if package replace-by-fee is allowed in the future.
2021-05-26 13:02:00 -04:00
assert ( ! args . m_allow_bip125_replacement ) ;
2021-04-05 13:12:58 -04:00
m_viewmempool . PackageAddTransaction ( ws . m_ptx ) ;
}
2021-07-20 08:26:26 -04:00
// Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
// For transactions consisting of exactly one child and its parents, it suffices to use the
// package feerate (total modified fees / total virtual size) to check this requirement.
const auto m_total_vsize = std : : accumulate ( workspaces . cbegin ( ) , workspaces . cend ( ) , int64_t { 0 } ,
[ ] ( int64_t sum , auto & ws ) { return sum + ws . m_vsize ; } ) ;
const auto m_total_modified_fees = std : : accumulate ( workspaces . cbegin ( ) , workspaces . cend ( ) , CAmount { 0 } ,
[ ] ( CAmount sum , auto & ws ) { return sum + ws . m_modified_fees ; } ) ;
const CFeeRate package_feerate ( m_total_modified_fees , m_total_vsize ) ;
TxValidationState placeholder_state ;
if ( args . m_package_feerates & &
! CheckFeeRate ( m_total_vsize , m_total_modified_fees , placeholder_state ) ) {
package_state . Invalid ( PackageValidationResult : : PCKG_POLICY , " package-fee-too-low " ) ;
return PackageMempoolAcceptResult ( package_state , package_feerate , { } ) ;
}
2021-07-15 02:29:19 -04:00
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
// because it's unnecessary. Also, CPFP carve out can increase the limit for individual
// transactions, but this exemption is not extended to packages in CheckPackageLimits().
std : : string err_string ;
2021-08-09 06:56:57 -04:00
if ( txns . size ( ) > 1 & & ! PackageMempoolChecks ( txns , package_state ) ) {
2021-07-20 08:26:26 -04:00
return PackageMempoolAcceptResult ( package_state , package_feerate , std : : move ( results ) ) ;
2021-07-15 02:29:19 -04:00
}
2021-04-05 13:12:58 -04:00
for ( Workspace & ws : workspaces ) {
2021-07-20 06:38:44 -04:00
if ( ! PolicyScriptChecks ( args , ws ) ) {
2021-04-05 13:12:58 -04:00
// Exit early to avoid doing pointless work. Update the failed tx result; the rest are unfinished.
package_state . Invalid ( PackageValidationResult : : PCKG_TX , " transaction failed " ) ;
results . emplace ( ws . m_ptx - > GetWitnessHash ( ) , MempoolAcceptResult : : Failure ( ws . m_state ) ) ;
2021-07-20 08:26:26 -04:00
return PackageMempoolAcceptResult ( package_state , package_feerate , std : : move ( results ) ) ;
2021-04-05 13:12:58 -04:00
}
if ( args . m_test_accept ) {
// When test_accept=true, transactions that pass PolicyScriptChecks are valid because there are
// no further mempool checks (passing PolicyScriptChecks implies passing ConsensusScriptChecks).
results . emplace ( ws . m_ptx - > GetWitnessHash ( ) ,
2021-09-02 08:09:11 -04:00
MempoolAcceptResult : : Success ( std : : move ( ws . m_replaced_transactions ) ,
ws . m_vsize , ws . m_base_fees ) ) ;
2021-04-05 13:12:58 -04:00
}
}
2021-07-20 08:26:26 -04:00
if ( args . m_test_accept ) return PackageMempoolAcceptResult ( package_state , package_feerate , std : : move ( results ) ) ;
2021-07-20 06:07:25 -04:00
2022-01-07 12:45:23 -03:00
if ( ! SubmitPackage ( args , workspaces , package_state , results ) ) {
2022-01-07 13:55:53 -03:00
// PackageValidationState filled in by SubmitPackage().
2021-07-20 08:26:26 -04:00
return PackageMempoolAcceptResult ( package_state , package_feerate , std : : move ( results ) ) ;
2021-07-20 06:07:25 -04:00
}
2021-07-20 08:26:26 -04:00
return PackageMempoolAcceptResult ( package_state , package_feerate , std : : move ( results ) ) ;
2014-06-26 02:41:44 -04:00
}
2021-09-22 11:40:22 -03:00
PackageMempoolAcceptResult MemPoolAccept : : AcceptPackage ( const Package & package , ATMPArgs & args )
{
AssertLockHeld ( cs_main ) ;
PackageValidationState package_state ;
// Check that the package is well-formed. If it isn't, we won't try to validate any of the
// transactions and thus won't return any MempoolAcceptResults, just a package-wide error.
// Context-free package checks.
if ( ! CheckPackage ( package , package_state ) ) return PackageMempoolAcceptResult ( package_state , { } ) ;
// All transactions in the package must be a parent of the last transaction. This is just an
// opportunity for us to fail fast on a context-free check without taking the mempool lock.
if ( ! IsChildWithParents ( package ) ) {
package_state . Invalid ( PackageValidationResult : : PCKG_POLICY , " package-not-child-with-parents " ) ;
return PackageMempoolAcceptResult ( package_state , { } ) ;
}
2022-01-07 12:45:23 -03:00
// IsChildWithParents() guarantees the package is > 1 transactions.
assert ( package . size ( ) > 1 ) ;
2021-09-22 11:40:22 -03:00
// The package must be 1 child with all of its unconfirmed parents. The package is expected to
// be sorted, so the last transaction is the child.
2022-01-07 12:45:23 -03:00
const auto & child = package . back ( ) ;
2021-09-22 11:40:22 -03:00
std : : unordered_set < uint256 , SaltedTxidHasher > unconfirmed_parent_txids ;
2022-01-07 12:45:23 -03:00
std : : transform ( package . cbegin ( ) , package . cend ( ) - 1 ,
2021-09-22 11:40:22 -03:00
std : : inserter ( unconfirmed_parent_txids , unconfirmed_parent_txids . end ( ) ) ,
[ ] ( const auto & tx ) { return tx - > GetHash ( ) ; } ) ;
// All child inputs must refer to a preceding package transaction or a confirmed UTXO. The only
// way to verify this is to look up the child's inputs in our current coins view (not including
// mempool), and enforce that all parents not present in the package be available at chain tip.
// Since this check can bring new coins into the coins cache, keep track of these coins and
// uncache them if we don't end up submitting this package to the mempool.
const CCoinsViewCache & coins_tip_cache = m_active_chainstate . CoinsTip ( ) ;
for ( const auto & input : child - > vin ) {
if ( ! coins_tip_cache . HaveCoinInCache ( input . prevout ) ) {
args . m_coins_to_uncache . push_back ( input . prevout ) ;
}
}
// Using the MemPoolAccept m_view cache allows us to look up these same coins faster later.
// This should be connecting directly to CoinsTip, not to m_viewmempool, because we specifically
// require inputs to be confirmed if they aren't in the package.
m_view . SetBackend ( m_active_chainstate . CoinsTip ( ) ) ;
const auto package_or_confirmed = [ this , & unconfirmed_parent_txids ] ( const auto & input ) {
return unconfirmed_parent_txids . count ( input . prevout . hash ) > 0 | | m_view . HaveCoin ( input . prevout ) ;
} ;
if ( ! std : : all_of ( child - > vin . cbegin ( ) , child - > vin . cend ( ) , package_or_confirmed ) ) {
package_state . Invalid ( PackageValidationResult : : PCKG_POLICY , " package-not-child-with-unconfirmed-parents " ) ;
return PackageMempoolAcceptResult ( package_state , { } ) ;
}
// Protect against bugs where we pull more inputs from disk that miss being added to
// coins_to_uncache. The backend will be connected again when needed in PreChecks.
m_view . SetBackend ( m_dummy ) ;
LOCK ( m_pool . cs ) ;
2021-08-23 11:57:10 -04:00
std : : map < const uint256 , const MempoolAcceptResult > results ;
2021-12-17 11:18:02 -03:00
// Node operators are free to set their mempool policies however they please, nodes may receive
// transactions in different orders, and malicious counterparties may try to take advantage of
// policy differences to pin or delay propagation of transactions. As such, it's possible for
// some package transaction(s) to already be in the mempool, and we don't want to reject the
// entire package in that case (as that could be a censorship vector). De-duplicate the
// transactions that are already in the mempool, and only call AcceptMultipleTransactions() with
// the new transactions. This ensures we don't double-count transaction counts and sizes when
// checking ancestor/descendant limits, or double-count transaction fees for fee-related policy.
2022-01-25 08:39:03 -03:00
ATMPArgs single_args = ATMPArgs : : SingleInPackageAccept ( args ) ;
2022-02-23 08:42:33 -03:00
bool quit_early { false } ;
2021-08-23 11:57:10 -04:00
std : : vector < CTransactionRef > txns_new ;
for ( const auto & tx : package ) {
const auto & wtxid = tx - > GetWitnessHash ( ) ;
const auto & txid = tx - > GetHash ( ) ;
// There are 3 possibilities: already in mempool, same-txid-diff-wtxid already in mempool,
// or not in mempool. An already confirmed tx is treated as one not in mempool, because all
// we know is that the inputs aren't available.
if ( m_pool . exists ( GenTxid : : Wtxid ( wtxid ) ) ) {
// Exact transaction already exists in the mempool.
2022-01-21 09:40:59 -03:00
auto iter = m_pool . GetIter ( txid ) ;
2021-08-23 11:57:10 -04:00
assert ( iter ! = std : : nullopt ) ;
results . emplace ( wtxid , MempoolAcceptResult : : MempoolTx ( iter . value ( ) - > GetTxSize ( ) , iter . value ( ) - > GetFee ( ) ) ) ;
} else if ( m_pool . exists ( GenTxid : : Txid ( txid ) ) ) {
// Transaction with the same non-witness data but different witness (same txid,
// different wtxid) already exists in the mempool.
//
// We don't allow replacement transactions right now, so just swap the package
// transaction for the mempool one. Note that we are ignoring the validity of the
// package transaction passed in.
// TODO: allow witness replacement in packages.
2021-12-17 11:06:16 -03:00
auto iter = m_pool . GetIter ( txid ) ;
2021-08-23 11:57:10 -04:00
assert ( iter ! = std : : nullopt ) ;
2021-12-17 11:06:16 -03:00
// Provide the wtxid of the mempool tx so that the caller can look it up in the mempool.
results . emplace ( wtxid , MempoolAcceptResult : : MempoolTxDifferentWitness ( iter . value ( ) - > GetTx ( ) . GetWitnessHash ( ) ) ) ;
2021-08-23 11:57:10 -04:00
} else {
// Transaction does not already exist in the mempool.
2022-01-25 08:39:03 -03:00
// Try submitting the transaction on its own.
const auto single_res = AcceptSingleTransaction ( tx , single_args ) ;
if ( single_res . m_result_type = = MempoolAcceptResult : : ResultType : : VALID ) {
// The transaction succeeded on its own and is now in the mempool. Don't include it
// in package validation, because its fees should only be "used" once.
assert ( m_pool . exists ( GenTxid : : Wtxid ( wtxid ) ) ) ;
results . emplace ( wtxid , single_res ) ;
2022-02-23 08:42:33 -03:00
} else if ( single_res . m_state . GetResult ( ) ! = TxValidationResult : : TX_MEMPOOL_POLICY & &
single_res . m_state . GetResult ( ) ! = TxValidationResult : : TX_MISSING_INPUTS ) {
// Package validation policy only differs from individual policy in its evaluation
// of feerate. For example, if a transaction fails here due to violation of a
// consensus rule, the result will not change when it is submitted as part of a
// package. To minimize the amount of repeated work, unless the transaction fails
// due to feerate or missing inputs (its parent is a previous transaction in the
// package that failed due to feerate), don't run package validation. Note that this
// decision might not make sense if different types of packages are allowed in the
// future. Continue individually validating the rest of the transactions, because
// some of them may still be valid.
quit_early = true ;
2022-01-25 08:39:03 -03:00
} else {
txns_new . push_back ( tx ) ;
}
2021-08-23 11:57:10 -04:00
}
}
// Nothing to do if the entire package has already been submitted.
2022-02-23 08:42:33 -03:00
if ( quit_early | | txns_new . empty ( ) ) {
2022-01-25 08:39:03 -03:00
// No package feerate when no package validation was done.
return PackageMempoolAcceptResult ( package_state , std : : move ( results ) ) ;
}
2021-08-23 11:57:10 -04:00
// Validate the (deduplicated) transactions as a package.
auto submission_result = AcceptMultipleTransactions ( txns_new , args ) ;
// Include already-in-mempool transaction results in the final result.
for ( const auto & [ wtxid , mempoolaccept_res ] : results ) {
submission_result . m_tx_results . emplace ( wtxid , mempoolaccept_res ) ;
}
2022-01-25 08:39:03 -03:00
if ( submission_result . m_state . IsValid ( ) ) assert ( submission_result . m_package_feerate . has_value ( ) ) ;
2021-08-23 11:57:10 -04:00
return submission_result ;
2021-09-22 11:40:22 -03:00
}
2019-07-10 11:38:03 -04:00
} // anon namespace
2021-12-02 01:50:27 -03:00
MempoolAcceptResult AcceptToMemoryPool ( CChainState & active_chainstate , const CTransactionRef & tx ,
2021-11-03 22:23:38 -03:00
int64_t accept_time , bool bypass_limits , bool test_accept )
2022-01-27 07:48:19 -03:00
EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main )
2015-10-22 19:50:33 -03:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2021-11-03 22:23:38 -03:00
const CChainParams & chainparams { active_chainstate . m_params } ;
2021-12-02 01:50:27 -03:00
assert ( active_chainstate . GetMempool ( ) ! = nullptr ) ;
CTxMemPool & pool { * active_chainstate . GetMempool ( ) } ;
2017-05-30 20:58:54 -04:00
std : : vector < COutPoint > coins_to_uncache ;
2021-11-03 22:23:38 -03:00
auto args = MemPoolAccept : : ATMPArgs : : SingleAccept ( chainparams , accept_time , bypass_limits , coins_to_uncache , test_accept ) ;
2020-09-16 17:08:41 -03:00
const MempoolAcceptResult result = MemPoolAccept ( pool , active_chainstate ) . AcceptSingleTransaction ( tx , args ) ;
2021-01-19 10:29:40 -03:00
if ( result . m_result_type ! = MempoolAcceptResult : : ResultType : : VALID ) {
2021-03-23 17:32:03 -03:00
// Remove coins that were not present in the coins cache before calling
// AcceptSingleTransaction(); this is to prevent memory DoS in case we receive a large
// number of invalid transactions that attempt to overrun the in-memory coins cache
2019-01-25 18:33:21 -03:00
// (`CCoinsViewCache::cacheCoins`).
2017-06-01 21:18:57 -04:00
for ( const COutPoint & hashTx : coins_to_uncache )
2020-09-16 17:08:41 -03:00
active_chainstate . CoinsTip ( ) . Uncache ( hashTx ) ;
2015-10-22 19:50:33 -03:00
}
2016-10-03 11:06:10 -03:00
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
2019-10-24 12:35:42 -03:00
BlockValidationState state_dummy ;
2021-04-27 16:54:53 -04:00
active_chainstate . FlushStateToDisk ( state_dummy , FlushStateMode : : PERIODIC ) ;
2021-01-19 10:29:40 -03:00
return result ;
2015-10-22 19:50:33 -03:00
}
2021-04-05 13:12:58 -04:00
PackageMempoolAcceptResult ProcessNewPackage ( CChainState & active_chainstate , CTxMemPool & pool ,
const Package & package , bool test_accept )
{
AssertLockHeld ( cs_main ) ;
assert ( ! package . empty ( ) ) ;
assert ( std : : all_of ( package . cbegin ( ) , package . cend ( ) , [ ] ( const auto & tx ) { return tx ! = nullptr ; } ) ) ;
std : : vector < COutPoint > coins_to_uncache ;
2022-04-14 15:41:19 -04:00
const CChainParams & chainparams = active_chainstate . m_params ;
2021-09-22 11:40:22 -03:00
const auto result = [ & ] ( ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) {
AssertLockHeld ( cs_main ) ;
if ( test_accept ) {
auto args = MemPoolAccept : : ATMPArgs : : PackageTestAccept ( chainparams , GetTime ( ) , coins_to_uncache ) ;
return MemPoolAccept ( pool , active_chainstate ) . AcceptMultipleTransactions ( package , args ) ;
} else {
auto args = MemPoolAccept : : ATMPArgs : : PackageChildWithParents ( chainparams , GetTime ( ) , coins_to_uncache ) ;
return MemPoolAccept ( pool , active_chainstate ) . AcceptPackage ( package , args ) ;
}
} ( ) ;
2021-04-05 13:12:58 -04:00
// Uncache coins pertaining to transactions that were not submitted to the mempool.
2021-07-20 06:07:25 -04:00
if ( test_accept | | result . m_state . IsInvalid ( ) ) {
for ( const COutPoint & hashTx : coins_to_uncache ) {
active_chainstate . CoinsTip ( ) . Uncache ( hashTx ) ;
}
2021-04-05 13:12:58 -04:00
}
2022-01-07 12:45:23 -03:00
// Ensure the coins cache is still within limits.
2021-07-20 06:07:25 -04:00
BlockValidationState state_dummy ;
active_chainstate . FlushStateToDisk ( state_dummy , FlushStateMode : : PERIODIC ) ;
2021-04-05 13:12:58 -04:00
return result ;
}
2015-04-01 11:03:11 -03:00
CAmount GetBlockSubsidy ( int nHeight , const Consensus : : Params & consensusParams )
2010-08-29 12:58:15 -04:00
{
2015-04-01 11:03:11 -03:00
int halvings = nHeight / consensusParams . nSubsidyHalvingInterval ;
2014-03-10 21:02:36 -03:00
// Force block reward to zero when right shift is undefined.
if ( halvings > = 64 )
2015-04-01 11:03:11 -03:00
return 0 ;
2010-08-29 12:58:15 -04:00
2015-04-01 11:03:11 -03:00
CAmount nSubsidy = 50 * COIN ;
2013-05-07 09:16:25 -04:00
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
2014-03-10 21:02:36 -03:00
nSubsidy > > = halvings ;
2015-04-01 11:03:11 -03:00
return nSubsidy ;
2010-08-29 12:58:15 -04:00
}
2019-07-24 13:23:48 -04:00
CoinsViews : : CoinsViews (
2022-03-03 16:40:18 -03:00
fs : : path ldb_name ,
2019-07-24 13:23:48 -04:00
size_t cache_size_bytes ,
bool in_memory ,
bool should_wipe ) : m_dbview (
2021-05-04 07:00:25 -04:00
gArgs . GetDataDirNet ( ) / ldb_name , cache_size_bytes , in_memory , should_wipe ) ,
2019-07-24 13:23:48 -04:00
m_catcherview ( & m_dbview ) { }
void CoinsViews : : InitCache ( )
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2021-03-10 06:28:08 -03:00
m_cacheview = std : : make_unique < CCoinsViewCache > ( & m_catcherview ) ;
2019-07-24 13:23:48 -04:00
}
2021-06-12 10:52:40 -04:00
CChainState : : CChainState (
CTxMemPool * mempool ,
BlockManager & blockman ,
ChainstateManager & chainman ,
std : : optional < uint256 > from_snapshot_blockhash )
2020-09-02 16:05:54 -04:00
: m_mempool ( mempool ) ,
m_blockman ( blockman ) ,
2022-04-14 15:41:19 -04:00
m_params ( chainman . GetParams ( ) ) ,
2021-06-12 10:52:40 -04:00
m_chainman ( chainman ) ,
2019-12-11 18:41:40 -03:00
m_from_snapshot_blockhash ( from_snapshot_blockhash ) { }
2019-07-24 13:23:48 -04:00
void CChainState : : InitCoinsDB (
size_t cache_size_bytes ,
bool in_memory ,
bool should_wipe ,
2022-03-03 16:40:18 -03:00
fs : : path leveldb_name )
2019-07-24 13:23:48 -04:00
{
2021-04-03 12:26:39 -03:00
if ( m_from_snapshot_blockhash ) {
leveldb_name + = " _ " + m_from_snapshot_blockhash - > ToString ( ) ;
2019-12-11 18:41:40 -03:00
}
2021-03-10 06:28:08 -03:00
m_coins_views = std : : make_unique < CoinsViews > (
2019-07-24 13:23:48 -04:00
leveldb_name , cache_size_bytes , in_memory , should_wipe ) ;
}
2019-09-16 16:01:12 -03:00
void CChainState : : InitCoinsCache ( size_t cache_size_bytes )
2019-07-24 13:23:48 -04:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2019-07-24 13:23:48 -04:00
assert ( m_coins_views ! = nullptr ) ;
2019-09-16 16:01:12 -03:00
m_coinstip_cache_size_bytes = cache_size_bytes ;
2019-07-24 13:23:48 -04:00
m_coins_views - > InitCache ( ) ;
}
2019-03-27 13:21:50 -03:00
// Note that though this is marked const, we may end up modifying `m_cached_finished_ibd`, which
// is a performance-related implementation detail. This function must be marked
// `const` so that `CValidationInterface` clients (which are given a `const CChainState*`)
// can call it.
//
bool CChainState : : IsInitialBlockDownload ( ) const
2010-08-29 12:58:15 -04:00
{
2016-04-26 21:21:22 -03:00
// Optimization: pre-test latch before taking the lock.
2019-03-27 13:21:50 -03:00
if ( m_cached_finished_ibd . load ( std : : memory_order_relaxed ) )
2016-04-26 21:21:22 -03:00
return false ;
2014-04-15 12:38:25 -03:00
LOCK ( cs_main ) ;
2019-03-27 13:21:50 -03:00
if ( m_cached_finished_ibd . load ( std : : memory_order_relaxed ) )
2016-04-26 21:21:22 -03:00
return false ;
2015-04-23 00:22:36 -03:00
if ( fImporting | | fReindex )
return true ;
2019-03-27 13:21:50 -03:00
if ( m_chain . Tip ( ) = = nullptr )
2010-08-29 12:58:15 -04:00
return true ;
2019-03-27 13:21:50 -03:00
if ( m_chain . Tip ( ) - > nChainWork < nMinimumChainWork )
2010-08-29 12:58:15 -04:00
return true ;
2019-03-27 13:21:50 -03:00
if ( m_chain . Tip ( ) - > GetBlockTime ( ) < ( GetTime ( ) - nMaxTipAge ) )
2016-10-31 21:37:54 -03:00
return true ;
2017-05-11 14:11:36 -03:00
LogPrintf ( " Leaving InitialBlockDownload (latching to false) \n " ) ;
2019-03-27 13:21:50 -03:00
m_cached_finished_ibd . store ( true , std : : memory_order_relaxed ) ;
2016-10-31 21:37:54 -03:00
return false ;
2010-08-29 12:58:15 -04:00
}
2016-04-27 13:04:02 -03:00
static void AlertNotify ( const std : : string & strMessage )
2016-03-06 07:07:25 -03:00
{
uiInterface . NotifyAlertChanged ( ) ;
2019-07-05 12:30:15 -04:00
# if HAVE_SYSTEM
2017-08-01 15:17:40 -04:00
std : : string strCmd = gArgs . GetArg ( " -alertnotify " , " " ) ;
2016-03-06 07:07:25 -03:00
if ( strCmd . empty ( ) ) return ;
// Alert text should be plain ascii coming from a trusted source, but to
// be safe we first strip anything not in safeChars, then add single quotes around
// the whole string before passing it to the shell:
std : : string singleQuote ( " ' " ) ;
std : : string safeStatus = SanitizeString ( strMessage ) ;
safeStatus = singleQuote + safeStatus + singleQuote ;
2022-05-05 02:28:29 -04:00
ReplaceAll ( strCmd , " %s " , safeStatus ) ;
2016-03-06 07:07:25 -03:00
2018-02-07 21:19:34 -03:00
std : : thread t ( runCommand , strCmd ) ;
t . detach ( ) ; // thread runs free
2019-03-14 07:30:37 -03:00
# endif
2016-03-06 07:07:25 -03:00
}
2020-10-05 16:14:35 -03:00
void CChainState : : CheckForkWarningConditions ( )
2013-05-07 12:33:52 -04:00
{
2014-04-15 07:43:17 -03:00
AssertLockHeld ( cs_main ) ;
2020-10-05 16:14:35 -03:00
2013-09-03 22:06:02 -04:00
// Before we get past initial download, we cannot reliably alert about forks
2016-10-22 02:33:25 -03:00
// (we assume we don't get stuck on a fork before finishing our initial sync)
2020-10-05 16:14:35 -03:00
if ( IsInitialBlockDownload ( ) ) {
2013-09-03 22:06:02 -04:00
return ;
2013-05-17 21:09:28 -04:00
}
2013-05-07 12:33:52 -04:00
2021-11-23 15:49:48 -03:00
if ( m_chainman . m_best_invalid & & m_chainman . m_best_invalid - > nChainWork > m_chain . Tip ( ) - > nChainWork + ( GetBlockProof ( * m_chain . Tip ( ) ) * 6 ) ) {
2020-09-07 02:58:42 -03:00
LogPrintf ( " %s: Warning: Found invalid chain at least ~6 blocks longer than our best chain. \n Chain state database corruption likely. \n " , __func__ ) ;
SetfLargeWorkInvalidChainFound ( true ) ;
2020-10-28 07:08:01 -03:00
} else {
2016-11-29 06:46:19 -03:00
SetfLargeWorkInvalidChainFound ( false ) ;
2013-05-07 12:33:52 -04:00
}
}
Walk pindexBestHeader back to ChainActive().Tip() if it is invalid
Instead of keeping pindexBestHeader set to the best header we've
ever seen, reset it back to our validated tip if we find an ancestor
of it turns out to be invalid. While the name is now a bit confusing,
this matches much better with how it is used in practice, see below.
Further, this opens up more use-cases for it in the future, namely
aggressively searching for new peers in case we have discovered
(possibly via some covert channel) headers which we do not know to be
invalid, but which we cannot find block data for.
Places pindexBestHeader is used:
* Various GUI displays of the best header and getblockchaininfo["headers"],
I don't think changing this is bad, and if anything this is less confusing
in the presence of an invalid block.
* IsCurrentForFeeEstimation(): If anything I think ensuring pindexBestHeader
isn't some crazy invalid chain is better than the alternative, even in the
case where you are rejecting the current chain due to hardware error (since
hopefully in that case you won't get any new blocks anyway).
* ConnectBlock assumevalid checks: We use pindexBestHeader to check that the
block we're connecting leads to something with nMinimumChainWork (preventing
a user-set assumevalid from having bogus work) and that the block we're
connecting leads to pindexBestHeader (I'm not too worried about this one -
it's nice to "disable" assumevalid if we have a long invalid headers chain,
but I don't see it as a critical protection).
* BlockRequestAllowed() uses pindexBestHeader as its target to ensure the
requested block is within a month of the "current chain". I don't think this
is a meaningful difference, if we're rejecting the current tip we're
trivially fingerprintable anyway, and if the chain really does have a bunch
of invalid crap near the tip, using the best not-invalid header is likely a
better criteria.
* ProcessGetBlockData uses pindexBestHeader as the "current chain" definition
of whether a block request is "historical" for the purpose of bandwidth
limiting. Similarly, I don't see why this is a meaningful change.
* We use pindexBestHeader for requesting missing headers on receipt of a
headers/compact block message or block inv as well as for initial getheaders.
I think this is definitely wrong, using the best not-invalid header for such
requests is much better.
* We use pindexBestHeader to define the "current chain" for deciding when
we're close to done with initial headers sync. I don't think this is a
meaningful change.
* We use pindexBestHeader to decide if initial headers sync has timed out. If
we're rejecting the chain due to hardware error this may result in
additional cases where we ban a peer, but this is already true, so I think
its fine.
2019-09-26 19:02:31 -03:00
// Called both upon regular invalid block discovery *and* InvalidateBlock
2020-10-05 16:14:35 -03:00
void CChainState : : InvalidChainFound ( CBlockIndex * pindexNew )
2010-08-29 12:58:15 -04:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
2021-11-23 15:49:48 -03:00
if ( ! m_chainman . m_best_invalid | | pindexNew - > nChainWork > m_chainman . m_best_invalid - > nChainWork ) {
m_chainman . m_best_invalid = pindexNew ;
}
2022-03-18 13:35:52 -03:00
if ( m_chainman . m_best_header ! = nullptr & & m_chainman . m_best_header - > GetAncestor ( pindexNew - > nHeight ) = = pindexNew ) {
m_chainman . m_best_header = m_chain . Tip ( ) ;
Walk pindexBestHeader back to ChainActive().Tip() if it is invalid
Instead of keeping pindexBestHeader set to the best header we've
ever seen, reset it back to our validated tip if we find an ancestor
of it turns out to be invalid. While the name is now a bit confusing,
this matches much better with how it is used in practice, see below.
Further, this opens up more use-cases for it in the future, namely
aggressively searching for new peers in case we have discovered
(possibly via some covert channel) headers which we do not know to be
invalid, but which we cannot find block data for.
Places pindexBestHeader is used:
* Various GUI displays of the best header and getblockchaininfo["headers"],
I don't think changing this is bad, and if anything this is less confusing
in the presence of an invalid block.
* IsCurrentForFeeEstimation(): If anything I think ensuring pindexBestHeader
isn't some crazy invalid chain is better than the alternative, even in the
case where you are rejecting the current chain due to hardware error (since
hopefully in that case you won't get any new blocks anyway).
* ConnectBlock assumevalid checks: We use pindexBestHeader to check that the
block we're connecting leads to something with nMinimumChainWork (preventing
a user-set assumevalid from having bogus work) and that the block we're
connecting leads to pindexBestHeader (I'm not too worried about this one -
it's nice to "disable" assumevalid if we have a long invalid headers chain,
but I don't see it as a critical protection).
* BlockRequestAllowed() uses pindexBestHeader as its target to ensure the
requested block is within a month of the "current chain". I don't think this
is a meaningful difference, if we're rejecting the current tip we're
trivially fingerprintable anyway, and if the chain really does have a bunch
of invalid crap near the tip, using the best not-invalid header is likely a
better criteria.
* ProcessGetBlockData uses pindexBestHeader as the "current chain" definition
of whether a block request is "historical" for the purpose of bandwidth
limiting. Similarly, I don't see why this is a meaningful change.
* We use pindexBestHeader for requesting missing headers on receipt of a
headers/compact block message or block inv as well as for initial getheaders.
I think this is definitely wrong, using the best not-invalid header for such
requests is much better.
* We use pindexBestHeader to define the "current chain" for deciding when
we're close to done with initial headers sync. I don't think this is a
meaningful change.
* We use pindexBestHeader to decide if initial headers sync has timed out. If
we're rejecting the chain due to hardware error this may result in
additional cases where we ban a peer, but this is already true, so I think
its fine.
2019-09-26 19:02:31 -03:00
}
2014-07-29 10:53:38 -04:00
2020-06-17 23:00:59 -04:00
LogPrintf ( " %s: invalid block=%s height=%d log2_work=%f date=%s \n " , __func__ ,
2014-01-16 12:15:27 -03:00
pindexNew - > GetBlockHash ( ) . ToString ( ) , pindexNew - > nHeight ,
2018-02-28 12:46:31 -03:00
log ( pindexNew - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , FormatISO8601DateTime ( pindexNew - > GetBlockTime ( ) ) ) ;
2020-10-05 16:14:35 -03:00
CBlockIndex * tip = m_chain . Tip ( ) ;
2015-07-04 16:14:03 -03:00
assert ( tip ) ;
2020-06-17 23:00:59 -04:00
LogPrintf ( " %s: current best=%s height=%d log2_work=%f date=%s \n " , __func__ ,
2020-10-05 16:14:35 -03:00
tip - > GetBlockHash ( ) . ToString ( ) , m_chain . Height ( ) , log ( tip - > nChainWork . getdouble ( ) ) / log ( 2.0 ) ,
2018-02-28 12:46:31 -03:00
FormatISO8601DateTime ( tip - > GetBlockTime ( ) ) ) ;
2013-05-07 12:33:52 -04:00
CheckForkWarningConditions ( ) ;
2010-08-29 12:58:15 -04:00
}
Walk pindexBestHeader back to ChainActive().Tip() if it is invalid
Instead of keeping pindexBestHeader set to the best header we've
ever seen, reset it back to our validated tip if we find an ancestor
of it turns out to be invalid. While the name is now a bit confusing,
this matches much better with how it is used in practice, see below.
Further, this opens up more use-cases for it in the future, namely
aggressively searching for new peers in case we have discovered
(possibly via some covert channel) headers which we do not know to be
invalid, but which we cannot find block data for.
Places pindexBestHeader is used:
* Various GUI displays of the best header and getblockchaininfo["headers"],
I don't think changing this is bad, and if anything this is less confusing
in the presence of an invalid block.
* IsCurrentForFeeEstimation(): If anything I think ensuring pindexBestHeader
isn't some crazy invalid chain is better than the alternative, even in the
case where you are rejecting the current chain due to hardware error (since
hopefully in that case you won't get any new blocks anyway).
* ConnectBlock assumevalid checks: We use pindexBestHeader to check that the
block we're connecting leads to something with nMinimumChainWork (preventing
a user-set assumevalid from having bogus work) and that the block we're
connecting leads to pindexBestHeader (I'm not too worried about this one -
it's nice to "disable" assumevalid if we have a long invalid headers chain,
but I don't see it as a critical protection).
* BlockRequestAllowed() uses pindexBestHeader as its target to ensure the
requested block is within a month of the "current chain". I don't think this
is a meaningful difference, if we're rejecting the current tip we're
trivially fingerprintable anyway, and if the chain really does have a bunch
of invalid crap near the tip, using the best not-invalid header is likely a
better criteria.
* ProcessGetBlockData uses pindexBestHeader as the "current chain" definition
of whether a block request is "historical" for the purpose of bandwidth
limiting. Similarly, I don't see why this is a meaningful change.
* We use pindexBestHeader for requesting missing headers on receipt of a
headers/compact block message or block inv as well as for initial getheaders.
I think this is definitely wrong, using the best not-invalid header for such
requests is much better.
* We use pindexBestHeader to define the "current chain" for deciding when
we're close to done with initial headers sync. I don't think this is a
meaningful change.
* We use pindexBestHeader to decide if initial headers sync has timed out. If
we're rejecting the chain due to hardware error this may result in
additional cases where we ban a peer, but this is already true, so I think
its fine.
2019-09-26 19:02:31 -03:00
// Same as InvalidChainFound, above, except not called directly from InvalidateBlock,
2021-04-28 03:16:48 -04:00
// which does its own setBlockIndexCandidates management.
void CChainState : : InvalidBlockFound ( CBlockIndex * pindex , const BlockValidationState & state )
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
2019-10-24 12:35:42 -03:00
if ( state . GetResult ( ) ! = BlockValidationResult : : BLOCK_MUTATED ) {
2013-11-16 15:28:24 -03:00
pindex - > nStatus | = BLOCK_FAILED_VALID ;
2021-11-23 15:44:38 -03:00
m_chainman . m_failed_blocks . insert ( pindex ) ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( pindex ) ;
2014-10-06 03:31:33 -03:00
setBlockIndexCandidates . erase ( pindex ) ;
2013-11-16 15:28:24 -03:00
InvalidChainFound ( pindex ) ;
}
2012-08-18 18:33:01 -04:00
}
2016-04-30 00:45:20 -03:00
void UpdateCoins ( const CTransaction & tx , CCoinsViewCache & inputs , CTxUndo & txundo , int nHeight )
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
{
// mark inputs spent
2013-01-08 09:17:15 -03:00
if ( ! tx . IsCoinBase ( ) ) {
2014-09-03 09:54:37 -04:00
txundo . vprevout . reserve ( tx . vin . size ( ) ) ;
2017-06-01 21:18:57 -04:00
for ( const CTxIn & txin : tx . vin ) {
2017-04-25 15:29:30 -03:00
txundo . vprevout . emplace_back ( ) ;
2017-06-05 11:50:47 -04:00
bool is_spent = inputs . SpendCoin ( txin . prevout , & txundo . vprevout . back ( ) ) ;
assert ( is_spent ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
}
}
2015-11-12 18:57:03 -03:00
// add outputs
2017-04-25 15:29:30 -03:00
AddCoins ( inputs , tx , nHeight ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
}
2014-11-29 12:01:37 -03:00
bool CScriptCheck : : operator ( ) ( ) {
2012-12-01 18:30:06 -03:00
const CScript & scriptSig = ptxTo - > vin [ nIn ] . scriptSig ;
2016-08-03 20:49:16 -04:00
const CScriptWitness * witness = & ptxTo - > vin [ nIn ] . scriptWitness ;
2017-09-22 03:27:03 -03:00
return VerifyScript ( scriptSig , m_tx_out . scriptPubKey , witness , nFlags , CachingTransactionSignatureChecker ( ptxTo , nIn , m_tx_out . nValue , cacheStore , * txdata ) , & error ) ;
2012-12-01 18:30:06 -03:00
}
2018-05-09 15:05:46 -03:00
static CuckooCache : : cache < uint256 , SignatureCacheHasher > g_scriptExecutionCache ;
static CSHA256 g_scriptExecutionCacheHasher ;
Cache full script execution results in addition to signatures
This adds a new CuckooCache in validation, caching whether all of a
transaction's scripts were valid with a given set of script flags.
Unlike previous attempts at caching an entire transaction's
validity, which have nearly universally introduced consensus
failures, this only caches the validity of a transaction's
scriptSigs. As these are pure functions of the transaction and
data it commits to, this should be much safer.
This is somewhat duplicative with the sigcache, as entries in the
new cache will also have several entries in the sigcache. However,
the sigcache is kept both as ATMP relies on it and because it
prevents malleability-based DoS attacks on the new higher-level
cache. Instead, the -sigcachesize option is re-used - cutting the
sigcache size in half and using the newly freed memory for the
script execution cache.
Transactions which match the script execution cache never even have
entries in the script check thread's workqueue created.
Note that the cache is indexed only on the script execution flags
and the transaction's witness hash. While this is sufficient to
make the CScriptCheck() calls pure functions, this introduces
dependancies on the mempool calculating things such as the
PrecomputedTransactionData object, filling the CCoinsViewCache, etc
in the exact same way as ConnectBlock. I belive this is a reasonable
assumption, but should be noted carefully.
In a rather naive benchmark (reindex-chainstate up to block 284k
with cuckoocache always returning true for contains(),
-assumevalid=0 and a very large dbcache), this connected blocks
~1.7x faster.
2017-04-11 17:46:39 -03:00
void InitScriptExecutionCache ( ) {
2018-05-09 15:05:46 -03:00
// Setup the salted hasher
uint256 nonce = GetRandHash ( ) ;
// We want the nonce to be 64 bytes long to force the hasher to process
// this chunk, which makes later hash computations more efficient. We
// just write our 32-byte entropy twice to fill the 64 bytes.
g_scriptExecutionCacheHasher . Write ( nonce . begin ( ) , 32 ) ;
g_scriptExecutionCacheHasher . Write ( nonce . begin ( ) , 32 ) ;
Cache full script execution results in addition to signatures
This adds a new CuckooCache in validation, caching whether all of a
transaction's scripts were valid with a given set of script flags.
Unlike previous attempts at caching an entire transaction's
validity, which have nearly universally introduced consensus
failures, this only caches the validity of a transaction's
scriptSigs. As these are pure functions of the transaction and
data it commits to, this should be much safer.
This is somewhat duplicative with the sigcache, as entries in the
new cache will also have several entries in the sigcache. However,
the sigcache is kept both as ATMP relies on it and because it
prevents malleability-based DoS attacks on the new higher-level
cache. Instead, the -sigcachesize option is re-used - cutting the
sigcache size in half and using the newly freed memory for the
script execution cache.
Transactions which match the script execution cache never even have
entries in the script check thread's workqueue created.
Note that the cache is indexed only on the script execution flags
and the transaction's witness hash. While this is sufficient to
make the CScriptCheck() calls pure functions, this introduces
dependancies on the mempool calculating things such as the
PrecomputedTransactionData object, filling the CCoinsViewCache, etc
in the exact same way as ConnectBlock. I belive this is a reasonable
assumption, but should be noted carefully.
In a rather naive benchmark (reindex-chainstate up to block 284k
with cuckoocache always returning true for contains(),
-assumevalid=0 and a very large dbcache), this connected blocks
~1.7x faster.
2017-04-11 17:46:39 -03:00
// nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
// setup_bytes creates the minimum possible cache (2 elements).
2019-08-22 21:40:41 -04:00
size_t nMaxCacheSize = std : : min ( std : : max ( ( int64_t ) 0 , gArgs . GetIntArg ( " -maxsigcachesize " , DEFAULT_MAX_SIG_CACHE_SIZE ) / 2 ) , MAX_MAX_SIG_CACHE_SIZE ) * ( ( size_t ) 1 < < 20 ) ;
2018-05-09 15:05:46 -03:00
size_t nElems = g_scriptExecutionCache . setup_bytes ( nMaxCacheSize ) ;
2017-04-21 17:38:12 -03:00
LogPrintf ( " Using %zu MiB out of %zu/2 requested for script execution cache, able to store %zu elements \n " ,
( nElems * sizeof ( uint256 ) ) > > 20 , ( nMaxCacheSize * 2 ) > > 20 , nElems ) ;
Cache full script execution results in addition to signatures
This adds a new CuckooCache in validation, caching whether all of a
transaction's scripts were valid with a given set of script flags.
Unlike previous attempts at caching an entire transaction's
validity, which have nearly universally introduced consensus
failures, this only caches the validity of a transaction's
scriptSigs. As these are pure functions of the transaction and
data it commits to, this should be much safer.
This is somewhat duplicative with the sigcache, as entries in the
new cache will also have several entries in the sigcache. However,
the sigcache is kept both as ATMP relies on it and because it
prevents malleability-based DoS attacks on the new higher-level
cache. Instead, the -sigcachesize option is re-used - cutting the
sigcache size in half and using the newly freed memory for the
script execution cache.
Transactions which match the script execution cache never even have
entries in the script check thread's workqueue created.
Note that the cache is indexed only on the script execution flags
and the transaction's witness hash. While this is sufficient to
make the CScriptCheck() calls pure functions, this introduces
dependancies on the mempool calculating things such as the
PrecomputedTransactionData object, filling the CCoinsViewCache, etc
in the exact same way as ConnectBlock. I belive this is a reasonable
assumption, but should be noted carefully.
In a rather naive benchmark (reindex-chainstate up to block 284k
with cuckoocache always returning true for contains(),
-assumevalid=0 and a very large dbcache), this connected blocks
~1.7x faster.
2017-04-11 17:46:39 -03:00
}
2017-04-21 15:45:30 -03:00
/**
2019-08-19 12:10:45 -04:00
* Check whether all of this transaction ' s input scripts succeed .
*
* This involves ECDSA signature checks so can be computationally intensive . This function should
* only be called after the cheap sanity checks in CheckTxInputs passed .
2017-06-07 11:05:34 -04:00
*
2017-08-07 01:36:37 -04:00
* If pvChecks is not nullptr , script checks are pushed onto it instead of being performed inline . Any
2017-06-07 11:05:34 -04:00
* script checks which are not necessary ( eg due to script execution cache hits ) are , obviously ,
* not pushed onto pvChecks / run .
*
* Setting cacheSigStore / cacheFullScriptStore to false will remove elements from the corresponding cache
* which are matched . This is useful for checking blocks where we will likely never need the cache
* entry again .
2017-06-23 16:23:55 -04:00
*
2019-01-16 00:11:13 -03:00
* Note that we may set state . reason to NOT_STANDARD for extra soft - fork flags in flags , block - checking
* callers should probably reset it to CONSENSUS in such cases .
*
2017-06-23 16:23:55 -04:00
* Non - static ( and re - declared ) in src / test / txvalidationcache_tests . cpp
2017-04-21 15:45:30 -03:00
*/
2021-02-16 16:41:41 -03:00
bool CheckInputScripts ( const CTransaction & tx , TxValidationState & state ,
const CCoinsViewCache & inputs , unsigned int flags , bool cacheSigStore ,
bool cacheFullScriptStore , PrecomputedTransactionData & txdata ,
std : : vector < CScriptCheck > * pvChecks )
2015-04-24 11:45:16 -03:00
{
2018-05-11 14:52:49 -03:00
if ( tx . IsCoinBase ( ) ) return true ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
2018-05-11 14:52:49 -03:00
if ( pvChecks ) {
pvChecks - > reserve ( tx . vin . size ( ) ) ;
}
Cache full script execution results in addition to signatures
This adds a new CuckooCache in validation, caching whether all of a
transaction's scripts were valid with a given set of script flags.
Unlike previous attempts at caching an entire transaction's
validity, which have nearly universally introduced consensus
failures, this only caches the validity of a transaction's
scriptSigs. As these are pure functions of the transaction and
data it commits to, this should be much safer.
This is somewhat duplicative with the sigcache, as entries in the
new cache will also have several entries in the sigcache. However,
the sigcache is kept both as ATMP relies on it and because it
prevents malleability-based DoS attacks on the new higher-level
cache. Instead, the -sigcachesize option is re-used - cutting the
sigcache size in half and using the newly freed memory for the
script execution cache.
Transactions which match the script execution cache never even have
entries in the script check thread's workqueue created.
Note that the cache is indexed only on the script execution flags
and the transaction's witness hash. While this is sufficient to
make the CScriptCheck() calls pure functions, this introduces
dependancies on the mempool calculating things such as the
PrecomputedTransactionData object, filling the CCoinsViewCache, etc
in the exact same way as ConnectBlock. I belive this is a reasonable
assumption, but should be noted carefully.
In a rather naive benchmark (reindex-chainstate up to block 284k
with cuckoocache always returning true for contains(),
-assumevalid=0 and a very large dbcache), this connected blocks
~1.7x faster.
2017-04-11 17:46:39 -03:00
2018-05-11 14:52:49 -03:00
// First check if script executions have been cached with the same
// flags. Note that this assumes that the inputs provided are
// correct (ie that the transaction hash which is in tx's prevouts
// properly commits to the scriptPubKey in the inputs view of that
// transaction).
uint256 hashCacheEntry ;
2018-05-09 15:05:46 -03:00
CSHA256 hasher = g_scriptExecutionCacheHasher ;
hasher . Write ( tx . GetWitnessHash ( ) . begin ( ) , 32 ) . Write ( ( unsigned char * ) & flags , sizeof ( flags ) ) . Finalize ( hashCacheEntry . begin ( ) ) ;
2018-05-11 14:52:49 -03:00
AssertLockHeld ( cs_main ) ; //TODO: Remove this requirement by making CuckooCache not require external locks
2018-05-09 15:05:46 -03:00
if ( g_scriptExecutionCache . contains ( hashCacheEntry , ! cacheFullScriptStore ) ) {
2018-05-11 14:52:49 -03:00
return true ;
}
Cache full script execution results in addition to signatures
This adds a new CuckooCache in validation, caching whether all of a
transaction's scripts were valid with a given set of script flags.
Unlike previous attempts at caching an entire transaction's
validity, which have nearly universally introduced consensus
failures, this only caches the validity of a transaction's
scriptSigs. As these are pure functions of the transaction and
data it commits to, this should be much safer.
This is somewhat duplicative with the sigcache, as entries in the
new cache will also have several entries in the sigcache. However,
the sigcache is kept both as ATMP relies on it and because it
prevents malleability-based DoS attacks on the new higher-level
cache. Instead, the -sigcachesize option is re-used - cutting the
sigcache size in half and using the newly freed memory for the
script execution cache.
Transactions which match the script execution cache never even have
entries in the script check thread's workqueue created.
Note that the cache is indexed only on the script execution flags
and the transaction's witness hash. While this is sufficient to
make the CScriptCheck() calls pure functions, this introduces
dependancies on the mempool calculating things such as the
PrecomputedTransactionData object, filling the CCoinsViewCache, etc
in the exact same way as ConnectBlock. I belive this is a reasonable
assumption, but should be noted carefully.
In a rather naive benchmark (reindex-chainstate up to block 284k
with cuckoocache always returning true for contains(),
-assumevalid=0 and a very large dbcache), this connected blocks
~1.7x faster.
2017-04-11 17:46:39 -03:00
2020-09-11 18:33:10 -03:00
if ( ! txdata . m_spent_outputs_ready ) {
2020-09-11 18:33:00 -03:00
std : : vector < CTxOut > spent_outputs ;
spent_outputs . reserve ( tx . vin . size ( ) ) ;
for ( const auto & txin : tx . vin ) {
const COutPoint & prevout = txin . prevout ;
const Coin & coin = inputs . AccessCoin ( prevout ) ;
assert ( ! coin . IsSpent ( ) ) ;
spent_outputs . emplace_back ( coin . out ) ;
}
txdata . Init ( tx , std : : move ( spent_outputs ) ) ;
2019-04-02 17:12:08 -03:00
}
2020-09-11 18:33:00 -03:00
assert ( txdata . m_spent_outputs . size ( ) = = tx . vin . size ( ) ) ;
2019-04-02 17:12:08 -03:00
2018-05-11 14:52:49 -03:00
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
// We very carefully only pass in things to CScriptCheck which
// are clearly committed to by tx' witness hash. This provides
// a sanity check that our caching is not introducing consensus
// failures through additional data in, eg, the coins being
// spent being checked as a part of CScriptCheck.
// Verify signature
2020-09-11 18:33:00 -03:00
CScriptCheck check ( txdata . m_spent_outputs [ i ] , tx , i , flags , cacheSigStore , & txdata ) ;
2018-05-11 14:52:49 -03:00
if ( pvChecks ) {
pvChecks - > push_back ( CScriptCheck ( ) ) ;
check . swap ( pvChecks - > back ( ) ) ;
} else if ( ! check ( ) ) {
if ( flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS ) {
// Check whether the failure was caused by a
// non-mandatory script verification check, such as
// non-standard DER encodings or non-null dummy
// arguments; if so, ensure we return NOT_STANDARD
// instead of CONSENSUS to avoid downstream users
// splitting the network between upgraded and
// non-upgraded nodes by banning CONSENSUS-failing
// data providers.
2020-09-11 18:33:00 -03:00
CScriptCheck check2 ( txdata . m_spent_outputs [ i ] , tx , i ,
2018-05-11 14:52:49 -03:00
flags & ~ STANDARD_NOT_MANDATORY_VERIFY_FLAGS , cacheSigStore , & txdata ) ;
if ( check2 ( ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_NOT_STANDARD , strprintf ( " non-mandatory-script-verify-flag (%s) " , ScriptErrorString ( check . GetScriptError ( ) ) ) ) ;
Cache full script execution results in addition to signatures
This adds a new CuckooCache in validation, caching whether all of a
transaction's scripts were valid with a given set of script flags.
Unlike previous attempts at caching an entire transaction's
validity, which have nearly universally introduced consensus
failures, this only caches the validity of a transaction's
scriptSigs. As these are pure functions of the transaction and
data it commits to, this should be much safer.
This is somewhat duplicative with the sigcache, as entries in the
new cache will also have several entries in the sigcache. However,
the sigcache is kept both as ATMP relies on it and because it
prevents malleability-based DoS attacks on the new higher-level
cache. Instead, the -sigcachesize option is re-used - cutting the
sigcache size in half and using the newly freed memory for the
script execution cache.
Transactions which match the script execution cache never even have
entries in the script check thread's workqueue created.
Note that the cache is indexed only on the script execution flags
and the transaction's witness hash. While this is sufficient to
make the CScriptCheck() calls pure functions, this introduces
dependancies on the mempool calculating things such as the
PrecomputedTransactionData object, filling the CCoinsViewCache, etc
in the exact same way as ConnectBlock. I belive this is a reasonable
assumption, but should be noted carefully.
In a rather naive benchmark (reindex-chainstate up to block 284k
with cuckoocache always returning true for contains(),
-assumevalid=0 and a very large dbcache), this connected blocks
~1.7x faster.
2017-04-11 17:46:39 -03:00
}
2018-05-11 14:52:49 -03:00
// MANDATORY flag failures correspond to
2019-10-24 12:35:42 -03:00
// TxValidationResult::TX_CONSENSUS. Because CONSENSUS
2018-05-11 14:52:49 -03:00
// failures are the most serious case of validation
// failures, we may need to consider using
// RECENT_CONSENSUS_CHANGE for any script failure that
// could be due to non-upgraded nodes which we may want to
// support, to avoid splitting the network (but this
// depends on the details of how net_processing handles
// such errors).
2019-04-28 16:40:01 -04:00
return state . Invalid ( TxValidationResult : : TX_CONSENSUS , strprintf ( " mandatory-script-verify-flag-failed (%s) " , ScriptErrorString ( check . GetScriptError ( ) ) ) ) ;
2010-08-29 12:58:15 -04:00
}
}
2018-05-11 14:52:49 -03:00
if ( cacheFullScriptStore & & ! pvChecks ) {
// We executed all of the provided scripts, and were told to
// cache the result. Do so now.
2018-05-09 15:05:46 -03:00
g_scriptExecutionCache . insert ( hashCacheEntry ) ;
2018-05-11 14:52:49 -03:00
}
2010-08-29 12:58:15 -04:00
return true ;
}
2021-04-18 09:41:08 -04:00
bool AbortNode ( BlockValidationState & state , const std : : string & strMessage , const bilingual_str & userMessage )
2015-01-16 20:57:14 -03:00
{
2020-05-10 05:43:30 -04:00
AbortNode ( strMessage , userMessage ) ;
2015-01-16 20:57:14 -03:00
return state . Error ( strMessage ) ;
}
2015-02-03 11:44:39 -03:00
/**
2017-04-25 15:29:25 -03:00
* Restore the UTXO in a Coin at a given COutPoint
* @ param undo The Coin to be restored .
2015-02-03 11:44:39 -03:00
* @ param view The coins view to which to apply the changes .
* @ param out The out point that corresponds to the tx input .
2017-04-25 15:29:09 -03:00
* @ return A DisconnectResult as an int
2015-02-03 11:44:39 -03:00
*/
2017-04-25 15:29:27 -03:00
int ApplyTxInUndo ( Coin & & undo , CCoinsViewCache & view , const COutPoint & out )
2015-02-03 11:44:39 -03:00
{
bool fClean = true ;
2017-05-30 20:58:54 -04:00
if ( view . HaveCoin ( out ) ) fClean = false ; // overwriting transaction output
2017-04-25 15:29:30 -03:00
if ( undo . nHeight = = 0 ) {
// Missing undo metadata (height and coinbase). Older versions included this
// information only in undo records for the last spend of a transactions'
// outputs. This implies that it must be present for some other output of the same tx.
const Coin & alternate = AccessByTxid ( view , out . hash ) ;
2017-05-30 20:58:54 -04:00
if ( ! alternate . IsSpent ( ) ) {
2017-04-25 15:29:30 -03:00
undo . nHeight = alternate . nHeight ;
undo . fCoinBase = alternate . fCoinBase ;
} else {
return DISCONNECT_FAILED ; // adding output for transaction without known metadata
2017-04-25 15:29:19 -03:00
}
2015-02-03 11:44:39 -03:00
}
2020-03-23 11:45:34 -03:00
// If the coin already exists as an unspent coin in the cache, then the
// possible_overwrite parameter to AddCoin must be set to true. We have
// already checked whether an unspent coin exists above using HaveCoin, so
// we don't need to guess. When fClean is false, an unspent coin already
// existed and it is an overwrite.
2017-04-19 13:34:30 -03:00
view . AddCoin ( out , std : : move ( undo ) , ! fClean ) ;
2015-02-03 11:44:39 -03:00
2017-04-25 15:29:09 -03:00
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN ;
2015-02-03 11:44:39 -03:00
}
2017-01-17 18:01:48 -03:00
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
2017-04-19 13:34:30 -03:00
* When FAILED is returned , view is left in an indeterminate state . */
2017-12-04 11:34:46 -03:00
DisconnectResult CChainState : : DisconnectBlock ( const CBlock & block , const CBlockIndex * pindex , CCoinsViewCache & view )
2010-08-29 12:58:15 -04:00
{
2021-12-03 12:34:07 -03:00
AssertLockHeld ( : : cs_main ) ;
2012-12-30 11:29:39 -03:00
bool fClean = true ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
CBlockUndo blockUndo ;
2017-06-09 12:57:23 -04:00
if ( ! UndoReadFromDisk ( blockUndo , pindex ) ) {
2017-04-28 20:08:39 -03:00
error ( " DisconnectBlock(): failure reading undo data " ) ;
return DISCONNECT_FAILED ;
}
2010-08-29 12:58:15 -04:00
2017-04-28 20:08:39 -03:00
if ( blockUndo . vtxundo . size ( ) + 1 ! = block . vtx . size ( ) ) {
error ( " DisconnectBlock(): block and undo data inconsistent " ) ;
return DISCONNECT_FAILED ;
}
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
// undo transactions in reverse order
2013-06-23 21:32:58 -04:00
for ( int i = block . vtx . size ( ) - 1 ; i > = 0 ; i - - ) {
2016-11-10 22:26:00 -03:00
const CTransaction & tx = * ( block . vtx [ i ] ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
uint256 hash = tx . GetHash ( ) ;
2017-06-08 12:08:32 -04:00
bool is_coinbase = tx . IsCoinBase ( ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
2013-10-26 16:26:29 -03:00
// Check that all outputs are available and match the outputs in the block itself
2015-02-03 11:44:39 -03:00
// exactly.
2017-04-25 15:29:30 -03:00
for ( size_t o = 0 ; o < tx . vout . size ( ) ; o + + ) {
if ( ! tx . vout [ o ] . scriptPubKey . IsUnspendable ( ) ) {
COutPoint out ( hash , o ) ;
Coin coin ;
2017-06-05 11:50:47 -04:00
bool is_spent = view . SpendCoin ( out , & coin ) ;
2017-06-08 12:08:32 -04:00
if ( ! is_spent | | tx . vout [ o ] ! = coin . out | | pindex - > nHeight ! = coin . nHeight | | is_coinbase ! = coin . fCoinBase ) {
2017-04-25 15:29:30 -03:00
fClean = false ; // transaction output mismatch
}
}
2014-09-03 03:01:24 -04:00
}
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
// restore inputs
if ( i > 0 ) { // not coinbases
2017-04-25 15:29:27 -03:00
CTxUndo & txundo = blockUndo . vtxundo [ i - 1 ] ;
2017-04-28 20:08:39 -03:00
if ( txundo . vprevout . size ( ) ! = tx . vin . size ( ) ) {
error ( " DisconnectBlock(): transaction and undo data inconsistent " ) ;
return DISCONNECT_FAILED ;
}
2022-01-28 13:36:44 -03:00
for ( unsigned int j = tx . vin . size ( ) ; j > 0 ; ) {
- - j ;
const COutPoint & out = tx . vin [ j ] . prevout ;
2017-04-25 15:29:27 -03:00
int res = ApplyTxInUndo ( std : : move ( txundo . vprevout [ j ] ) , view , out ) ;
2017-04-25 15:29:09 -03:00
if ( res = = DISCONNECT_FAILED ) return DISCONNECT_FAILED ;
fClean = fClean & & res ! = DISCONNECT_UNCLEAN ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
}
2017-04-25 15:29:27 -03:00
// At this point, all of txundo.vprevout should have been moved out.
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
}
}
// move best block pointer to prevout block
2013-11-04 22:27:39 -03:00
view . SetBestBlock ( pindex - > pprev - > GetBlockHash ( ) ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
2017-04-28 20:08:39 -03:00
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN ;
2010-08-29 12:58:15 -04:00
}
2012-12-01 19:04:14 -03:00
static CCheckQueue < CScriptCheck > scriptcheckqueue ( 128 ) ;
2020-08-21 02:24:05 -04:00
void StartScriptCheckWorkerThreads ( int threads_num )
{
scriptcheckqueue . StartWorkerThreads ( threads_num ) ;
}
void StopScriptCheckWorkerThreads ( )
{
scriptcheckqueue . StopWorkerThreads ( ) ;
2012-12-01 19:04:14 -03:00
}
2016-02-15 01:13:27 -03:00
/**
* Threshold condition checker that triggers when unknown versionbits are seen on the network .
*/
class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
{
private :
2022-04-14 16:53:19 -04:00
const ChainstateManager & m_chainman ;
int m_bit ;
2016-02-15 01:13:27 -03:00
public :
2022-04-14 16:53:19 -04:00
explicit WarningBitsConditionChecker ( const ChainstateManager & chainman , int bit ) : m_chainman { chainman } , m_bit ( bit ) { }
2016-02-15 01:13:27 -03:00
2017-06-20 15:58:56 -04:00
int64_t BeginTime ( const Consensus : : Params & params ) const override { return 0 ; }
int64_t EndTime ( const Consensus : : Params & params ) const override { return std : : numeric_limits < int64_t > : : max ( ) ; }
int Period ( const Consensus : : Params & params ) const override { return params . nMinerConfirmationWindow ; }
int Threshold ( const Consensus : : Params & params ) const override { return params . nRuleChangeActivationThreshold ; }
2016-02-15 01:13:27 -03:00
2017-06-20 15:58:56 -04:00
bool Condition ( const CBlockIndex * pindex , const Consensus : : Params & params ) const override
2016-02-15 01:13:27 -03:00
{
2019-09-05 10:28:52 -04:00
return pindex - > nHeight > = params . MinBIP9WarningHeight & &
( ( pindex - > nVersion & VERSIONBITS_TOP_MASK ) = = VERSIONBITS_TOP_BITS ) & &
2022-04-14 16:53:19 -04:00
( ( pindex - > nVersion > > m_bit ) & 1 ) ! = 0 & &
( ( m_chainman . m_versionbitscache . ComputeBlockVersion ( pindex - > pprev , params ) > > m_bit ) & 1 ) = = 0 ;
2016-02-15 01:13:27 -03:00
}
} ;
2021-01-07 18:41:51 -03:00
static std : : array < ThresholdConditionCache , VERSIONBITS_NUM_BITS > warningcache GUARDED_BY ( cs_main ) ;
2016-02-15 01:13:27 -03:00
2022-04-14 15:50:53 -04:00
static unsigned int GetBlockScriptFlags ( const CBlockIndex & block_index , const ChainstateManager & chainman )
2020-12-29 09:43:18 -03:00
{
2022-04-14 15:50:53 -04:00
const Consensus : : Params & consensusparams = chainman . GetConsensus ( ) ;
2017-09-12 12:38:20 -03:00
// BIP16 didn't become active until Apr 1 2012 (on mainnet, and
// retroactively applied to testnet)
// However, only one historical block violated the P2SH rules (on both
2021-11-16 10:40:19 -03:00
// mainnet and testnet).
// Similarly, only one historical block violated the TAPROOT rules on
// mainnet.
// For simplicity, always leave P2SH+WITNESS+TAPROOT on except for the two
// violating blocks.
uint32_t flags { SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_TAPROOT } ;
const auto it { consensusparams . script_flag_exceptions . find ( * Assert ( block_index . phashBlock ) ) } ;
if ( it ! = consensusparams . script_flag_exceptions . end ( ) ) {
flags = it - > second ;
2017-09-13 11:13:57 -03:00
}
2020-06-16 04:58:56 -04:00
// Enforce the DERSIG (BIP66) rule
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAt ( block_index , chainman , Consensus : : DEPLOYMENT_DERSIG ) ) {
2017-04-11 17:04:37 -03:00
flags | = SCRIPT_VERIFY_DERSIG ;
}
2020-06-16 04:58:56 -04:00
// Enforce CHECKLOCKTIMEVERIFY (BIP65)
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAt ( block_index , chainman , Consensus : : DEPLOYMENT_CLTV ) ) {
2017-04-11 17:04:37 -03:00
flags | = SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY ;
}
2020-06-16 04:58:56 -04:00
// Enforce CHECKSEQUENCEVERIFY (BIP112)
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAt ( block_index , chainman , Consensus : : DEPLOYMENT_CSV ) ) {
2017-04-11 17:04:37 -03:00
flags | = SCRIPT_VERIFY_CHECKSEQUENCEVERIFY ;
}
2020-06-16 04:58:56 -04:00
// Enforce BIP147 NULLDUMMY (activated simultaneously with segwit)
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAt ( block_index , chainman , Consensus : : DEPLOYMENT_SEGWIT ) ) {
2017-04-11 17:04:37 -03:00
flags | = SCRIPT_VERIFY_NULLDUMMY ;
}
return flags ;
}
2015-11-06 20:12:30 -03:00
static int64_t nTimeCheck = 0 ;
static int64_t nTimeForks = 0 ;
2014-07-26 16:49:17 -04:00
static int64_t nTimeConnect = 0 ;
2022-01-31 10:51:11 -03:00
static int64_t nTimeVerify = 0 ;
static int64_t nTimeUndo = 0 ;
2014-07-26 16:49:17 -04:00
static int64_t nTimeIndex = 0 ;
static int64_t nTimeTotal = 0 ;
2017-04-28 04:16:33 -03:00
static int64_t nBlocksTotal = 0 ;
2014-07-26 16:49:17 -04:00
2017-01-17 18:01:48 -03:00
/** Apply the effects of this block (with given index) on the UTXO set represented by coins.
* Validity checks that depend on the UTXO set are also done ; ConnectBlock ( )
* can fail if those validity checks fail ( among other reasons ) . */
2019-10-24 12:35:42 -03:00
bool CChainState : : ConnectBlock ( const CBlock & block , BlockValidationState & state , CBlockIndex * pindex ,
2021-04-27 16:54:53 -04:00
CCoinsViewCache & view , bool fJustCheck )
2010-08-29 12:58:15 -04:00
{
2014-04-23 03:55:24 -03:00
AssertLockHeld ( cs_main ) ;
2016-09-08 23:51:08 -03:00
assert ( pindex ) ;
2021-12-19 17:52:59 -03:00
uint256 block_hash { block . GetHash ( ) } ;
assert ( * pindex - > phashBlock = = block_hash ) ;
2015-11-06 20:12:30 -03:00
int64_t nTimeStart = GetTimeMicros ( ) ;
2010-08-29 12:58:15 -04:00
// Check it again in case a previous version let a bad block in
2017-11-20 16:13:12 -03:00
// NOTE: We don't currently (re-)invoke ContextualCheckBlock() or
// ContextualCheckBlockHeader() here. This means that if we add a new
// consensus rule that is enforced in one of those two functions, then we
// may have let in a block that violates the rule prior to updating the
// software, and we would NOT be enforcing the rule here. Fully solving
// upgrade from one software version to the next after a consensus rule
2021-04-28 03:16:48 -04:00
// change is potentially tricky and issue-specific (see NeedsRedownload()
// for one approach that was used for BIP 141 deployment).
2017-11-20 16:13:12 -03:00
// Also, currently the rule against blocks more than 2 hours in the future
// is enforced in ContextualCheckBlockHeader(); we wouldn't want to
// re-enforce that rule here (at least until we make it impossible for
2022-03-01 18:14:12 -03:00
// m_adjusted_time_callback() to go backward).
2021-04-27 16:54:53 -04:00
if ( ! CheckBlock ( block , state , m_params . GetConsensus ( ) , ! fJustCheck , ! fJustCheck ) ) {
2019-10-24 12:35:42 -03:00
if ( state . GetResult ( ) = = BlockValidationResult : : BLOCK_MUTATED ) {
2018-03-05 12:42:26 -03:00
// We don't write down blocks to disk if they may have been
// corrupted, so this should be impossible unless we're having hardware
// problems.
return AbortNode ( state , " Corrupt block found indicating potential hardware failure; shutting down " ) ;
}
2019-11-08 18:22:36 -03:00
return error ( " %s: Consensus::CheckBlock: %s " , __func__ , state . ToString ( ) ) ;
2018-03-05 12:42:26 -03:00
}
2010-08-29 12:58:15 -04:00
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
// verify that the view's current state corresponds to the previous block
2017-08-07 01:36:37 -04:00
uint256 hashPrevBlock = pindex - > pprev = = nullptr ? uint256 ( ) : pindex - > pprev - > GetBlockHash ( ) ;
2013-11-04 22:27:39 -03:00
assert ( hashPrevBlock = = view . GetBestBlock ( ) ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
2019-01-29 10:03:53 -03:00
nBlocksTotal + + ;
2013-01-18 20:35:17 -03:00
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
2021-12-19 17:52:59 -03:00
if ( block_hash = = m_params . GetConsensus ( ) . hashGenesisBlock ) {
2014-12-31 00:28:05 -03:00
if ( ! fJustCheck )
view . SetBestBlock ( pindex - > GetBlockHash ( ) ) ;
2013-01-18 20:35:17 -03:00
return true ;
}
2015-03-19 09:34:06 -03:00
bool fScriptChecks = true ;
2017-01-06 08:49:59 -03:00
if ( ! hashAssumeValid . IsNull ( ) ) {
// We've been configured with the hash of a block which has been externally verified to have a valid history.
// A suitable default value is included with the software and updated from time to time. Because validity
// relative to a piece of software is an objective fact these defaults can be easily reviewed.
// This setting doesn't force the selection of any particular chain but makes validating some faster by
// effectively caching the result of part of the verification.
2019-03-27 18:07:32 -03:00
BlockMap : : const_iterator it = m_blockman . m_block_index . find ( hashAssumeValid ) ;
if ( it ! = m_blockman . m_block_index . end ( ) ) {
2021-01-08 20:56:48 -03:00
if ( it - > second . GetAncestor ( pindex - > nHeight ) = = pindex & &
2022-03-18 13:35:52 -03:00
m_chainman . m_best_header - > GetAncestor ( pindex - > nHeight ) = = pindex & &
m_chainman . m_best_header - > nChainWork > = nMinimumChainWork ) {
2017-01-06 08:49:59 -03:00
// This block is a member of the assumed verified chain and an ancestor of the best header.
2018-05-11 14:52:49 -03:00
// Script verification is skipped when connecting blocks under the
// assumevalid block. Assuming the assumevalid block is valid this
// is safe because block merkle hashes are still computed and checked,
// Of course, if an assumed valid block is invalid due to false scriptSigs
// this optimization would allow an invalid chain to be accepted.
2017-02-06 11:16:18 -03:00
// The equivalent time check discourages hash power from extorting the network via DOS attack
2017-01-06 08:49:59 -03:00
// into accepting an invalid block through telling users they must manually set assumevalid.
// Requiring a software change or burying the invalid block, regardless of the setting, makes
// it hard to hide the implication of the demand. This also avoids having release candidates
// that are hardly doing any signature verification at all in testing without having to
// artificially set the default assumed verified block further back.
// The test against nMinimumChainWork prevents the skipping when denied access to any chain at
// least as good as the expected chain.
2022-03-18 13:35:52 -03:00
fScriptChecks = ( GetBlockProofEquivalentTime ( * m_chainman . m_best_header , * pindex , * m_chainman . m_best_header , m_params . GetConsensus ( ) ) < = 60 * 60 * 24 * 7 * 2 ) ;
2017-01-06 08:49:59 -03:00
}
2015-03-19 09:34:06 -03:00
}
}
2012-12-01 18:51:10 -03:00
2015-11-06 20:12:30 -03:00
int64_t nTime1 = GetTimeMicros ( ) ; nTimeCheck + = nTime1 - nTimeStart ;
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Sanity checks: %.2fms [%.2fs (%.2fms/blk)] \n " , MILLI * ( nTime1 - nTimeStart ) , nTimeCheck * MICRO , nTimeCheck * MILLI / nBlocksTotal ) ;
2015-11-06 20:12:30 -03:00
2012-02-17 13:58:02 -03:00
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
// unless those are already completely spent.
// If such overwrites are allowed, coinbases and transactions depending upon those
// can be duplicated to remove the ability to spend the first instance -- even after
// being sent to another address.
2018-11-10 14:11:22 -03:00
// See BIP30, CVE-2012-1909, and http://r6.ca/blog/20120206T005236Z.html for more information.
2015-04-28 11:48:28 -03:00
// This rule was originally applied to all blocks with a timestamp after March 15, 2012, 0:00 UTC.
2012-09-09 21:11:04 -03:00
// Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the
2015-04-28 11:47:17 -03:00
// two in the chain that violate it. This prevents exploiting the issue against nodes during their
2012-09-09 21:11:04 -03:00
// initial block download.
2017-12-12 15:30:22 -03:00
bool fEnforceBIP30 = ! ( ( pindex - > nHeight = = 91842 & & pindex - > GetBlockHash ( ) = = uint256S ( " 0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec " ) ) | |
2014-12-16 10:50:05 -03:00
( pindex - > nHeight = = 91880 & & pindex - > GetBlockHash ( ) = = uint256S ( " 0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721 " ) ) ) ;
2015-11-02 18:10:57 -03:00
// Once BIP34 activated it was not possible to create new duplicate coinbases and thus other than starting
// with the 2 existing duplicate coinbase pairs, not possible to create overwriting txs. But by the
// time BIP34 activated, in each of the existing pairs the duplicate coinbase had overwritten the first
2018-03-18 11:26:45 -03:00
// before the first had been spent. Since those coinbases are sufficiently buried it's no longer possible to create further
2015-11-02 18:10:57 -03:00
// duplicate transactions descending from the known pairs either.
2015-11-02 18:41:55 -03:00
// If we're on the known chain at height greater than where BIP34 activated, we can save the db accesses needed for the BIP30 check.
2017-10-05 14:43:47 -03:00
// BIP34 requires that a block at height X (block X) has its coinbase
// scriptSig start with a CScriptNum of X (indicated height X). The above
// logic of no longer requiring BIP30 once BIP34 activates is flawed in the
// case that there is a block X before the BIP34 height of 227,931 which has
// an indicated height Y where Y is greater than X. The coinbase for block
// X would also be a valid coinbase for block Y, which could be a BIP30
// violation. An exhaustive search of all mainnet coinbases before the
// BIP34 height which have an indicated height greater than the block height
// reveals many occurrences. The 3 lowest indicated heights found are
// 209,921, 490,897, and 1,983,702 and thus coinbases for blocks at these 3
// heights would be the first opportunity for BIP30 to be violated.
// The search reveals a great many blocks which have an indicated height
// greater than 1,983,702, so we simply remove the optimization to skip
// BIP30 checking for blocks at height 1,983,702 or higher. Before we reach
// that block in another 25 years or so, we should take advantage of a
// future consensus change to do a new and improved version of BIP34 that
// will actually prevent ever creating any duplicate coinbases in the
// future.
static constexpr int BIP34_IMPLIES_BIP30_LIMIT = 1983702 ;
// There is no potential to create a duplicate coinbase at block 209,921
// because this is still before the BIP34 height and so explicit BIP30
// checking is still active.
// The final case is block 176,684 which has an indicated height of
// 490,897. Unfortunately, this issue was not discovered until about 2 weeks
// before block 490,897 so there was not much opportunity to address this
// case other than to carefully analyze it and determine it would not be a
// problem. Block 490,897 was, in fact, mined with a different coinbase than
// block 176,684, but it is important to note that even if it hadn't been or
// is remined on an alternate fork with a duplicate coinbase, we would still
// not run into a BIP30 violation. This is because the coinbase for 176,684
// is spent in block 185,956 in transaction
// d4f7fbbf92f4a3014a230b2dc70b8058d02eb36ac06b4a0736d9d60eaa9e8781. This
// spending transaction can't be duplicated because it also spends coinbase
// 0328dd85c331237f18e781d692c92de57649529bd5edf1d01036daea32ffde29. This
// coinbase has an indicated height of over 4.2 billion, and wouldn't be
// duplicatable until that height, and it's currently impossible to create a
// chain that long. Nevertheless we may wish to consider a future soft fork
// which retroactively prevents block 490,897 from creating a duplicate
// coinbase. The two historical BIP30 violations often provide a confusing
// edge case when manipulating the UTXO and it would be simpler not to have
// another edge case to deal with.
// testnet3 has no blocks before the BIP34 height with indicated heights
2021-12-27 15:00:13 -03:00
// post BIP34 before approximately height 486,000,000. After block
// 1,983,702 testnet3 starts doing unnecessary BIP30 checking again.
2017-08-28 04:24:17 -03:00
assert ( pindex - > pprev ) ;
2021-04-27 16:54:53 -04:00
CBlockIndex * pindexBIP34height = pindex - > pprev - > GetAncestor ( m_params . GetConsensus ( ) . BIP34Height ) ;
2015-11-02 18:41:55 -03:00
//Only continue to enforce if we're below BIP34 activation height or the block hash at that height doesn't correspond.
2021-04-27 16:54:53 -04:00
fEnforceBIP30 = fEnforceBIP30 & & ( ! pindexBIP34height | | ! ( pindexBIP34height - > GetBlockHash ( ) = = m_params . GetConsensus ( ) . BIP34Hash ) ) ;
2015-11-02 18:10:57 -03:00
2017-10-05 14:43:47 -03:00
// TODO: Remove BIP30 checking from block height 1,983,702 on, once we have a
2022-02-17 08:54:39 -03:00
// consensus change that ensures coinbases at those heights cannot
2017-10-05 14:43:47 -03:00
// duplicate earlier coinbases.
if ( fEnforceBIP30 | | pindex - > nHeight > = BIP34_IMPLIES_BIP30_LIMIT ) {
2016-11-10 22:26:00 -03:00
for ( const auto & tx : block . vtx ) {
2017-04-25 15:29:30 -03:00
for ( size_t o = 0 ; o < tx - > vout . size ( ) ; o + + ) {
2017-05-30 20:58:54 -04:00
if ( view . HaveCoin ( COutPoint ( tx - > GetHash ( ) , o ) ) ) {
2019-04-28 16:32:34 -04:00
LogPrintf ( " ERROR: ConnectBlock(): tried to overwrite transaction \n " ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-txns-BIP30 " ) ;
2017-04-25 15:29:30 -03:00
}
}
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
}
}
2012-02-17 13:58:02 -03:00
2020-06-16 04:58:56 -04:00
// Enforce BIP68 (sequence locks)
2016-02-16 13:37:43 -03:00
int nLockTimeFlags = 0 ;
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAt ( * pindex , m_chainman , Consensus : : DEPLOYMENT_CSV ) ) {
2016-02-16 13:37:43 -03:00
nLockTimeFlags | = LOCKTIME_VERIFY_SEQUENCE ;
2016-02-20 19:37:13 -03:00
}
2017-04-11 17:04:37 -03:00
// Get the script flags for this block
2022-04-14 15:50:53 -04:00
unsigned int flags { GetBlockScriptFlags ( * pindex , m_chainman ) } ;
2015-11-05 21:42:38 -03:00
2015-11-06 20:12:30 -03:00
int64_t nTime2 = GetTimeMicros ( ) ; nTimeForks + = nTime2 - nTime1 ;
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Fork checks: %.2fms [%.2fs (%.2fms/blk)] \n " , MILLI * ( nTime2 - nTime1 ) , nTimeForks * MICRO , nTimeForks * MILLI / nBlocksTotal ) ;
2015-11-06 20:12:30 -03:00
2012-06-23 08:17:13 -04:00
CBlockUndo blockundo ;
2019-04-02 17:12:08 -03:00
// Precomputed transaction data pointers must not be invalidated
// until after `control` has run the script checks (potentially
// in multiple threads). Preallocate the vector size so a new allocation
// doesn't invalidate pointers into the vector, and keep txsdata in scope
// for as long as `control`.
2019-11-02 18:14:38 -03:00
CCheckQueueControl < CScriptCheck > control ( fScriptChecks & & g_parallel_script_checks ? & scriptcheckqueue : nullptr ) ;
2019-04-02 17:12:08 -03:00
std : : vector < PrecomputedTransactionData > txsdata ( block . vtx . size ( ) ) ;
2012-12-01 19:04:14 -03:00
2015-12-07 17:44:16 -03:00
std : : vector < int > prevheights ;
2014-04-22 19:46:19 -03:00
CAmount nFees = 0 ;
2012-12-01 16:10:23 -03:00
int nInputs = 0 ;
2016-01-03 14:54:50 -03:00
int64_t nSigOpsCost = 0 ;
2014-09-03 09:54:37 -04:00
blockundo . vtxundo . reserve ( block . vtx . size ( ) - 1 ) ;
2013-06-23 21:50:06 -04:00
for ( unsigned int i = 0 ; i < block . vtx . size ( ) ; i + + )
2010-08-29 12:58:15 -04:00
{
2016-11-10 22:26:00 -03:00
const CTransaction & tx = * ( block . vtx [ i ] ) ;
2012-07-07 18:06:34 -04:00
2012-12-01 16:10:23 -03:00
nInputs + = tx . vin . size ( ) ;
2012-01-20 19:07:40 -03:00
2012-01-10 22:18:00 -03:00
if ( ! tx . IsCoinBase ( ) )
{
2016-08-10 22:42:36 -04:00
CAmount txfee = 0 ;
2019-10-24 12:35:42 -03:00
TxValidationState tx_state ;
if ( ! Consensus : : CheckTxInputs ( tx , tx_state , view , pindex - > nHeight , txfee ) ) {
// Any transaction validation failure in ConnectBlock is a block consensus failure
2019-04-28 16:40:01 -04:00
state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS ,
2019-10-24 12:35:42 -03:00
tx_state . GetRejectReason ( ) , tx_state . GetDebugMessage ( ) ) ;
2019-11-08 18:22:36 -03:00
return error ( " %s: Consensus::CheckTxInputs: %s, %s " , __func__ , tx . GetHash ( ) . ToString ( ) , state . ToString ( ) ) ;
2016-08-10 22:42:36 -04:00
}
nFees + = txfee ;
2017-07-04 11:45:46 -04:00
if ( ! MoneyRange ( nFees ) ) {
2019-04-28 16:32:34 -04:00
LogPrintf ( " ERROR: %s: accumulated fee in the block out of range. \n " , __func__ ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-txns-accumulated-fee-outofrange " ) ;
2017-07-04 11:45:46 -04:00
}
2012-01-04 23:40:52 -03:00
2015-12-07 17:44:16 -03:00
// Check that transaction is BIP68 final
// BIP68 lock checks (as opposed to nLockTime checks) must
// be in ConnectBlock because they require the UTXO set
prevheights . resize ( tx . vin . size ( ) ) ;
for ( size_t j = 0 ; j < tx . vin . size ( ) ; j + + ) {
2017-04-25 15:29:30 -03:00
prevheights [ j ] = view . AccessCoin ( tx . vin [ j ] . prevout ) . nHeight ;
2015-12-07 17:44:16 -03:00
}
2020-05-26 10:05:51 -04:00
if ( ! SequenceLocks ( tx , nLockTimeFlags , prevheights , * pindex ) ) {
2019-04-28 16:32:34 -04:00
LogPrintf ( " ERROR: %s: contains a non-BIP68-final transaction \n " , __func__ ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-txns-nonfinal " ) ;
2015-12-07 17:44:16 -03:00
}
2016-01-03 14:54:50 -03:00
}
2015-12-07 17:44:16 -03:00
2016-01-03 14:54:50 -03:00
// GetTransactionSigOpCost counts 3 types of sigops:
// * legacy (always)
// * p2sh (when P2SH enabled in flags and excludes coinbase)
// * witness (when witness enabled in flags and excludes coinbase)
nSigOpsCost + = GetTransactionSigOpCost ( tx , view , flags ) ;
2019-04-28 16:32:34 -04:00
if ( nSigOpsCost > MAX_BLOCK_SIGOPS_COST ) {
LogPrintf ( " ERROR: ConnectBlock(): too many sigops \n " ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-blk-sigops " ) ;
2019-04-28 16:32:34 -04:00
}
2012-01-04 23:40:52 -03:00
2016-01-03 14:54:50 -03:00
if ( ! tx . IsCoinBase ( ) )
{
2012-12-01 19:04:14 -03:00
std : : vector < CScriptCheck > vChecks ;
2015-11-01 22:01:45 -03:00
bool fCacheResults = fJustCheck ; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
2019-10-24 12:35:42 -03:00
TxValidationState tx_state ;
2019-04-02 17:12:08 -03:00
if ( fScriptChecks & & ! CheckInputScripts ( tx , tx_state , view , flags , fCacheResults , fCacheResults , txsdata [ i ] , g_parallel_script_checks ? & vChecks : nullptr ) ) {
2019-10-24 12:35:42 -03:00
// Any transaction validation failure in ConnectBlock is a block consensus failure
2019-04-28 16:40:01 -04:00
state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS ,
2019-10-24 12:35:42 -03:00
tx_state . GetRejectReason ( ) , tx_state . GetDebugMessage ( ) ) ;
2019-08-19 11:55:38 -04:00
return error ( " ConnectBlock(): CheckInputScripts on %s failed with %s " ,
2019-11-08 18:22:36 -03:00
tx . GetHash ( ) . ToString ( ) , state . ToString ( ) ) ;
2019-04-16 12:38:14 -04:00
}
2012-12-01 19:04:14 -03:00
control . Add ( vChecks ) ;
2012-01-10 22:18:00 -03:00
}
2014-09-03 09:54:37 -04:00
CTxUndo undoDummy ;
if ( i > 0 ) {
blockundo . vtxundo . push_back ( CTxUndo ( ) ) ;
}
2016-04-30 00:45:20 -03:00
UpdateCoins ( tx , view , i = = 0 ? undoDummy : blockundo . vtxundo . back ( ) , pindex - > nHeight ) ;
2010-08-29 12:58:15 -04:00
}
2015-11-06 20:12:30 -03:00
int64_t nTime3 = GetTimeMicros ( ) ; nTimeConnect + = nTime3 - nTime2 ;
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)] \n " , ( unsigned ) block . vtx . size ( ) , MILLI * ( nTime3 - nTime2 ) , MILLI * ( nTime3 - nTime2 ) / block . vtx . size ( ) , nInputs < = 1 ? 0 : MILLI * ( nTime3 - nTime2 ) / ( nInputs - 1 ) , nTimeConnect * MICRO , nTimeConnect * MILLI / nBlocksTotal ) ;
2011-10-03 14:05:43 -03:00
2021-04-27 16:54:53 -04:00
CAmount blockReward = nFees + GetBlockSubsidy ( pindex - > nHeight , m_params . GetConsensus ( ) ) ;
2019-04-28 16:32:34 -04:00
if ( block . vtx [ 0 ] - > GetValueOut ( ) > blockReward ) {
LogPrintf ( " ERROR: ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d) \n " , block . vtx [ 0 ] - > GetValueOut ( ) , blockReward ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-cb-amount " ) ;
2019-04-28 16:32:34 -04:00
}
if ( ! control . Wait ( ) ) {
LogPrintf ( " ERROR: %s: CheckQueue failed \n " , __func__ ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " block-validation-failed " ) ;
2019-04-28 16:32:34 -04:00
}
2015-11-06 20:12:30 -03:00
int64_t nTime4 = GetTimeMicros ( ) ; nTimeVerify + = nTime4 - nTime2 ;
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)] \n " , nInputs - 1 , MILLI * ( nTime4 - nTime2 ) , nInputs < = 1 ? 0 : MILLI * ( nTime4 - nTime2 ) / ( nInputs - 1 ) , nTimeVerify * MICRO , nTimeVerify * MILLI / nBlocksTotal ) ;
2012-12-01 19:04:14 -03:00
2012-05-09 13:24:44 -04:00
if ( fJustCheck )
return true ;
2022-01-04 10:04:30 -03:00
if ( ! m_blockman . WriteUndoDataForBlock ( blockundo , state , pindex , m_params ) ) {
2016-12-02 21:54:15 -03:00
return false ;
2021-04-27 16:54:53 -04:00
}
2012-08-18 18:33:01 -04:00
2022-01-31 10:51:11 -03:00
int64_t nTime5 = GetTimeMicros ( ) ; nTimeUndo + = nTime5 - nTime4 ;
LogPrint ( BCLog : : BENCH , " - Write undo data: %.2fms [%.2fs (%.2fms/blk)] \n " , MILLI * ( nTime5 - nTime4 ) , nTimeUndo * MICRO , nTimeUndo * MILLI / nBlocksTotal ) ;
2016-12-02 21:54:15 -03:00
if ( ! pindex - > IsValid ( BLOCK_VALID_SCRIPTS ) ) {
2014-03-12 23:48:27 -03:00
pindex - > RaiseValidity ( BLOCK_VALID_SCRIPTS ) ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( pindex ) ;
2010-08-29 12:58:15 -04:00
}
2017-08-28 04:24:17 -03:00
assert ( pindex - > phashBlock ) ;
2012-10-05 14:22:21 -03:00
// add this block to the view's block chain
2014-09-03 03:25:32 -04:00
view . SetBestBlock ( pindex - > GetBlockHash ( ) ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
2022-01-31 10:51:11 -03:00
int64_t nTime6 = GetTimeMicros ( ) ; nTimeIndex + = nTime6 - nTime5 ;
LogPrint ( BCLog : : BENCH , " - Index writing: %.2fms [%.2fs (%.2fms/blk)] \n " , MILLI * ( nTime6 - nTime5 ) , nTimeIndex * MICRO , nTimeIndex * MILLI / nBlocksTotal ) ;
2014-07-26 16:49:17 -04:00
2021-10-18 08:19:13 -03:00
TRACE6 ( validation , block_connected ,
2021-12-19 17:52:59 -03:00
block_hash . data ( ) ,
2021-05-20 11:53:24 -04:00
pindex - > nHeight ,
block . vtx . size ( ) ,
nInputs ,
nSigOpsCost ,
2021-12-19 18:39:25 -03:00
nTime5 - nTimeStart // in microseconds (µs)
2021-05-20 11:53:24 -04:00
) ;
2010-08-29 12:58:15 -04:00
return true ;
}
2021-07-09 09:24:27 -04:00
CoinsCacheSizeState CChainState : : GetCoinsCacheSizeState ( )
2019-04-16 16:40:40 -04:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2019-04-16 16:40:40 -04:00
return this - > GetCoinsCacheSizeState (
2019-09-16 16:01:12 -03:00
m_coinstip_cache_size_bytes ,
2021-10-28 14:46:19 -03:00
m_mempool ? m_mempool - > m_max_size_bytes : 0 ) ;
2019-04-16 16:40:40 -04:00
}
CoinsCacheSizeState CChainState : : GetCoinsCacheSizeState (
size_t max_coins_cache_size_bytes ,
size_t max_mempool_size_bytes )
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2021-07-09 09:24:27 -04:00
const int64_t nMempoolUsage = m_mempool ? m_mempool - > DynamicMemoryUsage ( ) : 0 ;
2019-04-16 16:40:40 -04:00
int64_t cacheSize = CoinsTip ( ) . DynamicMemoryUsage ( ) ;
int64_t nTotalSpace =
2021-12-16 12:56:44 -03:00
max_coins_cache_size_bytes + std : : max < int64_t > ( int64_t ( max_mempool_size_bytes ) - nMempoolUsage , 0 ) ;
2019-04-16 16:40:40 -04:00
//! No need to periodic flush if at least this much space still available.
static constexpr int64_t MAX_BLOCK_COINSDB_USAGE_BYTES = 10 * 1024 * 1024 ; // 10MB
int64_t large_threshold =
std : : max ( ( 9 * nTotalSpace ) / 10 , nTotalSpace - MAX_BLOCK_COINSDB_USAGE_BYTES ) ;
if ( cacheSize > nTotalSpace ) {
LogPrintf ( " Cache size (%s) exceeds total space (%s) \n " , cacheSize , nTotalSpace ) ;
return CoinsCacheSizeState : : CRITICAL ;
} else if ( cacheSize > large_threshold ) {
return CoinsCacheSizeState : : LARGE ;
}
return CoinsCacheSizeState : : OK ;
}
2019-03-27 13:07:52 -03:00
bool CChainState : : FlushStateToDisk (
2019-10-24 12:35:42 -03:00
BlockValidationState & state ,
2019-03-27 13:07:52 -03:00
FlushStateMode mode ,
int nManualPruneHeight )
{
2017-07-24 11:24:12 -04:00
LOCK ( cs_main ) ;
2019-07-24 13:23:48 -04:00
assert ( this - > CanFlushToDisk ( ) ) ;
2020-05-28 03:00:19 -04:00
static std : : chrono : : microseconds nLastWrite { 0 } ;
static std : : chrono : : microseconds nLastFlush { 0 } ;
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
std : : set < int > setFilesToPrune ;
2018-04-27 15:08:39 -03:00
bool full_flush_completed = false ;
2019-08-21 12:03:39 -04:00
const size_t coins_count = CoinsTip ( ) . GetCacheSize ( ) ;
const size_t coins_mem_usage = CoinsTip ( ) . DynamicMemoryUsage ( ) ;
2015-01-04 15:11:44 -03:00
try {
2017-07-24 11:24:12 -04:00
{
2018-04-27 15:08:39 -03:00
bool fFlushForPrune = false ;
bool fDoFullFlush = false ;
2020-12-10 09:21:54 -03:00
2021-07-09 09:24:27 -04:00
CoinsCacheSizeState cache_state = GetCoinsCacheSizeState ( ) ;
2022-01-04 11:00:34 -03:00
LOCK ( m_blockman . cs_LastBlockFile ) ;
2022-01-05 11:44:16 -03:00
if ( fPruneMode & & ( m_blockman . m_check_for_pruning | | nManualPruneHeight > 0 ) & & ! fReindex ) {
2021-05-13 13:13:08 -04:00
// make sure we don't prune above any of the prune locks bestblocks
2020-12-10 09:21:54 -03:00
// pruning is height-based
2021-05-13 13:13:08 -04:00
int last_prune { m_chain . Height ( ) } ; // last height we can prune
std : : optional < std : : string > limiting_lock ; // prune lock that actually was the limiting factor, only used for logging
for ( const auto & prune_lock : m_blockman . m_prune_locks ) {
if ( prune_lock . second . height_first = = std : : numeric_limits < int > : : max ( ) ) continue ;
// Remove the buffer and one additional block here to get actual height that is outside of the buffer
const int lock_height { prune_lock . second . height_first - PRUNE_LOCK_BUFFER - 1 } ;
last_prune = std : : max ( 1 , std : : min ( last_prune , lock_height ) ) ;
if ( last_prune = = lock_height ) {
limiting_lock = prune_lock . first ;
}
}
if ( limiting_lock ) {
LogPrint ( BCLog : : PRUNE , " %s limited pruning to height %d \n " , limiting_lock . value ( ) , last_prune ) ;
}
2017-07-24 11:24:12 -04:00
if ( nManualPruneHeight > 0 ) {
2020-02-07 13:29:07 -03:00
LOG_TIME_MILLIS_WITH_CATEGORY ( " find files to prune (manual) " , BCLog : : BENCH ) ;
2019-08-21 12:03:39 -04:00
2020-12-10 09:21:54 -03:00
m_blockman . FindFilesToPruneManual ( setFilesToPrune , std : : min ( last_prune , nManualPruneHeight ) , m_chain . Height ( ) ) ;
2017-07-24 11:24:12 -04:00
} else {
2020-02-07 13:29:07 -03:00
LOG_TIME_MILLIS_WITH_CATEGORY ( " find files to prune " , BCLog : : BENCH ) ;
2019-08-21 12:03:39 -04:00
2021-04-27 16:54:53 -04:00
m_blockman . FindFilesToPrune ( setFilesToPrune , m_params . PruneAfterHeight ( ) , m_chain . Height ( ) , last_prune , IsInitialBlockDownload ( ) ) ;
2022-01-05 11:44:16 -03:00
m_blockman . m_check_for_pruning = false ;
2014-11-25 12:26:20 -03:00
}
2017-07-24 11:24:12 -04:00
if ( ! setFilesToPrune . empty ( ) ) {
fFlushForPrune = true ;
2022-03-18 13:35:52 -03:00
if ( ! m_blockman . m_have_pruned ) {
2021-07-01 04:24:58 -04:00
m_blockman . m_block_tree_db - > WriteFlag ( " prunedblockfiles " , true ) ;
2022-03-18 13:35:52 -03:00
m_blockman . m_have_pruned = true ;
2017-07-24 11:24:12 -04:00
}
2014-11-25 12:26:20 -03:00
}
2017-07-24 11:24:12 -04:00
}
2020-05-28 03:00:19 -04:00
const auto nNow = GetTime < std : : chrono : : microseconds > ( ) ;
2017-07-24 11:24:12 -04:00
// Avoid writing/flushing immediately after startup.
2020-05-28 03:00:19 -04:00
if ( nLastWrite . count ( ) = = 0 ) {
2017-07-24 11:24:12 -04:00
nLastWrite = nNow ;
}
2020-05-28 03:00:19 -04:00
if ( nLastFlush . count ( ) = = 0 ) {
2017-07-24 11:24:12 -04:00
nLastFlush = nNow ;
}
// The cache is large and we're within 10% and 10 MiB of the limit, but we have time now (not in the middle of a block processing).
2019-04-16 16:40:40 -04:00
bool fCacheLarge = mode = = FlushStateMode : : PERIODIC & & cache_state > = CoinsCacheSizeState : : LARGE ;
2017-07-24 11:24:12 -04:00
// The cache is over the limit, we have to write now.
2019-04-16 16:40:40 -04:00
bool fCacheCritical = mode = = FlushStateMode : : IF_NEEDED & & cache_state > = CoinsCacheSizeState : : CRITICAL ;
2017-07-24 11:24:12 -04:00
// It's been a while since we wrote the block index to disk. Do this frequently, so we don't need to redownload after a crash.
2020-05-28 03:00:19 -04:00
bool fPeriodicWrite = mode = = FlushStateMode : : PERIODIC & & nNow > nLastWrite + DATABASE_WRITE_INTERVAL ;
2017-07-24 11:24:12 -04:00
// It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
2020-05-28 03:00:19 -04:00
bool fPeriodicFlush = mode = = FlushStateMode : : PERIODIC & & nNow > nLastFlush + DATABASE_FLUSH_INTERVAL ;
2017-07-24 11:24:12 -04:00
// Combine all conditions that result in a full cache flush.
2018-03-09 11:03:40 -03:00
fDoFullFlush = ( mode = = FlushStateMode : : ALWAYS ) | | fCacheLarge | | fCacheCritical | | fPeriodicFlush | | fFlushForPrune ;
2017-07-24 11:24:12 -04:00
// Write blocks and block index to disk.
if ( fDoFullFlush | | fPeriodicWrite ) {
2019-03-05 17:33:26 -03:00
// Ensure we can write block index
2021-04-09 02:16:36 -04:00
if ( ! CheckDiskSpace ( gArgs . GetBlocksDirPath ( ) ) ) {
2020-05-10 05:43:30 -04:00
return AbortNode ( state , " Disk space is too low! " , _ ( " Disk space is too low! " ) ) ;
2018-09-01 19:18:02 -03:00
}
2019-08-21 12:03:39 -04:00
{
2020-02-07 13:29:07 -03:00
LOG_TIME_MILLIS_WITH_CATEGORY ( " write block and undo data to disk " , BCLog : : BENCH ) ;
2019-08-21 12:03:39 -04:00
// First make sure all block and undo data is flushed to disk.
2022-01-04 10:04:30 -03:00
m_blockman . FlushBlockFile ( ) ;
2019-08-21 12:03:39 -04:00
}
2017-07-24 11:24:12 -04:00
// Then update all block file information (which may refer to block and undo files).
{
2020-02-07 13:29:07 -03:00
LOG_TIME_MILLIS_WITH_CATEGORY ( " write block index to disk " , BCLog : : BENCH ) ;
2019-08-21 12:03:39 -04:00
2022-01-05 11:06:56 -03:00
if ( ! m_blockman . WriteBlockIndexDB ( ) ) {
2017-07-24 11:24:12 -04:00
return AbortNode ( state , " Failed to write to block index database " ) ;
}
Improve chainstate/blockindex disk writing policy
There are 3 pieces of data that are maintained on disk. The actual block
and undo data, the block index (which can refer to positions on disk),
and the chainstate (which refers to the best block hash).
Earlier, there was no guarantee that blocks were written to disk before
block index entries referring to them were written. This commit introduces
dirty flags for block index data, and delays writing entries until the actual
block data is flushed.
With this stricter ordering in writes, it is now safe to not always flush
after every block, so there is no need for the IsInitialBlockDownload()
check there - instead we just write whenever enough time has passed or
the cache size grows too large. Also updating the wallet's best known block
is delayed until this is done, otherwise the wallet may end up referring to an
unknown block.
In addition, only do a write inside the block processing loop if necessary
(because of cache size exceeded). Otherwise, move the writing to a point
after processing is done, after relaying.
2014-11-07 07:38:35 -03:00
}
2017-07-24 11:24:12 -04:00
// Finally remove any pruned files
2019-08-21 12:03:39 -04:00
if ( fFlushForPrune ) {
2020-02-07 13:29:07 -03:00
LOG_TIME_MILLIS_WITH_CATEGORY ( " unlink pruned files " , BCLog : : BENCH ) ;
2019-08-21 12:03:39 -04:00
2017-07-24 11:24:12 -04:00
UnlinkPrunedFiles ( setFilesToPrune ) ;
2019-08-21 12:03:39 -04:00
}
2017-07-24 11:24:12 -04:00
nLastWrite = nNow ;
}
// Flush best chain related state. This can only be done if the blocks / block index write was also done.
2019-07-24 11:45:04 -04:00
if ( fDoFullFlush & & ! CoinsTip ( ) . GetBestBlock ( ) . IsNull ( ) ) {
2021-10-04 01:45:08 -03:00
LOG_TIME_MILLIS_WITH_CATEGORY ( strprintf ( " write coins cache to disk (%d coins, %.2fkB) " ,
coins_count , coins_mem_usage / 1000 ) , BCLog : : BENCH ) ;
2019-08-21 12:03:39 -04:00
2017-07-24 11:24:12 -04:00
// Typical Coin structures on disk are around 48 bytes in size.
// Pushing a new one to the database can cause it to be written
// twice (once in the log, and once in the tables). This is already
// an overestimation, as most will delete an existing entry or
// overwrite one. Still, use a conservative safety factor of 2.
2021-05-04 07:00:25 -04:00
if ( ! CheckDiskSpace ( gArgs . GetDataDirNet ( ) , 48 * 2 * 2 * CoinsTip ( ) . GetCacheSize ( ) ) ) {
2020-05-10 05:43:30 -04:00
return AbortNode ( state , " Disk space is too low! " , _ ( " Disk space is too low! " ) ) ;
2018-09-01 19:18:02 -03:00
}
2017-07-24 11:24:12 -04:00
// Flush the chainstate (which may refer to block index entries).
2019-07-24 11:45:04 -04:00
if ( ! CoinsTip ( ) . Flush ( ) )
2017-07-24 11:24:12 -04:00
return AbortNode ( state , " Failed to write to coin database " ) ;
nLastFlush = nNow ;
2018-04-27 15:08:39 -03:00
full_flush_completed = true ;
2021-12-22 03:27:44 -03:00
TRACE5 ( utxocache , flush ,
( int64_t ) ( GetTimeMicros ( ) - nNow . count ( ) ) , // in microseconds (µs)
2022-05-12 09:44:24 -04:00
( uint32_t ) mode ,
( uint64_t ) coins_count ,
( uint64_t ) coins_mem_usage ,
2021-12-22 03:27:44 -03:00
( bool ) fFlushForPrune ) ;
Improve chainstate/blockindex disk writing policy
There are 3 pieces of data that are maintained on disk. The actual block
and undo data, the block index (which can refer to positions on disk),
and the chainstate (which refers to the best block hash).
Earlier, there was no guarantee that blocks were written to disk before
block index entries referring to them were written. This commit introduces
dirty flags for block index data, and delays writing entries until the actual
block data is flushed.
With this stricter ordering in writes, it is now safe to not always flush
after every block, so there is no need for the IsInitialBlockDownload()
check there - instead we just write whenever enough time has passed or
the cache size grows too large. Also updating the wallet's best known block
is delayed until this is done, otherwise the wallet may end up referring to an
unknown block.
In addition, only do a write inside the block processing loop if necessary
(because of cache size exceeded). Otherwise, move the writing to a point
after processing is done, after relaying.
2014-11-07 07:38:35 -03:00
}
2015-05-04 17:00:19 -03:00
}
2018-04-27 15:08:39 -03:00
if ( full_flush_completed ) {
Improve chainstate/blockindex disk writing policy
There are 3 pieces of data that are maintained on disk. The actual block
and undo data, the block index (which can refer to positions on disk),
and the chainstate (which refers to the best block hash).
Earlier, there was no guarantee that blocks were written to disk before
block index entries referring to them were written. This commit introduces
dirty flags for block index data, and delays writing entries until the actual
block data is flushed.
With this stricter ordering in writes, it is now safe to not always flush
after every block, so there is no need for the IsInitialBlockDownload()
check there - instead we just write whenever enough time has passed or
the cache size grows too large. Also updating the wallet's best known block
is delayed until this is done, otherwise the wallet may end up referring to an
unknown block.
In addition, only do a write inside the block processing loop if necessary
(because of cache size exceeded). Otherwise, move the writing to a point
after processing is done, after relaying.
2014-11-07 07:38:35 -03:00
// Update best block in wallet (so we can detect restored wallets).
2019-03-27 13:07:52 -03:00
GetMainSignals ( ) . ChainStateFlushed ( m_chain . GetLocator ( ) ) ;
2012-09-05 22:21:18 -03:00
}
2015-01-04 15:11:44 -03:00
} catch ( const std : : runtime_error & e ) {
2015-01-16 20:57:14 -03:00
return AbortNode ( state , std : : string ( " System error while flushing: " ) + e . what ( ) ) ;
2015-01-04 15:11:44 -03:00
}
2013-11-16 14:40:55 -03:00
return true ;
}
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 12:54:00 -04:00
2021-04-27 15:06:48 -04:00
void CChainState : : ForceFlushStateToDisk ( )
{
2019-10-24 12:35:42 -03:00
BlockValidationState state ;
2021-04-27 16:54:53 -04:00
if ( ! this - > FlushStateToDisk ( state , FlushStateMode : : ALWAYS ) ) {
2019-11-08 18:22:36 -03:00
LogPrintf ( " %s: failed to flush state (%s) \n " , __func__ , state . ToString ( ) ) ;
2018-04-18 10:58:13 -03:00
}
Improve chainstate/blockindex disk writing policy
There are 3 pieces of data that are maintained on disk. The actual block
and undo data, the block index (which can refer to positions on disk),
and the chainstate (which refers to the best block hash).
Earlier, there was no guarantee that blocks were written to disk before
block index entries referring to them were written. This commit introduces
dirty flags for block index data, and delays writing entries until the actual
block data is flushed.
With this stricter ordering in writes, it is now safe to not always flush
after every block, so there is no need for the IsInitialBlockDownload()
check there - instead we just write whenever enough time has passed or
the cache size grows too large. Also updating the wallet's best known block
is delayed until this is done, otherwise the wallet may end up referring to an
unknown block.
In addition, only do a write inside the block processing loop if necessary
(because of cache size exceeded). Otherwise, move the writing to a point
after processing is done, after relaying.
2014-11-07 07:38:35 -03:00
}
2021-04-27 15:06:48 -04:00
void CChainState : : PruneAndFlush ( )
{
2019-10-24 12:35:42 -03:00
BlockValidationState state ;
2022-01-05 11:44:16 -03:00
m_blockman . m_check_for_pruning = true ;
2021-04-27 16:54:53 -04:00
if ( ! this - > FlushStateToDisk ( state , FlushStateMode : : NONE ) ) {
2019-11-08 18:22:36 -03:00
LogPrintf ( " %s: failed to flush state (%s) \n " , __func__ , state . ToString ( ) ) ;
2018-04-18 10:58:13 -03:00
}
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
}
2020-06-10 05:14:32 -04:00
static void DoWarning ( const bilingual_str & warning )
2017-05-26 23:31:04 -04:00
{
static bool fWarned = false ;
2020-06-10 05:14:32 -04:00
SetMiscWarning ( warning ) ;
2017-05-26 23:31:04 -04:00
if ( ! fWarned ) {
2020-06-10 05:14:32 -04:00
AlertNotify ( warning . original ) ;
2017-05-26 23:31:04 -04:00
fWarned = true ;
}
}
2018-07-20 17:48:26 -04:00
/** Private helper function that concatenates warning messages. */
2020-06-10 05:14:32 -04:00
static void AppendWarning ( bilingual_str & res , const bilingual_str & warn )
2018-07-20 17:48:26 -04:00
{
2020-06-10 05:14:32 -04:00
if ( ! res . empty ( ) ) res + = Untranslated ( " , " ) ;
2018-07-20 17:48:26 -04:00
res + = warn ;
}
2019-09-16 17:32:18 -03:00
static void UpdateTipLog (
const CCoinsViewCache & coins_tip ,
const CBlockIndex * tip ,
const CChainParams & params ,
const std : : string & func_name ,
const std : : string & prefix ,
const std : : string & warning_messages ) EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main )
{
AssertLockHeld ( : : cs_main ) ;
LogPrintf ( " %s%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s \n " ,
prefix , func_name ,
tip - > GetBlockHash ( ) . ToString ( ) , tip - > nHeight , tip - > nVersion ,
log ( tip - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , ( unsigned long ) tip - > nChainTx ,
FormatISO8601DateTime ( tip - > GetBlockTime ( ) ) ,
GuessVerificationProgress ( params . TxData ( ) , tip ) ,
coins_tip . DynamicMemoryUsage ( ) * ( 1.0 / ( 1 < < 20 ) ) ,
coins_tip . GetCacheSize ( ) ,
! warning_messages . empty ( ) ? strprintf ( " warning='%s' " , warning_messages ) : " " ) ;
}
2021-07-09 09:34:39 -04:00
void CChainState : : UpdateTip ( const CBlockIndex * pindexNew )
2019-07-24 13:39:42 -04:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2019-09-16 17:32:18 -03:00
const auto & coins_tip = this - > CoinsTip ( ) ;
// The remainder of the function isn't relevant if we are not acting on
// the active chainstate, so return if need be.
if ( this ! = & m_chainman . ActiveChainstate ( ) ) {
// Only log every so often so that we don't bury log messages at the tip.
constexpr int BACKGROUND_LOG_INTERVAL = 2000 ;
if ( pindexNew - > nHeight % BACKGROUND_LOG_INTERVAL = = 0 ) {
UpdateTipLog ( coins_tip , pindexNew , m_params , __func__ , " [background validation] " , " " ) ;
}
return ;
}
2010-08-29 12:58:15 -04:00
// New best block
2021-07-09 09:34:39 -04:00
if ( m_mempool ) {
m_mempool - > AddTransactionsUpdated ( 1 ) ;
2021-07-06 17:05:25 -04:00
}
2012-05-13 00:43:24 -04:00
2018-03-21 01:04:27 -03:00
{
2017-11-08 19:07:40 -03:00
LOCK ( g_best_block_mutex ) ;
2018-04-04 01:53:07 -03:00
g_best_block = pindexNew - > GetBlockHash ( ) ;
g_best_block_cv . notify_all ( ) ;
2018-03-21 01:04:27 -03:00
}
2012-05-13 00:43:24 -04:00
2020-06-10 05:14:32 -04:00
bilingual_str warning_messages ;
2021-07-09 09:34:39 -04:00
if ( ! this - > IsInitialBlockDownload ( ) ) {
2017-04-25 22:31:08 -03:00
const CBlockIndex * pindex = pindexNew ;
2016-02-15 01:13:27 -03:00
for ( int bit = 0 ; bit < VERSIONBITS_NUM_BITS ; bit + + ) {
2022-04-14 16:53:19 -04:00
WarningBitsConditionChecker checker ( m_chainman , bit ) ;
2021-01-07 18:41:51 -03:00
ThresholdState state = checker . GetStateFor ( pindex , m_params . GetConsensus ( ) , warningcache . at ( bit ) ) ;
2018-03-09 11:03:40 -03:00
if ( state = = ThresholdState : : ACTIVE | | state = = ThresholdState : : LOCKED_IN ) {
2021-05-30 11:26:49 -04:00
const bilingual_str warning = strprintf ( _ ( " Unknown new rules activated (versionbit %i) " ) , bit ) ;
2018-03-09 11:03:40 -03:00
if ( state = = ThresholdState : : ACTIVE ) {
2020-06-10 05:14:32 -04:00
DoWarning ( warning ) ;
2016-02-15 01:13:27 -03:00
} else {
2020-06-10 05:14:32 -04:00
AppendWarning ( warning_messages , warning ) ;
2016-02-15 01:13:27 -03:00
}
}
}
2012-06-27 13:51:51 -04:00
}
2019-09-16 17:32:18 -03:00
UpdateTipLog ( coins_tip , pindexNew , m_params , __func__ , " " , warning_messages . original ) ;
2013-11-16 15:28:24 -03:00
}
2012-06-27 13:51:51 -04:00
2019-03-27 11:36:30 -03:00
/** Disconnect m_chain's tip.
2016-11-03 15:45:10 -03:00
* After calling , the mempool will be in an inconsistent state , with
* transactions from disconnected blocks being added to disconnectpool . You
2021-07-09 13:06:19 -04:00
* should make the mempool consistent again by calling MaybeUpdateMempoolForReorg .
2016-11-03 15:45:10 -03:00
* with cs_main held .
*
2017-08-07 01:36:37 -04:00
* If disconnectpool is nullptr , then no disconnected transactions are added to
2016-11-03 15:45:10 -03:00
* disconnectpool ( note that the caller is responsible for mempool consistency
* in any case ) .
*/
2021-04-27 16:54:53 -04:00
bool CChainState : : DisconnectTip ( BlockValidationState & state , DisconnectedBlockTransactions * disconnectpool )
2015-04-17 09:19:21 -03:00
{
2020-07-28 01:40:49 -04:00
AssertLockHeld ( cs_main ) ;
2021-07-06 17:05:25 -04:00
if ( m_mempool ) AssertLockHeld ( m_mempool - > cs ) ;
2020-07-28 01:40:49 -04:00
2019-03-27 11:36:30 -03:00
CBlockIndex * pindexDelete = m_chain . Tip ( ) ;
2013-11-16 15:28:24 -03:00
assert ( pindexDelete ) ;
// Read block from disk.
2017-03-29 22:12:42 -03:00
std : : shared_ptr < CBlock > pblock = std : : make_shared < CBlock > ( ) ;
CBlock & block = * pblock ;
2021-04-27 16:54:53 -04:00
if ( ! ReadBlockFromDisk ( block , pindexDelete , m_params . GetConsensus ( ) ) ) {
2019-01-31 17:47:25 -03:00
return error ( " DisconnectTip() : Failed to read block " ) ;
2021-04-27 16:54:53 -04:00
}
2013-11-16 15:28:24 -03:00
// Apply the block atomically to the chain state.
int64_t nStart = GetTimeMicros ( ) ;
2012-01-03 17:24:28 -03:00
{
2019-07-24 11:45:04 -04:00
CCoinsViewCache view ( & CoinsTip ( ) ) ;
2017-04-19 13:34:30 -03:00
assert ( view . GetBestBlock ( ) = = pindexDelete - > GetBlockHash ( ) ) ;
2017-04-28 20:08:39 -03:00
if ( DisconnectBlock ( block , pindexDelete , view ) ! = DISCONNECT_OK )
2015-01-08 07:44:25 -03:00
return error ( " DisconnectTip() : DisconnectBlock % s failed " , pindexDelete->GetBlockHash().ToString()) ;
2016-12-13 22:50:00 -03:00
bool flushed = view . Flush ( ) ;
assert ( flushed ) ;
2012-01-03 17:24:28 -03:00
}
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Disconnect block: %.2fms \n " , ( GetTimeMicros ( ) - nStart ) * MILLI ) ;
2021-05-13 13:13:08 -04:00
{
// Prune locks that began at or after the tip should be moved backward so they get a chance to reorg
const int max_height_first { pindexDelete - > nHeight - 1 } ;
for ( auto & prune_lock : m_blockman . m_prune_locks ) {
if ( prune_lock . second . height_first < = max_height_first ) continue ;
prune_lock . second . height_first = max_height_first ;
LogPrint ( BCLog : : PRUNE , " %s prune lock moved back to %d \n " , prune_lock . first , max_height_first ) ;
}
}
2013-11-16 15:28:24 -03:00
// Write the chain state to disk, if necessary.
2021-04-27 16:54:53 -04:00
if ( ! FlushStateToDisk ( state , FlushStateMode : : IF_NEEDED ) ) {
2013-11-16 15:28:24 -03:00
return false ;
2021-04-27 16:54:53 -04:00
}
2016-03-18 13:20:12 -03:00
2021-07-06 17:05:25 -04:00
if ( disconnectpool & & m_mempool ) {
2016-11-03 15:45:10 -03:00
// Save transactions to re-add to mempool at end of reorg
for ( auto it = block . vtx . rbegin ( ) ; it ! = block . vtx . rend ( ) ; + + it ) {
disconnectpool - > addTransaction ( * it ) ;
}
while ( disconnectpool - > DynamicMemoryUsage ( ) > MAX_DISCONNECTED_TX_POOL_SIZE * 1000 ) {
// Drop the earliest entry, and remove its children from the mempool.
auto it = disconnectpool - > queuedTx . get < insertion_order > ( ) . begin ( ) ;
2021-07-06 17:05:25 -04:00
m_mempool - > removeRecursive ( * * it , MemPoolRemovalReason : : REORG ) ;
2016-11-03 15:45:10 -03:00
disconnectpool - > removeEntry ( it ) ;
2015-07-15 15:47:45 -03:00
}
2013-11-16 15:28:24 -03:00
}
2016-03-18 13:20:12 -03:00
2019-03-27 11:36:30 -03:00
m_chain . SetTip ( pindexDelete - > pprev ) ;
2017-04-25 22:31:08 -03:00
2021-07-09 09:34:39 -04:00
UpdateTip ( pindexDelete - > pprev ) ;
2014-02-15 18:38:28 -03:00
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
2019-07-24 15:41:41 -04:00
GetMainSignals ( ) . BlockDisconnected ( pblock , pindexDelete ) ;
2013-11-16 15:28:24 -03:00
return true ;
2013-11-16 14:40:55 -03:00
}
2012-01-03 17:24:28 -03:00
2022-01-31 10:51:11 -03:00
static int64_t nTimeReadFromDiskTotal = 0 ;
2014-07-26 16:49:17 -04:00
static int64_t nTimeConnectTotal = 0 ;
static int64_t nTimeFlush = 0 ;
static int64_t nTimeChainState = 0 ;
static int64_t nTimePostConnect = 0 ;
2017-03-07 16:43:35 -03:00
struct PerBlockConnectTrace {
2017-08-07 01:36:37 -04:00
CBlockIndex * pindex = nullptr ;
2017-03-07 16:43:35 -03:00
std : : shared_ptr < const CBlock > pblock ;
2022-05-11 11:02:15 -04:00
PerBlockConnectTrace ( ) = default ;
2017-03-07 16:43:35 -03:00
} ;
2016-10-25 14:20:45 -03:00
/**
2016-11-29 19:15:12 -03:00
* Used to track blocks whose transactions were applied to the UTXO state as a
* part of a single ActivateBestChainStep call .
2017-03-06 19:19:22 -03:00
*
2017-03-07 16:43:35 -03:00
* This class is single - use , once you call GetBlocksConnected ( ) you have to throw
* it away and make a new one .
2016-10-25 14:20:45 -03:00
*/
2017-03-06 19:19:22 -03:00
class ConnectTrace {
2017-03-06 19:14:53 -03:00
private :
2017-03-07 16:43:35 -03:00
std : : vector < PerBlockConnectTrace > blocksConnected ;
2017-03-06 19:14:53 -03:00
public :
2019-11-15 17:33:27 -03:00
explicit ConnectTrace ( ) : blocksConnected ( 1 ) { }
2017-03-06 19:19:22 -03:00
2017-03-06 19:14:53 -03:00
void BlockConnected ( CBlockIndex * pindex , std : : shared_ptr < const CBlock > pblock ) {
2017-03-07 16:43:35 -03:00
assert ( ! blocksConnected . back ( ) . pindex ) ;
assert ( pindex ) ;
assert ( pblock ) ;
blocksConnected . back ( ) . pindex = pindex ;
blocksConnected . back ( ) . pblock = std : : move ( pblock ) ;
blocksConnected . emplace_back ( ) ;
}
std : : vector < PerBlockConnectTrace > & GetBlocksConnected ( ) {
// We always keep one extra block at the end of our list because
// blocks are added after all the conflicted transactions have
// been filled in. Thus, the last entry should always be an empty
// one waiting for the transactions from the next block. We pop
// the last entry here to make sure the list we return is sane.
assert ( ! blocksConnected . back ( ) . pindex ) ;
blocksConnected . pop_back ( ) ;
2017-03-06 19:14:53 -03:00
return blocksConnected ;
}
2016-10-25 14:20:45 -03:00
} ;
2015-05-31 10:36:44 -03:00
/**
2019-03-27 11:36:30 -03:00
* Connect a new block to m_chain . pblock is either nullptr or a pointer to a CBlock
2014-11-30 22:39:44 -03:00
* corresponding to pindexNew , to bypass loading it again from disk .
2016-11-30 02:25:39 -03:00
*
2017-03-06 19:11:33 -03:00
* The block is added to connectTrace if connection succeeds .
2014-11-30 22:39:44 -03:00
*/
2021-04-27 16:54:53 -04:00
bool CChainState : : ConnectTip ( BlockValidationState & state , CBlockIndex * pindexNew , const std : : shared_ptr < const CBlock > & pblock , ConnectTrace & connectTrace , DisconnectedBlockTransactions & disconnectpool )
2015-04-17 09:40:24 -03:00
{
2020-07-28 01:40:49 -04:00
AssertLockHeld ( cs_main ) ;
2021-07-06 17:05:25 -04:00
if ( m_mempool ) AssertLockHeld ( m_mempool - > cs ) ;
2020-07-28 01:40:49 -04:00
2019-03-27 11:36:30 -03:00
assert ( pindexNew - > pprev = = m_chain . Tip ( ) ) ;
2013-11-16 15:28:24 -03:00
// Read block from disk.
2014-07-26 16:49:17 -04:00
int64_t nTime1 = GetTimeMicros ( ) ;
2017-03-06 19:11:33 -03:00
std : : shared_ptr < const CBlock > pthisBlock ;
2014-08-25 20:26:41 -04:00
if ( ! pblock ) {
2016-10-15 13:12:50 -03:00
std : : shared_ptr < CBlock > pblockNew = std : : make_shared < CBlock > ( ) ;
2021-04-27 16:54:53 -04:00
if ( ! ReadBlockFromDisk ( * pblockNew , pindexNew , m_params . GetConsensus ( ) ) ) {
2015-01-16 20:57:14 -03:00
return AbortNode ( state , " Failed to read block " ) ;
2021-04-27 16:54:53 -04:00
}
2017-03-06 19:11:33 -03:00
pthisBlock = pblockNew ;
2016-10-15 13:12:50 -03:00
} else {
2022-01-31 10:51:11 -03:00
LogPrint ( BCLog : : BENCH , " - Using cached block \n " ) ;
2017-03-06 19:11:33 -03:00
pthisBlock = pblock ;
2014-08-25 20:26:41 -04:00
}
2017-03-06 19:11:33 -03:00
const CBlock & blockConnecting = * pthisBlock ;
2013-11-16 15:28:24 -03:00
// Apply the block atomically to the chain state.
2022-01-31 10:51:11 -03:00
int64_t nTime2 = GetTimeMicros ( ) ; nTimeReadFromDiskTotal + = nTime2 - nTime1 ;
2014-07-26 16:49:17 -04:00
int64_t nTime3 ;
2022-01-31 10:51:11 -03:00
LogPrint ( BCLog : : BENCH , " - Load block from disk: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime2 - nTime1 ) * MILLI , nTimeReadFromDiskTotal * MICRO , nTimeReadFromDiskTotal * MILLI / nBlocksTotal ) ;
2010-08-29 12:58:15 -04:00
{
2019-07-24 11:45:04 -04:00
CCoinsViewCache view ( & CoinsTip ( ) ) ;
2021-04-27 16:54:53 -04:00
bool rv = ConnectBlock ( blockConnecting , state , pindexNew , view ) ;
2016-10-25 15:22:41 -03:00
GetMainSignals ( ) . BlockChecked ( blockConnecting , state ) ;
2014-10-20 00:55:04 -03:00
if ( ! rv ) {
2013-11-16 15:28:24 -03:00
if ( state . IsInvalid ( ) )
InvalidBlockFound ( pindexNew , state ) ;
2019-11-08 18:22:36 -03:00
return error ( " %s: ConnectBlock %s failed, %s " , __func__ , pindexNew - > GetBlockHash ( ) . ToString ( ) , state . ToString ( ) ) ;
2013-01-26 21:24:06 -03:00
}
2014-07-26 16:49:17 -04:00
nTime3 = GetTimeMicros ( ) ; nTimeConnectTotal + = nTime3 - nTime2 ;
2019-01-29 10:03:53 -03:00
assert ( nBlocksTotal > 0 ) ;
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Connect total: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime3 - nTime2 ) * MILLI , nTimeConnectTotal * MICRO , nTimeConnectTotal * MILLI / nBlocksTotal ) ;
2016-12-13 22:50:00 -03:00
bool flushed = view . Flush ( ) ;
assert ( flushed ) ;
2010-08-29 12:58:15 -04:00
}
2014-07-26 16:49:17 -04:00
int64_t nTime4 = GetTimeMicros ( ) ; nTimeFlush + = nTime4 - nTime3 ;
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Flush: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime4 - nTime3 ) * MILLI , nTimeFlush * MICRO , nTimeFlush * MILLI / nBlocksTotal ) ;
2013-11-16 15:28:24 -03:00
// Write the chain state to disk, if necessary.
2021-04-27 16:54:53 -04:00
if ( ! FlushStateToDisk ( state , FlushStateMode : : IF_NEEDED ) ) {
2013-11-16 15:28:24 -03:00
return false ;
2021-04-27 16:54:53 -04:00
}
2014-07-26 16:49:17 -04:00
int64_t nTime5 = GetTimeMicros ( ) ; nTimeChainState + = nTime5 - nTime4 ;
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime5 - nTime4 ) * MILLI , nTimeChainState * MICRO , nTimeChainState * MILLI / nBlocksTotal ) ;
2016-04-26 08:55:13 -03:00
// Remove conflicting transactions from the mempool.;
2021-07-06 17:05:25 -04:00
if ( m_mempool ) {
m_mempool - > removeForBlock ( blockConnecting . vtx , pindexNew - > nHeight ) ;
disconnectpool . removeForBlock ( blockConnecting . vtx ) ;
}
2019-03-27 11:36:30 -03:00
// Update m_chain & related variables.
m_chain . SetTip ( pindexNew ) ;
2021-07-09 09:34:39 -04:00
UpdateTip ( pindexNew ) ;
2016-04-26 08:55:13 -03:00
2014-07-26 16:49:17 -04:00
int64_t nTime6 = GetTimeMicros ( ) ; nTimePostConnect + = nTime6 - nTime5 ; nTimeTotal + = nTime6 - nTime1 ;
2017-05-31 22:42:34 -04:00
LogPrint ( BCLog : : BENCH , " - Connect postprocess: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime6 - nTime5 ) * MILLI , nTimePostConnect * MICRO , nTimePostConnect * MILLI / nBlocksTotal ) ;
LogPrint ( BCLog : : BENCH , " - Connect block: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime6 - nTime1 ) * MILLI , nTimeTotal * MICRO , nTimeTotal * MILLI / nBlocksTotal ) ;
2017-03-06 19:11:33 -03:00
2017-03-06 19:14:53 -03:00
connectTrace . BlockConnected ( pindexNew , std : : move ( pthisBlock ) ) ;
2010-08-29 12:58:15 -04:00
return true ;
}
2014-11-30 22:39:44 -03:00
/**
* Return the tip of the chain with the most work in it , that isn ' t
* known to be invalid ( it ' s however far from certain to be valid ) .
*/
2022-01-27 07:48:19 -03:00
CBlockIndex * CChainState : : FindMostWorkChain ( )
{
AssertLockHeld ( : : cs_main ) ;
2013-11-16 15:28:24 -03:00
do {
2017-08-07 01:36:37 -04:00
CBlockIndex * pindexNew = nullptr ;
2014-05-05 18:54:10 -04:00
2013-11-16 15:28:24 -03:00
// Find the best candidate header.
{
2014-10-06 03:31:33 -03:00
std : : set < CBlockIndex * , CBlockIndexWorkComparator > : : reverse_iterator it = setBlockIndexCandidates . rbegin ( ) ;
if ( it = = setBlockIndexCandidates . rend ( ) )
2017-08-07 01:36:37 -04:00
return nullptr ;
2013-11-16 15:28:24 -03:00
pindexNew = * it ;
}
// Check whether all blocks on the path between the currently active chain and the candidate are valid.
// Just going until the active chain is an optimization, as we know all blocks in it are valid already.
CBlockIndex * pindexTest = pindexNew ;
bool fInvalidAncestor = false ;
2019-03-27 11:36:30 -03:00
while ( pindexTest & & ! m_chain . Contains ( pindexTest ) ) {
2018-12-03 20:14:08 -03:00
assert ( pindexTest - > HaveTxsDownloaded ( ) | | pindexTest - > nHeight = = 0 ) ;
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// Pruned nodes may have entries in setBlockIndexCandidates for
// which block files have been deleted. Remove those as candidates
// for the most work chain if we come across them; we can't switch
// to a chain unless we have all the non-active-chain parent blocks.
bool fFailedChain = pindexTest - > nStatus & BLOCK_FAILED_MASK ;
bool fMissingData = ! ( pindexTest - > nStatus & BLOCK_HAVE_DATA ) ;
if ( fFailedChain | | fMissingData ) {
// Candidate chain is not usable (either invalid or missing data)
2021-11-23 15:49:48 -03:00
if ( fFailedChain & & ( m_chainman . m_best_invalid = = nullptr | | pindexNew - > nChainWork > m_chainman . m_best_invalid - > nChainWork ) ) {
m_chainman . m_best_invalid = pindexNew ;
}
2014-03-12 23:48:27 -03:00
CBlockIndex * pindexFailed = pindexNew ;
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// Remove the entire chain from the set.
2013-11-16 15:28:24 -03:00
while ( pindexTest ! = pindexFailed ) {
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
if ( fFailedChain ) {
pindexFailed - > nStatus | = BLOCK_FAILED_CHILD ;
} else if ( fMissingData ) {
2019-03-27 18:07:32 -03:00
// If we're missing data, then add back to m_blocks_unlinked,
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// so that if the block arrives in the future we can try adding
// to setBlockIndexCandidates again.
2019-03-27 18:07:32 -03:00
m_blockman . m_blocks_unlinked . insert (
std : : make_pair ( pindexFailed - > pprev , pindexFailed ) ) ;
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
}
2014-10-06 03:31:33 -03:00
setBlockIndexCandidates . erase ( pindexFailed ) ;
2013-11-16 15:28:24 -03:00
pindexFailed = pindexFailed - > pprev ;
}
2014-10-06 03:31:33 -03:00
setBlockIndexCandidates . erase ( pindexTest ) ;
2013-11-16 15:28:24 -03:00
fInvalidAncestor = true ;
break ;
2013-01-26 20:14:11 -03:00
}
2013-11-16 15:28:24 -03:00
pindexTest = pindexTest - > pprev ;
2010-08-29 12:58:15 -04:00
}
2014-05-05 18:54:10 -04:00
if ( ! fInvalidAncestor )
return pindexNew ;
2013-11-16 15:28:24 -03:00
} while ( true ) ;
}
2010-08-29 12:58:15 -04:00
2014-11-30 22:39:44 -03:00
/** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
2017-12-04 11:34:46 -03:00
void CChainState : : PruneBlockIndexCandidates ( ) {
2014-11-01 18:42:12 -03:00
// Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails.
std : : set < CBlockIndex * , CBlockIndexWorkComparator > : : iterator it = setBlockIndexCandidates . begin ( ) ;
2019-03-27 11:36:30 -03:00
while ( it ! = setBlockIndexCandidates . end ( ) & & setBlockIndexCandidates . value_comp ( ) ( * it , m_chain . Tip ( ) ) ) {
2014-11-01 18:42:12 -03:00
setBlockIndexCandidates . erase ( it + + ) ;
}
2014-11-20 08:43:50 -03:00
// Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
assert ( ! setBlockIndexCandidates . empty ( ) ) ;
2014-11-01 18:42:12 -03:00
}
2014-11-30 22:39:44 -03:00
/**
* Try to make some progress towards making pindexMostWork the active block .
2017-08-07 01:36:37 -04:00
* pblock is either nullptr or a pointer to a CBlock corresponding to pindexMostWork .
2019-08-29 12:42:00 -04:00
*
* @ returns true unless a system error occurred
2014-11-30 22:39:44 -03:00
*/
2021-04-27 16:54:53 -04:00
bool CChainState : : ActivateBestChainStep ( BlockValidationState & state , CBlockIndex * pindexMostWork , const std : : shared_ptr < const CBlock > & pblock , bool & fInvalidFound , ConnectTrace & connectTrace )
2015-04-17 09:40:24 -03:00
{
2014-05-05 19:23:13 -04:00
AssertLockHeld ( cs_main ) ;
2021-07-06 17:05:25 -04:00
if ( m_mempool ) AssertLockHeld ( m_mempool - > cs ) ;
2018-05-10 16:57:16 -03:00
2020-10-28 07:08:01 -03:00
const CBlockIndex * pindexOldTip = m_chain . Tip ( ) ;
const CBlockIndex * pindexFork = m_chain . FindFork ( pindexMostWork ) ;
2010-08-29 12:58:15 -04:00
2014-05-05 19:23:13 -04:00
// Disconnect active blocks which are no longer in the best chain.
2015-10-02 18:20:38 -03:00
bool fBlocksDisconnected = false ;
2016-11-03 15:45:10 -03:00
DisconnectedBlockTransactions disconnectpool ;
2019-03-27 11:36:30 -03:00
while ( m_chain . Tip ( ) & & m_chain . Tip ( ) ! = pindexFork ) {
2021-04-27 16:54:53 -04:00
if ( ! DisconnectTip ( state , & disconnectpool ) ) {
2016-11-03 15:45:10 -03:00
// This is likely a fatal error, but keep the mempool consistent,
// just in case. Only remove from the mempool in this case.
2021-07-09 13:06:19 -04:00
MaybeUpdateMempoolForReorg ( disconnectpool , false ) ;
2019-01-31 17:47:25 -03:00
// If we're unable to disconnect a block during normal operation,
// then that is a failure of our local system -- we should abort
// rather than stay on a less work chain.
AbortNode ( state , " Failed to disconnect block; see debug.log for details " ) ;
2014-05-05 19:23:13 -04:00
return false ;
2016-11-03 15:45:10 -03:00
}
2015-10-02 18:20:38 -03:00
fBlocksDisconnected = true ;
2014-05-05 19:23:13 -04:00
}
2013-11-16 15:28:24 -03:00
2020-10-28 07:08:01 -03:00
// Build list of new blocks to connect (in descending height order).
2014-05-05 19:23:13 -04:00
std : : vector < CBlockIndex * > vpindexToConnect ;
2014-10-10 17:13:47 -03:00
bool fContinue = true ;
int nHeight = pindexFork ? pindexFork - > nHeight : - 1 ;
while ( fContinue & & nHeight ! = pindexMostWork - > nHeight ) {
2015-09-09 18:54:11 -03:00
// Don't iterate the entire list of potential improvements toward the best tip, as we likely only need
// a few blocks along the way.
int nTargetHeight = std : : min ( nHeight + 32 , pindexMostWork - > nHeight ) ;
vpindexToConnect . clear ( ) ;
vpindexToConnect . reserve ( nTargetHeight - nHeight ) ;
2020-10-28 07:08:01 -03:00
CBlockIndex * pindexIter = pindexMostWork - > GetAncestor ( nTargetHeight ) ;
2015-09-09 18:54:11 -03:00
while ( pindexIter & & pindexIter - > nHeight ! = nHeight ) {
vpindexToConnect . push_back ( pindexIter ) ;
pindexIter = pindexIter - > pprev ;
}
nHeight = nTargetHeight ;
// Connect new blocks.
2020-10-28 07:08:01 -03:00
for ( CBlockIndex * pindexConnect : reverse_iterate ( vpindexToConnect ) ) {
2021-04-27 16:54:53 -04:00
if ( ! ConnectTip ( state , pindexConnect , pindexConnect = = pindexMostWork ? pblock : std : : shared_ptr < const CBlock > ( ) , connectTrace , disconnectpool ) ) {
2015-09-09 18:54:11 -03:00
if ( state . IsInvalid ( ) ) {
// The block violates a consensus rule.
2019-10-24 12:35:42 -03:00
if ( state . GetResult ( ) ! = BlockValidationResult : : BLOCK_MUTATED ) {
2018-05-07 15:18:27 -03:00
InvalidChainFound ( vpindexToConnect . front ( ) ) ;
}
2019-10-24 12:35:42 -03:00
state = BlockValidationState ( ) ;
2015-09-09 18:54:11 -03:00
fInvalidFound = true ;
fContinue = false ;
break ;
} else {
// A system error occurred (disk space, database error, ...).
2016-11-03 15:45:10 -03:00
// Make the mempool consistent with the current tip, just in case
// any observers try to use it before shutdown.
2021-07-09 13:06:19 -04:00
MaybeUpdateMempoolForReorg ( disconnectpool , false ) ;
2015-09-09 18:54:11 -03:00
return false ;
}
2014-05-05 19:23:13 -04:00
} else {
2015-09-09 18:54:11 -03:00
PruneBlockIndexCandidates ( ) ;
2019-03-27 11:36:30 -03:00
if ( ! pindexOldTip | | m_chain . Tip ( ) - > nChainWork > pindexOldTip - > nChainWork ) {
2015-09-09 18:54:11 -03:00
// We're in a better position than we were. Return temporarily to release the lock.
fContinue = false ;
break ;
}
2013-11-16 15:28:24 -03:00
}
}
2012-11-24 10:26:51 -03:00
}
2010-08-29 12:58:15 -04:00
2015-09-09 20:31:20 -03:00
if ( fBlocksDisconnected ) {
2016-11-03 15:45:10 -03:00
// If any blocks were disconnected, disconnectpool may be non empty. Add
// any disconnected transactions back to the mempool.
2021-07-09 13:06:19 -04:00
MaybeUpdateMempoolForReorg ( disconnectpool , true ) ;
2015-09-09 20:31:20 -03:00
}
2021-09-29 15:36:01 -03:00
if ( m_mempool ) m_mempool - > check ( this - > CoinsTip ( ) , this - > m_chain . Height ( ) + 1 ) ;
2015-10-02 18:20:38 -03:00
2020-09-07 02:58:42 -03:00
CheckForkWarningConditions ( ) ;
2014-05-07 10:45:33 -04:00
2010-08-29 12:58:15 -04:00
return true ;
}
2020-03-04 15:05:42 -03:00
static SynchronizationState GetSynchronizationState ( bool init )
{
if ( ! init ) return SynchronizationState : : POST_INIT ;
if ( : : fReindex ) return SynchronizationState : : INIT_REINDEX ;
return SynchronizationState : : INIT_DOWNLOAD ;
}
2020-09-15 17:06:45 -03:00
static bool NotifyHeaderTip ( CChainState & chainstate ) LOCKS_EXCLUDED ( cs_main ) {
2016-04-28 11:18:45 -03:00
bool fNotify = false ;
bool fInitialBlockDownload = false ;
2017-08-07 01:36:37 -04:00
static CBlockIndex * pindexHeaderOld = nullptr ;
CBlockIndex * pindexHeader = nullptr ;
2016-04-28 11:18:45 -03:00
{
LOCK ( cs_main ) ;
2022-03-18 13:35:52 -03:00
pindexHeader = chainstate . m_chainman . m_best_header ;
2016-10-20 13:53:05 -03:00
2016-04-28 11:18:45 -03:00
if ( pindexHeader ! = pindexHeaderOld ) {
fNotify = true ;
2020-09-15 17:06:45 -03:00
fInitialBlockDownload = chainstate . IsInitialBlockDownload ( ) ;
2016-04-28 11:18:45 -03:00
pindexHeaderOld = pindexHeader ;
}
}
// Send block tip changed notifications without cs_main
if ( fNotify ) {
2020-03-04 15:05:42 -03:00
uiInterface . NotifyHeaderTip ( GetSynchronizationState ( fInitialBlockDownload ) , pindexHeader ) ;
2016-04-28 11:18:45 -03:00
}
2019-08-31 15:59:04 -04:00
return fNotify ;
2016-04-28 11:18:45 -03:00
}
2019-05-07 04:07:09 -04:00
static void LimitValidationInterfaceQueue ( ) LOCKS_EXCLUDED ( cs_main ) {
2019-02-13 22:17:59 -03:00
AssertLockNotHeld ( cs_main ) ;
if ( GetMainSignals ( ) . CallbacksPending ( ) > 10 ) {
SyncWithValidationInterfaceQueue ( ) ;
}
}
2021-04-27 16:54:53 -04:00
bool CChainState : : ActivateBestChain ( BlockValidationState & state , std : : shared_ptr < const CBlock > pblock )
{
2022-01-19 18:47:54 -03:00
AssertLockNotHeld ( m_chainstate_mutex ) ;
2017-01-12 17:15:17 -03:00
// Note that while we're often called here from ProcessNewBlock, this is
// far from a guarantee. Things in the P2P/RPC will often end up calling
// us in the middle of ProcessNewBlock - do not assume pblock is set
// sanely for performance or correctness!
2022-01-27 07:48:19 -03:00
AssertLockNotHeld ( : : cs_main ) ;
2017-01-12 17:15:17 -03:00
2018-05-10 16:57:16 -03:00
// ABC maintains a fair degree of expensive-to-calculate internal state
// because this function periodically releases cs_main so that it does not lock up other threads for too long
// during large connects - and to allow for e.g. the callback queue to drain
2022-01-19 14:43:15 -03:00
// we use m_chainstate_mutex to enforce mutual exclusion so that only one caller may execute this function at a time
LOCK ( m_chainstate_mutex ) ;
2018-05-10 16:57:16 -03:00
2017-08-07 01:36:37 -04:00
CBlockIndex * pindexMostWork = nullptr ;
CBlockIndex * pindexNewTip = nullptr ;
2019-08-22 21:40:41 -04:00
int nStopAtHeight = gArgs . GetIntArg ( " -stopatheight " , DEFAULT_STOPATHEIGHT ) ;
2014-05-05 19:23:13 -04:00
do {
2019-02-13 22:17:59 -03:00
// Block until the validation queue drains. This should largely
// never happen in normal operation, however may happen during
// reindex, causing memory blowup if we run too far ahead.
// Note that if a validationinterface callback ends up calling
// ActivateBestChain this may lead to a deadlock! We should
// probably have a DEBUG_LOCKORDER test for this in the future.
LimitValidationInterfaceQueue ( ) ;
2017-12-04 20:57:55 -03:00
2014-05-07 10:45:33 -04:00
{
2020-07-28 01:40:49 -04:00
LOCK ( cs_main ) ;
2021-07-06 17:05:25 -04:00
// Lock transaction pool for at least as long as it takes for connectTrace to be consumed
LOCK ( MempoolMutex ( ) ) ;
2019-03-27 11:36:30 -03:00
CBlockIndex * starting_tip = m_chain . Tip ( ) ;
2017-10-09 12:19:10 -03:00
bool blocks_connected = false ;
do {
// We absolutely may not unlock cs_main until we've made forward progress
// (with the exception of shutdown due to hardware issues, low disk space, etc).
2019-11-15 17:33:27 -03:00
ConnectTrace connectTrace ; // Destructed before cs_main is unlocked
2017-10-09 12:19:10 -03:00
if ( pindexMostWork = = nullptr ) {
pindexMostWork = FindMostWorkChain ( ) ;
}
2017-03-06 19:19:22 -03:00
2017-10-09 12:19:10 -03:00
// Whether we have anything to do at all.
2019-03-27 11:36:30 -03:00
if ( pindexMostWork = = nullptr | | pindexMostWork = = m_chain . Tip ( ) ) {
2017-10-09 12:19:10 -03:00
break ;
}
2014-05-05 19:23:13 -04:00
2017-10-09 12:19:10 -03:00
bool fInvalidFound = false ;
std : : shared_ptr < const CBlock > nullBlockPtr ;
2021-04-27 16:54:53 -04:00
if ( ! ActivateBestChainStep ( state , pindexMostWork , pblock & & pblock - > GetHash ( ) = = pindexMostWork - > GetBlockHash ( ) ? pblock : nullBlockPtr , fInvalidFound , connectTrace ) ) {
2019-08-29 12:42:00 -04:00
// A system error occurred
2017-10-09 12:19:10 -03:00
return false ;
2019-08-29 12:42:00 -04:00
}
2017-10-09 12:19:10 -03:00
blocks_connected = true ;
2014-05-05 19:23:13 -04:00
2017-10-09 12:19:10 -03:00
if ( fInvalidFound ) {
// Wipe cache, we may need another branch now.
pindexMostWork = nullptr ;
}
2019-03-27 11:36:30 -03:00
pindexNewTip = m_chain . Tip ( ) ;
2014-05-05 19:23:13 -04:00
2017-10-09 12:19:10 -03:00
for ( const PerBlockConnectTrace & trace : connectTrace . GetBlocksConnected ( ) ) {
assert ( trace . pblock & & trace . pindex ) ;
2019-11-11 12:43:34 -03:00
GetMainSignals ( ) . BlockConnected ( trace . pblock , trace . pindex ) ;
2017-10-09 12:19:10 -03:00
}
2019-03-27 11:36:30 -03:00
} while ( ! m_chain . Tip ( ) | | ( starting_tip & & CBlockIndexWorkComparator ( ) ( m_chain . Tip ( ) , starting_tip ) ) ) ;
2017-10-09 12:19:10 -03:00
if ( ! blocks_connected ) return true ;
2017-01-19 13:03:36 -03:00
2019-03-27 11:36:30 -03:00
const CBlockIndex * pindexFork = m_chain . FindFork ( starting_tip ) ;
2017-10-09 12:19:10 -03:00
bool fInitialDownload = IsInitialBlockDownload ( ) ;
2014-05-07 10:45:33 -04:00
2018-04-15 12:22:28 -03:00
// Notify external listeners about the new tip.
// Enqueue while holding cs_main to ensure that UpdatedBlockTip is called in the order in which blocks are connected
if ( pindexFork ! = pindexNewTip ) {
2017-10-09 12:19:10 -03:00
// Notify ValidationInterface subscribers
GetMainSignals ( ) . UpdatedBlockTip ( pindexNewTip , pindexFork , fInitialDownload ) ;
// Always notify the UI if a new block tip was connected
2020-03-04 15:05:42 -03:00
uiInterface . NotifyBlockTip ( GetSynchronizationState ( fInitialDownload ) , pindexNewTip ) ;
2018-04-15 12:22:28 -03:00
}
2014-05-07 10:45:33 -04:00
}
2018-04-15 12:22:28 -03:00
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
2017-06-09 14:38:30 -04:00
if ( nStopAtHeight & & pindexNewTip & & pindexNewTip - > nHeight > = nStopAtHeight ) StartShutdown ( ) ;
2018-02-06 15:38:54 -03:00
// We check shutdown only after giving ActivateBestChainStep a chance to run once so that we
// never shutdown before connecting the genesis block during LoadChainTip(). Previously this
// caused an assert() failure during shutdown in such cases as the UTXO DB flushing checks
// that the best block hash is non-null.
2020-06-02 13:33:52 -04:00
if ( ShutdownRequested ( ) ) break ;
2016-04-25 16:31:32 -03:00
} while ( pindexNewTip ! = pindexMostWork ) ;
2021-04-27 16:54:53 -04:00
CheckBlockIndex ( ) ;
2014-05-05 19:23:13 -04:00
Improve chainstate/blockindex disk writing policy
There are 3 pieces of data that are maintained on disk. The actual block
and undo data, the block index (which can refer to positions on disk),
and the chainstate (which refers to the best block hash).
Earlier, there was no guarantee that blocks were written to disk before
block index entries referring to them were written. This commit introduces
dirty flags for block index data, and delays writing entries until the actual
block data is flushed.
With this stricter ordering in writes, it is now safe to not always flush
after every block, so there is no need for the IsInitialBlockDownload()
check there - instead we just write whenever enough time has passed or
the cache size grows too large. Also updating the wallet's best known block
is delayed until this is done, otherwise the wallet may end up referring to an
unknown block.
In addition, only do a write inside the block processing loop if necessary
(because of cache size exceeded). Otherwise, move the writing to a point
after processing is done, after relaying.
2014-11-07 07:38:35 -03:00
// Write changes periodically to disk, after relay.
2021-04-27 16:54:53 -04:00
if ( ! FlushStateToDisk ( state , FlushStateMode : : PERIODIC ) ) {
Improve chainstate/blockindex disk writing policy
There are 3 pieces of data that are maintained on disk. The actual block
and undo data, the block index (which can refer to positions on disk),
and the chainstate (which refers to the best block hash).
Earlier, there was no guarantee that blocks were written to disk before
block index entries referring to them were written. This commit introduces
dirty flags for block index data, and delays writing entries until the actual
block data is flushed.
With this stricter ordering in writes, it is now safe to not always flush
after every block, so there is no need for the IsInitialBlockDownload()
check there - instead we just write whenever enough time has passed or
the cache size grows too large. Also updating the wallet's best known block
is delayed until this is done, otherwise the wallet may end up referring to an
unknown block.
In addition, only do a write inside the block processing loop if necessary
(because of cache size exceeded). Otherwise, move the writing to a point
after processing is done, after relaying.
2014-11-07 07:38:35 -03:00
return false ;
}
2014-05-05 19:23:13 -04:00
return true ;
}
2017-10-09 12:19:10 -03:00
2021-04-27 16:54:53 -04:00
bool CChainState : : PreciousBlock ( BlockValidationState & state , CBlockIndex * pindex )
2016-08-26 18:05:09 -03:00
{
2022-01-27 07:48:19 -03:00
AssertLockNotHeld ( m_chainstate_mutex ) ;
AssertLockNotHeld ( : : cs_main ) ;
2016-08-26 18:05:09 -03:00
{
LOCK ( cs_main ) ;
2019-03-27 11:36:30 -03:00
if ( pindex - > nChainWork < m_chain . Tip ( ) - > nChainWork ) {
2016-08-26 18:05:09 -03:00
// Nothing to do, this block is not at the tip.
return true ;
}
2019-03-27 11:36:30 -03:00
if ( m_chain . Tip ( ) - > nChainWork > nLastPreciousChainwork ) {
2016-08-26 18:05:09 -03:00
// The chain has been extended since the last call, reset the counter.
nBlockReverseSequenceId = - 1 ;
}
2019-03-27 11:36:30 -03:00
nLastPreciousChainwork = m_chain . Tip ( ) - > nChainWork ;
2016-08-26 18:05:09 -03:00
setBlockIndexCandidates . erase ( pindex ) ;
pindex - > nSequenceId = nBlockReverseSequenceId ;
if ( nBlockReverseSequenceId > std : : numeric_limits < int32_t > : : min ( ) ) {
// We can't keep reducing the counter if somebody really wants to
// call preciousblock 2**31-1 times on the same set of tips...
nBlockReverseSequenceId - - ;
}
2018-12-03 20:14:08 -03:00
if ( pindex - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & & pindex - > HaveTxsDownloaded ( ) ) {
2016-08-26 18:05:09 -03:00
setBlockIndexCandidates . insert ( pindex ) ;
PruneBlockIndexCandidates ( ) ;
}
}
2021-04-27 16:54:53 -04:00
return ActivateBestChain ( state , std : : shared_ptr < const CBlock > ( ) ) ;
2017-12-04 11:34:46 -03:00
}
2016-08-26 18:05:09 -03:00
2021-04-27 16:54:53 -04:00
bool CChainState : : InvalidateBlock ( BlockValidationState & state , CBlockIndex * pindex )
2015-04-17 09:19:21 -03:00
{
2022-01-19 18:47:54 -03:00
AssertLockNotHeld ( m_chainstate_mutex ) ;
2022-01-27 07:48:19 -03:00
AssertLockNotHeld ( : : cs_main ) ;
2022-01-19 18:47:54 -03:00
2021-01-12 19:52:06 -03:00
// Genesis block can't be invalidated
assert ( pindex ) ;
if ( pindex - > nHeight = = 0 ) return false ;
2019-02-13 21:37:30 -03:00
CBlockIndex * to_mark_failed = pindex ;
2017-10-19 17:55:31 -03:00
bool pindex_was_in_chain = false ;
2019-02-13 23:07:16 -03:00
int disconnected = 0 ;
2014-11-19 05:39:42 -03:00
2019-09-10 14:58:41 -03:00
// We do not allow ActivateBestChain() to run while InvalidateBlock() is
// running, as that could cause the tip to change while we disconnect
// blocks.
2022-01-19 14:43:15 -03:00
LOCK ( m_chainstate_mutex ) ;
2019-09-10 14:58:41 -03:00
// We'll be acquiring and releasing cs_main below, to allow the validation
// callbacks to run. However, we should keep the block index in a
// consistent state as we disconnect blocks -- in particular we need to
// add equal-work blocks to setBlockIndexCandidates as we disconnect.
// To avoid walking the block index repeatedly in search of candidates,
// build a map once so that we can look up candidate blocks by chain
// work as we go.
std : : multimap < const arith_uint256 , CBlockIndex * > candidate_blocks_by_work ;
{
LOCK ( cs_main ) ;
2021-01-08 20:56:48 -03:00
for ( auto & entry : m_blockman . m_block_index ) {
CBlockIndex * candidate = & entry . second ;
2019-09-10 14:58:41 -03:00
// We don't need to put anything in our active chain into the
// multimap, because those candidates will be found and considered
// as we disconnect.
// Instead, consider only non-active-chain blocks that have at
// least as much work as where we expect the new tip to end up.
if ( ! m_chain . Contains ( candidate ) & &
! CBlockIndexWorkComparator ( ) ( candidate , pindex - > pprev ) & &
candidate - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & &
candidate - > HaveTxsDownloaded ( ) ) {
candidate_blocks_by_work . insert ( std : : make_pair ( candidate - > nChainWork , candidate ) ) ;
}
}
}
2019-02-13 21:37:30 -03:00
// Disconnect (descendants of) pindex, and mark them invalid.
while ( true ) {
if ( ShutdownRequested ( ) ) break ;
2017-10-19 17:55:31 -03:00
2019-02-13 22:17:59 -03:00
// Make sure the queue of validation callbacks doesn't grow unboundedly.
LimitValidationInterfaceQueue ( ) ;
2014-11-19 05:39:42 -03:00
2019-02-13 21:37:30 -03:00
LOCK ( cs_main ) ;
2021-07-09 13:06:19 -04:00
// Lock for as long as disconnectpool is in scope to make sure MaybeUpdateMempoolForReorg is
2021-07-06 17:05:25 -04:00
// called after DisconnectTip without unlocking in between
LOCK ( MempoolMutex ( ) ) ;
2019-03-27 11:36:30 -03:00
if ( ! m_chain . Contains ( pindex ) ) break ;
2017-10-19 17:55:31 -03:00
pindex_was_in_chain = true ;
2019-03-27 11:36:30 -03:00
CBlockIndex * invalid_walk_tip = m_chain . Tip ( ) ;
2019-02-13 21:37:30 -03:00
2019-03-27 11:36:30 -03:00
// ActivateBestChain considers blocks already in m_chain
2014-11-19 05:39:42 -03:00
// unconditionally valid already, so force disconnect away from it.
2019-02-13 21:37:30 -03:00
DisconnectedBlockTransactions disconnectpool ;
2021-04-27 16:54:53 -04:00
bool ret = DisconnectTip ( state , & disconnectpool ) ;
2019-02-13 21:37:30 -03:00
// DisconnectTip will add transactions to disconnectpool.
// Adjust the mempool to be consistent with the new tip, adding
2019-03-22 14:21:58 -03:00
// transactions back to the mempool if disconnecting was successful,
2019-02-13 23:07:16 -03:00
// and we're not doing a very deep invalidation (in which case
// keeping the mempool up to date is probably futile anyway).
2021-07-09 13:06:19 -04:00
MaybeUpdateMempoolForReorg ( disconnectpool , /* fAddToMempool = */ ( + + disconnected < = 10 ) & & ret ) ;
2019-02-13 21:37:30 -03:00
if ( ! ret ) return false ;
2019-03-27 11:36:30 -03:00
assert ( invalid_walk_tip - > pprev = = m_chain . Tip ( ) ) ;
2019-02-13 21:37:30 -03:00
// We immediately mark the disconnected blocks as invalid.
// This prevents a case where pruned nodes may fail to invalidateblock
// and be left unable to start as they have no tip candidates (as there
// are no blocks that meet the "have data and are not invalid per
// nStatus" criteria for inclusion in setBlockIndexCandidates).
2019-03-03 18:01:26 -03:00
invalid_walk_tip - > nStatus | = BLOCK_FAILED_VALID ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( invalid_walk_tip ) ;
2017-10-19 17:55:31 -03:00
setBlockIndexCandidates . erase ( invalid_walk_tip ) ;
2019-02-13 21:37:30 -03:00
setBlockIndexCandidates . insert ( invalid_walk_tip - > pprev ) ;
2019-03-03 18:01:26 -03:00
if ( invalid_walk_tip - > pprev = = to_mark_failed & & ( to_mark_failed - > nStatus & BLOCK_FAILED_VALID ) ) {
// We only want to mark the last disconnected block as BLOCK_FAILED_VALID; its children
// need to be BLOCK_FAILED_CHILD instead.
to_mark_failed - > nStatus = ( to_mark_failed - > nStatus ^ BLOCK_FAILED_VALID ) | BLOCK_FAILED_CHILD ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( to_mark_failed ) ;
2019-03-03 18:01:26 -03:00
}
2017-10-19 17:55:31 -03:00
2019-09-10 14:58:41 -03:00
// Add any equal or more work headers to setBlockIndexCandidates
auto candidate_it = candidate_blocks_by_work . lower_bound ( invalid_walk_tip - > pprev - > nChainWork ) ;
while ( candidate_it ! = candidate_blocks_by_work . end ( ) ) {
if ( ! CBlockIndexWorkComparator ( ) ( candidate_it - > second , invalid_walk_tip - > pprev ) ) {
setBlockIndexCandidates . insert ( candidate_it - > second ) ;
candidate_it = candidate_blocks_by_work . erase ( candidate_it ) ;
} else {
+ + candidate_it ;
}
}
2019-03-03 18:01:26 -03:00
// Track the last disconnected block, so we can correct its BLOCK_FAILED_CHILD status in future
// iterations, or, if it's the last one, call InvalidChainFound on it.
2019-02-13 21:37:30 -03:00
to_mark_failed = invalid_walk_tip ;
2017-10-19 17:55:31 -03:00
}
2021-04-27 16:54:53 -04:00
CheckBlockIndex ( ) ;
2019-09-10 14:58:41 -03:00
2019-02-13 21:37:30 -03:00
{
LOCK ( cs_main ) ;
2019-03-27 11:36:30 -03:00
if ( m_chain . Contains ( to_mark_failed ) ) {
2019-02-13 21:37:30 -03:00
// If the to-be-marked invalid block is in the active chain, something is interfering and we can't proceed.
return false ;
}
2015-10-02 18:20:38 -03:00
2019-03-03 18:01:26 -03:00
// Mark pindex (or the last disconnected block) as invalid, even when it never was in the main chain
2019-02-13 21:37:30 -03:00
to_mark_failed - > nStatus | = BLOCK_FAILED_VALID ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( to_mark_failed ) ;
2019-02-13 21:37:30 -03:00
setBlockIndexCandidates . erase ( to_mark_failed ) ;
2021-11-23 15:44:38 -03:00
m_chainman . m_failed_blocks . insert ( to_mark_failed ) ;
2015-10-02 18:20:38 -03:00
2019-09-10 14:58:41 -03:00
// If any new blocks somehow arrived while we were disconnecting
// (above), then the pre-calculation of what should go into
// setBlockIndexCandidates may have missed entries. This would
// technically be an inconsistency in the block index, but if we clean
// it up here, this should be an essentially unobservable error.
// Loop back over all block index entries and add any missing entries
// to setBlockIndexCandidates.
2022-01-13 14:44:19 -03:00
for ( auto & [ _ , block_index ] : m_blockman . m_block_index ) {
if ( block_index . IsValid ( BLOCK_VALID_TRANSACTIONS ) & & block_index . HaveTxsDownloaded ( ) & & ! setBlockIndexCandidates . value_comp ( ) ( & block_index , m_chain . Tip ( ) ) ) {
setBlockIndexCandidates . insert ( & block_index ) ;
2019-02-13 21:37:30 -03:00
}
2014-11-19 05:39:42 -03:00
}
2019-02-13 21:37:30 -03:00
InvalidChainFound ( to_mark_failed ) ;
}
2018-02-14 00:39:04 -03:00
// Only notify about a new block tip if the active chain was modified.
if ( pindex_was_in_chain ) {
2020-03-04 15:05:42 -03:00
uiInterface . NotifyBlockTip ( GetSynchronizationState ( IsInitialBlockDownload ( ) ) , to_mark_failed - > pprev ) ;
2018-02-14 00:39:04 -03:00
}
2014-11-19 05:39:42 -03:00
return true ;
}
2018-08-13 08:24:52 -03:00
2018-07-27 02:22:42 -04:00
void CChainState : : ResetBlockFailureFlags ( CBlockIndex * pindex ) {
2014-11-19 05:39:42 -03:00
AssertLockHeld ( cs_main ) ;
int nHeight = pindex - > nHeight ;
// Remove the invalidity flag from this block and all its descendants.
2022-01-13 14:44:19 -03:00
for ( auto & [ _ , block_index ] : m_blockman . m_block_index ) {
if ( ! block_index . IsValid ( ) & & block_index . GetAncestor ( nHeight ) = = pindex ) {
block_index . nStatus & = ~ BLOCK_FAILED_MASK ;
m_blockman . m_dirty_blockindex . insert ( & block_index ) ;
if ( block_index . IsValid ( BLOCK_VALID_TRANSACTIONS ) & & block_index . HaveTxsDownloaded ( ) & & setBlockIndexCandidates . value_comp ( ) ( m_chain . Tip ( ) , & block_index ) ) {
setBlockIndexCandidates . insert ( & block_index ) ;
2014-11-19 05:39:42 -03:00
}
2022-01-13 14:44:19 -03:00
if ( & block_index = = m_chainman . m_best_invalid ) {
2014-11-19 05:39:42 -03:00
// Reset invalid block marker if it was pointing to one of those.
2021-11-23 15:49:48 -03:00
m_chainman . m_best_invalid = nullptr ;
2014-11-19 05:39:42 -03:00
}
2022-01-13 14:44:19 -03:00
m_chainman . m_failed_blocks . erase ( & block_index ) ;
2014-11-19 05:39:42 -03:00
}
}
// Remove the invalidity flag from all ancestors too.
2017-08-07 01:36:37 -04:00
while ( pindex ! = nullptr ) {
2014-11-25 08:33:43 -03:00
if ( pindex - > nStatus & BLOCK_FAILED_MASK ) {
pindex - > nStatus & = ~ BLOCK_FAILED_MASK ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( pindex ) ;
2021-11-23 15:44:38 -03:00
m_chainman . m_failed_blocks . erase ( pindex ) ;
2014-11-19 05:39:42 -03:00
}
pindex = pindex - > pprev ;
}
}
2018-07-27 02:22:42 -04:00
2014-11-30 22:39:44 -03:00
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
2021-04-27 16:54:53 -04:00
void CChainState : : ReceivedBlockTransactions ( const CBlock & block , CBlockIndex * pindexNew , const FlatFilePos & pos )
2014-03-12 23:48:27 -03:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
2014-03-12 23:48:27 -03:00
pindexNew - > nTx = block . vtx . size ( ) ;
2014-07-11 18:02:35 -04:00
pindexNew - > nChainTx = 0 ;
2012-08-18 18:33:01 -04:00
pindexNew - > nFile = pos . nFile ;
pindexNew - > nDataPos = pos . nPos ;
2012-08-13 13:11:05 -04:00
pindexNew - > nUndoPos = 0 ;
2014-03-12 23:48:27 -03:00
pindexNew - > nStatus | = BLOCK_HAVE_DATA ;
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAt ( * pindexNew , m_chainman , Consensus : : DEPLOYMENT_SEGWIT ) ) {
2016-03-18 13:20:12 -03:00
pindexNew - > nStatus | = BLOCK_OPT_WITNESS ;
}
2014-07-11 18:02:35 -04:00
pindexNew - > RaiseValidity ( BLOCK_VALID_TRANSACTIONS ) ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( pindexNew ) ;
2014-03-12 23:48:27 -03:00
2018-12-03 20:14:08 -03:00
if ( pindexNew - > pprev = = nullptr | | pindexNew - > pprev - > HaveTxsDownloaded ( ) ) {
2014-07-11 18:02:35 -04:00
// If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
2017-01-27 05:43:41 -03:00
std : : deque < CBlockIndex * > queue ;
2014-07-11 18:02:35 -04:00
queue . push_back ( pindexNew ) ;
2010-08-29 12:58:15 -04:00
2014-07-11 18:02:35 -04:00
// Recursively process any descendant blocks that now may be eligible to be connected.
while ( ! queue . empty ( ) ) {
CBlockIndex * pindex = queue . front ( ) ;
queue . pop_front ( ) ;
pindex - > nChainTx = ( pindex - > pprev ? pindex - > pprev - > nChainTx : 0 ) + pindex - > nTx ;
2021-08-28 05:51:36 -04:00
pindex - > nSequenceId = nBlockSequenceId + + ;
2019-03-27 11:36:30 -03:00
if ( m_chain . Tip ( ) = = nullptr | | ! setBlockIndexCandidates . value_comp ( ) ( pindex , m_chain . Tip ( ) ) ) {
2015-03-13 13:25:34 -03:00
setBlockIndexCandidates . insert ( pindex ) ;
}
2019-03-27 18:07:32 -03:00
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > range = m_blockman . m_blocks_unlinked . equal_range ( pindex ) ;
2014-07-11 18:02:35 -04:00
while ( range . first ! = range . second ) {
std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator it = range . first ;
queue . push_back ( it - > second ) ;
range . first + + ;
2019-03-27 18:07:32 -03:00
m_blockman . m_blocks_unlinked . erase ( it ) ;
2014-07-11 18:02:35 -04:00
}
}
} else {
if ( pindexNew - > pprev & & pindexNew - > pprev - > IsValid ( BLOCK_VALID_TREE ) ) {
2019-03-27 18:07:32 -03:00
m_blockman . m_blocks_unlinked . insert ( std : : make_pair ( pindexNew - > pprev , pindexNew ) ) ;
2014-07-11 18:02:35 -04:00
}
}
2010-08-29 12:58:15 -04:00
}
2019-10-24 12:35:42 -03:00
static bool CheckBlockHeader ( const CBlockHeader & block , BlockValidationState & state , const Consensus : : Params & consensusParams , bool fCheckPOW = true )
2010-08-29 12:58:15 -04:00
{
2010-09-19 17:20:34 -04:00
// Check proof of work matches claimed amount
2016-05-20 08:43:37 -04:00
if ( fCheckPOW & & ! CheckProofOfWork ( block . GetHash ( ) , block . nBits , consensusParams ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_INVALID_HEADER , " high-hash " , " proof of work failed " ) ;
2010-09-19 17:20:34 -04:00
2014-03-11 13:36:21 -03:00
return true ;
}
2019-10-24 12:35:42 -03:00
bool CheckBlock ( const CBlock & block , BlockValidationState & state , const Consensus : : Params & consensusParams , bool fCheckPOW , bool fCheckMerkleRoot )
2010-08-29 12:58:15 -04:00
{
2014-07-11 18:02:35 -04:00
// These are checks that are independent of context.
2010-08-29 12:58:15 -04:00
2015-08-15 18:32:38 -03:00
if ( block . fChecked )
return true ;
2014-11-20 04:28:19 -03:00
// Check that the header is valid (particularly PoW). This is mostly
// redundant with the call in AcceptBlockHeader.
2016-06-08 19:12:52 -04:00
if ( ! CheckBlockHeader ( block , state , consensusParams , fCheckPOW ) )
2014-03-11 13:36:21 -03:00
return false ;
2019-07-17 05:40:34 -04:00
// Signet only: check block solution
if ( consensusParams . signet_blocks & & fCheckPOW & & ! CheckSignetBlockSolution ( block , consensusParams ) ) {
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-signet-blksig " , " signet block signature validation failure " ) ;
}
2014-07-11 18:02:35 -04:00
// Check the merkle root.
if ( fCheckMerkleRoot ) {
bool mutated ;
2015-11-17 13:35:44 -03:00
uint256 hashMerkleRoot2 = BlockMerkleRoot ( block , & mutated ) ;
2014-07-11 18:02:35 -04:00
if ( block . hashMerkleRoot ! = hashMerkleRoot2 )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_MUTATED , " bad-txnmrklroot " , " hashMerkleRoot mismatch " ) ;
2014-07-11 18:02:35 -04:00
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
// of transactions in a block without affecting the merkle root of a block,
// while still invalidating it.
if ( mutated )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_MUTATED , " bad-txns-duplicate " , " duplicate transaction " ) ;
2014-07-11 18:02:35 -04:00
}
// All potential-corruption validation must be done before we do any
// transaction validation, as otherwise we may mark the header as invalid
// because we receive the wrong transactions for it.
2016-01-03 14:54:50 -03:00
// Note that witness malleability is checked in ContextualCheckBlock, so no
// checks that use witness data may be performed here.
2014-07-11 18:02:35 -04:00
2010-08-29 12:58:15 -04:00
// Size limits
2018-06-22 14:27:18 -04:00
if ( block . vtx . empty ( ) | | block . vtx . size ( ) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT | | : : GetSerializeSize ( block , PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS ) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-blk-length " , " size limits failed " ) ;
2010-08-29 12:58:15 -04:00
// First transaction must be coinbase, the rest must not be
2016-11-10 22:26:00 -03:00
if ( block . vtx . empty ( ) | | ! block . vtx [ 0 ] - > IsCoinBase ( ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-cb-missing " , " first tx is not coinbase " ) ;
2013-06-23 22:14:11 -04:00
for ( unsigned int i = 1 ; i < block . vtx . size ( ) ; i + + )
2016-11-10 22:26:00 -03:00
if ( block . vtx [ i ] - > IsCoinBase ( ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-cb-multiple " , " more than one coinbase " ) ;
2010-08-29 12:58:15 -04:00
// Check transactions
2019-10-24 12:35:42 -03:00
// Must check for duplicate inputs (see CVE-2018-17144)
for ( const auto & tx : block . vtx ) {
TxValidationState tx_state ;
if ( ! CheckTransaction ( * tx , tx_state ) ) {
// CheckBlock() does context-free validation checks. The only
// possible failures are consensus failures.
assert ( tx_state . GetResult ( ) = = TxValidationResult : : TX_CONSENSUS ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , tx_state . GetRejectReason ( ) ,
2019-10-24 12:35:42 -03:00
strprintf ( " Transaction check failed (tx hash %s) %s " , tx - > GetHash ( ) . ToString ( ) , tx_state . GetDebugMessage ( ) ) ) ;
}
}
2012-04-23 15:14:03 -03:00
unsigned int nSigOps = 0 ;
2016-07-15 01:20:13 -04:00
for ( const auto & tx : block . vtx )
2011-10-03 14:05:43 -03:00
{
2016-11-10 22:26:00 -03:00
nSigOps + = GetLegacySigOpCount ( * tx ) ;
2011-10-03 14:05:43 -03:00
}
2016-01-03 14:54:50 -03:00
if ( nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-blk-sigops " , " out-of-bounds SigOpCount " ) ;
2010-08-29 12:58:15 -04:00
2015-08-15 18:32:38 -03:00
if ( fCheckPOW & & fCheckMerkleRoot )
block . fChecked = true ;
2010-08-29 12:58:15 -04:00
return true ;
}
2022-01-18 15:10:26 -03:00
void ChainstateManager : : UpdateUncommittedBlockStructures ( CBlock & block , const CBlockIndex * pindexPrev ) const
2015-11-05 21:42:38 -03:00
{
int commitpos = GetWitnessCommitmentIndex ( block ) ;
static const std : : vector < unsigned char > nonce ( 32 , 0x00 ) ;
2022-04-14 15:50:53 -04:00
if ( commitpos ! = NO_WITNESS_COMMITMENT & & DeploymentActiveAfter ( pindexPrev , * this , Consensus : : DEPLOYMENT_SEGWIT ) & & ! block . vtx [ 0 ] - > HasWitness ( ) ) {
2016-11-10 22:26:00 -03:00
CMutableTransaction tx ( * block . vtx [ 0 ] ) ;
2016-08-03 20:49:16 -04:00
tx . vin [ 0 ] . scriptWitness . stack . resize ( 1 ) ;
tx . vin [ 0 ] . scriptWitness . stack [ 0 ] = nonce ;
2016-11-10 22:34:17 -03:00
block . vtx [ 0 ] = MakeTransactionRef ( std : : move ( tx ) ) ;
2015-11-05 21:42:38 -03:00
}
}
2022-01-18 15:10:26 -03:00
std : : vector < unsigned char > ChainstateManager : : GenerateCoinbaseCommitment ( CBlock & block , const CBlockIndex * pindexPrev ) const
2015-11-05 21:42:38 -03:00
{
std : : vector < unsigned char > commitment ;
int commitpos = GetWitnessCommitmentIndex ( block ) ;
std : : vector < unsigned char > ret ( 32 , 0x00 ) ;
2021-06-20 14:26:35 -04:00
if ( commitpos = = NO_WITNESS_COMMITMENT ) {
uint256 witnessroot = BlockWitnessMerkleRoot ( block , nullptr ) ;
CHash256 ( ) . Write ( witnessroot ) . Write ( ret ) . Finalize ( witnessroot ) ;
CTxOut out ;
out . nValue = 0 ;
out . scriptPubKey . resize ( MINIMUM_WITNESS_COMMITMENT ) ;
out . scriptPubKey [ 0 ] = OP_RETURN ;
out . scriptPubKey [ 1 ] = 0x24 ;
out . scriptPubKey [ 2 ] = 0xaa ;
out . scriptPubKey [ 3 ] = 0x21 ;
out . scriptPubKey [ 4 ] = 0xa9 ;
out . scriptPubKey [ 5 ] = 0xed ;
memcpy ( & out . scriptPubKey [ 6 ] , witnessroot . begin ( ) , 32 ) ;
commitment = std : : vector < unsigned char > ( out . scriptPubKey . begin ( ) , out . scriptPubKey . end ( ) ) ;
CMutableTransaction tx ( * block . vtx [ 0 ] ) ;
tx . vout . push_back ( out ) ;
block . vtx [ 0 ] = MakeTransactionRef ( std : : move ( tx ) ) ;
2015-11-05 21:42:38 -03:00
}
2022-01-18 15:10:26 -03:00
UpdateUncommittedBlockStructures ( block , pindexPrev ) ;
2015-11-05 21:42:38 -03:00
return commitment ;
}
2017-04-21 15:45:30 -03:00
/** Context-dependent validity checks.
* By " context " , we mean only the previous block headers , but not the UTXO
2017-11-20 16:13:12 -03:00
* set ; UTXO - related validity checks are done in ConnectBlock ( ) .
* NOTE : This function is not currently invoked by ConnectBlock ( ) , so we
* should consider upgrade issues if we change which consensus rules are
* enforced in this function ( eg by adding a new consensus rule ) . See comment
* in ConnectBlock ( ) .
* Note that - reindex - chainstate skips the validation that happens here !
*/
2022-04-14 15:50:53 -04:00
static bool ContextualCheckBlockHeader ( const CBlockHeader & block , BlockValidationState & state , BlockManager & blockman , const ChainstateManager & chainman , const CBlockIndex * pindexPrev , int64_t nAdjustedTime ) EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main )
2015-03-30 08:48:04 -03:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2017-08-07 01:36:37 -04:00
assert ( pindexPrev ! = nullptr ) ;
2016-09-05 03:55:04 -03:00
const int nHeight = pindexPrev - > nHeight + 1 ;
2017-08-09 20:48:38 -04:00
2014-10-19 20:09:50 -03:00
// Check proof of work
2022-04-14 15:50:53 -04:00
const Consensus : : Params & consensusParams = chainman . GetConsensus ( ) ;
2015-04-22 19:19:11 -03:00
if ( block . nBits ! = GetNextWorkRequired ( pindexPrev , & block , consensusParams ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_INVALID_HEADER , " bad-diffbits " , " incorrect proof of work " ) ;
2014-10-19 20:09:50 -03:00
2017-08-09 20:48:38 -04:00
// Check against checkpoints
if ( fCheckpointsEnabled ) {
// Don't accept any forks from the main chain prior to last checkpoint.
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
2019-12-12 12:48:28 -03:00
// BlockIndex().
2022-04-14 15:50:53 -04:00
const CBlockIndex * pcheckpoint = blockman . GetLastCheckpoint ( chainman . GetParams ( ) . Checkpoints ( ) ) ;
2019-04-28 16:32:34 -04:00
if ( pcheckpoint & & nHeight < pcheckpoint - > nHeight ) {
LogPrintf ( " ERROR: %s: forked chain older than last checkpoint (height %d) \n " , __func__ , nHeight ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CHECKPOINT , " bad-fork-prior-to-checkpoint " ) ;
2019-04-28 16:32:34 -04:00
}
2017-08-09 20:48:38 -04:00
}
2014-10-19 20:09:50 -03:00
// Check timestamp against prev
if ( block . GetBlockTime ( ) < = pindexPrev - > GetMedianTimePast ( ) )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_INVALID_HEADER , " time-too-old " , " block's timestamp is too early " ) ;
2015-01-19 20:37:21 -03:00
2016-06-08 19:12:52 -04:00
// Check timestamp
2017-03-02 14:20:34 -03:00
if ( block . GetBlockTime ( ) > nAdjustedTime + MAX_FUTURE_BLOCK_TIME )
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_TIME_FUTURE , " time-too-new " , " block timestamp too far in the future " ) ;
2016-06-08 19:12:52 -04:00
2020-06-16 04:58:56 -04:00
// Reject blocks with outdated version
2022-04-14 15:50:53 -04:00
if ( ( block . nVersion < 2 & & DeploymentActiveAfter ( pindexPrev , chainman , Consensus : : DEPLOYMENT_HEIGHTINCB ) ) | |
( block . nVersion < 3 & & DeploymentActiveAfter ( pindexPrev , chainman , Consensus : : DEPLOYMENT_DERSIG ) ) | |
( block . nVersion < 4 & & DeploymentActiveAfter ( pindexPrev , chainman , Consensus : : DEPLOYMENT_CLTV ) ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_INVALID_HEADER , strprintf ( " bad-version(0x%08x) " , block . nVersion ) ,
2016-07-21 19:27:55 -04:00
strprintf ( " rejected nVersion=0x%08x block " , block . nVersion ) ) ;
2020-06-16 04:58:56 -04:00
}
2015-01-19 20:37:21 -03:00
2014-10-19 20:09:50 -03:00
return true ;
}
2017-11-20 16:13:12 -03:00
/** NOTE: This function is not currently invoked by ConnectBlock(), so we
* should consider upgrade issues if we change which consensus rules are
* enforced in this function ( eg by adding a new consensus rule ) . See comment
* in ConnectBlock ( ) .
* Note that - reindex - chainstate skips the validation that happens here !
*/
2022-04-14 15:50:53 -04:00
static bool ContextualCheckBlock ( const CBlock & block , BlockValidationState & state , const ChainstateManager & chainman , const CBlockIndex * pindexPrev )
2014-10-19 20:09:50 -03:00
{
2017-08-07 01:36:37 -04:00
const int nHeight = pindexPrev = = nullptr ? 0 : pindexPrev - > nHeight + 1 ;
2014-10-19 20:09:50 -03:00
2020-06-16 04:58:56 -04:00
// Enforce BIP113 (Median Time Past).
2022-03-14 14:20:03 -03:00
bool enforce_locktime_median_time_past { false } ;
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAfter ( pindexPrev , chainman , Consensus : : DEPLOYMENT_CSV ) ) {
2018-11-29 01:14:58 -03:00
assert ( pindexPrev ! = nullptr ) ;
2022-03-14 14:20:03 -03:00
enforce_locktime_median_time_past = true ;
2016-02-16 13:33:31 -03:00
}
2022-03-14 14:20:03 -03:00
const int64_t nLockTimeCutoff { enforce_locktime_median_time_past ?
pindexPrev - > GetMedianTimePast ( ) :
block . GetBlockTime ( ) } ;
2016-02-16 13:33:31 -03:00
2014-10-19 20:09:50 -03:00
// Check that all transactions are finalized
2016-07-15 01:20:13 -04:00
for ( const auto & tx : block . vtx ) {
2016-11-10 22:26:00 -03:00
if ( ! IsFinalTx ( * tx , nHeight , nLockTimeCutoff ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-txns-nonfinal " , " non-final transaction " ) ;
2014-10-19 20:09:50 -03:00
}
2015-11-03 14:12:36 -03:00
}
2014-10-19 20:09:50 -03:00
2016-07-21 19:27:55 -04:00
// Enforce rule that the coinbase starts with serialized block height
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAfter ( pindexPrev , chainman , Consensus : : DEPLOYMENT_HEIGHTINCB ) )
2014-10-19 20:09:50 -03:00
{
CScript expect = CScript ( ) < < nHeight ;
2016-11-10 22:26:00 -03:00
if ( block . vtx [ 0 ] - > vin [ 0 ] . scriptSig . size ( ) < expect . size ( ) | |
! std : : equal ( expect . begin ( ) , expect . end ( ) , block . vtx [ 0 ] - > vin [ 0 ] . scriptSig . begin ( ) ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-cb-height " , " block height mismatch in coinbase " ) ;
2014-10-19 20:09:50 -03:00
}
}
2015-11-05 21:42:38 -03:00
// Validation for witness commitments.
// * We compute the witness hash (which is the hash including witnesses) of all the block's transactions, except the
// coinbase (where 0x0000....0000 is used instead).
2018-03-26 18:24:17 -03:00
// * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness reserved value (unconstrained).
2015-11-05 21:42:38 -03:00
// * We build a merkle tree with all those witness hashes as leaves (similar to the hashMerkleRoot in the block header).
// * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are
2018-03-26 18:24:17 -03:00
// {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are
2015-11-05 21:42:38 -03:00
// multiple, the last one is used.
bool fHaveWitness = false ;
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAfter ( pindexPrev , chainman , Consensus : : DEPLOYMENT_SEGWIT ) ) {
2015-11-05 21:42:38 -03:00
int commitpos = GetWitnessCommitmentIndex ( block ) ;
2020-04-29 23:25:45 -04:00
if ( commitpos ! = NO_WITNESS_COMMITMENT ) {
2015-11-05 21:42:38 -03:00
bool malleated = false ;
uint256 hashWitness = BlockWitnessMerkleRoot ( block , & malleated ) ;
// The malleation check is ignored; as the transaction tree itself
// already does not permit it, it is impossible to trigger in the
// witness tree.
2016-08-03 20:49:16 -04:00
if ( block . vtx [ 0 ] - > vin [ 0 ] . scriptWitness . stack . size ( ) ! = 1 | | block . vtx [ 0 ] - > vin [ 0 ] . scriptWitness . stack [ 0 ] . size ( ) ! = 32 ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_MUTATED , " bad-witness-nonce-size " , strprintf ( " %s : invalid witness reserved value size " , __func__ ) ) ;
2015-11-05 21:42:38 -03:00
}
2020-06-18 20:19:46 -04:00
CHash256 ( ) . Write ( hashWitness ) . Write ( block . vtx [ 0 ] - > vin [ 0 ] . scriptWitness . stack [ 0 ] ) . Finalize ( hashWitness ) ;
2016-11-10 22:26:00 -03:00
if ( memcmp ( hashWitness . begin ( ) , & block . vtx [ 0 ] - > vout [ commitpos ] . scriptPubKey [ 6 ] , 32 ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_MUTATED , " bad-witness-merkle-match " , strprintf ( " %s : witness merkle commitment mismatch " , __func__ ) ) ;
2015-11-05 21:42:38 -03:00
}
fHaveWitness = true ;
}
}
// No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
if ( ! fHaveWitness ) {
2017-05-18 03:42:14 -04:00
for ( const auto & tx : block . vtx ) {
if ( tx - > HasWitness ( ) ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_MUTATED , " unexpected-witness " , strprintf ( " %s : unexpected witness data found " , __func__ ) ) ;
2015-11-05 21:42:38 -03:00
}
}
}
2018-03-26 18:24:17 -03:00
// After the coinbase witness reserved value and commitment are verified,
2016-07-18 13:28:26 -04:00
// we can check if the block weight passes (before we've checked the
// coinbase witness, it would be possible for the weight to be too
2016-01-03 14:54:50 -03:00
// large by filling up the coinbase witness, which doesn't change
// the block hash, so we couldn't mark the block as permanently
// failed).
2016-07-18 13:28:26 -04:00
if ( GetBlockWeight ( block ) > MAX_BLOCK_WEIGHT ) {
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CONSENSUS , " bad-blk-weight " , strprintf ( " %s : weight limit failed " , __func__ ) ) ;
2016-01-03 14:54:50 -03:00
}
2014-10-19 20:09:50 -03:00
return true ;
}
2022-01-18 08:49:30 -03:00
bool ChainstateManager : : AcceptBlockHeader ( const CBlockHeader & block , BlockValidationState & state , CBlockIndex * * ppindex )
2010-08-29 12:58:15 -04:00
{
2014-04-15 07:43:17 -03:00
AssertLockHeld ( cs_main ) ;
2010-08-29 12:58:15 -04:00
// Check for duplicate
2013-06-23 22:27:02 -04:00
uint256 hash = block . GetHash ( ) ;
2021-11-23 16:05:07 -03:00
BlockMap : : iterator miSelf { m_blockman . m_block_index . find ( hash ) } ;
2022-01-18 08:49:30 -03:00
if ( hash ! = GetConsensus ( ) . hashGenesisBlock ) {
2021-11-23 16:05:07 -03:00
if ( miSelf ! = m_blockman . m_block_index . end ( ) ) {
2015-06-17 16:23:53 -03:00
// Block header is already known.
2021-01-08 20:56:48 -03:00
CBlockIndex * pindex = & ( miSelf - > second ) ;
2015-06-17 16:23:53 -03:00
if ( ppindex )
* ppindex = pindex ;
2019-04-28 16:32:34 -04:00
if ( pindex - > nStatus & BLOCK_FAILED_MASK ) {
2021-10-04 00:08:34 -03:00
LogPrint ( BCLog : : VALIDATION , " %s: block %s is marked invalid \n " , __func__ , hash . ToString ( ) ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_CACHED_INVALID , " duplicate " ) ;
2019-04-28 16:32:34 -04:00
}
2015-06-17 16:23:53 -03:00
return true ;
}
2014-11-20 04:28:19 -03:00
2022-01-18 08:49:30 -03:00
if ( ! CheckBlockHeader ( block , state , GetConsensus ( ) ) ) {
2020-07-15 04:39:38 -04:00
LogPrint ( BCLog : : VALIDATION , " %s: Consensus::CheckBlockHeader: %s, %s \n " , __func__ , hash . ToString ( ) , state . ToString ( ) ) ;
return false ;
}
2015-06-17 16:23:53 -03:00
// Get prev block index
2017-08-07 01:36:37 -04:00
CBlockIndex * pindexPrev = nullptr ;
2021-11-23 16:05:07 -03:00
BlockMap : : iterator mi { m_blockman . m_block_index . find ( block . hashPrevBlock ) } ;
if ( mi = = m_blockman . m_block_index . end ( ) ) {
2021-10-04 00:08:34 -03:00
LogPrint ( BCLog : : VALIDATION , " %s: %s prev block not found \n " , __func__ , hash . ToString ( ) ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_MISSING_PREV , " prev-blk-not-found " ) ;
2019-04-28 16:32:34 -04:00
}
2021-01-08 20:56:48 -03:00
pindexPrev = & ( ( * mi ) . second ) ;
2019-04-28 16:32:34 -04:00
if ( pindexPrev - > nStatus & BLOCK_FAILED_MASK ) {
2021-10-04 00:08:34 -03:00
LogPrint ( BCLog : : VALIDATION , " %s: %s prev block invalid \n " , __func__ , hash . ToString ( ) ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_INVALID_PREV , " bad-prevblk " ) ;
2019-04-28 16:32:34 -04:00
}
2022-03-01 18:14:12 -03:00
if ( ! ContextualCheckBlockHeader ( block , state , m_blockman , * this , pindexPrev , m_adjusted_time_callback ( ) ) ) {
2021-10-04 00:08:34 -03:00
LogPrint ( BCLog : : VALIDATION , " %s: Consensus::ContextualCheckBlockHeader: %s, %s \n " , __func__ , hash . ToString ( ) , state . ToString ( ) ) ;
return false ;
}
2017-10-19 17:55:31 -03:00
2018-09-04 05:50:19 -03:00
/* Determine if this block descends from any block which has been found
* invalid ( m_failed_blocks ) , then mark pindexPrev and any blocks between
* them as failed . For example :
*
* D3
* /
* B2 - C2
* / \
* A D2 - E2 - F2
* \
* B1 - C1 - D1 - E1
*
* In the case that we attempted to reorg from E1 to F2 , only to find
* C2 to be invalid , we would mark D2 , E2 , and F2 as BLOCK_FAILED_CHILD
* but NOT D3 ( it was not in any of our candidate sets at the time ) .
*
* In any case D3 will also be marked as BLOCK_FAILED_CHILD at restart
* in LoadBlockIndex .
*/
2017-10-19 17:55:31 -03:00
if ( ! pindexPrev - > IsValid ( BLOCK_VALID_SCRIPTS ) ) {
2018-09-04 05:50:19 -03:00
// The above does not mean "invalid": it checks if the previous block
// hasn't been validated up to BLOCK_VALID_SCRIPTS. This is a performance
// optimization, in the common case of adding a new block to the tip,
// we don't need to iterate over the failed blocks list.
2018-04-18 08:57:18 -03:00
for ( const CBlockIndex * failedit : m_failed_blocks ) {
2017-10-19 17:55:31 -03:00
if ( pindexPrev - > GetAncestor ( failedit - > nHeight ) = = failedit ) {
assert ( failedit - > nStatus & BLOCK_FAILED_VALID ) ;
CBlockIndex * invalid_walk = pindexPrev ;
while ( invalid_walk ! = failedit ) {
invalid_walk - > nStatus | = BLOCK_FAILED_CHILD ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( invalid_walk ) ;
2017-10-19 17:55:31 -03:00
invalid_walk = invalid_walk - > pprev ;
}
2021-10-04 00:08:34 -03:00
LogPrint ( BCLog : : VALIDATION , " %s: %s prev block invalid \n " , __func__ , hash . ToString ( ) ) ;
2019-04-28 16:40:01 -04:00
return state . Invalid ( BlockValidationResult : : BLOCK_INVALID_PREV , " bad-prevblk " ) ;
2017-10-19 17:55:31 -03:00
}
}
}
2015-06-17 16:23:53 -03:00
}
2022-03-18 13:35:52 -03:00
CBlockIndex * pindex { m_blockman . AddToBlockIndex ( block , m_best_header ) } ;
2014-03-12 23:48:27 -03:00
if ( ppindex )
* ppindex = pindex ;
return true ;
}
2016-10-02 13:22:05 -03:00
// Exposed wrapper for AcceptBlockHeader
2022-01-18 08:49:30 -03:00
bool ChainstateManager : : ProcessNewBlockHeaders ( const std : : vector < CBlockHeader > & headers , BlockValidationState & state , const CBlockIndex * * ppindex )
2016-10-02 13:22:05 -03:00
{
2020-04-18 09:55:57 -04:00
AssertLockNotHeld ( cs_main ) ;
2016-10-02 13:22:05 -03:00
{
LOCK ( cs_main ) ;
for ( const CBlockHeader & header : headers ) {
2017-08-07 01:36:37 -04:00
CBlockIndex * pindex = nullptr ; // Use a temp pindex instead of ppindex to avoid a const_cast
2022-01-18 08:49:30 -03:00
bool accepted { AcceptBlockHeader ( header , state , & pindex ) } ;
2021-04-27 16:54:53 -04:00
ActiveChainstate ( ) . CheckBlockIndex ( ) ;
2019-03-27 18:07:32 -03:00
if ( ! accepted ) {
2016-10-02 13:22:05 -03:00
return false ;
}
2017-01-11 19:47:52 -03:00
if ( ppindex ) {
* ppindex = pindex ;
}
2016-10-02 13:22:05 -03:00
}
}
2020-08-26 14:42:01 -04:00
if ( NotifyHeaderTip ( ActiveChainstate ( ) ) ) {
if ( ActiveChainstate ( ) . IsInitialBlockDownload ( ) & & ppindex & & * ppindex ) {
2022-01-11 09:07:23 -03:00
const CBlockIndex & last_accepted { * * ppindex } ;
2022-01-18 08:49:30 -03:00
const int64_t blocks_left { ( GetTime ( ) - last_accepted . GetBlockTime ( ) ) / GetConsensus ( ) . nPowTargetSpacing } ;
2022-01-11 09:07:23 -03:00
const double progress { 100.0 * last_accepted . nHeight / ( last_accepted . nHeight + blocks_left ) } ;
LogPrintf ( " Synchronizing blockheaders, height: %d (~%.2f%%) \n " , last_accepted . nHeight , progress ) ;
2019-03-17 15:55:56 -03:00
}
}
2016-10-02 13:22:05 -03:00
return true ;
}
2017-08-07 01:36:37 -04:00
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
2021-04-27 16:54:53 -04:00
bool CChainState : : AcceptBlock ( const std : : shared_ptr < const CBlock > & pblock , BlockValidationState & state , CBlockIndex * * ppindex , bool fRequested , const FlatFilePos * dbp , bool * fNewBlock )
2014-03-12 23:48:27 -03:00
{
2016-12-19 04:24:11 -03:00
const CBlock & block = * pblock ;
2016-05-22 01:55:15 -04:00
if ( fNewBlock ) * fNewBlock = false ;
2014-03-12 23:48:27 -03:00
AssertLockHeld ( cs_main ) ;
2017-08-07 01:36:37 -04:00
CBlockIndex * pindexDummy = nullptr ;
2016-04-20 10:45:41 -03:00
CBlockIndex * & pindex = ppindex ? * ppindex : pindexDummy ;
2014-03-12 23:48:27 -03:00
2022-01-18 08:49:30 -03:00
bool accepted_header { m_chainman . AcceptBlockHeader ( block , state , & pindex ) } ;
2021-04-27 16:54:53 -04:00
CheckBlockIndex ( ) ;
2019-03-27 18:07:32 -03:00
if ( ! accepted_header )
2014-03-12 23:48:27 -03:00
return false ;
2015-04-09 14:21:11 -03:00
// Try to process all requested blocks that we don't have, but only
// process an unrequested block if it's new and has enough work to
2015-06-02 16:17:36 -03:00
// advance our tip, and isn't too many blocks ahead.
2015-04-09 14:21:11 -03:00
bool fAlreadyHave = pindex - > nStatus & BLOCK_HAVE_DATA ;
2019-03-27 11:36:30 -03:00
bool fHasMoreOrSameWork = ( m_chain . Tip ( ) ? pindex - > nChainWork > = m_chain . Tip ( ) - > nChainWork : true ) ;
2015-06-02 16:17:36 -03:00
// Blocks that are too out-of-order needlessly limit the effectiveness of
// pruning, because pruning will not delete block files that contain any
// blocks which are too close in height to the tip. Apply this test
// regardless of whether pruning is enabled; it should generally be safe to
// not process unrequested blocks.
2021-12-16 12:56:44 -03:00
bool fTooFarAhead { pindex - > nHeight > m_chain . Height ( ) + int ( MIN_BLOCKS_TO_KEEP ) } ;
2015-04-09 14:21:11 -03:00
2016-10-02 00:44:40 -03:00
// TODO: Decouple this function from the block download logic by removing fRequested
2017-03-21 15:49:08 -03:00
// This requires some new chain data structure to efficiently look up if a
2016-10-02 00:44:40 -03:00
// block is in a chain leading to a candidate for best tip, despite not
// being such a candidate itself.
2021-05-13 12:51:47 -04:00
// Note that this would break the getblockfrompeer RPC
2016-10-02 00:44:40 -03:00
2015-04-09 14:21:11 -03:00
// TODO: deal better with return value and error conditions for duplicate
// and unrequested blocks.
if ( fAlreadyHave ) return true ;
if ( ! fRequested ) { // If we didn't ask for it:
2017-10-11 17:04:13 -03:00
if ( pindex - > nTx ! = 0 ) return true ; // This is a previously-processed block that was pruned
if ( ! fHasMoreOrSameWork ) return true ; // Don't process less-work chains
if ( fTooFarAhead ) return true ; // Block height is too high
2017-10-06 15:11:43 -03:00
// Protect against DoS attacks from low-work chains.
// If our tip is behind, a peer could try to send us
// low-work blocks on a fake chain that we would never
// request; don't process these.
if ( pindex - > nChainWork < nMinimumChainWork ) return true ;
2014-07-11 18:02:35 -04:00
}
2021-04-27 16:54:53 -04:00
if ( ! CheckBlock ( block , state , m_params . GetConsensus ( ) ) | |
2022-04-14 15:50:53 -04:00
! ContextualCheckBlock ( block , state , m_chainman , pindex - > pprev ) ) {
2019-10-24 12:35:42 -03:00
if ( state . IsInvalid ( ) & & state . GetResult ( ) ! = BlockValidationResult : : BLOCK_MUTATED ) {
2014-03-12 23:48:27 -03:00
pindex - > nStatus | = BLOCK_FAILED_VALID ;
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( pindex ) ;
2014-03-12 23:48:27 -03:00
}
2019-11-08 18:22:36 -03:00
return error ( " %s: %s " , __func__ , state . ToString ( ) ) ;
2014-03-12 23:48:27 -03:00
}
2016-12-19 04:26:20 -03:00
// Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW
// (but if it does not build on our best tip, let the SendMessages loop relay it)
2019-03-27 11:36:30 -03:00
if ( ! IsInitialBlockDownload ( ) & & m_chain . Tip ( ) = = pindex - > pprev )
2016-12-19 04:26:20 -03:00
GetMainSignals ( ) . NewPoWValidBlock ( pindex , pblock ) ;
2010-08-29 12:58:15 -04:00
// Write block to history file
2018-06-11 15:13:04 -04:00
if ( fNewBlock ) * fNewBlock = true ;
2013-01-28 21:44:19 -03:00
try {
2022-01-04 10:04:30 -03:00
FlatFilePos blockPos { m_blockman . SaveBlockToDisk ( block , pindex - > nHeight , m_chain , m_params , dbp ) } ;
2017-04-25 22:35:02 -03:00
if ( blockPos . IsNull ( ) ) {
state . Error ( strprintf ( " %s: Failed to find position to write new block to disk " , __func__ ) ) ;
return false ;
}
2021-04-27 16:54:53 -04:00
ReceivedBlockTransactions ( block , pindex , blockPos ) ;
2014-12-07 09:29:06 -03:00
} catch ( const std : : runtime_error & e ) {
2015-01-16 20:57:14 -03:00
return AbortNode ( state , std : : string ( " System error: " ) + e . what ( ) ) ;
2013-01-28 21:44:19 -03:00
}
2010-08-29 12:58:15 -04:00
2021-04-27 16:54:53 -04:00
FlushStateToDisk ( state , FlushStateMode : : NONE ) ;
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
2021-04-27 16:54:53 -04:00
CheckBlockIndex ( ) ;
2017-12-04 11:34:46 -03:00
2010-08-29 12:58:15 -04:00
return true ;
}
2022-01-18 08:49:30 -03:00
bool ChainstateManager : : ProcessNewBlock ( const std : : shared_ptr < const CBlock > & block , bool force_processing , bool * new_block )
2010-08-29 12:58:15 -04:00
{
2017-12-04 20:25:57 -03:00
AssertLockNotHeld ( cs_main ) ;
2010-08-29 12:58:15 -04:00
{
2017-08-07 01:36:37 -04:00
CBlockIndex * pindex = nullptr ;
2021-05-31 01:54:58 -04:00
if ( new_block ) * new_block = false ;
2019-10-24 12:35:42 -03:00
BlockValidationState state ;
2017-02-13 19:28:39 -03:00
2018-11-29 08:36:12 -03:00
// CheckBlock() does not support multi-threaded block validation because CBlock::fChecked can cause data race.
// Therefore, the following critical section must include the CheckBlock() call as well.
2017-02-13 19:28:39 -03:00
LOCK ( cs_main ) ;
2019-03-06 08:26:58 -03:00
// Skipping AcceptBlock() for CheckBlock() failures means that we will never mark a block as invalid if
// CheckBlock() fails. This is protective against consensus failure if there are any unknown forms of block
// malleability that cause CheckBlock() to fail; see e.g. CVE-2012-2459 and
// https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-February/016697.html. Because CheckBlock() is
// not very expensive, the anti-DoS benefits of caching failure (of a definitely-invalid block) are not substantial.
2022-01-18 08:49:30 -03:00
bool ret = CheckBlock ( * block , state , GetConsensus ( ) ) ;
2017-02-13 19:28:39 -03:00
if ( ret ) {
// Store to disk
2021-04-27 16:54:53 -04:00
ret = ActiveChainstate ( ) . AcceptBlock ( block , state , & pindex , force_processing , nullptr , new_block ) ;
2017-02-13 19:28:39 -03:00
}
2016-10-27 17:30:17 -03:00
if ( ! ret ) {
2021-05-31 01:54:58 -04:00
GetMainSignals ( ) . BlockChecked ( * block , state ) ;
2019-11-08 18:22:36 -03:00
return error ( " %s: AcceptBlock FAILED (%s) " , __func__, state.ToString()) ;
2016-10-27 17:30:17 -03:00
}
2014-05-07 11:10:35 -04:00
}
2020-08-26 14:44:47 -04:00
NotifyHeaderTip ( ActiveChainstate ( ) ) ;
2016-04-28 11:18:45 -03:00
2019-10-24 12:35:42 -03:00
BlockValidationState state ; // Only used to report errors, not invalidity - ignore it
2021-04-27 16:54:53 -04:00
if ( ! ActiveChainstate ( ) . ActivateBestChain ( state , block ) ) {
2019-11-08 18:22:36 -03:00
return error ( " %s: ActivateBestChain failed (%s) " , __func__, state.ToString()) ;
2021-04-27 16:54:53 -04:00
}
2014-05-07 11:10:35 -04:00
2010-08-29 12:58:15 -04:00
return true ;
}
2021-09-27 12:55:42 -03:00
MempoolAcceptResult ChainstateManager : : ProcessTransaction ( const CTransactionRef & tx , bool test_accept )
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
2021-09-27 12:55:42 -03:00
CChainState & active_chainstate = ActiveChainstate ( ) ;
2021-12-02 01:50:27 -03:00
if ( ! active_chainstate . GetMempool ( ) ) {
2021-09-27 12:55:42 -03:00
TxValidationState state ;
state . Invalid ( TxValidationResult : : TX_NO_MEMPOOL , " no-mempool " ) ;
return MempoolAcceptResult : : Failure ( state ) ;
}
2021-12-02 01:50:27 -03:00
auto result = AcceptToMemoryPool ( active_chainstate , tx , GetTime ( ) , /*bypass_limits=*/ false , test_accept ) ;
active_chainstate . GetMempool ( ) - > check ( active_chainstate . CoinsTip ( ) , active_chainstate . m_chain . Height ( ) + 1 ) ;
2021-09-27 14:11:08 -03:00
return result ;
2021-09-27 12:55:42 -03:00
}
2021-01-20 16:27:27 -03:00
bool TestBlockValidity ( BlockValidationState & state ,
const CChainParams & chainparams ,
CChainState & chainstate ,
const CBlock & block ,
CBlockIndex * pindexPrev ,
2022-03-01 18:14:12 -03:00
const std : : function < int64_t ( ) > & adjusted_time_callback ,
2021-01-20 16:27:27 -03:00
bool fCheckPOW ,
bool fCheckMerkleRoot )
2014-10-19 23:10:03 -03:00
{
AssertLockHeld ( cs_main ) ;
2020-09-30 18:02:51 -03:00
assert ( pindexPrev & & pindexPrev = = chainstate . m_chain . Tip ( ) ) ;
CCoinsViewCache viewNew ( & chainstate . CoinsTip ( ) ) ;
2017-12-12 15:30:22 -03:00
uint256 block_hash ( block . GetHash ( ) ) ;
2014-10-19 23:10:03 -03:00
CBlockIndex indexDummy ( block ) ;
indexDummy . pprev = pindexPrev ;
indexDummy . nHeight = pindexPrev - > nHeight + 1 ;
2017-12-12 15:30:22 -03:00
indexDummy . phashBlock = & block_hash ;
2014-10-19 23:10:03 -03:00
// NOTE: CheckBlockHeader is called by CheckBlock
2022-03-01 18:14:12 -03:00
if ( ! ContextualCheckBlockHeader ( block , state , chainstate . m_blockman , chainstate . m_chainman , pindexPrev , adjusted_time_callback ( ) ) )
2019-11-08 18:22:36 -03:00
return error ( " %s: Consensus::ContextualCheckBlockHeader: %s " , __func__ , state . ToString ( ) ) ;
2016-06-08 19:12:52 -04:00
if ( ! CheckBlock ( block , state , chainparams . GetConsensus ( ) , fCheckPOW , fCheckMerkleRoot ) )
2019-11-08 18:22:36 -03:00
return error ( " %s: Consensus::CheckBlock: %s " , __func__ , state . ToString ( ) ) ;
2022-04-14 15:50:53 -04:00
if ( ! ContextualCheckBlock ( block , state , chainstate . m_chainman , pindexPrev ) )
2019-11-08 18:22:36 -03:00
return error ( " %s: Consensus::ContextualCheckBlock: %s " , __func__ , state . ToString ( ) ) ;
2021-04-27 16:54:53 -04:00
if ( ! chainstate . ConnectBlock ( block , state , & indexDummy , viewNew , true ) ) {
2014-10-19 23:10:03 -03:00
return false ;
2021-04-27 16:54:53 -04:00
}
2014-10-19 23:10:03 -03:00
assert ( state . IsValid ( ) ) ;
return true ;
}
2016-11-29 14:39:19 -03:00
/* This function is called from the RPC code for pruneblockchain */
2020-09-15 16:59:46 -03:00
void PruneBlockFilesManual ( CChainState & active_chainstate , int nManualPruneHeight )
2016-11-29 14:39:19 -03:00
{
2019-10-24 12:35:42 -03:00
BlockValidationState state ;
2020-09-15 16:59:46 -03:00
if ( ! active_chainstate . FlushStateToDisk (
2021-04-27 16:54:53 -04:00
state , FlushStateMode : : NONE , nManualPruneHeight ) ) {
2019-11-08 18:22:36 -03:00
LogPrintf ( " %s: failed to flush state (%s) \n " , __func__ , state . ToString ( ) ) ;
2018-04-18 10:58:13 -03:00
}
2016-11-29 14:39:19 -03:00
}
2022-05-17 14:45:18 -04:00
void CChainState : : LoadMempool ( const ArgsManager & args , FopenFn mockable_fopen_function )
2020-07-19 03:07:54 -04:00
{
2021-07-06 17:05:25 -04:00
if ( ! m_mempool ) return ;
2021-09-22 06:32:25 -03:00
if ( args . GetBoolArg ( " -persistmempool " , DEFAULT_PERSIST_MEMPOOL ) ) {
2022-05-17 14:45:18 -04:00
: : LoadMempool ( * m_mempool , * this , mockable_fopen_function ) ;
2020-07-19 03:07:54 -04:00
}
2022-07-07 16:32:52 -04:00
m_mempool - > SetLoadTried ( ! ShutdownRequested ( ) ) ;
2020-07-19 03:07:54 -04:00
}
2021-04-27 16:54:53 -04:00
bool CChainState : : LoadChainTip ( )
2017-04-19 13:34:30 -03:00
{
2018-01-11 20:32:32 -03:00
AssertLockHeld ( cs_main ) ;
2019-03-29 15:09:55 -03:00
const CCoinsViewCache & coins_cache = CoinsTip ( ) ;
2019-07-24 11:45:04 -04:00
assert ( ! coins_cache . GetBestBlock ( ) . IsNull ( ) ) ; // Never called when the coins view is empty
2019-03-29 15:09:55 -03:00
const CBlockIndex * tip = m_chain . Tip ( ) ;
2018-01-11 20:32:32 -03:00
2019-03-29 15:09:55 -03:00
if ( tip & & tip - > GetBlockHash ( ) = = coins_cache . GetBestBlock ( ) ) {
return true ;
}
2017-07-06 20:00:11 -04:00
2013-10-13 17:15:48 -03:00
// Load pointer to end of best chain
2020-08-25 17:27:05 -04:00
CBlockIndex * pindex = m_blockman . LookupBlockIndex ( coins_cache . GetBestBlock ( ) ) ;
2018-01-11 21:23:09 -03:00
if ( ! pindex ) {
2017-07-06 20:00:11 -04:00
return false ;
2018-01-11 21:23:09 -03:00
}
2019-03-29 15:09:55 -03:00
m_chain . SetTip ( pindex ) ;
PruneBlockIndexCandidates ( ) ;
2014-11-01 18:42:12 -03:00
2019-03-29 15:09:55 -03:00
tip = m_chain . Tip ( ) ;
2017-04-19 13:34:30 -03:00
LogPrintf ( " Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f \n " ,
2021-04-27 16:54:53 -04:00
tip - > GetBlockHash ( ) . ToString ( ) ,
m_chain . Height ( ) ,
FormatISO8601DateTime ( tip - > GetBlockTime ( ) ) ,
GuessVerificationProgress ( m_params . TxData ( ) , tip ) ) ;
2017-07-06 20:00:11 -04:00
return true ;
2013-01-03 11:29:07 -03:00
}
2014-05-23 12:04:09 -04:00
CVerifyDB : : CVerifyDB ( )
{
2021-05-02 14:53:36 -04:00
uiInterface . ShowProgress ( _ ( " Verifying blocks… " ) . translated , 0 , false ) ;
2014-05-23 12:04:09 -04:00
}
CVerifyDB : : ~ CVerifyDB ( )
{
2017-07-07 17:09:55 -04:00
uiInterface . ShowProgress ( " " , 100 , false ) ;
2014-05-23 12:04:09 -04:00
}
2021-04-13 09:57:20 -04:00
bool CVerifyDB : : VerifyDB (
CChainState & chainstate ,
2021-09-20 15:02:07 -03:00
const Consensus : : Params & consensus_params ,
2021-04-13 10:05:28 -04:00
CCoinsView & coinsview ,
2021-04-13 09:57:20 -04:00
int nCheckLevel , int nCheckDepth )
2013-06-19 11:32:49 -04:00
{
2021-03-01 19:06:51 -03:00
AssertLockHeld ( cs_main ) ;
2022-02-21 06:43:06 -03:00
if ( chainstate . m_chain . Tip ( ) = = nullptr | | chainstate . m_chain . Tip ( ) - > pprev = = nullptr ) {
2013-01-03 11:29:07 -03:00
return true ;
2022-02-21 06:43:06 -03:00
}
2013-01-03 11:29:07 -03:00
2012-09-03 16:14:03 -03:00
// Verify blocks in the best chain
2022-02-21 06:43:06 -03:00
if ( nCheckDepth < = 0 | | nCheckDepth > chainstate . m_chain . Height ( ) ) {
2021-04-13 09:57:20 -04:00
nCheckDepth = chainstate . m_chain . Height ( ) ;
2022-02-21 06:43:06 -03:00
}
2013-01-03 11:29:07 -03:00
nCheckLevel = std : : max ( 0 , std : : min ( 4 , nCheckLevel ) ) ;
2013-09-18 07:38:08 -03:00
LogPrintf ( " Verifying last %i blocks at level %i \n " , nCheckDepth , nCheckLevel ) ;
2021-04-13 10:05:28 -04:00
CCoinsViewCache coins ( & coinsview ) ;
2018-06-11 03:14:35 -04:00
CBlockIndex * pindex ;
2017-08-07 01:36:37 -04:00
CBlockIndex * pindexFailure = nullptr ;
2013-01-03 11:29:07 -03:00
int nGoodTransactions = 0 ;
2019-10-24 12:35:42 -03:00
BlockValidationState state ;
2016-06-02 07:52:09 -04:00
int reportDone = 0 ;
2018-04-05 11:17:32 -03:00
LogPrintf ( " [0%%]... " ) ; /* Continued */
2021-04-13 10:05:28 -04:00
2021-04-03 12:26:39 -03:00
const bool is_snapshot_cs { ! chainstate . m_from_snapshot_blockhash } ;
2021-04-13 10:05:28 -04:00
2021-04-13 09:57:20 -04:00
for ( pindex = chainstate . m_chain . Tip ( ) ; pindex & & pindex - > pprev ; pindex = pindex - > pprev ) {
const int percentageDone = std : : max ( 1 , std : : min ( 99 , ( int ) ( ( ( double ) ( chainstate . m_chain . Height ( ) - pindex - > nHeight ) ) / ( double ) nCheckDepth * ( nCheckLevel > = 4 ? 50 : 100 ) ) ) ) ;
2022-02-21 06:43:06 -03:00
if ( reportDone < percentageDone / 10 ) {
2016-06-02 07:52:09 -04:00
// report every 10% step
2018-04-05 11:17:32 -03:00
LogPrintf ( " [%d%%]... " , percentageDone ) ; /* Continued */
2022-02-21 06:43:06 -03:00
reportDone = percentageDone / 10 ;
2016-06-02 07:52:09 -04:00
}
2021-05-02 14:53:36 -04:00
uiInterface . ShowProgress ( _ ( " Verifying blocks… " ) . translated , percentageDone , false ) ;
2022-02-21 06:43:06 -03:00
if ( pindex - > nHeight < = chainstate . m_chain . Height ( ) - nCheckDepth ) {
2012-09-03 16:14:03 -03:00
break ;
2022-02-21 06:43:06 -03:00
}
2021-04-13 10:05:28 -04:00
if ( ( fPruneMode | | is_snapshot_cs ) & & ! ( pindex - > nStatus & BLOCK_HAVE_DATA ) ) {
// If pruning or running under an assumeutxo snapshot, only go
// back as far as we have data.
2016-05-20 04:59:57 -04:00
LogPrintf ( " VerifyDB(): block verification stopping at height %d (pruning, no data) \n " , pindex - > nHeight ) ;
break ;
}
2012-09-03 16:14:03 -03:00
CBlock block ;
2013-01-03 11:29:07 -03:00
// check level 0: read from disk
2022-02-21 06:43:06 -03:00
if ( ! ReadBlockFromDisk ( block , pindex , consensus_params ) ) {
2015-01-08 07:44:25 -03:00
return error ( " VerifyDB() : * * * ReadBlockFromDisk failed at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2022-02-21 06:43:06 -03:00
}
2012-09-03 16:14:03 -03:00
// check level 1: verify block validity
2022-02-21 06:43:06 -03:00
if ( nCheckLevel > = 1 & & ! CheckBlock ( block , state , consensus_params ) ) {
2016-03-26 12:44:50 -03:00
return error ( " %s: *** found bad block at %d, hash=%s (%s) \n " , __func__ ,
2019-11-08 18:22:36 -03:00
pindex - > nHeight , pindex - > GetBlockHash ( ) . ToString ( ) , state . ToString ( ) ) ;
2022-02-21 06:43:06 -03:00
}
2013-01-03 11:29:07 -03:00
// check level 2: verify undo validity
if ( nCheckLevel > = 2 & & pindex ) {
CBlockUndo undo ;
2017-06-09 12:57:23 -04:00
if ( ! pindex - > GetUndoPos ( ) . IsNull ( ) ) {
if ( ! UndoReadFromDisk ( undo , pindex ) ) {
2015-01-08 07:44:25 -03:00
return error ( " VerifyDB() : * * * found bad undo data at % d , hash = % s \ n " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2017-06-09 12:57:23 -04:00
}
2013-01-03 11:29:07 -03:00
}
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
2021-04-13 10:05:28 -04:00
size_t curr_coins_usage = coins . DynamicMemoryUsage ( ) + chainstate . CoinsTip ( ) . DynamicMemoryUsage ( ) ;
2021-04-13 09:57:20 -04:00
2021-04-13 10:05:28 -04:00
if ( nCheckLevel > = 3 & & curr_coins_usage < = chainstate . m_coinstip_cache_size_bytes ) {
2017-04-19 13:34:30 -03:00
assert ( coins . GetBestBlock ( ) = = pindex - > GetBlockHash ( ) ) ;
2021-04-13 09:57:20 -04:00
DisconnectResult res = chainstate . DisconnectBlock ( block , pindex , coins ) ;
2017-04-28 20:08:39 -03:00
if ( res = = DISCONNECT_FAILED ) {
2015-01-08 07:44:25 -03:00
return error ( " VerifyDB() : * * * irrecoverable inconsistency in block data at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2017-04-28 20:08:39 -03:00
}
if ( res = = DISCONNECT_UNCLEAN ) {
2013-01-03 11:29:07 -03:00
nGoodTransactions = 0 ;
pindexFailure = pindex ;
2017-04-28 20:08:39 -03:00
} else {
2013-01-03 11:29:07 -03:00
nGoodTransactions + = block . vtx . size ( ) ;
2017-04-28 20:08:39 -03:00
}
2012-09-03 16:14:03 -03:00
}
2020-06-02 13:45:19 -04:00
if ( ShutdownRequested ( ) ) return true ;
2012-09-03 16:14:03 -03:00
}
2022-02-21 06:43:06 -03:00
if ( pindexFailure ) {
2021-04-13 09:57:20 -04:00
return error ( " VerifyDB() : * * * coin database inconsistencies found ( last % i blocks , % i good transactions before that ) \ n " , chainstate.m_chain.Height() - pindexFailure->nHeight + 1, nGoodTransactions) ;
2022-02-21 06:43:06 -03:00
}
2013-01-03 11:29:07 -03:00
2018-06-11 03:14:35 -04:00
// store block count as we move pindex at check level >= 4
2021-04-13 09:57:20 -04:00
int block_count = chainstate . m_chain . Height ( ) - pindex - > nHeight ;
2018-06-11 03:14:35 -04:00
2013-01-03 11:29:07 -03:00
// check level 4: try reconnecting blocks
if ( nCheckLevel > = 4 ) {
2021-04-13 09:57:20 -04:00
while ( pindex ! = chainstate . m_chain . Tip ( ) ) {
const int percentageDone = std : : max ( 1 , std : : min ( 99 , 100 - ( int ) ( ( ( double ) ( chainstate . m_chain . Height ( ) - pindex - > nHeight ) ) / ( double ) nCheckDepth * 50 ) ) ) ;
2022-02-21 06:43:06 -03:00
if ( reportDone < percentageDone / 10 ) {
2018-08-08 07:22:13 -04:00
// report every 10% step
LogPrintf ( " [%d%%]... " , percentageDone ) ; /* Continued */
2022-02-21 06:43:06 -03:00
reportDone = percentageDone / 10 ;
2018-08-08 07:22:13 -04:00
}
2021-05-02 14:53:36 -04:00
uiInterface . ShowProgress ( _ ( " Verifying blocks… " ) . translated , percentageDone , false ) ;
2021-04-13 09:57:20 -04:00
pindex = chainstate . m_chain . Next ( pindex ) ;
2013-04-04 06:30:55 -03:00
CBlock block ;
2021-09-20 15:02:07 -03:00
if ( ! ReadBlockFromDisk ( block , pindex , consensus_params ) )
2015-01-08 07:44:25 -03:00
return error ( " VerifyDB() : * * * ReadBlockFromDisk failed at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2021-04-27 16:54:53 -04:00
if ( ! chainstate . ConnectBlock ( block , state , pindex , coins ) ) {
2019-11-08 18:22:36 -03:00
return error ( " VerifyDB() : * * * found unconnectable block at % d , hash = % s ( % s ) " , pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString()) ;
2021-04-27 16:54:53 -04:00
}
2020-06-02 13:45:19 -04:00
if ( ShutdownRequested ( ) ) return true ;
2013-01-03 11:29:07 -03:00
}
2012-09-03 16:14:03 -03:00
}
2016-06-02 07:52:09 -04:00
LogPrintf ( " [DONE]. \n " ) ;
2018-06-11 03:14:35 -04:00
LogPrintf ( " No coin database inconsistencies in last %i blocks (%i transactions) \n " , block_count , nGoodTransactions ) ;
2013-01-03 11:29:07 -03:00
2012-09-03 16:14:03 -03:00
return true ;
}
2017-04-19 13:34:30 -03:00
/** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */
2021-04-27 16:54:53 -04:00
bool CChainState : : RollforwardBlock ( const CBlockIndex * pindex , CCoinsViewCache & inputs )
2017-04-19 13:34:30 -03:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( cs_main ) ;
2017-04-19 13:34:30 -03:00
// TODO: merge with ConnectBlock
CBlock block ;
2021-04-27 16:54:53 -04:00
if ( ! ReadBlockFromDisk ( block , pindex , m_params . GetConsensus ( ) ) ) {
2017-04-19 13:34:30 -03:00
return error ( " ReplayBlock() : ReadBlockFromDisk failed at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
}
for ( const CTransactionRef & tx : block . vtx ) {
if ( ! tx - > IsCoinBase ( ) ) {
for ( const CTxIn & txin : tx - > vin ) {
inputs . SpendCoin ( txin . prevout ) ;
}
}
// Pass check = true as every addition may be an overwrite.
AddCoins ( inputs , * tx , pindex - > nHeight , true ) ;
}
return true ;
}
2021-04-27 16:54:53 -04:00
bool CChainState : : ReplayBlocks ( )
2017-04-19 13:34:30 -03:00
{
LOCK ( cs_main ) ;
2019-03-29 17:43:59 -03:00
CCoinsView & db = this - > CoinsDB ( ) ;
CCoinsViewCache cache ( & db ) ;
2017-04-19 13:34:30 -03:00
2019-03-29 17:43:59 -03:00
std : : vector < uint256 > hashHeads = db . GetHeadBlocks ( ) ;
2017-04-19 13:34:30 -03:00
if ( hashHeads . empty ( ) ) return true ; // We're already in a consistent state.
if ( hashHeads . size ( ) ! = 2 ) return error ( " ReplayBlocks(): unknown inconsistent state " ) ;
2021-05-02 14:53:36 -04:00
uiInterface . ShowProgress ( _ ( " Replaying blocks… " ) . translated , 0 , false ) ;
2017-04-19 13:34:30 -03:00
LogPrintf ( " Replaying blocks \n " ) ;
const CBlockIndex * pindexOld = nullptr ; // Old tip during the interrupted flush.
const CBlockIndex * pindexNew ; // New tip during the interrupted flush.
const CBlockIndex * pindexFork = nullptr ; // Latest block common to both the old and the new tip.
2019-04-10 14:34:46 -04:00
if ( m_blockman . m_block_index . count ( hashHeads [ 0 ] ) = = 0 ) {
2017-04-19 13:34:30 -03:00
return error ( " ReplayBlocks() : reorganization to unknown block requested " ) ;
}
2021-01-08 20:56:48 -03:00
pindexNew = & ( m_blockman . m_block_index [ hashHeads [ 0 ] ] ) ;
2017-04-19 13:34:30 -03:00
if ( ! hashHeads [ 1 ] . IsNull ( ) ) { // The old tip is allowed to be 0, indicating it's the first flush.
2019-04-10 14:34:46 -04:00
if ( m_blockman . m_block_index . count ( hashHeads [ 1 ] ) = = 0 ) {
2017-04-19 13:34:30 -03:00
return error ( " ReplayBlocks() : reorganization from unknown block requested " ) ;
}
2021-01-08 20:56:48 -03:00
pindexOld = & ( m_blockman . m_block_index [ hashHeads [ 1 ] ] ) ;
2017-04-19 13:34:30 -03:00
pindexFork = LastCommonAncestor ( pindexOld , pindexNew ) ;
assert ( pindexFork ! = nullptr ) ;
}
// Rollback along the old branch.
while ( pindexOld ! = pindexFork ) {
if ( pindexOld - > nHeight > 0 ) { // Never disconnect the genesis block.
CBlock block ;
2021-04-27 16:54:53 -04:00
if ( ! ReadBlockFromDisk ( block , pindexOld , m_params . GetConsensus ( ) ) ) {
2017-04-19 13:34:30 -03:00
return error ( " RollbackBlock() : ReadBlockFromDisk ( ) failed at % d , hash = % s " , pindexOld->nHeight, pindexOld->GetBlockHash().ToString()) ;
}
LogPrintf ( " Rolling back %s (%i) \n " , pindexOld - > GetBlockHash ( ) . ToString ( ) , pindexOld - > nHeight ) ;
DisconnectResult res = DisconnectBlock ( block , pindexOld , cache ) ;
if ( res = = DISCONNECT_FAILED ) {
return error ( " RollbackBlock() : DisconnectBlock failed at % d , hash = % s " , pindexOld->nHeight, pindexOld->GetBlockHash().ToString()) ;
}
// If DISCONNECT_UNCLEAN is returned, it means a non-existing UTXO was deleted, or an existing UTXO was
// overwritten. It corresponds to cases where the block-to-be-disconnect never had all its operations
// applied to the UTXO set. However, as both writing a UTXO and deleting a UTXO are idempotent operations,
// the result is still a version of the UTXO set with the effects of that block undone.
}
pindexOld = pindexOld - > pprev ;
}
// Roll forward from the forking point to the new tip.
int nForkHeight = pindexFork ? pindexFork - > nHeight : 0 ;
for ( int nHeight = nForkHeight + 1 ; nHeight < = pindexNew - > nHeight ; + + nHeight ) {
2019-10-21 14:17:22 -03:00
const CBlockIndex & pindex { * Assert ( pindexNew - > GetAncestor ( nHeight ) ) } ;
LogPrintf ( " Rolling forward %s (%i) \n " , pindex . GetBlockHash ( ) . ToString ( ) , nHeight ) ;
2021-05-02 14:53:36 -04:00
uiInterface . ShowProgress ( _ ( " Replaying blocks… " ) . translated , ( int ) ( ( nHeight - nForkHeight ) * 100.0 / ( pindexNew - > nHeight - nForkHeight ) ) , false ) ;
2019-10-21 14:17:22 -03:00
if ( ! RollforwardBlock ( & pindex , cache ) ) return false ;
2017-04-19 13:34:30 -03:00
}
cache . SetBestBlock ( pindexNew - > GetBlockHash ( ) ) ;
cache . Flush ( ) ;
2017-07-07 17:09:55 -04:00
uiInterface . ShowProgress ( " " , 100 , false ) ;
2017-04-19 13:34:30 -03:00
return true ;
}
2021-04-27 16:54:53 -04:00
bool CChainState : : NeedsRedownload ( ) const
2016-03-18 13:20:12 -03:00
{
2019-02-24 17:07:10 -03:00
AssertLockHeld ( cs_main ) ;
2016-03-18 13:20:12 -03:00
2021-04-27 16:54:53 -04:00
// At and above m_params.SegwitHeight, segwit consensus rules must be validated
2021-01-24 20:14:15 -03:00
CBlockIndex * block { m_chain . Tip ( ) } ;
2019-02-13 20:32:34 -03:00
2022-04-14 15:50:53 -04:00
while ( block ! = nullptr & & DeploymentActiveAt ( * block , m_chainman , Consensus : : DEPLOYMENT_SEGWIT ) ) {
2021-01-24 20:14:15 -03:00
if ( ! ( block - > nStatus & BLOCK_OPT_WITNESS ) ) {
// block is insufficiently validated for a segwit client
return true ;
2017-07-06 21:29:46 -04:00
}
2021-01-24 20:14:15 -03:00
block = block - > pprev ;
2016-03-18 13:20:12 -03:00
}
2021-01-24 20:14:15 -03:00
return false ;
2016-03-18 13:20:12 -03:00
}
2022-01-27 07:48:19 -03:00
void CChainState : : UnloadBlockIndex ( )
{
AssertLockHeld ( : : cs_main ) ;
2017-04-25 22:31:08 -03:00
nBlockSequenceId = 1 ;
2017-12-04 11:34:46 -03:00
setBlockIndexCandidates . clear ( ) ;
}
2021-04-27 16:54:53 -04:00
bool ChainstateManager : : LoadBlockIndex ( )
2010-08-29 12:58:15 -04:00
{
2020-04-18 08:27:46 -04:00
AssertLockHeld ( cs_main ) ;
2012-09-03 10:26:57 -03:00
// Load block index from databases
2017-07-06 19:57:20 -04:00
bool needs_init = fReindex ;
if ( ! fReindex ) {
2022-06-01 15:10:10 -04:00
bool ret = m_blockman . LoadBlockIndexDB ( GetConsensus ( ) ) ;
2017-07-06 19:57:20 -04:00
if ( ! ret ) return false ;
2022-03-07 23:42:27 -03:00
2022-03-15 20:28:46 -03:00
std : : vector < CBlockIndex * > vSortedByHeight { m_blockman . GetAllBlockIndices ( ) } ;
2022-03-15 20:19:58 -03:00
std : : sort ( vSortedByHeight . begin ( ) , vSortedByHeight . end ( ) ,
CBlockIndexHeightOnlyComparator ( ) ) ;
2022-03-07 23:42:27 -03:00
// Find start of assumed-valid region.
int first_assumed_valid_height = std : : numeric_limits < int > : : max ( ) ;
for ( const CBlockIndex * block : vSortedByHeight ) {
if ( block - > IsAssumedValid ( ) ) {
auto chainstates = GetAll ( ) ;
// If we encounter an assumed-valid block index entry, ensure that we have
// one chainstate that tolerates assumed-valid entries and another that does
// not (i.e. the background validation chainstate), since assumed-valid
// entries should always be pending validation by a fully-validated chainstate.
auto any_chain = [ & ] ( auto fnc ) { return std : : any_of ( chainstates . cbegin ( ) , chainstates . cend ( ) , fnc ) ; } ;
assert ( any_chain ( [ ] ( auto chainstate ) { return chainstate - > reliesOnAssumedValid ( ) ; } ) ) ;
assert ( any_chain ( [ ] ( auto chainstate ) { return ! chainstate - > reliesOnAssumedValid ( ) ; } ) ) ;
first_assumed_valid_height = block - > nHeight ;
break ;
}
}
for ( CBlockIndex * pindex : vSortedByHeight ) {
if ( ShutdownRequested ( ) ) return false ;
if ( pindex - > IsAssumedValid ( ) | |
( pindex - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & &
( pindex - > HaveTxsDownloaded ( ) | | pindex - > pprev = = nullptr ) ) ) {
// Fill each chainstate's block candidate set. Only add assumed-valid
// blocks to the tip candidate set if the chainstate is allowed to rely on
// assumed-valid blocks.
//
// If all setBlockIndexCandidates contained the assumed-valid blocks, the
// background chainstate's ActivateBestChain() call would add assumed-valid
// blocks to the chain (based on how FindMostWorkChain() works). Obviously
// we don't want this since the purpose of the background validation chain
// is to validate assued-valid blocks.
//
// Note: This is considering all blocks whose height is greater or equal to
// the first assumed-valid block to be assumed-valid blocks, and excluding
// them from the background chainstate's setBlockIndexCandidates set. This
// does mean that some blocks which are not technically assumed-valid
// (later blocks on a fork beginning before the first assumed-valid block)
// might not get added to the background chainstate, but this is ok,
// because they will still be attached to the active chainstate if they
// actually contain more work.
//
// Instead of this height-based approach, an earlier attempt was made at
// detecting "holistically" whether the block index under consideration
// relied on an assumed-valid ancestor, but this proved to be too slow to
// be practical.
for ( CChainState * chainstate : GetAll ( ) ) {
if ( chainstate - > reliesOnAssumedValid ( ) | |
pindex - > nHeight < first_assumed_valid_height ) {
chainstate - > setBlockIndexCandidates . insert ( pindex ) ;
}
}
}
if ( pindex - > nStatus & BLOCK_FAILED_MASK & & ( ! m_best_invalid | | pindex - > nChainWork > m_best_invalid - > nChainWork ) ) {
m_best_invalid = pindex ;
}
2022-03-18 13:35:52 -03:00
if ( pindex - > IsValid ( BLOCK_VALID_TREE ) & & ( m_best_header = = nullptr | | CBlockIndexWorkComparator ( ) ( m_best_header , pindex ) ) )
m_best_header = pindex ;
2022-03-07 23:42:27 -03:00
}
2020-04-18 08:27:46 -04:00
needs_init = m_blockman . m_block_index . empty ( ) ;
2017-07-06 19:57:20 -04:00
}
if ( needs_init ) {
// Everything here is for *new* reindex/DBs. Thus, though
// LoadBlockIndexDB may have set fReindex if we shut down
// mid-reindex previously, we don't check fReindex and
// instead only check it prior to LoadBlockIndexDB to set
// needs_init.
LogPrintf ( " Initializing databases... \n " ) ;
}
2013-01-30 17:43:36 -03:00
return true ;
}
2013-01-10 21:47:57 -03:00
2021-04-27 16:54:53 -04:00
bool CChainState : : LoadGenesisBlock ( )
2015-04-17 09:40:24 -03:00
{
2014-04-15 12:38:25 -03:00
LOCK ( cs_main ) ;
2015-07-31 12:55:05 -03:00
2017-07-06 19:57:20 -04:00
// Check whether we're already initialized by checking for genesis in
2019-04-10 14:34:46 -04:00
// m_blockman.m_block_index. Note that we can't use m_chain here, since it is
2017-07-06 19:57:20 -04:00
// set based on the coins db, not the block index db, which is the only
// thing loaded at this point.
2021-04-27 16:54:53 -04:00
if ( m_blockman . m_block_index . count ( m_params . GenesisBlock ( ) . GetHash ( ) ) )
2013-01-30 17:43:36 -03:00
return true ;
2017-07-06 19:57:20 -04:00
try {
2021-04-27 16:54:53 -04:00
const CBlock & block = m_params . GenesisBlock ( ) ;
2022-01-04 10:04:30 -03:00
FlatFilePos blockPos { m_blockman . SaveBlockToDisk ( block , 0 , m_chain , m_params , nullptr ) } ;
if ( blockPos . IsNull ( ) ) {
2017-07-06 19:57:20 -04:00
return error ( " %s: writing genesis block to disk failed " , __func__ ) ;
2022-01-04 10:04:30 -03:00
}
2022-03-18 13:35:52 -03:00
CBlockIndex * pindex = m_blockman . AddToBlockIndex ( block , m_chainman . m_best_header ) ;
2021-04-27 16:54:53 -04:00
ReceivedBlockTransactions ( block , pindex , blockPos ) ;
2017-07-06 19:57:20 -04:00
} catch ( const std : : runtime_error & e ) {
return error ( " %s: failed to write genesis block: %s " , __func__ , e . what ( ) ) ;
2010-08-29 12:58:15 -04:00
}
return true ;
}
2021-04-27 16:54:53 -04:00
void CChainState : : LoadExternalBlockFile ( FILE * fileIn , FlatFilePos * dbp )
2012-02-20 16:50:26 -03:00
{
2022-01-27 07:48:19 -03:00
AssertLockNotHeld ( m_chainstate_mutex ) ;
2014-10-07 13:06:30 -03:00
// Map of disk positions for blocks with unknown parent (only used for reindex)
2019-01-06 16:46:30 -03:00
static std : : multimap < uint256 , FlatFilePos > mapBlocksUnknownParent ;
2013-04-13 02:13:08 -03:00
int64_t nStart = GetTimeMillis ( ) ;
2012-08-16 18:14:40 -04:00
2012-02-20 16:50:26 -03:00
int nLoaded = 0 ;
2013-01-28 21:44:19 -03:00
try {
2014-09-25 03:53:43 -03:00
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
2016-01-03 14:54:50 -03:00
CBufferedFile blkdat ( fileIn , 2 * MAX_BLOCK_SERIALIZED_SIZE , MAX_BLOCK_SERIALIZED_SIZE + 8 , SER_DISK , CLIENT_VERSION ) ;
2013-04-13 02:13:08 -03:00
uint64_t nRewind = blkdat . GetPos ( ) ;
2014-08-01 16:57:55 -04:00
while ( ! blkdat . eof ( ) ) {
2020-04-27 15:36:05 -04:00
if ( ShutdownRequested ( ) ) return ;
2013-03-07 00:31:26 -03:00
2012-10-27 17:01:38 -03:00
blkdat . SetPos ( nRewind ) ;
nRewind + + ; // start one byte further next time, in case of failure
blkdat . SetLimit ( ) ; // remove former limit
2012-10-21 16:23:13 -03:00
unsigned int nSize = 0 ;
2012-10-27 17:01:38 -03:00
try {
// locate a header
2016-10-04 08:12:23 -03:00
unsigned char buf [ CMessageHeader : : MESSAGE_START_SIZE ] ;
2022-01-02 07:31:25 -03:00
blkdat . FindByte ( m_params . MessageStart ( ) [ 0 ] ) ;
2021-12-16 12:56:44 -03:00
nRewind = blkdat . GetPos ( ) + 1 ;
2018-03-20 21:37:32 -03:00
blkdat > > buf ;
2021-04-27 16:54:53 -04:00
if ( memcmp ( buf , m_params . MessageStart ( ) , CMessageHeader : : MESSAGE_START_SIZE ) ) {
2012-10-27 17:01:38 -03:00
continue ;
2021-04-27 16:54:53 -04:00
}
2012-10-27 17:01:38 -03:00
// read size
2012-02-20 16:50:26 -03:00
blkdat > > nSize ;
2016-01-03 14:54:50 -03:00
if ( nSize < 80 | | nSize > MAX_BLOCK_SERIALIZED_SIZE )
2012-10-27 17:01:38 -03:00
continue ;
2014-12-07 09:29:06 -03:00
} catch ( const std : : exception & ) {
2012-10-21 16:23:13 -03:00
// no valid block header found; don't complain
break ;
}
try {
2012-10-27 17:01:38 -03:00
// read block
2013-04-13 02:13:08 -03:00
uint64_t nBlockPos = blkdat . GetPos ( ) ;
2014-10-07 13:06:30 -03:00
if ( dbp )
dbp - > nPos = nBlockPos ;
2012-10-21 16:23:13 -03:00
blkdat . SetLimit ( nBlockPos + nSize ) ;
2016-12-19 04:24:11 -03:00
std : : shared_ptr < CBlock > pblock = std : : make_shared < CBlock > ( ) ;
CBlock & block = * pblock ;
2014-10-07 16:15:32 -03:00
blkdat > > block ;
2014-10-07 13:06:30 -03:00
nRewind = blkdat . GetPos ( ) ;
2014-10-07 16:15:32 -03:00
uint256 hash = block . GetHash ( ) ;
2018-01-11 20:40:43 -03:00
{
2016-04-20 10:45:41 -03:00
LOCK ( cs_main ) ;
2018-01-11 20:40:43 -03:00
// detect out of order blocks, and store them for later
2021-04-27 16:54:53 -04:00
if ( hash ! = m_params . GetConsensus ( ) . hashGenesisBlock & & ! m_blockman . LookupBlockIndex ( block . hashPrevBlock ) ) {
2018-01-11 20:40:43 -03:00
LogPrint ( BCLog : : REINDEX , " %s: Out of order block %s, parent %s not known \n " , __func__ , hash . ToString ( ) ,
block . hashPrevBlock . ToString ( ) ) ;
if ( dbp )
mapBlocksUnknownParent . insert ( std : : make_pair ( block . hashPrevBlock , * dbp ) ) ;
continue ;
}
// process in case the block isn't known yet
2022-03-02 02:42:57 -03:00
const CBlockIndex * pindex = m_blockman . LookupBlockIndex ( hash ) ;
2018-01-11 21:23:09 -03:00
if ( ! pindex | | ( pindex - > nStatus & BLOCK_HAVE_DATA ) = = 0 ) {
2019-10-24 12:35:42 -03:00
BlockValidationState state ;
2021-04-27 16:54:53 -04:00
if ( AcceptBlock ( pblock , state , nullptr , true , dbp , nullptr ) ) {
2018-01-11 21:23:09 -03:00
nLoaded + + ;
}
if ( state . IsError ( ) ) {
break ;
}
2021-04-27 16:54:53 -04:00
} else if ( hash ! = m_params . GetConsensus ( ) . hashGenesisBlock & & pindex - > nHeight % 1000 = = 0 ) {
LogPrint ( BCLog : : REINDEX , " Block Import: already had block %s at height %d \n " , hash . ToString ( ) , pindex - > nHeight ) ;
2018-01-11 20:40:43 -03:00
}
2014-10-07 16:15:32 -03:00
}
2014-10-07 13:06:30 -03:00
2016-04-28 11:18:45 -03:00
// Activate the genesis block so normal node progress can continue
2021-04-27 16:54:53 -04:00
if ( hash = = m_params . GetConsensus ( ) . hashGenesisBlock ) {
2019-10-24 12:35:42 -03:00
BlockValidationState state ;
2021-04-27 16:54:53 -04:00
if ( ! ActivateBestChain ( state , nullptr ) ) {
2016-04-28 11:18:45 -03:00
break ;
}
2014-10-07 16:15:32 -03:00
}
2014-10-07 13:06:30 -03:00
2020-08-25 17:17:22 -04:00
NotifyHeaderTip ( * this ) ;
2016-04-28 11:18:45 -03:00
2014-10-07 13:06:30 -03:00
// Recursively process earlier encountered successors of this block
2017-01-27 05:43:41 -03:00
std : : deque < uint256 > queue ;
2014-10-07 13:06:30 -03:00
queue . push_back ( hash ) ;
while ( ! queue . empty ( ) ) {
uint256 head = queue . front ( ) ;
queue . pop_front ( ) ;
2019-01-06 16:46:30 -03:00
std : : pair < std : : multimap < uint256 , FlatFilePos > : : iterator , std : : multimap < uint256 , FlatFilePos > : : iterator > range = mapBlocksUnknownParent . equal_range ( head ) ;
2014-10-07 13:06:30 -03:00
while ( range . first ! = range . second ) {
2019-01-06 16:46:30 -03:00
std : : multimap < uint256 , FlatFilePos > : : iterator it = range . first ;
2016-12-19 04:24:11 -03:00
std : : shared_ptr < CBlock > pblockrecursive = std : : make_shared < CBlock > ( ) ;
2021-04-27 16:54:53 -04:00
if ( ReadBlockFromDisk ( * pblockrecursive , it - > second , m_params . GetConsensus ( ) ) ) {
2016-12-25 17:19:40 -03:00
LogPrint ( BCLog : : REINDEX , " %s: Processing out of order child %s of %s \n " , __func__ , pblockrecursive - > GetHash ( ) . ToString ( ) ,
2014-10-07 13:06:30 -03:00
head . ToString ( ) ) ;
2016-04-20 10:45:41 -03:00
LOCK ( cs_main ) ;
2019-10-24 12:35:42 -03:00
BlockValidationState dummy ;
2021-04-27 16:54:53 -04:00
if ( AcceptBlock ( pblockrecursive , dummy , nullptr , true , & it - > second , nullptr ) ) {
2014-10-07 13:06:30 -03:00
nLoaded + + ;
2016-12-19 04:24:11 -03:00
queue . push_back ( pblockrecursive - > GetHash ( ) ) ;
2014-10-07 13:06:30 -03:00
}
}
range . first + + ;
mapBlocksUnknownParent . erase ( it ) ;
2020-08-25 17:17:22 -04:00
NotifyHeaderTip ( * this ) ;
2014-10-07 13:06:30 -03:00
}
2012-02-20 16:50:26 -03:00
}
2014-12-07 09:29:06 -03:00
} catch ( const std : : exception & e ) {
2015-07-31 11:41:06 -03:00
LogPrintf ( " %s: Deserialize or I/O error - %s \n " , __func__ , e . what ( ) ) ;
2012-02-20 16:50:26 -03:00
}
}
2014-12-07 09:29:06 -03:00
} catch ( const std : : runtime_error & e ) {
2014-10-02 17:17:57 -03:00
AbortNode ( std : : string ( " System error: " ) + e . what ( ) ) ;
2012-02-20 16:50:26 -03:00
}
2020-04-27 15:36:05 -04:00
LogPrintf ( " Loaded %i blocks from external file in %dms \n " , nLoaded , GetTimeMillis ( ) - nStart ) ;
2012-02-20 16:50:26 -03:00
}
2010-08-29 12:58:15 -04:00
2021-04-27 16:54:53 -04:00
void CChainState : : CheckBlockIndex ( )
2015-03-13 13:25:34 -03:00
{
if ( ! fCheckBlockIndex ) {
return ;
}
LOCK ( cs_main ) ;
2015-04-09 12:08:39 -03:00
// During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain,
2019-04-10 14:34:46 -04:00
// so we have the genesis block in m_blockman.m_block_index but no active chain. (A few of the
// tests when iterating the block tree require that m_chain has been initialized.)
2019-03-27 11:36:30 -03:00
if ( m_chain . Height ( ) < 0 ) {
2019-04-10 14:34:46 -04:00
assert ( m_blockman . m_block_index . size ( ) < = 1 ) ;
2015-04-09 12:08:39 -03:00
return ;
}
2015-03-13 13:25:34 -03:00
// Build forward-pointing map of the entire block tree.
std : : multimap < CBlockIndex * , CBlockIndex * > forward ;
2022-01-13 14:44:19 -03:00
for ( auto & [ _ , block_index ] : m_blockman . m_block_index ) {
forward . emplace ( block_index . pprev , & block_index ) ;
2015-03-13 13:25:34 -03:00
}
2019-04-10 14:34:46 -04:00
assert ( forward . size ( ) = = m_blockman . m_block_index . size ( ) ) ;
2015-03-13 13:25:34 -03:00
2017-08-07 01:36:37 -04:00
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > rangeGenesis = forward . equal_range ( nullptr ) ;
2015-03-13 13:25:34 -03:00
CBlockIndex * pindex = rangeGenesis . first - > second ;
rangeGenesis . first + + ;
2017-08-07 01:36:37 -04:00
assert ( rangeGenesis . first = = rangeGenesis . second ) ; // There is only one index entry with parent nullptr.
2015-03-13 13:25:34 -03:00
// Iterate over the entire block tree, using depth-first search.
// Along the way, remember whether there are blocks on the path from genesis
// block being explored which are the first to have certain properties.
size_t nNodes = 0 ;
int nHeight = 0 ;
2017-08-07 01:36:37 -04:00
CBlockIndex * pindexFirstInvalid = nullptr ; // Oldest ancestor of pindex which is invalid.
CBlockIndex * pindexFirstMissing = nullptr ; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA.
CBlockIndex * pindexFirstNeverProcessed = nullptr ; // Oldest ancestor of pindex for which nTx == 0.
CBlockIndex * pindexFirstNotTreeValid = nullptr ; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not).
CBlockIndex * pindexFirstNotTransactionsValid = nullptr ; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not).
CBlockIndex * pindexFirstNotChainValid = nullptr ; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not).
CBlockIndex * pindexFirstNotScriptsValid = nullptr ; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not).
while ( pindex ! = nullptr ) {
2015-03-13 13:25:34 -03:00
nNodes + + ;
2017-08-07 01:36:37 -04:00
if ( pindexFirstInvalid = = nullptr & & pindex - > nStatus & BLOCK_FAILED_VALID ) pindexFirstInvalid = pindex ;
2021-04-08 10:04:08 -04:00
// Assumed-valid index entries will not have data since we haven't downloaded the
// full block yet.
if ( pindexFirstMissing = = nullptr & & ! ( pindex - > nStatus & BLOCK_HAVE_DATA ) & & ! pindex - > IsAssumedValid ( ) ) {
pindexFirstMissing = pindex ;
}
2017-08-07 01:36:37 -04:00
if ( pindexFirstNeverProcessed = = nullptr & & pindex - > nTx = = 0 ) pindexFirstNeverProcessed = pindex ;
if ( pindex - > pprev ! = nullptr & & pindexFirstNotTreeValid = = nullptr & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_TREE ) pindexFirstNotTreeValid = pindex ;
2021-04-08 10:04:08 -04:00
if ( pindex - > pprev ! = nullptr & & ! pindex - > IsAssumedValid ( ) ) {
// Skip validity flag checks for BLOCK_ASSUMED_VALID index entries, since these
// *_VALID_MASK flags will not be present for index entries we are temporarily assuming
// valid.
if ( pindexFirstNotTransactionsValid = = nullptr & &
( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_TRANSACTIONS ) {
pindexFirstNotTransactionsValid = pindex ;
}
if ( pindexFirstNotChainValid = = nullptr & &
( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_CHAIN ) {
pindexFirstNotChainValid = pindex ;
}
if ( pindexFirstNotScriptsValid = = nullptr & &
( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_SCRIPTS ) {
pindexFirstNotScriptsValid = pindex ;
}
}
2015-03-13 13:25:34 -03:00
// Begin: actual consistency checks.
2017-08-07 01:36:37 -04:00
if ( pindex - > pprev = = nullptr ) {
2015-03-13 13:25:34 -03:00
// Genesis block checks.
2021-04-27 16:54:53 -04:00
assert ( pindex - > GetBlockHash ( ) = = m_params . GetConsensus ( ) . hashGenesisBlock ) ; // Genesis block's hash must match.
2019-03-27 11:36:30 -03:00
assert ( pindex = = m_chain . Genesis ( ) ) ; // The current active chain's genesis block must be this block.
2015-03-13 13:25:34 -03:00
}
2018-12-03 20:14:08 -03:00
if ( ! pindex - > HaveTxsDownloaded ( ) ) assert ( pindex - > nSequenceId < = 0 ) ; // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
2021-04-08 10:04:08 -04:00
// Unless these indexes are assumed valid and pending block download on a
// background chainstate.
2022-03-18 13:35:52 -03:00
if ( ! m_blockman . m_have_pruned & & ! pindex - > IsAssumedValid ( ) ) {
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// If we've never pruned, then HAVE_DATA should be equivalent to nTx > 0
assert ( ! ( pindex - > nStatus & BLOCK_HAVE_DATA ) = = ( pindex - > nTx = = 0 ) ) ;
assert ( pindexFirstMissing = = pindexFirstNeverProcessed ) ;
} else {
// If we have pruned, then we can only say that HAVE_DATA implies nTx > 0
if ( pindex - > nStatus & BLOCK_HAVE_DATA ) assert ( pindex - > nTx > 0 ) ;
}
if ( pindex - > nStatus & BLOCK_HAVE_UNDO ) assert ( pindex - > nStatus & BLOCK_HAVE_DATA ) ;
2021-04-08 10:04:08 -04:00
if ( pindex - > IsAssumedValid ( ) ) {
// Assumed-valid blocks should have some nTx value.
assert ( pindex - > nTx > 0 ) ;
// Assumed-valid blocks should connect to the main chain.
assert ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_TREE ) ;
} else {
// Otherwise there should only be an nTx value if we have
// actually seen a block's transactions.
assert ( ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_TRANSACTIONS ) = = ( pindex - > nTx > 0 ) ) ; // This is pruning-independent.
}
2018-12-03 20:14:08 -03:00
// All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to HaveTxsDownloaded().
assert ( ( pindexFirstNeverProcessed = = nullptr ) = = pindex - > HaveTxsDownloaded ( ) ) ;
assert ( ( pindexFirstNotTransactionsValid = = nullptr ) = = pindex - > HaveTxsDownloaded ( ) ) ;
2015-03-13 13:25:34 -03:00
assert ( pindex - > nHeight = = nHeight ) ; // nHeight must be consistent.
2017-08-07 01:36:37 -04:00
assert ( pindex - > pprev = = nullptr | | pindex - > nChainWork > = pindex - > pprev - > nChainWork ) ; // For every block except the genesis block, the chainwork must be larger than the parent's.
2015-03-13 13:25:34 -03:00
assert ( nHeight < 2 | | ( pindex - > pskip & & ( pindex - > pskip - > nHeight < nHeight ) ) ) ; // The pskip pointer must point back for all but the first 2 blocks.
2019-04-10 14:34:46 -04:00
assert ( pindexFirstNotTreeValid = = nullptr ) ; // All m_blockman.m_block_index entries must at least be TREE valid
2017-08-07 01:36:37 -04:00
if ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_TREE ) assert ( pindexFirstNotTreeValid = = nullptr ) ; // TREE valid implies all parents are TREE valid
if ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_CHAIN ) assert ( pindexFirstNotChainValid = = nullptr ) ; // CHAIN valid implies all parents are CHAIN valid
if ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_SCRIPTS ) assert ( pindexFirstNotScriptsValid = = nullptr ) ; // SCRIPTS valid implies all parents are SCRIPTS valid
if ( pindexFirstInvalid = = nullptr ) {
2015-03-13 13:25:34 -03:00
// Checks for not-invalid blocks.
assert ( ( pindex - > nStatus & BLOCK_FAILED_MASK ) = = 0 ) ; // The failed mask cannot be set for blocks without invalid parents.
}
2019-03-27 11:36:30 -03:00
if ( ! CBlockIndexWorkComparator ( ) ( pindex , m_chain . Tip ( ) ) & & pindexFirstNeverProcessed = = nullptr ) {
2017-08-07 01:36:37 -04:00
if ( pindexFirstInvalid = = nullptr ) {
2021-04-08 10:04:08 -04:00
const bool is_active = this = = & m_chainman . ActiveChainstate ( ) ;
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// If this block sorts at least as good as the current tip and
// is valid and we have all data for its parents, it must be in
2019-03-27 11:36:30 -03:00
// setBlockIndexCandidates. m_chain.Tip() must also be there
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// even if some data has been pruned.
2021-04-08 10:04:08 -04:00
//
// Don't perform this check for the background chainstate since
// its setBlockIndexCandidates shouldn't have some entries (i.e. those past the
// snapshot block) which do exist in the block index for the active chainstate.
if ( is_active & & ( pindexFirstMissing = = nullptr | | pindex = = m_chain . Tip ( ) ) ) {
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
assert ( setBlockIndexCandidates . count ( pindex ) ) ;
}
// If some parent is missing, then it could be that this block was in
// setBlockIndexCandidates but had to be removed because of the missing data.
2019-03-27 18:07:32 -03:00
// In this case it must be in m_blocks_unlinked -- see test below.
2015-03-13 13:25:34 -03:00
}
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
} else { // If this block sorts worse than the current tip or some ancestor's block has never been seen, it cannot be in setBlockIndexCandidates.
2015-03-13 13:25:34 -03:00
assert ( setBlockIndexCandidates . count ( pindex ) = = 0 ) ;
}
2019-03-27 18:07:32 -03:00
// Check whether this block is in m_blocks_unlinked.
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > rangeUnlinked = m_blockman . m_blocks_unlinked . equal_range ( pindex - > pprev ) ;
2015-03-13 13:25:34 -03:00
bool foundInUnlinked = false ;
while ( rangeUnlinked . first ! = rangeUnlinked . second ) {
assert ( rangeUnlinked . first - > first = = pindex - > pprev ) ;
if ( rangeUnlinked . first - > second = = pindex ) {
foundInUnlinked = true ;
break ;
}
rangeUnlinked . first + + ;
}
2017-08-07 01:36:37 -04:00
if ( pindex - > pprev & & ( pindex - > nStatus & BLOCK_HAVE_DATA ) & & pindexFirstNeverProcessed ! = nullptr & & pindexFirstInvalid = = nullptr ) {
2019-03-27 18:07:32 -03:00
// If this block has block data available, some parent was never received, and has no invalid parents, it must be in m_blocks_unlinked.
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
assert ( foundInUnlinked ) ;
}
2019-03-27 18:07:32 -03:00
if ( ! ( pindex - > nStatus & BLOCK_HAVE_DATA ) ) assert ( ! foundInUnlinked ) ; // Can't be in m_blocks_unlinked if we don't HAVE_DATA
if ( pindexFirstMissing = = nullptr ) assert ( ! foundInUnlinked ) ; // We aren't missing data for any parent -- cannot be in m_blocks_unlinked.
2017-08-07 01:36:37 -04:00
if ( pindex - > pprev & & ( pindex - > nStatus & BLOCK_HAVE_DATA ) & & pindexFirstNeverProcessed = = nullptr & & pindexFirstMissing ! = nullptr ) {
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// We HAVE_DATA for this block, have received data for all parents at some point, but we're currently missing data for some parent.
2022-03-18 13:35:52 -03:00
assert ( m_blockman . m_have_pruned ) ; // We must have pruned.
2019-03-27 18:07:32 -03:00
// This block may have entered m_blocks_unlinked if:
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// - it has a descendant that at some point had more work than the
// tip, and
// - we tried switching to that descendant but were missing
2019-03-27 11:36:30 -03:00
// data for some intermediate block between m_chain and the
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
// tip.
2019-03-27 11:36:30 -03:00
// So if this block is itself better than m_chain.Tip() and it wasn't in
2019-03-27 18:07:32 -03:00
// setBlockIndexCandidates, then it must be in m_blocks_unlinked.
2019-03-27 11:36:30 -03:00
if ( ! CBlockIndexWorkComparator ( ) ( pindex , m_chain . Tip ( ) ) & & setBlockIndexCandidates . count ( pindex ) = = 0 ) {
2017-08-07 01:36:37 -04:00
if ( pindexFirstInvalid = = nullptr ) {
Add block pruning functionality
This adds a -prune=N option to bitcoind, which if set to N>0 will enable block
file pruning. When pruning is enabled, block and undo files will be deleted to
try to keep total space used by those files to below the prune target (N, in
MB) specified by the user, subject to some constraints:
- The last 288 blocks on the main chain are always kept (MIN_BLOCKS_TO_KEEP),
- N must be at least 550MB (chosen as a value for the target that could
reasonably be met, with some assumptions about block sizes, orphan rates,
etc; see comment in main.h),
- No blocks are pruned until chainActive is at least 100,000 blocks long (on
mainnet; defined separately for mainnet, testnet, and regtest in chainparams
as nPruneAfterHeight).
This unsets NODE_NETWORK if pruning is enabled.
Also included is an RPC test for pruning (pruning.py).
Thanks to @rdponticelli for earlier work on this feature; this is based in
part off that work.
2015-02-23 16:27:44 -03:00
assert ( foundInUnlinked ) ;
}
2015-03-13 13:25:34 -03:00
}
}
// assert(pindex->GetBlockHash() == pindex->GetBlockHeader().GetHash()); // Perhaps too slow
// End: actual consistency checks.
// Try descending into the first subnode.
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > range = forward . equal_range ( pindex ) ;
if ( range . first ! = range . second ) {
// A subnode was found.
pindex = range . first - > second ;
nHeight + + ;
continue ;
}
// This is a leaf node.
// Move upwards until we reach a node of which we have not yet visited the last child.
while ( pindex ) {
// We are going to either move to a parent or a sibling of pindex.
// If pindex was the first with a certain property, unset the corresponding variable.
2017-08-07 01:36:37 -04:00
if ( pindex = = pindexFirstInvalid ) pindexFirstInvalid = nullptr ;
if ( pindex = = pindexFirstMissing ) pindexFirstMissing = nullptr ;
if ( pindex = = pindexFirstNeverProcessed ) pindexFirstNeverProcessed = nullptr ;
if ( pindex = = pindexFirstNotTreeValid ) pindexFirstNotTreeValid = nullptr ;
if ( pindex = = pindexFirstNotTransactionsValid ) pindexFirstNotTransactionsValid = nullptr ;
if ( pindex = = pindexFirstNotChainValid ) pindexFirstNotChainValid = nullptr ;
if ( pindex = = pindexFirstNotScriptsValid ) pindexFirstNotScriptsValid = nullptr ;
2015-03-13 13:25:34 -03:00
// Find our parent.
CBlockIndex * pindexPar = pindex - > pprev ;
// Find which child we just visited.
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > rangePar = forward . equal_range ( pindexPar ) ;
while ( rangePar . first - > second ! = pindex ) {
assert ( rangePar . first ! = rangePar . second ) ; // Our parent must have at least the node we're coming from as child.
rangePar . first + + ;
}
// Proceed to the next one.
rangePar . first + + ;
if ( rangePar . first ! = rangePar . second ) {
// Move to the sibling.
pindex = rangePar . first - > second ;
break ;
} else {
// Move up further.
pindex = pindexPar ;
nHeight - - ;
continue ;
}
}
}
// Check that we actually traversed the entire map.
assert ( nNodes = = forward . size ( ) ) ;
}
2019-12-12 12:20:44 -03:00
std : : string CChainState : : ToString ( )
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2019-12-12 12:20:44 -03:00
CBlockIndex * tip = m_chain . Tip ( ) ;
return strprintf ( " Chainstate [%s] @ height %d (%s) " ,
2021-04-03 12:26:39 -03:00
m_from_snapshot_blockhash ? " snapshot " : " ibd " ,
tip ? tip - > nHeight : - 1 , tip ? tip - > GetBlockHash ( ) . ToString ( ) : " null " ) ;
2019-12-12 12:20:44 -03:00
}
2019-09-16 16:01:12 -03:00
bool CChainState : : ResizeCoinsCaches ( size_t coinstip_size , size_t coinsdb_size )
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2019-09-16 16:01:12 -03:00
if ( coinstip_size = = m_coinstip_cache_size_bytes & &
coinsdb_size = = m_coinsdb_cache_size_bytes ) {
// Cache sizes are unchanged, no need to continue.
return true ;
}
size_t old_coinstip_size = m_coinstip_cache_size_bytes ;
m_coinstip_cache_size_bytes = coinstip_size ;
m_coinsdb_cache_size_bytes = coinsdb_size ;
CoinsDB ( ) . ResizeCache ( coinsdb_size ) ;
LogPrintf ( " [%s] resized coinsdb cache to %.1f MiB \n " ,
this - > ToString ( ) , coinsdb_size * ( 1.0 / 1024 / 1024 ) ) ;
LogPrintf ( " [%s] resized coinstip cache to %.1f MiB \n " ,
this - > ToString ( ) , coinstip_size * ( 1.0 / 1024 / 1024 ) ) ;
BlockValidationState state ;
bool ret ;
if ( coinstip_size > old_coinstip_size ) {
// Likely no need to flush if cache sizes have grown.
2021-04-27 16:54:53 -04:00
ret = FlushStateToDisk ( state , FlushStateMode : : IF_NEEDED ) ;
2019-09-16 16:01:12 -03:00
} else {
// Otherwise, flush state to disk and deallocate the in-memory coins map.
2021-04-27 16:54:53 -04:00
ret = FlushStateToDisk ( state , FlushStateMode : : ALWAYS ) ;
2019-09-16 16:01:12 -03:00
CoinsTip ( ) . ReallocateCache ( ) ;
}
return ret ;
}
2016-12-01 20:45:50 -03:00
static const uint64_t MEMPOOL_DUMP_VERSION = 1 ;
2010-08-29 12:58:15 -04:00
2020-06-12 10:17:44 -04:00
bool LoadMempool ( CTxMemPool & pool , CChainState & active_chainstate , FopenFn mockable_fopen_function )
2016-10-31 03:53:38 -03:00
{
2021-05-04 07:00:25 -04:00
FILE * filestr { mockable_fopen_function ( gArgs . GetDataDirNet ( ) / " mempool.dat " , " rb " ) } ;
2016-10-31 03:53:38 -03:00
CAutoFile file ( filestr , SER_DISK , CLIENT_VERSION ) ;
if ( file . IsNull ( ) ) {
LogPrintf ( " Failed to open mempool file from disk. Continuing anyway. \n " ) ;
return false ;
}
int64_t count = 0 ;
2017-08-16 05:19:02 -03:00
int64_t expired = 0 ;
2016-10-31 03:53:38 -03:00
int64_t failed = 0 ;
2017-08-16 05:19:02 -03:00
int64_t already_there = 0 ;
2020-03-17 14:39:25 -03:00
int64_t unbroadcast = 0 ;
2022-06-29 13:28:45 -04:00
auto now = NodeClock : : now ( ) ;
2016-10-31 03:53:38 -03:00
try {
uint64_t version ;
file > > version ;
if ( version ! = MEMPOOL_DUMP_VERSION ) {
return false ;
}
uint64_t num ;
file > > num ;
2022-02-01 12:08:57 -03:00
while ( num ) {
- - num ;
2016-11-11 03:29:19 -03:00
CTransactionRef tx ;
2016-10-31 03:53:38 -03:00
int64_t nTime ;
int64_t nFeeDelta ;
2016-11-11 03:29:19 -03:00
file > > tx ;
2016-10-31 03:53:38 -03:00
file > > nTime ;
file > > nFeeDelta ;
CAmount amountdelta = nFeeDelta ;
if ( amountdelta ) {
2019-03-07 11:54:44 -03:00
pool . PrioritiseTransaction ( tx - > GetHash ( ) , amountdelta ) ;
2016-10-31 03:53:38 -03:00
}
2022-06-29 13:28:45 -04:00
if ( nTime > TicksSinceEpoch < std : : chrono : : seconds > ( now - pool . m_expiry ) ) {
2016-10-31 03:53:38 -03:00
LOCK ( cs_main ) ;
2021-12-02 01:50:27 -03:00
const auto & accepted = AcceptToMemoryPool ( active_chainstate , tx , nTime , /*bypass_limits=*/ false , /*test_accept=*/ false ) ;
if ( accepted . m_result_type = = MempoolAcceptResult : : ResultType : : VALID ) {
2016-10-31 03:53:38 -03:00
+ + count ;
} else {
2017-08-16 05:19:02 -03:00
// mempool may contain the transaction already, e.g. from
// wallet(s) having loaded it while we were processing
// mempool transactions; consider these as valid, instead of
// failed, but mark them as 'already there'
2021-10-20 12:41:45 -03:00
if ( pool . exists ( GenTxid : : Txid ( tx - > GetHash ( ) ) ) ) {
2017-08-16 05:19:02 -03:00
+ + already_there ;
} else {
+ + failed ;
}
2016-10-31 03:53:38 -03:00
}
} else {
2017-08-16 05:19:02 -03:00
+ + expired ;
2016-10-31 03:53:38 -03:00
}
2016-12-22 16:11:26 -03:00
if ( ShutdownRequested ( ) )
return false ;
2016-10-31 03:53:38 -03:00
}
std : : map < uint256 , CAmount > mapDeltas ;
file > > mapDeltas ;
for ( const auto & i : mapDeltas ) {
2019-03-07 11:54:44 -03:00
pool . PrioritiseTransaction ( i . first , i . second ) ;
2016-10-31 03:53:38 -03:00
}
2020-03-17 14:39:25 -03:00
2020-07-28 00:30:50 -04:00
std : : set < uint256 > unbroadcast_txids ;
2021-01-04 17:02:29 -03:00
file > > unbroadcast_txids ;
unbroadcast = unbroadcast_txids . size ( ) ;
2020-07-28 00:30:50 -04:00
for ( const auto & txid : unbroadcast_txids ) {
// Ensure transactions were accepted to mempool then add to
// unbroadcast set.
if ( pool . get ( txid ) ! = nullptr ) pool . AddUnbroadcastTx ( txid ) ;
2020-04-30 21:20:01 -04:00
}
2016-10-31 03:53:38 -03:00
} catch ( const std : : exception & e ) {
LogPrintf ( " Failed to deserialize mempool data on disk: %s. Continuing anyway. \n " , e . what ( ) ) ;
return false ;
}
2020-03-17 14:39:25 -03:00
LogPrintf ( " Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there, %i waiting for initial broadcast \n " , count , failed , expired , already_there , unbroadcast ) ;
2016-10-31 03:53:38 -03:00
return true ;
}
2022-07-12 15:54:11 -04:00
bool DumpMempool ( const CTxMemPool & pool , const fs : : path & dump_path , FopenFn mockable_fopen_function , bool skip_file_commit )
2016-10-31 03:53:38 -03:00
{
2022-05-16 14:09:48 -04:00
auto start = SteadyClock : : now ( ) ;
2016-10-31 03:53:38 -03:00
std : : map < uint256 , CAmount > mapDeltas ;
std : : vector < TxMempoolInfo > vinfo ;
2020-07-28 00:30:50 -04:00
std : : set < uint256 > unbroadcast_txids ;
2016-10-31 03:53:38 -03:00
2018-03-30 13:48:20 -03:00
static Mutex dump_mutex ;
LOCK ( dump_mutex ) ;
2016-10-31 03:53:38 -03:00
{
2019-03-07 11:54:44 -03:00
LOCK ( pool . cs ) ;
for ( const auto & i : pool . mapDeltas ) {
2017-01-20 01:37:15 -03:00
mapDeltas [ i . first ] = i . second ;
2016-10-31 03:53:38 -03:00
}
2019-03-07 11:54:44 -03:00
vinfo = pool . infoAll ( ) ;
2020-03-17 14:39:25 -03:00
unbroadcast_txids = pool . GetUnbroadcastTxs ( ) ;
2016-10-31 03:53:38 -03:00
}
2022-05-16 14:09:48 -04:00
auto mid = SteadyClock : : now ( ) ;
2016-10-31 03:53:38 -03:00
try {
2022-07-12 15:54:11 -04:00
FILE * filestr { mockable_fopen_function ( dump_path + " .new " , " wb " ) } ;
2016-10-31 03:53:38 -03:00
if ( ! filestr ) {
2017-08-21 08:22:23 -03:00
return false ;
2016-10-31 03:53:38 -03:00
}
CAutoFile file ( filestr , SER_DISK , CLIENT_VERSION ) ;
uint64_t version = MEMPOOL_DUMP_VERSION ;
file < < version ;
file < < ( uint64_t ) vinfo . size ( ) ;
for ( const auto & i : vinfo ) {
file < < * ( i . tx ) ;
2019-09-18 14:31:59 -03:00
file < < int64_t { count_seconds ( i . m_time ) } ;
file < < int64_t { i . nFeeDelta } ;
2016-10-31 03:53:38 -03:00
mapDeltas . erase ( i . tx - > GetHash ( ) ) ;
}
file < < mapDeltas ;
2020-03-17 14:39:25 -03:00
LogPrintf ( " Writing %d unbroadcast transactions to disk. \n " , unbroadcast_txids . size ( ) ) ;
file < < unbroadcast_txids ;
2020-06-12 10:17:44 -04:00
if ( ! skip_file_commit & & ! FileCommit ( file . Get ( ) ) )
2018-04-20 06:21:08 -03:00
throw std : : runtime_error ( " FileCommit failed " ) ;
2016-10-31 03:53:38 -03:00
file . fclose ( ) ;
2022-07-12 15:54:11 -04:00
if ( ! RenameOver ( dump_path + " .new " , dump_path ) ) {
2020-11-27 09:41:07 -03:00
throw std : : runtime_error ( " Rename failed " ) ;
}
2022-05-16 14:09:48 -04:00
auto last = SteadyClock : : now ( ) ;
LogPrintf ( " Dumped mempool: %gs to copy, %gs to dump \n " ,
Ticks < SecondsDouble > ( mid - start ) ,
Ticks < SecondsDouble > ( last - mid ) ) ;
2016-10-31 03:53:38 -03:00
} catch ( const std : : exception & e ) {
LogPrintf ( " Failed to dump mempool: %s. Continuing anyway. \n " , e . what ( ) ) ;
2017-08-21 08:22:23 -03:00
return false ;
2016-10-31 03:53:38 -03:00
}
2017-08-21 08:22:23 -03:00
return true ;
2016-10-31 03:53:38 -03:00
}
2017-01-04 12:09:02 -03:00
//! Guess how far we are in the verification process at the given block index
2018-01-28 16:15:18 -03:00
//! require cs_main if pindex has not been validated yet (because nChainTx might be unset)
2017-04-25 22:31:08 -03:00
double GuessVerificationProgress ( const ChainTxData & data , const CBlockIndex * pindex ) {
2017-08-07 01:36:37 -04:00
if ( pindex = = nullptr )
2017-01-04 12:09:02 -03:00
return 0.0 ;
2017-08-07 01:36:37 -04:00
int64_t nNow = time ( nullptr ) ;
2017-01-04 12:09:02 -03:00
2017-01-04 18:09:20 -03:00
double fTxTotal ;
2017-01-04 12:09:02 -03:00
2017-01-04 12:35:39 -03:00
if ( pindex - > nChainTx < = data . nTxCount ) {
fTxTotal = data . nTxCount + ( nNow - data . nTime ) * data . dTxRate ;
2017-01-04 12:09:02 -03:00
} else {
2017-01-04 12:35:39 -03:00
fTxTotal = pindex - > nChainTx + ( nNow - pindex - > GetBlockTime ( ) ) * data . dTxRate ;
2017-01-04 12:09:02 -03:00
}
2019-10-31 11:40:14 -03:00
return std : : min < double > ( pindex - > nChainTx / fTxTotal , 1.0 ) ;
2017-01-04 12:09:02 -03:00
}
2021-04-03 12:26:39 -03:00
std : : optional < uint256 > ChainstateManager : : SnapshotBlockhash ( ) const
{
2021-01-27 18:20:59 -03:00
LOCK ( : : cs_main ) ;
2021-04-03 12:26:39 -03:00
if ( m_active_chainstate & & m_active_chainstate - > m_from_snapshot_blockhash ) {
2019-12-12 12:20:44 -03:00
// If a snapshot chainstate exists, it will always be our active.
return m_active_chainstate - > m_from_snapshot_blockhash ;
}
2021-03-22 00:22:06 -03:00
return std : : nullopt ;
2019-12-12 12:20:44 -03:00
}
std : : vector < CChainState * > ChainstateManager : : GetAll ( )
{
2021-01-27 18:20:59 -03:00
LOCK ( : : cs_main ) ;
2019-12-12 12:20:44 -03:00
std : : vector < CChainState * > out ;
if ( ! IsSnapshotValidated ( ) & & m_ibd_chainstate ) {
out . push_back ( m_ibd_chainstate . get ( ) ) ;
}
if ( m_snapshot_chainstate ) {
out . push_back ( m_snapshot_chainstate . get ( ) ) ;
}
return out ;
}
2021-07-06 17:05:25 -04:00
CChainState & ChainstateManager : : InitializeChainstate (
CTxMemPool * mempool , const std : : optional < uint256 > & snapshot_blockhash )
2019-12-12 12:20:44 -03:00
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2021-04-03 12:26:39 -03:00
bool is_snapshot = snapshot_blockhash . has_value ( ) ;
2019-12-12 12:20:44 -03:00
std : : unique_ptr < CChainState > & to_modify =
is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate ;
if ( to_modify ) {
throw std : : logic_error ( " should not be overwriting a chainstate " ) ;
}
2021-06-12 10:52:40 -04:00
to_modify . reset ( new CChainState ( mempool , m_blockman , * this , snapshot_blockhash ) ) ;
2019-12-12 12:20:44 -03:00
// Snapshot chainstates and initial IBD chaintates always become active.
if ( is_snapshot | | ( ! is_snapshot & & ! m_active_chainstate ) ) {
LogPrintf ( " Switching active chainstate to %s \n " , to_modify - > ToString ( ) ) ;
m_active_chainstate = to_modify . get ( ) ;
} else {
throw std : : logic_error ( " unexpected chainstate activation " ) ;
}
return * to_modify ;
}
2019-04-25 11:09:29 -04:00
const AssumeutxoData * ExpectedAssumeutxo (
const int height , const CChainParams & chainparams )
{
const MapAssumeutxo & valid_assumeutxos_map = chainparams . Assumeutxo ( ) ;
const auto assumeutxo_found = valid_assumeutxos_map . find ( height ) ;
if ( assumeutxo_found ! = valid_assumeutxos_map . end ( ) ) {
return & assumeutxo_found - > second ;
}
return nullptr ;
}
2020-08-25 13:50:23 -04:00
bool ChainstateManager : : ActivateSnapshot (
CAutoFile & coins_file ,
const SnapshotMetadata & metadata ,
bool in_memory )
{
uint256 base_blockhash = metadata . m_base_blockhash ;
if ( this - > SnapshotBlockhash ( ) ) {
LogPrintf ( " [snapshot] can't activate a snapshot-based chainstate more than once \n " ) ;
return false ;
}
int64_t current_coinsdb_cache_size { 0 } ;
int64_t current_coinstip_cache_size { 0 } ;
// Cache percentages to allocate to each chainstate.
//
// These particular percentages don't matter so much since they will only be
// relevant during snapshot activation; caches are rebalanced at the conclusion of
// this function. We want to give (essentially) all available cache capacity to the
// snapshot to aid the bulk load later in this function.
static constexpr double IBD_CACHE_PERC = 0.01 ;
static constexpr double SNAPSHOT_CACHE_PERC = 0.99 ;
{
LOCK ( : : cs_main ) ;
// Resize the coins caches to ensure we're not exceeding memory limits.
//
// Allocate the majority of the cache to the incoming snapshot chainstate, since
// (optimistically) getting to its tip will be the top priority. We'll need to call
// `MaybeRebalanceCaches()` once we're done with this function to ensure
// the right allocation (including the possibility that no snapshot was activated
// and that we should restore the active chainstate caches to their original size).
//
current_coinsdb_cache_size = this - > ActiveChainstate ( ) . m_coinsdb_cache_size_bytes ;
current_coinstip_cache_size = this - > ActiveChainstate ( ) . m_coinstip_cache_size_bytes ;
// Temporarily resize the active coins cache to make room for the newly-created
// snapshot chain.
this - > ActiveChainstate ( ) . ResizeCoinsCaches (
static_cast < size_t > ( current_coinstip_cache_size * IBD_CACHE_PERC ) ,
static_cast < size_t > ( current_coinsdb_cache_size * IBD_CACHE_PERC ) ) ;
}
2021-06-12 10:52:40 -04:00
auto snapshot_chainstate = WITH_LOCK ( : : cs_main ,
return std : : make_unique < CChainState > (
2022-04-06 09:41:11 -04:00
/*mempool=*/ nullptr , m_blockman , * this , base_blockhash ) ) ;
2020-08-25 13:50:23 -04:00
{
LOCK ( : : cs_main ) ;
snapshot_chainstate - > InitCoinsDB (
static_cast < size_t > ( current_coinsdb_cache_size * SNAPSHOT_CACHE_PERC ) ,
in_memory , false , " chainstate " ) ;
snapshot_chainstate - > InitCoinsCache (
static_cast < size_t > ( current_coinstip_cache_size * SNAPSHOT_CACHE_PERC ) ) ;
}
const bool snapshot_ok = this - > PopulateAndValidateSnapshot (
* snapshot_chainstate , coins_file , metadata ) ;
if ( ! snapshot_ok ) {
WITH_LOCK ( : : cs_main , this - > MaybeRebalanceCaches ( ) ) ;
return false ;
}
{
LOCK ( : : cs_main ) ;
assert ( ! m_snapshot_chainstate ) ;
m_snapshot_chainstate . swap ( snapshot_chainstate ) ;
2021-04-27 16:54:53 -04:00
const bool chaintip_loaded = m_snapshot_chainstate - > LoadChainTip ( ) ;
2020-08-25 13:50:23 -04:00
assert ( chaintip_loaded ) ;
m_active_chainstate = m_snapshot_chainstate . get ( ) ;
LogPrintf ( " [snapshot] successfully activated snapshot %s \n " , base_blockhash . ToString ( ) ) ;
LogPrintf ( " [snapshot] (%.2f MB) \n " ,
m_snapshot_chainstate - > CoinsTip ( ) . DynamicMemoryUsage ( ) / ( 1000 * 1000 ) ) ;
this - > MaybeRebalanceCaches ( ) ;
}
return true ;
}
2021-12-10 13:12:27 -03:00
static void FlushSnapshotToDisk ( CCoinsViewCache & coins_cache , bool snapshot_loaded )
{
2021-12-10 13:16:34 -03:00
LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE (
strprintf ( " %s (%.2f MB) " ,
snapshot_loaded ? " saving snapshot chainstate " : " flushing coins cache " ,
coins_cache . DynamicMemoryUsage ( ) / ( 1000 * 1000 ) ) ,
BCLog : : LogFlags : : ALL ) ;
2021-12-10 13:12:27 -03:00
coins_cache . Flush ( ) ;
}
2020-08-25 13:50:23 -04:00
bool ChainstateManager : : PopulateAndValidateSnapshot (
CChainState & snapshot_chainstate ,
CAutoFile & coins_file ,
const SnapshotMetadata & metadata )
{
// It's okay to release cs_main before we're done using `coins_cache` because we know
// that nothing else will be referencing the newly created snapshot_chainstate yet.
CCoinsViewCache & coins_cache = * WITH_LOCK ( : : cs_main , return & snapshot_chainstate . CoinsTip ( ) ) ;
uint256 base_blockhash = metadata . m_base_blockhash ;
2021-04-04 02:23:06 -04:00
CBlockIndex * snapshot_start_block = WITH_LOCK ( : : cs_main , return m_blockman . LookupBlockIndex ( base_blockhash ) ) ;
if ( ! snapshot_start_block ) {
2022-02-16 17:23:11 -03:00
// Needed for ComputeUTXOStats and ExpectedAssumeutxo to determine the
// height and to avoid a crash when base_blockhash.IsNull()
2021-04-04 02:23:06 -04:00
LogPrintf ( " [snapshot] Did not find snapshot start blockheader %s \n " ,
base_blockhash . ToString ( ) ) ;
return false ;
}
int base_height = snapshot_start_block - > nHeight ;
2022-04-14 15:41:19 -04:00
auto maybe_au_data = ExpectedAssumeutxo ( base_height , GetParams ( ) ) ;
2021-04-04 02:23:06 -04:00
if ( ! maybe_au_data ) {
LogPrintf ( " [snapshot] assumeutxo height in snapshot metadata not recognized " /* Continued */
" (%d) - refusing to load snapshot \n " , base_height ) ;
return false ;
}
const AssumeutxoData & au_data = * maybe_au_data ;
2020-08-25 13:50:23 -04:00
COutPoint outpoint ;
Coin coin ;
const uint64_t coins_count = metadata . m_coins_count ;
uint64_t coins_left = metadata . m_coins_count ;
LogPrintf ( " [snapshot] loading coins from snapshot %s \n " , base_blockhash . ToString ( ) ) ;
int64_t coins_processed { 0 } ;
while ( coins_left > 0 ) {
try {
coins_file > > outpoint ;
2021-04-03 12:13:17 -03:00
coins_file > > coin ;
2020-08-25 13:50:23 -04:00
} catch ( const std : : ios_base : : failure & ) {
2021-04-03 12:13:17 -03:00
LogPrintf ( " [snapshot] bad snapshot format or truncated snapshot after deserializing %d coins \n " ,
coins_count - coins_left ) ;
2020-08-25 13:50:23 -04:00
return false ;
}
2021-06-04 03:21:04 -04:00
if ( coin . nHeight > base_height | |
outpoint . n > = std : : numeric_limits < decltype ( outpoint . n ) > : : max ( ) // Avoid integer wrap-around in coinstats.cpp:ApplyHash
) {
LogPrintf ( " [snapshot] bad snapshot data after deserializing %d coins \n " ,
coins_count - coins_left ) ;
return false ;
}
2020-08-25 13:50:23 -04:00
coins_cache . EmplaceCoinInternalDANGER ( std : : move ( outpoint ) , std : : move ( coin ) ) ;
- - coins_left ;
+ + coins_processed ;
if ( coins_processed % 1000000 = = 0 ) {
LogPrintf ( " [snapshot] %d coins loaded (%.2f%%, %.2f MB) \n " ,
coins_processed ,
static_cast < float > ( coins_processed ) * 100 / static_cast < float > ( coins_count ) ,
coins_cache . DynamicMemoryUsage ( ) / ( 1000 * 1000 ) ) ;
}
// Batch write and flush (if we need to) every so often.
//
// If our average Coin size is roughly 41 bytes, checking every 120,000 coins
// means <5MB of memory imprecision.
if ( coins_processed % 120000 = = 0 ) {
if ( ShutdownRequested ( ) ) {
return false ;
}
const auto snapshot_cache_state = WITH_LOCK ( : : cs_main ,
2021-07-09 09:24:27 -04:00
return snapshot_chainstate . GetCoinsCacheSizeState ( ) ) ;
2020-08-25 13:50:23 -04:00
2021-12-10 13:12:27 -03:00
if ( snapshot_cache_state > = CoinsCacheSizeState : : CRITICAL ) {
2020-08-25 13:50:23 -04:00
// This is a hack - we don't know what the actual best block is, but that
// doesn't matter for the purposes of flushing the cache here. We'll set this
// to its correct value (`base_blockhash`) below after the coins are loaded.
coins_cache . SetBestBlock ( GetRandHash ( ) ) ;
2021-12-10 13:12:27 -03:00
// No need to acquire cs_main since this chainstate isn't being used yet.
FlushSnapshotToDisk ( coins_cache , /*snapshot_loaded=*/ false ) ;
2020-08-25 13:50:23 -04:00
}
}
}
// Important that we set this. This and the coins_cache accesses above are
// sort of a layer violation, but either we reach into the innards of
// CCoinsViewCache here or we have to invert some of the CChainState to
// embed them in a snapshot-activation-specific CCoinsViewCache bulk load
// method.
coins_cache . SetBestBlock ( base_blockhash ) ;
bool out_of_coins { false } ;
try {
coins_file > > outpoint ;
} catch ( const std : : ios_base : : failure & ) {
// We expect an exception since we should be out of coins.
out_of_coins = true ;
}
if ( ! out_of_coins ) {
LogPrintf ( " [snapshot] bad snapshot - coins left over after deserializing %d coins \n " ,
coins_count ) ;
return false ;
}
LogPrintf ( " [snapshot] loaded %d (%.2f MB) coins from snapshot %s \n " ,
coins_count ,
coins_cache . DynamicMemoryUsage ( ) / ( 1000 * 1000 ) ,
base_blockhash . ToString ( ) ) ;
// No need to acquire cs_main since this chainstate isn't being used yet.
2021-12-10 13:12:27 -03:00
FlushSnapshotToDisk ( coins_cache , /*snapshot_loaded=*/ true ) ;
2020-08-25 13:50:23 -04:00
assert ( coins_cache . GetBestBlock ( ) = = base_blockhash ) ;
auto breakpoint_fnc = [ ] { /* TODO insert breakpoint here? */ } ;
// As above, okay to immediately release cs_main here since no other context knows
// about the snapshot_chainstate.
CCoinsViewDB * snapshot_coinsdb = WITH_LOCK ( : : cs_main , return & snapshot_chainstate . CoinsDB ( ) ) ;
2022-02-16 17:23:11 -03:00
const std : : optional < CCoinsStats > maybe_stats = ComputeUTXOStats ( CoinStatsHashType : : HASH_SERIALIZED , snapshot_coinsdb , m_blockman , breakpoint_fnc ) ;
2022-02-15 20:37:32 -03:00
if ( ! maybe_stats . has_value ( ) ) {
2020-08-25 13:50:23 -04:00
LogPrintf ( " [snapshot] failed to generate coins stats \n " ) ;
return false ;
}
// Assert that the deserialized chainstate contents match the expected assumeutxo value.
2022-02-15 20:37:32 -03:00
if ( AssumeutxoHash { maybe_stats - > hashSerialized } ! = au_data . hash_serialized ) {
2020-08-25 13:50:23 -04:00
LogPrintf ( " [snapshot] bad snapshot content hash: expected %s, got %s \n " ,
2022-02-15 20:37:32 -03:00
au_data . hash_serialized . ToString ( ) , maybe_stats - > hashSerialized . ToString ( ) ) ;
2020-08-25 13:50:23 -04:00
return false ;
}
snapshot_chainstate . m_chain . SetTip ( snapshot_start_block ) ;
// The remainder of this function requires modifying data protected by cs_main.
LOCK ( : : cs_main ) ;
// Fake various pieces of CBlockIndex state:
CBlockIndex * index = nullptr ;
2021-10-28 16:15:10 -03:00
// Don't make any modifications to the genesis block.
// This is especially important because we don't want to erroneously
// apply BLOCK_ASSUMED_VALID to genesis, which would happen if we didn't skip
// it here (since it apparently isn't BLOCK_VALID_SCRIPTS).
constexpr int AFTER_GENESIS_START { 1 } ;
for ( int i = AFTER_GENESIS_START ; i < = snapshot_chainstate . m_chain . Height ( ) ; + + i ) {
2020-08-25 13:50:23 -04:00
index = snapshot_chainstate . m_chain [ i ] ;
2021-04-28 03:16:48 -04:00
// Fake nTx so that LoadBlockIndex() loads assumed-valid CBlockIndex
// entries (among other things)
2020-08-25 13:50:23 -04:00
if ( ! index - > nTx ) {
index - > nTx = 1 ;
}
2021-04-28 03:16:48 -04:00
// Fake nChainTx so that GuessVerificationProgress reports accurately
2021-10-28 16:15:10 -03:00
index - > nChainTx = index - > pprev - > nChainTx + index - > nTx ;
2020-08-25 13:50:23 -04:00
2021-07-21 14:08:14 -04:00
// Mark unvalidated block index entries beneath the snapshot base block as assumed-valid.
if ( ! index - > IsValid ( BLOCK_VALID_SCRIPTS ) ) {
// This flag will be removed once the block is fully validated by a
// background chainstate.
index - > nStatus | = BLOCK_ASSUMED_VALID ;
}
2021-04-28 03:16:48 -04:00
// Fake BLOCK_OPT_WITNESS so that CChainState::NeedsRedownload()
// won't ask to rewind the entire assumed-valid chain on startup.
2022-04-14 15:50:53 -04:00
if ( DeploymentActiveAt ( * index , * this , Consensus : : DEPLOYMENT_SEGWIT ) ) {
2020-08-25 13:50:23 -04:00
index - > nStatus | = BLOCK_OPT_WITNESS ;
}
2021-07-21 14:08:14 -04:00
2022-01-05 11:44:16 -03:00
m_blockman . m_dirty_blockindex . insert ( index ) ;
2021-07-21 14:08:14 -04:00
// Changes to the block index will be flushed to disk after this call
// returns in `ActivateSnapshot()`, when `MaybeRebalanceCaches()` is
// called, since we've added a snapshot chainstate and therefore will
// have to downsize the IBD chainstate, which will result in a call to
// `FlushStateToDisk(ALWAYS)`.
2020-08-25 13:50:23 -04:00
}
assert ( index ) ;
2021-04-14 13:29:27 -04:00
index - > nChainTx = au_data . nChainTx ;
2020-08-25 13:50:23 -04:00
snapshot_chainstate . setBlockIndexCandidates . insert ( snapshot_start_block ) ;
LogPrintf ( " [snapshot] validated snapshot (%.2f MB) \n " ,
coins_cache . DynamicMemoryUsage ( ) / ( 1000 * 1000 ) ) ;
return true ;
}
2020-06-03 09:55:58 -04:00
CChainState & ChainstateManager : : ActiveChainstate ( ) const
2019-12-12 12:20:44 -03:00
{
2021-01-27 18:20:59 -03:00
LOCK ( : : cs_main ) ;
2019-12-12 12:20:44 -03:00
assert ( m_active_chainstate ) ;
2020-06-03 09:55:58 -04:00
return * m_active_chainstate ;
2019-12-12 12:20:44 -03:00
}
bool ChainstateManager : : IsSnapshotActive ( ) const
{
2021-01-27 18:20:59 -03:00
LOCK ( : : cs_main ) ;
return m_snapshot_chainstate & & m_active_chainstate = = m_snapshot_chainstate . get ( ) ;
2019-12-12 12:20:44 -03:00
}
2019-09-16 14:37:29 -03:00
void ChainstateManager : : MaybeRebalanceCaches ( )
{
2022-01-27 07:48:19 -03:00
AssertLockHeld ( : : cs_main ) ;
2019-09-16 14:37:29 -03:00
if ( m_ibd_chainstate & & ! m_snapshot_chainstate ) {
LogPrintf ( " [snapshot] allocating all cache to the IBD chainstate \n " ) ;
// Allocate everything to the IBD chainstate.
m_ibd_chainstate - > ResizeCoinsCaches ( m_total_coinstip_cache , m_total_coinsdb_cache ) ;
}
else if ( m_snapshot_chainstate & & ! m_ibd_chainstate ) {
LogPrintf ( " [snapshot] allocating all cache to the snapshot chainstate \n " ) ;
// Allocate everything to the snapshot chainstate.
m_snapshot_chainstate - > ResizeCoinsCaches ( m_total_coinstip_cache , m_total_coinsdb_cache ) ;
}
else if ( m_ibd_chainstate & & m_snapshot_chainstate ) {
// If both chainstates exist, determine who needs more cache based on IBD status.
//
// Note: shrink caches first so that we don't inadvertently overwhelm available memory.
if ( m_snapshot_chainstate - > IsInitialBlockDownload ( ) ) {
m_ibd_chainstate - > ResizeCoinsCaches (
m_total_coinstip_cache * 0.05 , m_total_coinsdb_cache * 0.05 ) ;
m_snapshot_chainstate - > ResizeCoinsCaches (
m_total_coinstip_cache * 0.95 , m_total_coinsdb_cache * 0.95 ) ;
} else {
m_snapshot_chainstate - > ResizeCoinsCaches (
m_total_coinstip_cache * 0.05 , m_total_coinsdb_cache * 0.05 ) ;
m_ibd_chainstate - > ResizeCoinsCaches (
m_total_coinstip_cache * 0.95 , m_total_coinsdb_cache * 0.95 ) ;
}
}
}
2022-01-11 16:49:28 -03:00
ChainstateManager : : ~ ChainstateManager ( )
{
LOCK ( : : cs_main ) ;
2022-04-14 16:53:19 -04:00
m_versionbitscache . Clear ( ) ;
// TODO: The warning cache should probably become non-global
2022-01-11 16:49:28 -03:00
for ( auto & i : warningcache ) {
i . clear ( ) ;
}
}