2010-08-29 18:58:15 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2018-05-16 21:17:40 +02:00
// Copyright (c) 2009-2018 The Bitcoin Core developers
2014-12-01 02:39:44 +01:00
// Distributed under the MIT software license, see the accompanying
2012-05-18 16:02:28 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-10 01:57:53 +01:00
# include <validation.h>
2013-08-27 07:51:57 +02:00
2017-11-10 01:57:53 +01:00
# include <arith_uint256.h>
# include <chain.h>
# include <chainparams.h>
# include <checkpoints.h>
# include <checkqueue.h>
2019-05-08 00:32:22 +02:00
# include <claimscriptop.h>
2017-11-10 01:57:53 +01:00
# include <consensus/consensus.h>
# include <consensus/merkle.h>
# include <consensus/tx_verify.h>
# include <consensus/validation.h>
# include <cuckoocache.h>
# include <hash.h>
2017-12-08 20:41:35 +01:00
# include <index/txindex.h>
2018-08-06 21:40:20 +02:00
# include <nameclaim.h>
2017-11-10 01:57:53 +01:00
# include <policy/fees.h>
# include <policy/policy.h>
# include <policy/rbf.h>
# include <pow.h>
# include <primitives/block.h>
# include <primitives/transaction.h>
2019-05-08 00:32:22 +02:00
# include <protocol.h>
2017-11-10 01:57:53 +01:00
# include <random.h>
# include <reverse_iterator.h>
# include <script/script.h>
# include <script/sigcache.h>
# include <script/standard.h>
2018-05-16 21:17:40 +02:00
# include <shutdown.h>
2017-11-10 01:57:53 +01:00
# include <timedata.h>
# include <tinyformat.h>
# include <txdb.h>
# include <txmempool.h>
# include <ui_interface.h>
# include <undo.h>
# include <util.h>
# include <utilmoneystr.h>
# include <utilstrencodings.h>
# include <validationinterface.h>
# include <warnings.h>
2013-04-13 07:13:08 +02:00
2017-12-05 00:57:55 +01:00
# include <future>
2013-10-28 07:36:11 +01:00
# include <sstream>
2013-04-13 07:13:08 +02:00
# include <boost/algorithm/string/replace.hpp>
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
# include <boost/thread.hpp>
2010-08-29 18:58:15 +02:00
2013-12-02 20:33:44 +01:00
# if defined(NDEBUG)
2018-08-06 21:40:20 +02:00
# error "LBRYcrd cannot be compiled without assertions."
2013-12-02 20:33:44 +01:00
# endif
2017-06-01 04:42:34 +02:00
# define MICRO 0.000001
# define MILLI 0.001
2018-08-06 21:40:20 +02:00
CChainState g_chainstate ;
2010-08-29 18:58:15 +02:00
CCriticalSection cs_main ;
2017-12-04 15:34:46 +01:00
BlockMap & mapBlockIndex = g_chainstate . mapBlockIndex ;
CChain & chainActive = g_chainstate . chainActive ;
2017-08-07 07:36:37 +02:00
CBlockIndex * pindexBestHeader = nullptr ;
2018-04-04 06:53:07 +02:00
CWaitableCriticalSection g_best_block_mutex ;
CConditionVariable g_best_block_cv ;
uint256 g_best_block ;
2012-12-01 23:04:14 +01:00
int nScriptCheckThreads = 0 ;
2016-11-26 06:52:44 +01:00
std : : atomic_bool fImporting ( false ) ;
2017-08-24 03:45:26 +02:00
std : : atomic_bool fReindex ( false ) ;
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 20:27:44 +01:00
bool fHavePruned = false ;
bool fPruneMode = false ;
2015-11-09 19:16:38 +01:00
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG ;
2015-06-24 05:36:22 +02:00
bool fRequireStandard = true ;
2015-03-13 17:25:34 +01:00
bool fCheckBlockIndex = false ;
2015-11-09 19:16:38 +01:00
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED ;
2015-05-04 01:38:08 +02:00
size_t nCoinCacheUsage = 5000 * 300 ;
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 20:27:44 +01:00
uint64_t nPruneTarget = 0 ;
2015-12-14 13:23:45 +01:00
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE ;
2016-01-28 06:09:29 +01:00
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT ;
2010-08-29 18:58:15 +02:00
2017-01-06 12:49:59 +01:00
uint256 hashAssumeValid ;
2017-05-07 20:10:19 +02:00
arith_uint256 nMinimumChainWork ;
2016-05-21 11:45:32 +02:00
2015-10-27 17:21:43 +01:00
CFeeRate minRelayTxFee = CFeeRate ( DEFAULT_MIN_RELAY_TX_FEE ) ;
2015-11-23 20:32:36 +01:00
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE ;
2018-08-06 21:40:20 +02:00
CAmount minFeePerNameClaimChar = MIN_FEE_PER_NAMECLAIM_CHAR ;
2014-07-03 20:25:32 +02:00
2017-02-14 22:54:46 +01:00
CBlockPolicyEstimator feeEstimator ;
CTxMemPool mempool ( & feeEstimator ) ;
2018-01-12 21:38:48 +01:00
std : : atomic_bool g_is_mempool_loaded { false } ;
2010-08-29 18:58:15 +02:00
2014-12-01 02:39:44 +01:00
/** Constant stuff for coinbase transactions we create: */
2012-02-06 21:48:00 +01:00
CScript COINBASE_FLAGS ;
2010-08-29 18:58:15 +02:00
2018-08-06 21:40:20 +02:00
const std : : string strMessageMagic = " LBRYcrd Signed Message: \n " ;
2011-12-23 16:14:57 +01:00
2013-10-14 02:13:44 +02:00
// Internal stuff
namespace {
2017-12-04 15:34:46 +01:00
CBlockIndex * & pindexBestInvalid = g_chainstate . pindexBestInvalid ;
2014-06-24 14:17:43 +02:00
2015-07-03 16:36:49 +02:00
/** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
* Pruned nodes may have entries where B is missing data .
*/
2017-12-04 15:34:46 +01:00
std : : multimap < CBlockIndex * , CBlockIndex * > & mapBlocksUnlinked = g_chainstate . mapBlocksUnlinked ;
2014-04-30 08:57:11 +02:00
CCriticalSection cs_LastBlockFile ;
2014-09-25 08:21:21 +02:00
std : : vector < CBlockFileInfo > vinfoBlockFile ;
2014-04-30 08:57:11 +02:00
int nLastBlockFile = 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 20:27:44 +01:00
/** Global flag to indicate we should check to see if there are
* block / undo files that should be deleted . Set on startup
* or if we allocate more file space when we ' re in prune mode
*/
bool fCheckForPruning = false ;
2014-04-30 08:57:11 +02:00
2014-12-01 02:39:44 +01:00
/** Dirty block index entries. */
2017-01-27 09:43:41 +01:00
std : : set < CBlockIndex * > setDirtyBlockIndex ;
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 11:38:35 +01:00
2014-12-01 02:39:44 +01:00
/** Dirty block file entries. */
2017-01-27 09:43:41 +01:00
std : : set < int > setDirtyFileInfo ;
2014-06-24 14:17:43 +02:00
} // anon namespace
2013-11-18 01:25:17 +01:00
2014-09-03 02:52:01 +02:00
CBlockIndex * FindForkInGlobalIndex ( const CChain & chain , const CBlockLocator & locator )
{
2018-01-12 00:32:32 +01:00
AssertLockHeld ( cs_main ) ;
2018-04-11 20:14:45 +02:00
// Find the latest block common to locator and chain - we expect that
// locator.vHave is sorted descending by height.
2017-06-02 03:18:57 +02:00
for ( const uint256 & hash : locator . vHave ) {
2018-01-12 01:23:09 +01:00
CBlockIndex * pindex = LookupBlockIndex ( hash ) ;
if ( pindex ) {
2014-09-03 02:52:01 +02:00
if ( chain . Contains ( pindex ) )
2013-05-07 13:59:29 +02:00
return pindex ;
2016-03-18 17:20:12 +01:00
if ( pindex - > GetAncestor ( chain . Height ( ) ) = = chain . Tip ( ) ) {
return chain . Tip ( ) ;
}
2013-05-07 13:59:29 +02:00
}
}
2018-08-06 21:40:20 +02:00
2014-09-03 02:52:01 +02:00
return chain . Genesis ( ) ;
2014-05-06 00:54:10 +02:00
}
2017-08-09 17:08:22 +02:00
std : : unique_ptr < CCoinsViewDB > pcoinsdbview ;
std : : unique_ptr < CCoinsViewCache > pcoinsTip ;
std : : unique_ptr < CBlockTreeDB > pblocktree ;
2018-08-06 21:40:20 +02:00
// FIXME: make unique_ptr
CClaimTrie * pclaimTrie = nullptr ;
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 18:54:00 +02:00
2018-03-09 15:03:40 +01:00
enum class FlushStateMode {
NONE ,
IF_NEEDED ,
PERIODIC ,
ALWAYS
2016-10-03 16:06:10 +02:00
} ;
// See definition for documentation
2017-04-21 20:45:30 +02:00
static bool FlushStateToDisk ( const CChainParams & chainParams , CValidationState & state , FlushStateMode mode , int nManualPruneHeight = 0 ) ;
static void FindFilesToPruneManual ( std : : set < int > & setFilesToPrune , int nManualPruneHeight ) ;
static void FindFilesToPrune ( std : : set < int > & setFilesToPrune , uint64_t nPruneAfterHeight ) ;
2017-06-23 22:23:55 +02:00
bool CheckInputs ( const CTransaction & tx , CValidationState & state , const CCoinsViewCache & inputs , bool fScriptChecks , unsigned int flags , bool cacheSigStore , bool cacheFullScriptStore , PrecomputedTransactionData & txdata , std : : vector < CScriptCheck > * pvChecks = nullptr ) ;
2017-04-21 20:45:30 +02:00
static FILE * OpenUndoFile ( const CDiskBlockPos & pos , bool fReadOnly = false ) ;
2016-10-03 16:06:10 +02:00
2015-11-03 18:12:36 +01:00
bool CheckFinalTx ( const CTransaction & tx , int flags )
2015-05-25 06:48:33 +02:00
{
AssertLockHeld ( cs_main ) ;
2015-11-03 18:12:36 +01:00
// By convention a negative value for flags indicates that the
// current network-enforced consensus rules should be used. In
// a future soft-fork scenario that would mean checking which
// rules would be enforced for the next block and setting the
// appropriate flags. At the present time no soft-forks are
// scheduled, so no flags are set.
flags = std : : max ( flags , 0 ) ;
// CheckFinalTx() uses chainActive.Height()+1 to evaluate
// nLockTime because when IsFinalTx() is called within
// CBlock::AcceptBlock(), 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 *next* block, we need to call
// IsFinalTx() with one more than chainActive.Height().
const int nBlockHeight = chainActive . Height ( ) + 1 ;
2017-09-14 16:59:09 +02:00
// BIP113 requires that time-locked transactions have nLockTime set to
2015-11-13 22:36:54 +01: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
// IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set.
2015-11-03 18:12:36 +01:00
const int64_t nBlockTime = ( flags & LOCKTIME_MEDIAN_TIME_PAST )
? chainActive . Tip ( ) - > GetMedianTimePast ( )
: GetAdjustedTime ( ) ;
return IsFinalTx ( tx , nBlockHeight , nBlockTime ) ;
2015-05-25 06:48:33 +02:00
}
2015-12-04 21:01:22 +01:00
bool TestLockPointValidity ( const LockPoints * lp )
{
AssertLockHeld ( cs_main ) ;
assert ( lp ) ;
// If there are relative lock times then the maxInputBlock will be set
// If there are no relative lock times, the LockPoints don't depend on the chain
if ( lp - > maxInputBlock ) {
// Check whether chainActive is an extension of the block at which the LockPoints
// calculation was valid. If not LockPoints are no longer valid
if ( ! chainActive . Contains ( lp - > maxInputBlock ) ) {
return false ;
}
}
// LockPoints still valid
return true ;
}
bool CheckSequenceLocks ( const CTransaction & tx , int flags , LockPoints * lp , bool useExistingLockPoints )
2015-12-07 21:44:16 +01:00
{
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( mempool . cs ) ;
CBlockIndex * tip = chainActive . Tip ( ) ;
2017-08-23 09:47:56 +02:00
assert ( tip ! = nullptr ) ;
2018-04-15 17:22:28 +02:00
2015-12-07 21:44:16 +01:00
CBlockIndex index ;
index . pprev = tip ;
// CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
// height based locks because when SequenceLocks() is called within
2016-02-11 21:34:04 +01: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
// *next* block, we need to use one more than chainActive.Height()
2015-12-07 21:44:16 +01:00
index . nHeight = tip - > nHeight + 1 ;
2015-12-04 21:01:22 +01:00
std : : pair < int , int64_t > lockPair ;
if ( useExistingLockPoints ) {
assert ( lp ) ;
lockPair . first = lp - > height ;
lockPair . second = lp - > time ;
}
else {
// pcoinsTip contains the UTXO set for chainActive.Tip()
2017-08-09 17:08:22 +02:00
CCoinsViewMemPool viewMemPool ( pcoinsTip . get ( ) , mempool ) ;
2015-12-04 21:01:22 +01:00
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 20:29:39 +02:00
Coin coin ;
2017-05-31 02:58:54 +02:00
if ( ! viewMemPool . GetCoin ( txin . prevout , coin ) ) {
2015-12-04 21:01:22 +01:00
return error ( " %s: Missing input " , __func__ ) ;
}
2017-04-25 20:29:39 +02:00
if ( coin . nHeight = = MEMPOOL_HEIGHT ) {
2015-12-04 21:01:22 +01:00
// Assume all mempool transaction confirm in the next block
prevheights [ txinIndex ] = tip - > nHeight + 1 ;
} else {
2017-04-25 20:29:39 +02:00
prevheights [ txinIndex ] = coin . nHeight ;
2015-12-04 21:01:22 +01:00
}
2015-12-07 21:44:16 +01:00
}
2015-12-04 21:01:22 +01:00
lockPair = CalculateSequenceLocks ( tx , flags , & prevheights , index ) ;
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
// CheckSequenceLocks to indicate the LockPoints validity
int maxInputHeight = 0 ;
2017-06-02 03:18:57 +02:00
for ( int height : prevheights ) {
2015-12-04 21:01:22 +01: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 ) ;
}
}
lp - > maxInputBlock = tip - > GetAncestor ( maxInputHeight ) ;
2015-12-07 21:44:16 +01:00
}
}
return EvaluateSequenceLocks ( index , lockPair ) ;
}
2017-04-11 22:04:37 +02:00
// Returns the script flags which should be checked for a given block
static unsigned int GetBlockScriptFlags ( const CBlockIndex * pindex , const Consensus : : Params & chainparams ) ;
2017-04-21 20:45:30 +02:00
static void LimitMempoolSize ( CTxMemPool & pool , size_t limit , unsigned long age ) {
2015-10-22 20:52:55 +02:00
int expired = pool . Expire ( GetTime ( ) - age ) ;
2016-12-25 21:19:40 +01:00
if ( expired ! = 0 ) {
LogPrint ( BCLog : : MEMPOOL , " Expired %i transactions from the memory pool \n " , expired ) ;
}
2015-10-22 20:52:55 +02:00
2017-04-25 20:29:39 +02:00
std : : vector < COutPoint > vNoSpendsRemaining ;
2015-10-22 20:52:55 +02:00
pool . TrimToSize ( limit , & vNoSpendsRemaining ) ;
2017-06-02 03:18:57 +02:00
for ( const COutPoint & removed : vNoSpendsRemaining )
2015-10-22 20:52:55 +02:00
pcoinsTip - > Uncache ( removed ) ;
}
2015-08-06 09:53:24 +02:00
/** Convert CValidationState to a human-readable message for logging */
2015-10-28 19:56:28 +01:00
std : : string FormatStateMessage ( const CValidationState & state )
2015-08-06 09:53:24 +02:00
{
return strprintf ( " %s%s (code %i) " ,
state . GetRejectReason ( ) ,
state . GetDebugMessage ( ) . empty ( ) ? " " : " , " + state . GetDebugMessage ( ) ,
state . GetRejectCode ( ) ) ;
}
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 18:54:00 +02:00
2016-11-11 19:29:13 +01:00
static bool IsCurrentForFeeEstimation ( )
{
AssertLockHeld ( cs_main ) ;
if ( IsInitialBlockDownload ( ) )
return false ;
if ( chainActive . Tip ( ) - > GetBlockTime ( ) < ( GetTime ( ) - MAX_FEE_ESTIMATION_TIP_AGE ) )
return false ;
if ( chainActive . Height ( ) < pindexBestHeader - > nHeight - 1 )
return false ;
return true ;
}
2016-11-03 19:45:10 +01:00
/* Make mempool consistent after a reorg, by re-adding or recursively erasing
* disconnected block transactions from the mempool , and also removing any
* other transactions from the mempool that are no longer valid given the new
* tip / height .
*
* Note : we assume that disconnectpool only contains transactions that are NOT
* confirmed in the current chain nor already in the mempool ( otherwise ,
* in - mempool descendants of such transactions would be removed ) .
*
* Passing fAddToMempool = false will skip trying to add the transactions back ,
* and instead just erase from the mempool as needed .
*/
2018-05-02 17:14:48 +02:00
static void UpdateMempoolForReorg ( DisconnectedBlockTransactions & disconnectpool , bool fAddToMempool )
2016-11-03 19:45:10 +01:00
{
AssertLockHeld ( cs_main ) ;
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
CValidationState stateDummy ;
2017-09-12 18:30:26 +02:00
if ( ! fAddToMempool | | ( * it ) - > IsCoinBase ( ) | |
! AcceptToMemoryPool ( mempool , stateDummy , * it , nullptr /* pfMissingInputs */ ,
nullptr /* plTxnReplaced */ , true /* bypass_limits */ , 0 /* nAbsurdFee */ ) ) {
2016-11-03 19:45:10 +01:00
// If the transaction doesn't make it in to the mempool, remove any
// transactions that depend on it (which would now be orphans).
mempool . removeRecursive ( * * it , MemPoolRemovalReason : : REORG ) ;
} else if ( mempool . exists ( ( * it ) - > GetHash ( ) ) ) {
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.
mempool . UpdateTransactionsFromBlock ( vHashUpdate ) ;
// We also need to remove any now-immature transactions
2017-08-09 17:08:22 +02:00
mempool . removeForReorg ( pcoinsTip . get ( ) , chainActive . Tip ( ) - > nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS ) ;
2016-11-03 19:45:10 +01:00
// Re-limit mempool size, in case we added any transactions
2017-08-01 21:17:40 +02:00
LimitMempoolSize ( mempool , gArgs . GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 , gArgs . GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ) ;
2016-11-03 19:45:10 +01:00
}
2017-06-06 02:46:23 +02:00
// Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool
// were somehow broken and returning the wrong scriptPubKeys
2018-04-02 17:16:56 +02:00
static bool CheckInputsFromMempoolAndCache ( const CTransaction & tx , CValidationState & state , const CCoinsViewCache & view , const CTxMemPool & pool ,
2017-06-06 02:46:23 +02:00
unsigned int flags , bool cacheSigStore , PrecomputedTransactionData & txdata ) {
AssertLockHeld ( cs_main ) ;
// pool.cs should be locked already, but go ahead and re-take the lock here
// to enforce that mempool doesn't change between when we check the view
// and when we actually call through to CheckInputs
LOCK ( pool . cs ) ;
assert ( ! tx . IsCoinBase ( ) ) ;
for ( const CTxIn & txin : tx . vin ) {
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
// At this point we haven't actually checked if the coins are all
// available (or shouldn't assume we have, since CheckInputs does).
// So we just return failure if the inputs are not available here,
// and then only have to check equivalence for available inputs.
if ( coin . IsSpent ( ) ) return false ;
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 {
const Coin & coinFromDisk = pcoinsTip - > AccessCoin ( txin . prevout ) ;
assert ( ! coinFromDisk . IsSpent ( ) ) ;
assert ( coinFromDisk . out = = coin . out ) ;
}
}
return CheckInputs ( tx , state , view , true , flags , cacheSigStore , true , txdata ) ;
}
2017-09-12 18:30:26 +02:00
static bool AcceptToMemoryPoolWorker ( const CChainParams & chainparams , CTxMemPool & pool , CValidationState & state , const CTransactionRef & ptx ,
2016-12-05 03:53:26 +01:00
bool * pfMissingInputs , int64_t nAcceptTime , std : : list < CTransactionRef > * plTxnReplaced ,
2017-11-17 18:54:39 +01:00
bool bypass_limits , const CAmount & nAbsurdFee , std : : vector < COutPoint > & coins_to_uncache , bool test_accept )
2010-08-29 18:58:15 +02:00
{
2016-11-11 07:29:19 +01:00
const CTransaction & tx = * ptx ;
2015-12-02 03:13:47 +01:00
const uint256 hash = tx . GetHash ( ) ;
2014-04-15 12:43:17 +02:00
AssertLockHeld ( cs_main ) ;
2018-02-06 19:51:44 +01:00
LOCK ( pool . cs ) ; // mempool "read lock" (held through GetMainSignals().TransactionAddedToMempool())
2018-02-06 20:55:36 +01:00
if ( pfMissingInputs ) {
2010-08-29 18:58:15 +02:00
* pfMissingInputs = false ;
2018-02-06 20:55:36 +01:00
}
2010-08-29 18:58:15 +02:00
2013-01-08 13:17:15 +01:00
if ( ! CheckTransaction ( tx , state ) )
2016-02-24 18:34:37 +01:00
return false ; // state filled in by CheckTransaction
2010-09-30 18:23:07 +02:00
2010-08-29 18:58:15 +02:00
// Coinbase is only valid in a block, not as a loose transaction
2012-04-13 23:34:22 +02:00
if ( tx . IsCoinBase ( ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " coinbase " ) ;
2010-09-07 03:12:53 +02:00
2016-07-07 21:49:26 +02:00
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
2017-01-27 09:43:41 +01:00
std : : string reason ;
2018-04-30 01:34:57 +02:00
if ( fRequireStandard & & ! IsStandardTx ( tx , reason ) )
2018-08-06 21:40:20 +02:00
return state . DoS ( 0 , false , ( reason = = " dust " ? REJECT_DUST : REJECT_NONSTANDARD ) , reason ) ;
2016-07-07 21:49:26 +02:00
2018-04-26 21:31:36 +02: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.
// Transactions smaller than this are not relayed to reduce unnecessary malloc overhead.
2018-08-06 21:40:20 +02:00
//
// NOTE: LBRY does not honor this node rule.
/* if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) < MIN_STANDARD_TX_NONWITNESS_SIZE) */
/* return state.DoS(0, false, REJECT_NONSTANDARD, "tx-size-small"); */
2018-04-26 21:31:36 +02:00
2014-12-20 23:04:21 +01: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.
2015-11-03 18:12:36 +01:00
if ( ! CheckFinalTx ( tx , STANDARD_LOCKTIME_VERIFY_FLAGS ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " non-final " ) ;
2014-12-20 23:04:21 +01: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 18:54:00 +02:00
// is it already in the memory pool?
2017-06-01 20:12:59 +02:00
if ( pool . exists ( hash ) ) {
return state . Invalid ( false , REJECT_DUPLICATE , " txn-already-in-mempool " ) ;
}
2010-08-29 18:58:15 +02:00
// Check for conflicts with in-memory transactions
2017-01-27 09:43:41 +01:00
std : : set < uint256 > setConflicts ;
2017-06-02 03:18:57 +02:00
for ( const CTxIn & txin : tx . vin )
2010-08-29 18:58:15 +02:00
{
2016-05-01 06:45:26 +02:00
auto itConflicting = pool . mapNextTx . find ( txin . prevout ) ;
if ( itConflicting ! = pool . mapNextTx . end ( ) )
2010-08-29 18:58:15 +02:00
{
2016-05-01 06:45:26 +02:00
const CTransaction * ptxConflicting = itConflicting - > second ;
2015-10-22 20:13:18 +02:00
if ( ! setConflicts . count ( ptxConflicting - > GetHash ( ) ) )
{
// Allow opt-out of transaction replacement by setting
2017-07-17 19:00:00 +02:00
// nSequence > MAX_BIP125_RBF_SEQUENCE (SEQUENCE_FINAL-2) on all inputs.
2015-10-22 20:13:18 +02:00
//
2017-07-17 19:00:00 +02:00
// SEQUENCE_FINAL-1 is picked to still allow use of nLockTime by
2016-08-13 19:21:13 +02:00
// non-replaceable transactions. All inputs rather than just one
2015-10-22 20:13:18 +02:00
// is for the sake of multi-party protocols, where we don't
// want a single party to be able to disable replacement.
//
// The opt-out ignores descendants as anyone relying on
// first-seen mempool behavior should be checking all
// unconfirmed ancestors anyway; doing otherwise is hopelessly
// insecure.
bool fReplacementOptOut = true ;
2016-01-28 06:09:29 +01:00
if ( fEnableReplacement )
2015-10-22 20:13:18 +02:00
{
2017-06-02 03:18:57 +02:00
for ( const CTxIn & _txin : ptxConflicting - > vin )
2015-10-22 20:13:18 +02:00
{
2017-07-17 19:00:00 +02:00
if ( _txin . nSequence < = MAX_BIP125_RBF_SEQUENCE )
2016-01-21 11:11:01 +01:00
{
fReplacementOptOut = false ;
break ;
}
2015-10-22 20:13:18 +02:00
}
}
2017-06-01 20:12:59 +02:00
if ( fReplacementOptOut ) {
return state . Invalid ( false , REJECT_DUPLICATE , " txn-mempool-conflict " ) ;
}
2015-10-22 20:13:18 +02:00
setConflicts . insert ( ptxConflicting - > GetHash ( ) ) ;
}
2010-08-29 18:58:15 +02:00
}
}
2018-08-06 21:40:20 +02:00
2010-08-29 18:58:15 +02:00
{
2012-10-23 01:16:26 +02:00
CCoinsView dummy ;
2014-09-24 03:19:04 +02:00
CCoinsViewCache view ( & dummy ) ;
2012-10-23 01:16:26 +02:00
2015-12-04 21:01:22 +01:00
LockPoints lp ;
2017-08-09 17:08:22 +02:00
CCoinsViewMemPool viewMemPool ( pcoinsTip . get ( ) , pool ) ;
2012-10-23 01:16:26 +02:00
view . SetBackend ( viewMemPool ) ;
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 18:54:00 +02:00
// do all inputs exist?
2018-06-15 19:38:54 +02:00
for ( const CTxIn & txin : tx . vin ) {
2017-05-31 02:58:54 +02:00
if ( ! pcoinsTip - > HaveCoinInCache ( txin . prevout ) ) {
coins_to_uncache . push_back ( txin . prevout ) ;
2017-04-25 20:29:39 +02:00
}
2017-05-31 02:58:54 +02:00
if ( ! view . HaveCoin ( txin . prevout ) ) {
2017-06-08 16:41:19 +02:00
// 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 ( pcoinsTip - > HaveCoinInCache ( COutPoint ( hash , out ) ) ) {
return state . Invalid ( false , REJECT_DUPLICATE , " txn-already-known " ) ;
}
}
// Otherwise assume this might be an orphan tx for which we just haven't seen parents yet
2017-04-25 20:29:39 +02:00
if ( pfMissingInputs ) {
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 18:54:00 +02:00
* pfMissingInputs = true ;
2017-04-25 20:29:39 +02:00
}
2015-08-06 09:51:36 +02:00
return false ; // fMissingInputs and !state.IsInvalid() is used to detect this condition, don't set state.Invalid()
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 18:54:00 +02:00
}
2011-10-03 19:05:43 +02:00
}
2012-10-23 01:16:26 +02:00
// Bring the best block into scope
view . GetBestBlock ( ) ;
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
view . SetBackend ( dummy ) ;
2015-12-07 21:44:16 +01: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.
// Must keep pool.cs for this unless we change CheckSequenceLocks to take a
// CoinsViewCache instead of create its own
2015-12-04 21:01:22 +01:00
if ( ! CheckSequenceLocks ( tx , STANDARD_LOCKTIME_VERIFY_FLAGS , & lp ) )
2015-12-07 21:44:16 +01:00
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " non-BIP68-final " ) ;
2016-08-11 04:42:36 +02:00
CAmount nFees = 0 ;
if ( ! Consensus : : CheckTxInputs ( tx , state , view , GetSpendHeight ( view ) , nFees ) ) {
return error ( " %s: Consensus::CheckTxInputs: %s, %s " , __func__ , tx . GetHash ( ) . ToString ( ) , FormatStateMessage ( state ) ) ;
2012-10-23 01:16:26 +02:00
}
2012-07-08 19:04:05 +02:00
2012-01-05 03:40:52 +01:00
// Check for non-standard pay-to-script-hash in inputs
2015-06-24 05:36:22 +02:00
if ( fRequireStandard & & ! AreInputsStandard ( tx , view ) )
2015-08-06 09:51:36 +02:00
return state . Invalid ( false , REJECT_NONSTANDARD , " bad-txns-nonstandard-inputs " ) ;
2011-10-03 19:05:43 +02:00
2016-10-16 17:53:16 +02:00
// Check for non-standard witness in P2WSH
2016-08-04 02:49:16 +02:00
if ( tx . HasWitness ( ) & & fRequireStandard & & ! IsWitnessStandard ( tx , view ) )
2016-10-16 17:53:16 +02:00
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " bad-witness-nonstandard " , true ) ;
2016-01-03 18:54:50 +01:00
int64_t nSigOpsCost = GetTransactionSigOpCost ( tx , view , STANDARD_SCRIPT_VERIFY_FLAGS ) ;
2012-01-20 23:07:40 +01:00
2015-12-02 15:37:18 +01:00
// nModifiedFees includes any fee deltas from PrioritiseTransaction
CAmount nModifiedFees = nFees ;
2017-01-20 05:37:15 +01:00
pool . ApplyDelta ( hash , nModifiedFees ) ;
2013-11-11 08:35:14 +01:00
2015-10-29 19:06:13 +01: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 ;
2017-06-02 03:18:57 +02:00
for ( const CTxIn & txin : tx . vin ) {
2017-04-25 20:29:30 +02:00
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
if ( coin . IsCoinBase ( ) ) {
2015-10-29 19:06:13 +01:00
fSpendsCoinbase = true ;
break ;
}
}
2017-01-20 15:24:35 +01:00
CTxMemPoolEntry entry ( ptx , nFees , nAcceptTime , chainActive . Height ( ) ,
fSpendsCoinbase , nSigOpsCost , lp ) ;
2013-11-11 08:35:14 +01:00
unsigned int nSize = entry . GetTxSize ( ) ;
2012-01-11 02:18:00 +01:00
2014-02-22 03:41:01 +01:00
// Check that the transaction doesn't have an excessive number of
// sigops, making it impossible to mine. Since the coinbase transaction
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
// merely non-standard transaction.
2016-07-18 20:57:20 +02:00
if ( nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST )
2014-02-22 03:41:01 +01:00
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " bad-txns-too-many-sigops " , false ,
2016-01-03 18:54:50 +01:00
strprintf ( " %d " , nSigOpsCost ) ) ;
2014-02-22 03:41:01 +01:00
2017-08-01 21:17:40 +02:00
CAmount mempoolRejectFee = pool . GetMinFee ( gArgs . GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ) . GetFee ( nSize ) ;
2017-09-12 18:35:35 +02:00
if ( ! bypass_limits & & mempoolRejectFee > 0 & & nModifiedFees < mempoolRejectFee ) {
2018-02-05 16:53:33 +01:00
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " mempool min fee not met " , false , strprintf ( " %d < %d " , nModifiedFees , mempoolRejectFee ) ) ;
2014-12-23 23:50:21 +01:00
}
2017-01-20 04:07:56 +01:00
// No transactions are allowed below minRelayTxFee except from disconnected blocks
2017-09-12 18:30:26 +02:00
if ( ! bypass_limits & & nModifiedFees < : : minRelayTxFee . GetFee ( nSize ) ) {
2018-04-20 01:47:13 +02:00
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " min relay fee not met " , false , strprintf ( " %d < %d " , nModifiedFees , : : minRelayTxFee . GetFee ( nSize ) ) ) ;
2010-12-12 19:20:36 +01:00
}
2012-01-11 02:18:00 +01:00
2015-11-20 16:48:06 +01:00
if ( nAbsurdFee & & nFees > nAbsurdFee )
2015-08-06 09:59:09 +02:00
return state . Invalid ( false ,
REJECT_HIGHFEE , " absurdly-high-fee " ,
2015-11-20 16:48:06 +01:00
strprintf ( " %d > %d " , nFees , nAbsurdFee ) ) ;
2013-08-29 00:41:46 +02:00
2015-07-15 20:47:45 +02:00
// Calculate in-mempool ancestors, up to a limit.
CTxMemPool : : setEntries setAncestors ;
2017-08-01 21:17:40 +02:00
size_t nLimitAncestors = gArgs . GetArg ( " -limitancestorcount " , DEFAULT_ANCESTOR_LIMIT ) ;
size_t nLimitAncestorSize = gArgs . GetArg ( " -limitancestorsize " , DEFAULT_ANCESTOR_SIZE_LIMIT ) * 1000 ;
size_t nLimitDescendants = gArgs . GetArg ( " -limitdescendantcount " , DEFAULT_DESCENDANT_LIMIT ) ;
size_t nLimitDescendantSize = gArgs . GetArg ( " -limitdescendantsize " , DEFAULT_DESCENDANT_SIZE_LIMIT ) * 1000 ;
2015-07-15 20:47:45 +02:00
std : : string errString ;
if ( ! pool . CalculateMemPoolAncestors ( entry , setAncestors , nLimitAncestors , nLimitAncestorSize , nLimitDescendants , nLimitDescendantSize , errString ) ) {
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " too-long-mempool-chain " , false , errString ) ;
}
2015-10-22 20:13:18 +02: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
// pathological case by making sure setConflicts and setAncestors don't
// intersect.
2017-06-02 03:18:57 +02:00
for ( CTxMemPool : : txiter ancestorIt : setAncestors )
2015-10-22 20:13:18 +02:00
{
const uint256 & hashAncestor = ancestorIt - > GetTx ( ) . GetHash ( ) ;
if ( setConflicts . count ( hashAncestor ) )
{
2016-02-24 18:34:37 +01:00
return state . DoS ( 10 , false ,
REJECT_INVALID , " bad-txns-spends-conflicting-tx " , false ,
strprintf ( " %s spends conflicting transaction %s " ,
2015-10-22 20:13:18 +02:00
hash . ToString ( ) ,
2016-02-24 18:34:37 +01:00
hashAncestor . ToString ( ) ) ) ;
2015-10-22 20:13:18 +02:00
}
}
// Check if it's economically rational to mine this transaction rather
// than the ones it replaces.
CAmount nConflictingFees = 0 ;
size_t nConflictingSize = 0 ;
2015-10-30 03:49:00 +01:00
uint64_t nConflictingCount = 0 ;
CTxMemPool : : setEntries allConflicting ;
2015-11-10 23:58:06 +01:00
// If we don't hold the lock allConflicting might be incomplete; the
// subsequent RemoveStaged() and addUnchecked() calls don't guarantee
// mempool consistency for us.
2017-01-11 17:25:18 +01:00
const bool fReplacementTransaction = setConflicts . size ( ) ;
if ( fReplacementTransaction )
2015-10-22 20:13:18 +02:00
{
2015-11-30 22:42:36 +01:00
CFeeRate newFeeRate ( nModifiedFees , nSize ) ;
2017-01-27 09:43:41 +01:00
std : : set < uint256 > setConflictsParents ;
2015-10-30 03:49:00 +01:00
const int maxDescendantsToVisit = 100 ;
CTxMemPool : : setEntries setIterConflicting ;
2017-06-02 03:18:57 +02:00
for ( const uint256 & hashConflicting : setConflicts )
2015-10-22 20:13:18 +02:00
{
CTxMemPool : : txiter mi = pool . mapTx . find ( hashConflicting ) ;
if ( mi = = pool . mapTx . end ( ) )
continue ;
2015-10-30 03:55:48 +01:00
2015-10-30 03:49:00 +01:00
// Save these to avoid repeated lookups
setIterConflicting . insert ( mi ) ;
2015-10-30 03:55:48 +01:00
// Don't allow the replacement to reduce the feerate of the
// mempool.
//
// We usually don't want to accept replacements with lower
// feerates than what they replaced as that would lower the
// feerate of the next block. Requiring that the feerate always
// be increased is also an easy-to-reason about way to prevent
// DoS attacks via replacements.
//
2018-07-17 00:34:28 +02:00
// We only consider the feerates of transactions being directly
// replaced, not their indirect descendants. While that does
// mean high feerate children are ignored when deciding whether
// or not to replace, we do require the replacement to pay more
// overall fees too, mitigating most cases.
2015-11-30 22:42:36 +01:00
CFeeRate oldFeeRate ( mi - > GetModifiedFee ( ) , mi - > GetTxSize ( ) ) ;
2015-10-30 03:55:48 +01:00
if ( newFeeRate < = oldFeeRate )
{
2016-02-24 18:34:37 +01:00
return state . DoS ( 0 , false ,
REJECT_INSUFFICIENTFEE , " insufficient fee " , false ,
strprintf ( " rejecting replacement %s; new feerate %s <= old feerate %s " ,
2015-10-30 03:55:48 +01:00
hash . ToString ( ) ,
newFeeRate . ToString ( ) ,
2016-02-24 18:34:37 +01:00
oldFeeRate . ToString ( ) ) ) ;
2015-10-30 03:55:48 +01:00
}
2017-06-02 03:18:57 +02:00
for ( const CTxIn & txin : mi - > GetTx ( ) . vin )
2015-10-30 05:04:00 +01:00
{
setConflictsParents . insert ( txin . prevout . hash ) ;
}
2015-10-30 03:49:00 +01:00
nConflictingCount + = mi - > GetCountWithDescendants ( ) ;
}
// This potentially overestimates the number of actual descendants
// but we just want to be conservative to avoid doing too much
// work.
if ( nConflictingCount < = maxDescendantsToVisit ) {
// If not too many to replace, then calculate the set of
// transactions that would have to be evicted
2017-06-02 03:18:57 +02:00
for ( CTxMemPool : : txiter it : setIterConflicting ) {
2015-10-30 03:49:00 +01:00
pool . CalculateDescendants ( it , allConflicting ) ;
}
2017-06-02 03:18:57 +02:00
for ( CTxMemPool : : txiter it : allConflicting ) {
2015-11-30 22:42:36 +01:00
nConflictingFees + = it - > GetModifiedFee ( ) ;
2015-10-30 03:49:00 +01:00
nConflictingSize + = it - > GetTxSize ( ) ;
}
} else {
2016-02-24 18:34:37 +01:00
return state . DoS ( 0 , false ,
REJECT_NONSTANDARD , " too many potential replacements " , false ,
strprintf ( " rejecting replacement %s; too many potential replacements (%d > %d) \n " ,
2015-10-30 03:49:00 +01:00
hash . ToString ( ) ,
nConflictingCount ,
2016-02-24 18:34:37 +01:00
maxDescendantsToVisit ) ) ;
2015-10-22 20:13:18 +02:00
}
2015-10-30 05:04:00 +01:00
for ( unsigned int j = 0 ; j < tx . vin . size ( ) ; j + + )
{
// We don't want to accept replacements that require low
// feerate junk to be mined first. Ideally we'd keep track of
// the ancestor feerates and make the decision based on that,
// but for now requiring all new inputs to be confirmed works.
if ( ! setConflictsParents . count ( tx . vin [ j ] . prevout . hash ) )
{
// Rather than check the UTXO set - potentially expensive -
// it's cheaper to just check if the new input refers to a
// tx that's in the mempool.
if ( pool . mapTx . find ( tx . vin [ j ] . prevout . hash ) ! = pool . mapTx . end ( ) )
2016-02-24 18:34:37 +01:00
return state . DoS ( 0 , false ,
REJECT_NONSTANDARD , " replacement-adds-unconfirmed " , false ,
strprintf ( " replacement %s adds unconfirmed input, idx %d " ,
hash . ToString ( ) , j ) ) ;
2015-10-30 05:04:00 +01:00
}
}
2015-10-30 03:55:48 +01:00
// The replacement must pay greater fees than the transactions it
// replaces - if we did the bandwidth used by those conflicting
// transactions would not be paid for.
2015-11-30 22:42:36 +01:00
if ( nModifiedFees < nConflictingFees )
2015-10-22 20:13:18 +02:00
{
2016-02-24 18:34:37 +01:00
return state . DoS ( 0 , false ,
REJECT_INSUFFICIENTFEE , " insufficient fee " , false ,
strprintf ( " rejecting replacement %s, less fees than conflicting txs; %s < %s " ,
hash . ToString ( ) , FormatMoney ( nModifiedFees ) , FormatMoney ( nConflictingFees ) ) ) ;
2015-10-22 20:13:18 +02:00
}
2015-10-30 03:55:48 +01:00
// Finally in addition to paying more fees than the conflicts the
// new transaction must pay for its own bandwidth.
2015-11-30 22:42:36 +01:00
CAmount nDeltaFees = nModifiedFees - nConflictingFees ;
2017-01-19 22:17:38 +01:00
if ( nDeltaFees < : : incrementalRelayFee . GetFee ( nSize ) )
2015-10-22 20:13:18 +02:00
{
2016-02-24 18:34:37 +01:00
return state . DoS ( 0 , false ,
REJECT_INSUFFICIENTFEE , " insufficient fee " , false ,
strprintf ( " rejecting replacement %s, not enough additional fees to relay; %s < %s " ,
2015-10-22 20:13:18 +02:00
hash . ToString ( ) ,
FormatMoney ( nDeltaFees ) ,
2017-01-19 22:17:38 +01:00
FormatMoney ( : : incrementalRelayFee . GetFee ( nSize ) ) ) ) ;
2015-10-22 20:13:18 +02:00
}
}
2018-06-23 22:16:54 +02:00
constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS ;
2016-01-02 06:18:34 +01:00
2012-01-11 02:18:00 +01:00
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
2016-08-26 18:38:20 +02:00
PrecomputedTransactionData txdata ( tx ) ;
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 22:46:39 +02:00
if ( ! CheckInputs ( tx , state , view , true , scriptVerifyFlags , true , false , txdata ) ) {
2015-11-06 01:42:38 +01: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.
2017-01-10 22:53:10 +01:00
CValidationState stateDummy ; // Want reported failures to be from first CheckInputs
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 22:46:39 +02:00
if ( ! tx . HasWitness ( ) & & CheckInputs ( tx , stateDummy , view , true , scriptVerifyFlags & ~ ( SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK ) , true , false , txdata ) & &
! CheckInputs ( tx , stateDummy , view , true , scriptVerifyFlags & ~ SCRIPT_VERIFY_CLEANSTACK , true , false , txdata ) ) {
2016-08-16 17:38:57 +02:00
// Only the witness is missing, so the transaction itself may be fine.
2015-11-06 01:42:38 +01:00
state . SetCorruptionPossible ( ) ;
}
2017-01-10 22:53:10 +01:00
return false ; // state filled in by CheckInputs
2015-11-06 01:42:38 +01:00
}
2014-11-10 08:52:28 +01:00
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 22:46:39 +02: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
2014-11-10 08:52:28 +01:00
// 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
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 22:46:39 +02:00
// invalid blocks (using TestBlockValidity), however allowing such
// transactions into the mempool can be exploited as a DoS attack.
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags ( chainActive . Tip ( ) , Params ( ) . GetConsensus ( ) ) ;
2018-04-02 17:16:56 +02:00
if ( ! CheckInputsFromMempoolAndCache ( tx , state , view , pool , currentBlockScriptVerifyFlags , true , txdata ) ) {
2018-06-23 22:16:54 +02:00
return error ( " %s: BUG! PLEASE REPORT THIS! CheckInputs failed against latest-block but not STANDARD flags %s, %s " ,
2017-04-27 17:45:29 +02:00
__func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
2014-11-10 08:52:28 +01:00
}
2017-11-17 18:54:39 +01:00
if ( test_accept ) {
// Tx was accepted, but not added
return true ;
}
2015-10-22 20:13:18 +02:00
// Remove conflicting transactions from the mempool
2018-06-15 19:38:54 +02:00
for ( CTxMemPool : : txiter it : allConflicting )
2015-10-22 20:13:18 +02:00
{
2018-08-06 21:40:20 +02:00
LogPrint ( BCLog : : MEMPOOL , " replacing tx %s with %s for %s LBC additional fees, %d delta bytes \n " ,
2015-10-30 03:49:00 +01:00
it - > GetTx ( ) . GetHash ( ) . ToString ( ) ,
2015-10-22 20:13:18 +02:00
hash . ToString ( ) ,
2015-11-30 22:42:36 +01:00
FormatMoney ( nModifiedFees - nConflictingFees ) ,
2015-10-22 20:13:18 +02:00
( int ) nSize - ( int ) nConflictingSize ) ;
2016-12-05 03:53:26 +01:00
if ( plTxnReplaced )
plTxnReplaced - > push_back ( it - > GetSharedTx ( ) ) ;
2015-10-22 20:13:18 +02:00
}
2016-03-26 16:44:50 +01:00
pool . RemoveStaged ( allConflicting , false , MemPoolRemovalReason : : REPLACED ) ;
2015-10-22 20:13:18 +02:00
2017-09-12 18:40:06 +02:00
// This transaction should only count for fee estimation if:
// - it isn't a BIP 125 replacement transaction (may not be widely supported)
2018-03-18 15:26:45 +01:00
// - it's not being re-added during a reorg which bypasses typical mempool fee limits
2017-09-12 18:40:06 +02:00
// - the node is not behind
// - the transaction is not dependent on any other transactions in the mempool
bool validForFeeEstimation = ! fReplacementTransaction & & ! bypass_limits & & IsCurrentForFeeEstimation ( ) & & pool . HasNoInputsOf ( tx ) ;
2016-11-11 19:29:13 +01:00
2014-07-17 14:08:01 +02:00
// Store transaction in memory
2016-11-11 19:29:13 +01:00
pool . addUnchecked ( hash , entry , setAncestors , validForFeeEstimation ) ;
2015-10-02 23:19:55 +02:00
// trim mempool and check if tx was trimmed
2017-09-12 18:30:26 +02:00
if ( ! bypass_limits ) {
2017-08-01 21:17:40 +02:00
LimitMempoolSize ( pool , gArgs . GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 , gArgs . GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ) ;
2015-10-22 20:52:55 +02:00
if ( ! pool . exists ( hash ) )
2015-10-02 23:20:38 +02:00
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " mempool full " ) ;
}
2014-06-26 08:41:44 +02:00
}
2017-03-30 03:12:42 +02:00
GetMainSignals ( ) . TransactionAddedToMempool ( ptx ) ;
2014-06-26 08:41:44 +02:00
2014-07-17 14:08:01 +02:00
return true ;
2014-06-26 08:41:44 +02:00
}
2017-04-21 20:45:30 +02:00
/** (try to) add transaction to memory pool with a specified acceptance time **/
2017-09-12 18:30:26 +02:00
static bool AcceptToMemoryPoolWithTime ( const CChainParams & chainparams , CTxMemPool & pool , CValidationState & state , const CTransactionRef & tx ,
2016-12-05 03:53:26 +01:00
bool * pfMissingInputs , int64_t nAcceptTime , std : : list < CTransactionRef > * plTxnReplaced ,
2017-11-17 18:54:39 +01:00
bool bypass_limits , const CAmount nAbsurdFee , bool test_accept )
2015-10-23 00:50:33 +02:00
{
2017-05-31 02:58:54 +02:00
std : : vector < COutPoint > coins_to_uncache ;
2017-11-17 18:54:39 +01:00
bool res = AcceptToMemoryPoolWorker ( chainparams , pool , state , tx , pfMissingInputs , nAcceptTime , plTxnReplaced , bypass_limits , nAbsurdFee , coins_to_uncache , test_accept ) ;
2015-10-23 00:50:33 +02:00
if ( ! res ) {
2017-06-02 03:18:57 +02:00
for ( const COutPoint & hashTx : coins_to_uncache )
2015-10-23 00:50:33 +02:00
pcoinsTip - > Uncache ( hashTx ) ;
}
2016-10-03 16:06:10 +02:00
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
CValidationState stateDummy ;
2018-03-09 15:03:40 +01:00
FlushStateToDisk ( chainparams , stateDummy , FlushStateMode : : PERIODIC ) ;
2015-10-23 00:50:33 +02:00
return res ;
}
2017-09-12 18:30:26 +02:00
bool AcceptToMemoryPool ( CTxMemPool & pool , CValidationState & state , const CTransactionRef & tx ,
2016-12-05 03:53:26 +01:00
bool * pfMissingInputs , std : : list < CTransactionRef > * plTxnReplaced ,
2017-11-17 18:54:39 +01:00
bool bypass_limits , const CAmount nAbsurdFee , bool test_accept )
2016-10-31 07:24:41 +01:00
{
2017-04-21 20:45:30 +02:00
const CChainParams & chainparams = Params ( ) ;
2017-11-17 18:54:39 +01:00
return AcceptToMemoryPoolWithTime ( chainparams , pool , state , tx , pfMissingInputs , GetTime ( ) , plTxnReplaced , bypass_limits , nAbsurdFee , test_accept ) ;
2016-10-31 07:24:41 +01:00
}
2017-04-25 10:29:24 +02:00
/**
* Return transaction in txOut , and if it was found inside a block , its hash is placed in hashBlock .
* If blockIndex is provided , the transaction is fetched from the corresponding block .
*/
bool GetTransaction ( const uint256 & hash , CTransactionRef & txOut , const Consensus : : Params & consensusParams , uint256 & hashBlock , bool fAllowSlow , CBlockIndex * blockIndex )
2012-02-15 17:49:04 +01:00
{
2017-04-25 10:29:24 +02:00
CBlockIndex * pindexSlow = blockIndex ;
2015-09-17 23:43:34 +02:00
LOCK ( cs_main ) ;
2017-04-25 10:29:24 +02:00
if ( ! blockIndex ) {
CTransactionRef ptx = mempool . get ( hash ) ;
if ( ptx ) {
txOut = ptx ;
2015-09-17 23:43:34 +02:00
return true ;
2013-01-11 01:47:57 +01:00
}
2017-10-19 16:49:45 +02:00
2017-12-08 20:41:35 +01:00
if ( g_txindex ) {
2018-03-30 09:39:08 +02:00
return g_txindex - > FindTx ( hash , hashBlock , txOut ) ;
2017-04-25 10:29:24 +02:00
}
if ( fAllowSlow ) { // use coin database to locate block that contains transaction, and scan it
const Coin & coin = AccessByTxid ( * pcoinsTip , hash ) ;
if ( ! coin . IsSpent ( ) ) pindexSlow = chainActive [ coin . nHeight ] ;
}
2012-02-15 17:49:04 +01:00
}
2010-08-29 18:58:15 +02: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 18:54:00 +02:00
if ( pindexSlow ) {
CBlock block ;
2015-04-17 14:19:21 +02:00
if ( ReadBlockFromDisk ( block , pindexSlow , consensusParams ) ) {
2016-11-11 02:26:00 +01:00
for ( const auto & tx : block . vtx ) {
if ( tx - > GetHash ( ) = = hash ) {
2016-11-12 01:30:38 +01:00
txOut = tx ;
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 18:54:00 +02:00
hashBlock = pindexSlow - > GetBlockHash ( ) ;
return true ;
}
}
}
}
2010-08-29 18:58:15 +02: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 18:54:00 +02:00
return false ;
}
2010-08-29 18:58:15 +02:00
//////////////////////////////////////////////////////////////////////////////
//
// CBlock and CBlockIndex
//
2017-04-21 20:45:30 +02:00
static bool WriteBlockToDisk ( const CBlock & block , CDiskBlockPos & pos , const CMessageHeader : : MessageStartChars & messageStart )
2013-06-24 02:47:47 +02:00
{
// Open history file to append
2014-09-26 01:25:19 +02:00
CAutoFile fileout ( OpenBlockFile ( pos ) , SER_DISK , CLIENT_VERSION ) ;
2014-10-14 01:48:34 +02:00
if ( fileout . IsNull ( ) )
2015-01-08 11:44:25 +01:00
return error ( " WriteBlockToDisk: OpenBlockFile failed " ) ;
2013-06-24 02:47:47 +02:00
// Write index header
2016-10-29 01:51:33 +02:00
unsigned int nSize = GetSerializeSize ( fileout , block ) ;
2018-03-21 01:37:32 +01:00
fileout < < messageStart < < nSize ;
2013-06-24 02:47:47 +02:00
// Write block
2014-10-20 12:45:50 +02:00
long fileOutPos = ftell ( fileout . Get ( ) ) ;
2013-06-24 02:47:47 +02:00
if ( fileOutPos < 0 )
2015-01-08 11:44:25 +01:00
return error ( " WriteBlockToDisk: ftell failed " ) ;
2013-06-24 02:47:47 +02:00
pos . nPos = ( unsigned int ) fileOutPos ;
fileout < < block ;
return true ;
}
2015-04-17 14:19:21 +02:00
bool ReadBlockFromDisk ( CBlock & block , const CDiskBlockPos & pos , const Consensus : : Params & consensusParams )
2013-06-24 03:21:33 +02:00
{
block . SetNull ( ) ;
// Open history file to read
2014-09-26 01:25:19 +02:00
CAutoFile filein ( OpenBlockFile ( pos , true ) , SER_DISK , CLIENT_VERSION ) ;
2014-10-14 01:48:34 +02:00
if ( filein . IsNull ( ) )
2015-01-26 09:47:59 +01:00
return error ( " ReadBlockFromDisk: OpenBlockFile failed for %s " , pos . ToString ( ) ) ;
2013-06-24 03:21:33 +02:00
// Read block
try {
filein > > block ;
}
2014-12-07 13:29:06 +01:00
catch ( const std : : exception & e ) {
2015-01-26 09:47:59 +01:00
return error ( " %s: Deserialize or I/O error - %s at %s " , __func__ , e . what ( ) , pos . ToString ( ) ) ;
2013-06-24 03:21:33 +02:00
}
// Check the header
2018-08-06 21:40:20 +02:00
if ( ! CheckProofOfWork ( block . GetPoWHash ( ) , block . nBits , consensusParams ) )
2015-01-26 09:47:59 +01:00
return error ( " ReadBlockFromDisk: Errors in block header at %s " , pos . ToString ( ) ) ;
2013-06-24 03:21:33 +02:00
return true ;
}
2015-04-17 14:19:21 +02:00
bool ReadBlockFromDisk ( CBlock & block , const CBlockIndex * pindex , const Consensus : : Params & consensusParams )
2010-08-29 18:58:15 +02:00
{
2017-12-13 22:06:51 +01:00
CDiskBlockPos blockPos ;
{
LOCK ( cs_main ) ;
blockPos = pindex - > GetBlockPos ( ) ;
}
if ( ! ReadBlockFromDisk ( block , blockPos , consensusParams ) )
2010-08-29 18:58:15 +02:00
return false ;
2013-06-24 03:10:02 +02:00
if ( block . GetHash ( ) ! = pindex - > GetBlockHash ( ) )
2015-01-26 09:47:59 +01:00
return error ( " ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s " ,
pindex - > ToString ( ) , pindex - > GetBlockPos ( ) . ToString ( ) ) ;
2010-08-29 18:58:15 +02:00
return true ;
}
2018-05-02 14:10:27 +02:00
bool ReadRawBlockFromDisk ( std : : vector < uint8_t > & block , const CDiskBlockPos & pos , const CMessageHeader : : MessageStartChars & message_start )
{
CDiskBlockPos hpos = pos ;
hpos . nPos - = 8 ; // Seek back 8 bytes for meta header
CAutoFile filein ( OpenBlockFile ( hpos , true ) , SER_DISK , CLIENT_VERSION ) ;
if ( filein . IsNull ( ) ) {
return error ( " %s: OpenBlockFile failed for %s " , __func__ , pos . ToString ( ) ) ;
}
try {
CMessageHeader : : MessageStartChars blk_start ;
unsigned int blk_size ;
filein > > blk_start > > blk_size ;
if ( memcmp ( blk_start , message_start , CMessageHeader : : MESSAGE_START_SIZE ) ) {
return error ( " %s: Block magic mismatch for %s: %s versus expected %s " , __func__ , pos . ToString ( ) ,
HexStr ( blk_start , blk_start + CMessageHeader : : MESSAGE_START_SIZE ) ,
HexStr ( message_start , message_start + CMessageHeader : : MESSAGE_START_SIZE ) ) ;
}
if ( blk_size > MAX_SIZE ) {
return error ( " %s: Block data is larger than maximum deserialization size for %s: %s versus %s " , __func__ , pos . ToString ( ) ,
blk_size , MAX_SIZE ) ;
}
block . resize ( blk_size ) ; // Zeroing of memory is intentional here
filein . read ( ( char * ) block . data ( ) , blk_size ) ;
} catch ( const std : : exception & e ) {
return error ( " %s: Read from block file failed: %s for %s " , __func__ , e . what ( ) , pos . ToString ( ) ) ;
}
return true ;
}
bool ReadRawBlockFromDisk ( std : : vector < uint8_t > & block , const CBlockIndex * pindex , const CMessageHeader : : MessageStartChars & message_start )
{
CDiskBlockPos block_pos ;
{
LOCK ( cs_main ) ;
block_pos = pindex - > GetBlockPos ( ) ;
}
return ReadRawBlockFromDisk ( block , block_pos , message_start ) ;
}
2018-08-06 21:40:20 +02:00
bool withinLevelBounds ( int nReduction , int nLevel )
{
if ( ( ( nReduction * nReduction + nReduction ) > > 1 ) > nLevel )
return false ;
nReduction + = 1 ;
if ( ( ( nReduction * nReduction + nReduction ) > > 1 ) < = nLevel )
return false ;
return true ;
}
2015-04-01 16:03:11 +02:00
CAmount GetBlockSubsidy ( int nHeight , const Consensus : : Params & consensusParams )
2010-08-29 18:58:15 +02:00
{
2018-08-06 21:40:20 +02:00
if ( nHeight = = 0 )
{
return 400000000 * COIN ;
}
else if ( nHeight < = 5100 )
{
return 1 * COIN ;
}
else if ( nHeight < = 55000 )
{
int l = nHeight - 5000 ;
int nLevel = 0 ;
for ( int i = 0 ; i < l ; i + = 100 )
{
nLevel + + ;
}
return nLevel * COIN ;
}
CAmount nStartingSubsidy = 500 * COIN ;
int nLevel = ( nHeight - 55001 ) / consensusParams . nSubsidyLevelInterval ;
int nReduction = ( ( - 1 + ( int ) sqrt ( ( 8 * nLevel ) + 1 ) ) / 2 ) ;
while ( ! ( withinLevelBounds ( nReduction , nLevel ) ) )
{
if ( ( ( nReduction * nReduction + nReduction ) > > 1 ) > nLevel )
{
nReduction - - ;
}
else
{
nReduction + + ;
}
}
CAmount nSubsidyReduction = nReduction * COIN ;
if ( nSubsidyReduction > = nStartingSubsidy )
2015-04-01 16:03:11 +02:00
return 0 ;
2018-08-06 21:40:20 +02:00
return nStartingSubsidy - nSubsidyReduction ;
2010-08-29 18:58:15 +02:00
}
bool IsInitialBlockDownload ( )
{
2016-04-27 02:21:22 +02:00
// Once this function has returned false, it must remain false.
static std : : atomic < bool > latchToFalse { false } ;
// Optimization: pre-test latch before taking the lock.
if ( latchToFalse . load ( std : : memory_order_relaxed ) )
return false ;
2014-04-15 17:38:25 +02:00
LOCK ( cs_main ) ;
2016-04-27 02:21:22 +02:00
if ( latchToFalse . load ( std : : memory_order_relaxed ) )
return false ;
2015-04-23 05:22:36 +02:00
if ( fImporting | | fReindex )
return true ;
2017-08-07 07:36:37 +02:00
if ( chainActive . Tip ( ) = = nullptr )
2010-08-29 18:58:15 +02:00
return true ;
2017-05-07 20:10:19 +02:00
if ( chainActive . Tip ( ) - > nChainWork < nMinimumChainWork )
2010-08-29 18:58:15 +02:00
return true ;
2016-11-01 01:37:54 +01:00
if ( chainActive . Tip ( ) - > GetBlockTime ( ) < ( GetTime ( ) - nMaxTipAge ) )
return true ;
2017-05-11 19:11:36 +02:00
LogPrintf ( " Leaving InitialBlockDownload (latching to false) \n " ) ;
2016-11-01 01:37:54 +01:00
latchToFalse . store ( true , std : : memory_order_relaxed ) ;
return false ;
2010-08-29 18:58:15 +02:00
}
2017-08-07 07:36:37 +02:00
CBlockIndex * pindexBestForkTip = nullptr , * pindexBestForkBase = nullptr ;
2013-05-07 18:33:52 +02:00
2016-04-27 18:04:02 +02:00
static void AlertNotify ( const std : : string & strMessage )
2016-03-06 11:07:25 +01:00
{
uiInterface . NotifyAlertChanged ( ) ;
2017-08-01 21:17:40 +02:00
std : : string strCmd = gArgs . GetArg ( " -alertnotify " , " " ) ;
2016-03-06 11:07:25 +01: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 ;
boost : : replace_all ( strCmd , " %s " , safeStatus ) ;
2018-02-08 01:19:34 +01:00
std : : thread t ( runCommand , strCmd ) ;
t . detach ( ) ; // thread runs free
2016-03-06 11:07:25 +01:00
}
2017-04-21 20:45:30 +02:00
static void CheckForkWarningConditions ( )
2013-05-07 18:33:52 +02:00
{
2014-04-15 12:43:17 +02:00
AssertLockHeld ( cs_main ) ;
2013-09-04 04:06:02 +02:00
// Before we get past initial download, we cannot reliably alert about forks
2016-10-22 07:33:25 +02:00
// (we assume we don't get stuck on a fork before finishing our initial sync)
2013-09-04 04:06:02 +02:00
if ( IsInitialBlockDownload ( ) )
return ;
2013-05-07 18:33:52 +02:00
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
// of our head, drop it
2013-10-10 23:07:44 +02:00
if ( pindexBestForkTip & & chainActive . Height ( ) - pindexBestForkTip - > nHeight > = 72 )
2017-08-07 07:36:37 +02:00
pindexBestForkTip = nullptr ;
2013-05-07 18:33:52 +02:00
2014-10-29 17:00:02 +01:00
if ( pindexBestForkTip | | ( pindexBestInvalid & & pindexBestInvalid - > nChainWork > chainActive . Tip ( ) - > nChainWork + ( GetBlockProof ( * chainActive . Tip ( ) ) * 6 ) ) )
2013-05-07 18:33:52 +02:00
{
2016-11-29 10:46:19 +01:00
if ( ! GetfLargeWorkForkFound ( ) & & pindexBestForkBase )
2013-05-07 18:37:37 +02:00
{
2014-10-07 19:11:48 +02:00
std : : string warning = std : : string ( " 'Warning: Large-work fork detected, forking after block " ) +
pindexBestForkBase - > phashBlock - > ToString ( ) + std : : string ( " ' " ) ;
2016-04-27 18:04:02 +02:00
AlertNotify ( warning ) ;
2013-05-07 18:37:37 +02:00
}
2014-10-28 04:00:55 +01:00
if ( pindexBestForkTip & & pindexBestForkBase )
2013-05-18 03:09:28 +02:00
{
2015-02-24 18:32:34 +01:00
LogPrintf ( " %s: Warning: Large valid fork found \n forking the chain at height %d (%s) \n lasting to height %d (%s). \n Chain state database corruption likely. \n " , __func__ ,
2014-01-16 16:15:27 +01:00
pindexBestForkBase - > nHeight , pindexBestForkBase - > phashBlock - > ToString ( ) ,
pindexBestForkTip - > nHeight , pindexBestForkTip - > phashBlock - > ToString ( ) ) ;
2016-11-29 10:46:19 +01:00
SetfLargeWorkForkFound ( true ) ;
2013-05-18 03:09:28 +02:00
}
else
{
2015-02-24 18:32:34 +01:00
LogPrintf ( " %s: Warning: Found invalid chain at least ~6 blocks longer than our best chain. \n Chain state database corruption likely. \n " , __func__ ) ;
2016-11-29 10:46:19 +01:00
SetfLargeWorkInvalidChainFound ( true ) ;
2013-05-18 03:09:28 +02:00
}
}
else
{
2016-11-29 10:46:19 +01:00
SetfLargeWorkForkFound ( false ) ;
SetfLargeWorkInvalidChainFound ( false ) ;
2013-05-18 03:09:28 +02:00
}
2013-05-07 18:33:52 +02:00
}
2017-04-21 20:45:30 +02:00
static void CheckForkWarningConditionsOnNewFork ( CBlockIndex * pindexNewForkTip )
2013-05-07 18:33:52 +02:00
{
2014-04-15 12:43:17 +02:00
AssertLockHeld ( cs_main ) ;
2013-05-07 18:33:52 +02:00
// If we are on a fork that is sufficiently large, set a warning flag
CBlockIndex * pfork = pindexNewForkTip ;
2013-10-10 23:07:44 +02:00
CBlockIndex * plonger = chainActive . Tip ( ) ;
2013-05-07 18:33:52 +02:00
while ( pfork & & pfork ! = plonger )
{
while ( plonger & & plonger - > nHeight > pfork - > nHeight )
plonger = plonger - > pprev ;
if ( pfork = = plonger )
break ;
pfork = pfork - > pprev ;
}
2015-04-28 16:48:28 +02:00
// We define a condition where we should warn the user about as a fork of at least 7 blocks
// with a tip within 72 blocks (+/- 12 hours if no one mines it) of ours
2013-05-07 18:33:52 +02:00
// We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network
// hash rate operating on the fork.
// or a chain that is entirely longer than ours and invalid (note that this should be detected by both)
// We define it this way because it allows us to only store the highest fork tip (+ base) which meets
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
2017-07-09 13:35:39 +02:00
if ( pfork & & ( ! pindexBestForkTip | | pindexNewForkTip - > nHeight > pindexBestForkTip - > nHeight ) & &
2014-10-29 17:00:02 +01:00
pindexNewForkTip - > nChainWork - pfork - > nChainWork > ( GetBlockProof ( * pfork ) * 7 ) & &
2013-10-10 23:07:44 +02:00
chainActive . Height ( ) - pindexNewForkTip - > nHeight < 72 )
2013-05-07 18:33:52 +02:00
{
pindexBestForkTip = pindexNewForkTip ;
pindexBestForkBase = pfork ;
}
CheckForkWarningConditions ( ) ;
}
CWallet class
* A new class CKeyStore manages private keys, and script.cpp depends on access to CKeyStore.
* A new class CWallet extends CKeyStore, and contains all former wallet-specific globals; CWallet depends on script.cpp, not the other way around.
* Wallet-specific functions in CTransaction/CTxIn/CTxOut (GetDebit, GetCredit, GetChange, IsMine, IsFromMe), are moved to CWallet, taking their former 'this' argument as an explicit parameter
* CWalletTx objects know which CWallet they belong to, for convenience, so they have their own direct (and caching) GetDebit/... functions.
* Some code was moved from CWalletDB to CWallet, such as handling of reserve keys.
* Main.cpp keeps a set of all 'registered' wallets, which should be informed about updates to the block chain, and does not have any notion about any 'main' wallet. Function in main.cpp that require a wallet (such as GenerateCoins), take an explicit CWallet* argument.
* The actual CWallet instance used by the application is defined in init.cpp as "CWallet* pwalletMain". rpc.cpp and ui.cpp use this variable.
* Functions in main.cpp and db.cpp that are not used by other modules are marked static.
* The code for handling the 'submitorder' message is removed, as it not really compatible with the idea that a node is independent from the wallet(s) connected to it, and obsolete anyway.
2011-06-01 18:28:20 +02:00
void static InvalidChainFound ( CBlockIndex * pindexNew )
2010-08-29 18:58:15 +02:00
{
2013-10-13 22:15:48 +02:00
if ( ! pindexBestInvalid | | pindexNew - > nChainWork > pindexBestInvalid - > nChainWork )
pindexBestInvalid = pindexNew ;
2014-07-29 16:53:38 +02:00
2015-02-24 18:32:34 +01:00
LogPrintf ( " %s: invalid block=%s height=%d log2_work=%.8g date=%s \n " , __func__ ,
2014-01-16 16:15:27 +01:00
pindexNew - > GetBlockHash ( ) . ToString ( ) , pindexNew - > nHeight ,
2018-02-28 16:46:31 +01:00
log ( pindexNew - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , FormatISO8601DateTime ( pindexNew - > GetBlockTime ( ) ) ) ;
2015-07-04 21:14:03 +02:00
CBlockIndex * tip = chainActive . Tip ( ) ;
assert ( tip ) ;
2015-02-24 18:32:34 +01:00
LogPrintf ( " %s: current best=%s height=%d log2_work=%.8g date=%s \n " , __func__ ,
2015-07-04 21:14:03 +02:00
tip - > GetBlockHash ( ) . ToString ( ) , chainActive . Height ( ) , log ( tip - > nChainWork . getdouble ( ) ) / log ( 2.0 ) ,
2018-02-28 16:46:31 +01:00
FormatISO8601DateTime ( tip - > GetBlockTime ( ) ) ) ;
2013-05-07 18:33:52 +02:00
CheckForkWarningConditions ( ) ;
2010-08-29 18:58:15 +02:00
}
2017-12-04 15:34:46 +01:00
void CChainState : : InvalidBlockFound ( CBlockIndex * pindex , const CValidationState & state ) {
2013-11-16 19:28:24 +01:00
if ( ! state . CorruptionPossible ( ) ) {
pindex - > nStatus | = BLOCK_FAILED_VALID ;
2018-04-18 13:57:18 +02:00
m_failed_blocks . insert ( pindex ) ;
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 11:38:35 +01:00
setDirtyBlockIndex . insert ( pindex ) ;
2014-10-06 08:31:33 +02:00
setBlockIndexCandidates . erase ( pindex ) ;
2013-11-16 19:28:24 +01:00
InvalidChainFound ( pindex ) ;
}
2012-08-19 00:33:01 +02:00
}
2016-04-30 05:45:20 +02: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 18:54:00 +02:00
{
// mark inputs spent
2013-01-08 13:17:15 +01:00
if ( ! tx . IsCoinBase ( ) ) {
2014-09-03 15:54:37 +02:00
txundo . vprevout . reserve ( tx . vin . size ( ) ) ;
2019-05-23 19:46:37 +02:00
Coin coin ;
for ( const CTxIn & txin : tx . vin ) {
2018-08-06 21:40:20 +02:00
bool is_spent = inputs . SpendCoin ( txin . prevout , & coin ) ;
2017-06-05 17:50:47 +02:00
assert ( is_spent ) ;
2019-05-23 19:46:37 +02:00
txundo . vprevout . emplace_back ( coin . out , coin . IsCoinBase ( ) , int ( coin . 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 18:54:00 +02:00
}
}
2015-11-12 22:57:03 +01:00
// add outputs
2017-04-25 20:29:30 +02: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 18:54:00 +02:00
}
2016-04-30 05:45:20 +02:00
void UpdateCoins ( const CTransaction & tx , CCoinsViewCache & inputs , int nHeight )
2014-10-27 16:07:50 +01:00
{
CTxUndo txundo ;
2016-04-30 05:45:20 +02:00
UpdateCoins ( tx , inputs , txundo , nHeight ) ;
2014-10-27 16:07:50 +01:00
}
2014-11-29 16:01:37 +01:00
bool CScriptCheck : : operator ( ) ( ) {
2012-12-01 22:30:06 +01:00
const CScript & scriptSig = ptxTo - > vin [ nIn ] . scriptSig ;
2016-08-04 02:49:16 +02:00
const CScriptWitness * witness = & ptxTo - > vin [ nIn ] . scriptWitness ;
2017-09-22 08:27:03 +02:00
return VerifyScript ( scriptSig , m_tx_out . scriptPubKey , witness , nFlags , CachingTransactionSignatureChecker ( ptxTo , nIn , m_tx_out . nValue , cacheStore , * txdata ) , & error ) ;
2012-12-01 22:30:06 +01:00
}
2015-04-24 16:45:16 +02:00
int GetSpendHeight ( const CCoinsViewCache & inputs )
2010-08-29 18:58:15 +02:00
{
2015-04-24 16:45:16 +02:00
LOCK ( cs_main ) ;
2018-01-12 01:23:09 +01:00
CBlockIndex * pindexPrev = LookupBlockIndex ( inputs . GetBestBlock ( ) ) ;
2015-04-24 16:45:16 +02:00
return pindexPrev - > nHeight + 1 ;
}
2012-12-01 23:04:14 +01:00
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 22:46:39 +02:00
static CuckooCache : : cache < uint256 , SignatureCacheHasher > scriptExecutionCache ;
static uint256 scriptExecutionCacheNonce ( GetRandHash ( ) ) ;
void InitScriptExecutionCache ( ) {
// nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
// setup_bytes creates the minimum possible cache (2 elements).
2017-08-01 21:17:40 +02:00
size_t nMaxCacheSize = std : : min ( std : : max ( ( int64_t ) 0 , gArgs . GetArg ( " -maxsigcachesize " , DEFAULT_MAX_SIG_CACHE_SIZE ) / 2 ) , MAX_MAX_SIG_CACHE_SIZE ) * ( ( size_t ) 1 < < 20 ) ;
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 22:46:39 +02:00
size_t nElems = scriptExecutionCache . setup_bytes ( nMaxCacheSize ) ;
2017-04-21 22:38:12 +02: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 22:46:39 +02:00
}
2017-04-21 20:45:30 +02:00
/**
* Check whether all inputs of this transaction are valid ( no double spends , scripts & sigs , amounts )
2017-06-07 17:05:34 +02:00
* This does not modify the UTXO set .
*
2017-08-07 07:36:37 +02:00
* If pvChecks is not nullptr , script checks are pushed onto it instead of being performed inline . Any
2017-06-07 17:05:34 +02: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 22:23:55 +02:00
*
* Non - static ( and re - declared ) in src / test / txvalidationcache_tests . cpp
2017-04-21 20:45:30 +02:00
*/
2017-06-23 22:23:55 +02:00
bool CheckInputs ( const CTransaction & tx , CValidationState & state , const CCoinsViewCache & inputs , bool fScriptChecks , unsigned int flags , bool cacheSigStore , bool cacheFullScriptStore , PrecomputedTransactionData & txdata , std : : vector < CScriptCheck > * pvChecks )
2015-04-24 16:45:16 +02:00
{
if ( ! tx . IsCoinBase ( ) )
{
if ( pvChecks )
pvChecks - > reserve ( tx . vin . size ( ) ) ;
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 18:54:00 +02:00
2012-05-16 17:26:56 +02:00
// The first loop above does all the inexpensive checks.
// Only if ALL inputs pass do we perform expensive ECDSA signature checks.
// Helps prevent CPU exhaustion attacks.
2017-01-06 12:49:59 +01:00
// Skip script verification when connecting blocks under the
2017-02-06 15:16:18 +01:00
// assumevalid block. Assuming the assumevalid block is valid this
2016-01-04 05:39:05 +01:00
// is safe because block merkle hashes are still computed and checked,
2017-01-06 12:49:59 +01:00
// Of course, if an assumed valid block is invalid due to false scriptSigs
2016-08-13 19:21:13 +02:00
// this optimization would allow an invalid chain to be accepted.
2012-12-01 22:51:10 +01:00
if ( fScriptChecks ) {
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 22:46:39 +02: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 ;
// We only use the first 19 bytes of nonce to avoid a second SHA
// round - giving us 19 + 32 + 4 = 55 bytes (+ 8 + 1 = 64)
static_assert ( 55 - sizeof ( flags ) - 32 > = 128 / 8 , " Want at least 128 bits of nonce for script execution cache " ) ;
CSHA256 ( ) . Write ( scriptExecutionCacheNonce . begin ( ) , 55 - sizeof ( flags ) - 32 ) . Write ( tx . GetWitnessHash ( ) . begin ( ) , 32 ) . Write ( ( unsigned char * ) & flags , sizeof ( flags ) ) . Finalize ( hashCacheEntry . begin ( ) ) ;
AssertLockHeld ( cs_main ) ; //TODO: Remove this requirement by making CuckooCache not require external locks
if ( scriptExecutionCache . contains ( hashCacheEntry , ! cacheFullScriptStore ) ) {
return true ;
}
2013-01-08 13:17:15 +01:00
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
const COutPoint & prevout = tx . vin [ i ] . prevout ;
2017-04-25 20:29:32 +02:00
const Coin & coin = inputs . AccessCoin ( prevout ) ;
2017-05-31 02:58:54 +02:00
assert ( ! coin . IsSpent ( ) ) ;
2012-01-11 02:18:00 +01:00
2017-04-27 16:37:33 +02:00
// 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.
2012-01-11 02:18:00 +01:00
2011-09-02 22:59:47 +02:00
// Verify signature
2017-07-30 11:32:39 +02:00
CScriptCheck check ( coin . out , tx , i , flags , cacheSigStore , & txdata ) ;
2012-12-01 23:04:14 +01:00
if ( pvChecks ) {
pvChecks - > push_back ( CScriptCheck ( ) ) ;
check . swap ( pvChecks - > back ( ) ) ;
2013-04-18 22:17:05 +02:00
} else if ( ! check ( ) ) {
2014-03-11 03:36:46 +01:00
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, don't trigger DoS protection to
// avoid splitting the network between upgraded and
// non-upgraded nodes.
2017-07-30 11:32:39 +02:00
CScriptCheck check2 ( coin . out , tx , i ,
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 22:46:39 +02:00
flags & ~ STANDARD_NOT_MANDATORY_VERIFY_FLAGS , cacheSigStore , & txdata ) ;
2016-01-03 16:50:31 +01:00
if ( check2 ( ) )
2014-11-29 16:01:37 +01:00
return state . Invalid ( false , REJECT_NONSTANDARD , strprintf ( " non-mandatory-script-verify-flag (%s) " , ScriptErrorString ( check . GetScriptError ( ) ) ) ) ;
2013-04-18 22:17:05 +02:00
}
2014-03-11 03:36:46 +01:00
// Failures of other flags indicate a transaction that is
2017-06-20 00:57:31 +02:00
// invalid in new blocks, e.g. an invalid P2SH. We DoS ban
2014-03-11 03:36:46 +01:00
// such nodes as they are not following the protocol. That
// said during an upgrade careful thought should be taken
// as to the correct behavior - we may want to continue
2016-06-03 16:05:51 +02:00
// peering with non-upgraded nodes even after soft-fork
// super-majority signaling has occurred.
2014-11-29 16:01:37 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , strprintf ( " mandatory-script-verify-flag-failed (%s) " , ScriptErrorString ( check . GetScriptError ( ) ) ) ) ;
2013-04-18 22:17:05 +02:00
}
2011-11-08 19:20:29 +01:00
}
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 22:46:39 +02:00
if ( cacheFullScriptStore & & ! pvChecks ) {
// We executed all of the provided scripts, and were told to
// cache the result. Do so now.
scriptExecutionCache . insert ( hashCacheEntry ) ;
}
2010-08-29 18:58:15 +02:00
}
}
return true ;
}
2014-12-03 00:39:03 +01:00
namespace {
2015-04-19 23:48:25 +02:00
bool UndoWriteToDisk ( const CBlockUndo & blockundo , CDiskBlockPos & pos , const uint256 & hashBlock , const CMessageHeader : : MessageStartChars & messageStart )
2014-12-03 00:39:03 +01:00
{
// Open history file to append
CAutoFile fileout ( OpenUndoFile ( pos ) , SER_DISK , CLIENT_VERSION ) ;
if ( fileout . IsNull ( ) )
2015-01-08 11:44:25 +01:00
return error ( " %s: OpenUndoFile failed " , __func__ ) ;
2014-12-03 00:39:03 +01:00
// Write index header
2016-10-29 01:51:33 +02:00
unsigned int nSize = GetSerializeSize ( fileout , blockundo ) ;
2018-03-21 01:37:32 +01:00
fileout < < messageStart < < nSize ;
2014-12-03 00:39:03 +01:00
// Write undo data
long fileOutPos = ftell ( fileout . Get ( ) ) ;
if ( fileOutPos < 0 )
2015-01-08 11:44:25 +01:00
return error ( " %s: ftell failed " , __func__ ) ;
2014-12-03 00:39:03 +01:00
pos . nPos = ( unsigned int ) fileOutPos ;
fileout < < blockundo ;
// calculate & write checksum
CHashWriter hasher ( SER_GETHASH , PROTOCOL_VERSION ) ;
hasher < < hashBlock ;
hasher < < blockundo ;
fileout < < hasher . GetHash ( ) ;
return true ;
}
2017-06-09 18:57:23 +02:00
static bool UndoReadFromDisk ( CBlockUndo & blockundo , const CBlockIndex * pindex )
2014-12-03 00:39:03 +01:00
{
2017-06-09 18:57:23 +02:00
CDiskBlockPos pos = pindex - > GetUndoPos ( ) ;
if ( pos . IsNull ( ) ) {
return error ( " %s: no undo data available " , __func__ ) ;
}
2014-12-03 00:39:03 +01:00
// Open history file to read
CAutoFile filein ( OpenUndoFile ( pos , true ) , SER_DISK , CLIENT_VERSION ) ;
if ( filein . IsNull ( ) )
2016-09-15 12:40:09 +02:00
return error ( " %s: OpenUndoFile failed " , __func__ ) ;
2014-12-03 00:39:03 +01:00
// Read block
uint256 hashChecksum ;
2017-04-25 20:29:14 +02:00
CHashVerifier < CAutoFile > verifier ( & filein ) ; // We need a CHashVerifier as reserializing may lose data
2014-12-03 00:39:03 +01:00
try {
2017-06-09 18:57:23 +02:00
verifier < < pindex - > pprev - > GetBlockHash ( ) ;
2017-04-25 20:29:14 +02:00
verifier > > blockundo ;
2014-12-03 00:39:03 +01:00
filein > > hashChecksum ;
}
catch ( const std : : exception & e ) {
2015-01-08 11:44:25 +01:00
return error ( " %s: Deserialize or I/O error - %s " , __func__ , e . what ( ) ) ;
2014-12-03 00:39:03 +01:00
}
// Verify checksum
2017-04-25 20:29:14 +02:00
if ( hashChecksum ! = verifier . GetHash ( ) )
2015-01-08 11:44:25 +01:00
return error ( " %s: Checksum mismatch " , __func__ ) ;
2014-12-03 00:39:03 +01:00
return true ;
}
2015-01-17 00:57:14 +01:00
/** Abort with a message */
2018-05-02 17:14:48 +02:00
static bool AbortNode ( const std : : string & strMessage , const std : : string & userMessage = " " )
2015-01-17 00:57:14 +01:00
{
2016-11-29 10:46:19 +01:00
SetMiscWarning ( strMessage ) ;
2015-01-17 00:57:14 +01:00
LogPrintf ( " *** %s \n " , strMessage ) ;
uiInterface . ThreadSafeMessageBox (
2018-08-06 21:40:20 +02:00
userMessage . empty ( ) ? " Error: A fatal internal error occurred, see debug.log for details. System message: " + strMessage : userMessage ,
2015-01-17 00:57:14 +01:00
" " , CClientUIInterface : : MSG_ERROR ) ;
StartShutdown ( ) ;
return false ;
}
2018-05-02 17:14:48 +02:00
static bool AbortNode ( CValidationState & state , const std : : string & strMessage , const std : : string & userMessage = " " )
2015-01-17 00:57:14 +01:00
{
AbortNode ( strMessage , userMessage ) ;
return state . Error ( strMessage ) ;
}
2017-05-31 22:21:25 +02:00
} // namespace
2010-08-29 18:58:15 +02:00
2015-02-03 15:44:39 +01:00
/**
2017-04-25 20:29:25 +02:00
* Restore the UTXO in a Coin at a given COutPoint
* @ param undo The Coin to be restored .
2015-02-03 15:44:39 +01:00
* @ param view The coins view to which to apply the changes .
2018-08-06 21:40:20 +02:00
* @ param view The claim trieCache to which to apply the changes .
2015-02-03 15:44:39 +01:00
* @ param out The out point that corresponds to the tx input .
2017-04-25 20:29:09 +02:00
* @ return A DisconnectResult as an int
2015-02-03 15:44:39 +01:00
*/
2018-08-06 21:40:20 +02:00
int ApplyTxInUndo ( unsigned int index , CTxUndo & txUndo , CCoinsViewCache & view , CClaimTrieCache & trieCache , const COutPoint & out )
2015-02-03 15:44:39 +01:00
{
2019-05-23 19:46:37 +02:00
auto & undo = txUndo . vprevout [ index ] ;
2018-08-06 21:40:20 +02:00
bool fClean = true ;
2017-05-31 02:58:54 +02:00
if ( view . HaveCoin ( out ) ) fClean = false ; // overwriting transaction output
2017-04-25 20:29:30 +02:00
if ( undo . nHeight = = 0 ) {
2019-05-23 19:46:37 +02:00
// Missing undo metadata (height and coinbase, not txout). Older versions included this
2017-04-25 20:29:30 +02:00
// 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-31 02:58:54 +02:00
if ( ! alternate . IsSpent ( ) ) {
2017-04-25 20:29:30 +02:00
undo . nHeight = alternate . nHeight ;
undo . fCoinBase = alternate . fCoinBase ;
} else {
return DISCONNECT_FAILED ; // adding output for transaction without known metadata
2017-04-25 20:29:19 +02:00
}
2019-07-01 20:42:45 +02:00
// TODO: pick the above approach or this:
// what is more correct? the above AccessByTxid or this kind of lookup ?
// for (uint32_t i = index + 1; i < txUndo.vprevout.size(); ++i) {
// if (txUndo.vprevout[i].nHeight > 0) {
// assert(undo.nHeight == txUndo.vprevout[i].nHeight);
// assert(undo.fCoinBase == txUndo.vprevout[i].fCoinBase);
// break;
// }
// }
2015-02-03 15:44:39 +01:00
}
2018-08-06 21:40:20 +02:00
2019-05-08 00:32:22 +02:00
// restore claim if applicable
2019-05-23 19:46:37 +02:00
if ( undo . fIsClaim & & ! undo . txout . scriptPubKey . empty ( ) ) {
int nValidHeight = static_cast < int > ( undo . nClaimValidHeight ) ;
2019-05-08 00:32:22 +02:00
if ( nValidHeight > 0 & & nValidHeight > = undo . nHeight ) {
2019-05-23 19:46:37 +02:00
CClaimScriptUndoSpendOp undoSpend ( COutPoint ( out . hash , out . n ) , undo . txout . nValue , undo . nHeight , nValidHeight ) ;
ProcessClaim ( undoSpend , trieCache , undo . txout . scriptPubKey ) ;
2019-05-08 00:32:22 +02:00
} else {
LogPrintf ( " %s: (txid: %s, nOut: %d) Not restoring claim/support to the claim trie because it expired before it was spent \n " , __func__ , out . hash . ToString ( ) , out . n ) ;
LogPrintf ( " %s: nValidHeight = %d, undo.nHeight = %d, nCurrentHeight = %d \n " , __func__ , nValidHeight , undo . nHeight , chainActive . Height ( ) ) ;
2018-08-06 21:40:20 +02:00
}
}
2017-04-19 18:34:30 +02:00
// The potential_overwrite parameter to AddCoin is only allowed to be false if we know for
// sure that the coin did not already exist in the cache. As we have queried for that above
// using HaveCoin, we don't need to guess. When fClean is false, a coin already existed and
// it is an overwrite.
2019-05-23 19:46:37 +02:00
Coin coin ( undo . txout , int ( undo . nHeight ) , undo . fCoinBase ) ;
view . AddCoin ( out , std : : move ( coin ) , ! fClean ) ;
2015-02-03 15:44:39 +01:00
2017-04-25 20:29:09 +02:00
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN ;
2015-02-03 15:44:39 +01:00
}
2017-01-17 22:01:48 +01:00
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
2017-04-19 18:34:30 +02:00
* When FAILED is returned , view is left in an indeterminate state . */
2018-08-06 21:40:20 +02:00
DisconnectResult CChainState : : DisconnectBlock ( const CBlock & block , const CBlockIndex * pindex , CCoinsViewCache & view , CClaimTrieCache & trieCache )
2010-08-29 18:58:15 +02:00
{
2018-08-06 21:40:20 +02:00
assert ( pindex - > GetBlockHash ( ) = = view . GetBestBlock ( ) ) ;
2019-07-01 20:42:45 +02:00
if ( pindex - > hashClaimTrie ! = trieCache . getMerkleHash ( ) ) {
LogPrintf ( " %s: Indexed claim hash doesn't match current: %s vs %s \n " ,
__func__ , pindex - > hashClaimTrie . ToString ( ) , trieCache . getMerkleHash ( ) . ToString ( ) ) ;
assert ( false ) ;
}
2018-08-06 21:40:20 +02:00
2012-12-30 15:29:39 +01: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 18:54:00 +02:00
CBlockUndo blockUndo ;
2017-06-09 18:57:23 +02:00
if ( ! UndoReadFromDisk ( blockUndo , pindex ) ) {
2017-04-29 01:08:39 +02:00
error ( " DisconnectBlock(): failure reading undo data " ) ;
return DISCONNECT_FAILED ;
}
2010-08-29 18:58:15 +02:00
2017-04-29 01:08:39 +02: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 18:54:00 +02:00
2019-07-01 20:42:45 +02:00
const bool decremented = trieCache . decrementBlock ( blockUndo . insertUndo , blockUndo . expireUndo , blockUndo . insertSupportUndo , blockUndo . expireSupportUndo ) ;
2018-08-06 21:40:20 +02:00
assert ( decremented ) ;
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 18:54:00 +02:00
// undo transactions in reverse order
2013-06-24 03:32:58 +02:00
for ( int i = block . vtx . size ( ) - 1 ; i > = 0 ; i - - ) {
2016-11-11 02:26:00 +01: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 18:54:00 +02:00
uint256 hash = tx . GetHash ( ) ;
2017-06-08 18:08:32 +02: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 18:54:00 +02:00
2013-10-26 21:26:29 +02:00
// Check that all outputs are available and match the outputs in the block itself
2015-02-03 15:44:39 +01:00
// exactly.
2017-04-25 20:29:30 +02: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 17:50:47 +02:00
bool is_spent = view . SpendCoin ( out , & coin ) ;
2017-06-08 18:08:32 +02:00
if ( ! is_spent | | tx . vout [ o ] ! = coin . out | | pindex - > nHeight ! = coin . nHeight | | is_coinbase ! = coin . fCoinBase ) {
2017-04-25 20:29:30 +02:00
fClean = false ; // transaction output mismatch
}
}
2014-09-03 09:01:24 +02: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 18:54:00 +02:00
2018-08-06 21:40:20 +02:00
// remove any claims
for ( size_t j = 0 ; j < tx . vout . size ( ) ; j + + )
{
const CTxOut & txout = tx . vout [ j ] ;
2019-05-08 00:32:22 +02:00
if ( ! txout . scriptPubKey . empty ( ) ) {
CClaimScriptUndoAddOp undoAdd ( COutPoint ( hash , j ) , pindex - > nHeight ) ;
ProcessClaim ( undoAdd , trieCache , txout . scriptPubKey ) ;
2018-08-06 21:40:20 +02: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 18:54:00 +02:00
// restore inputs
if ( i > 0 ) { // not coinbases
2017-04-25 20:29:27 +02:00
CTxUndo & txundo = blockUndo . vtxundo [ i - 1 ] ;
2017-04-29 01:08:39 +02:00
if ( txundo . vprevout . size ( ) ! = tx . vin . size ( ) ) {
error ( " DisconnectBlock(): transaction 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 18:54:00 +02:00
for ( unsigned int j = tx . vin . size ( ) ; j - - > 0 ; ) {
const COutPoint & out = tx . vin [ j ] . prevout ;
2018-08-06 21:40:20 +02:00
/* int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), txundo, view, trieCache, out); */
int res = ApplyTxInUndo ( j , txundo , view , trieCache , out ) ;
2017-04-25 20:29:09 +02: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 18:54:00 +02:00
}
2017-04-25 20:29:27 +02:00
// At this point, all of txundo.vprevout should have been moved out.
2018-08-06 21:40:20 +02:00
//
// Note: This comment is no longer true, but doesn't
// affect anything either since it's no longer accessed.
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 18:54:00 +02:00
}
}
// move best block pointer to prevout block
2013-11-05 02:27:39 +01:00
view . SetBestBlock ( pindex - > pprev - > GetBlockHash ( ) ) ;
2019-07-01 20:42:45 +02:00
assert ( trieCache . finalizeDecrement ( blockUndo . takeoverHeightUndo ) ) ;
auto merkleHash = trieCache . getMerkleHash ( ) ;
if ( merkleHash ! = pindex - > pprev - > hashClaimTrie ) {
if ( trieCache . checkConsistency ( ) ) {
for ( auto cit = trieCache . begin ( ) ; cit ! = trieCache . end ( ) ; + + cit ) {
if ( cit - > claims . size ( ) & & cit - > nHeightOfLastTakeover < = 0 )
LogPrintf ( " Invalid takeover height discovered in cache for %s \n " , cit . key ( ) ) ;
if ( cit - > hash . IsNull ( ) )
LogPrintf ( " Invalid hash discovered in cache for %s \n " , cit . key ( ) ) ;
}
}
LogPrintf ( " Hash comparison failure at block %d \n " , pindex - > nHeight ) ;
assert ( merkleHash = = pindex - > pprev - > hashClaimTrie ) ;
}
2018-08-06 21:40:20 +02:00
if ( pindex - > nHeight = = Params ( ) . GetConsensus ( ) . nExtendedClaimExpirationForkHeight )
{
LogPrintf ( " Decremented past the extended claim expiration hard fork height \n " ) ;
2019-07-01 20:42:45 +02:00
trieCache . setExpirationTime ( Params ( ) . GetConsensus ( ) . GetExpirationTime ( pindex - > nHeight - 1 ) ) ;
2018-08-06 21:40:20 +02:00
trieCache . forkForExpirationChange ( false ) ;
}
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 18:54:00 +02:00
2017-04-29 01:08:39 +02:00
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN ;
2010-08-29 18:58:15 +02:00
}
2013-01-30 04:17:33 +01:00
void static FlushBlockFile ( bool fFinalize = false )
2012-09-06 03:21:18 +02:00
{
LOCK ( cs_LastBlockFile ) ;
2012-12-03 10:14:54 +01:00
CDiskBlockPos posOld ( nLastBlockFile , 0 ) ;
2018-04-20 11:21:08 +02:00
bool status = true ;
2012-09-06 03:21:18 +02:00
FILE * fileOld = OpenBlockFile ( posOld ) ;
2012-12-01 11:36:53 +01:00
if ( fileOld ) {
2013-01-30 04:17:33 +01:00
if ( fFinalize )
2018-04-20 11:21:08 +02:00
status & = TruncateFile ( fileOld , vinfoBlockFile [ nLastBlockFile ] . nSize ) ;
status & = FileCommit ( fileOld ) ;
2012-12-01 11:36:53 +01:00
fclose ( fileOld ) ;
}
2012-09-06 03:21:18 +02:00
fileOld = OpenUndoFile ( posOld ) ;
2012-12-01 11:36:53 +01:00
if ( fileOld ) {
2013-01-30 04:17:33 +01:00
if ( fFinalize )
2018-04-20 11:21:08 +02:00
status & = TruncateFile ( fileOld , vinfoBlockFile [ nLastBlockFile ] . nUndoSize ) ;
status & = FileCommit ( fileOld ) ;
2012-12-01 11:36:53 +01:00
fclose ( fileOld ) ;
}
2018-04-20 11:21:08 +02:00
if ( ! status ) {
AbortNode ( " Flushing block file to disk failed. This is likely the result of an I/O error. " ) ;
}
2012-09-06 03:21:18 +02:00
}
2017-04-21 20:45:30 +02:00
static bool FindUndoPos ( CValidationState & state , int nFile , CDiskBlockPos & pos , unsigned int nAddSize ) ;
2012-08-13 19:11:05 +02:00
2016-12-03 01:54:15 +01:00
static bool WriteUndoDataForBlock ( const CBlockUndo & blockundo , CValidationState & state , CBlockIndex * pindex , const CChainParams & chainparams )
{
// Write undo information to disk
if ( pindex - > GetUndoPos ( ) . IsNull ( ) ) {
CDiskBlockPos _pos ;
if ( ! FindUndoPos ( state , pindex - > nFile , _pos , : : GetSerializeSize ( blockundo , SER_DISK , CLIENT_VERSION ) + 40 ) )
2018-08-06 21:40:20 +02:00
return error ( " WriteUndoDataForBlock() : FindUndoPos failed " ) ;
2016-12-03 01:54:15 +01:00
if ( ! UndoWriteToDisk ( blockundo , _pos , pindex - > pprev - > GetBlockHash ( ) , chainparams . MessageStart ( ) ) )
return AbortNode ( state , " Failed to write undo data " ) ;
// update nUndoPos in block index
pindex - > nUndoPos = _pos . nPos ;
pindex - > nStatus | = BLOCK_HAVE_UNDO ;
setDirtyBlockIndex . insert ( pindex ) ;
}
return true ;
}
2012-12-01 23:04:14 +01:00
static CCheckQueue < CScriptCheck > scriptcheckqueue ( 128 ) ;
2013-03-07 04:31:26 +01:00
void ThreadScriptCheck ( ) {
2018-08-06 21:40:20 +02:00
RenameThread ( " lbrycrd-scriptch " ) ;
2012-12-01 23:04:14 +01:00
scriptcheckqueue . Thread ( ) ;
}
2016-02-15 05:13:27 +01:00
// Protected by cs_main
2016-04-24 01:30:20 +02:00
VersionBitsCache versionbitscache ;
2016-02-15 05:13:27 +01:00
int32_t ComputeBlockVersion ( const CBlockIndex * pindexPrev , const Consensus : : Params & params )
{
LOCK ( cs_main ) ;
int32_t nVersion = VERSIONBITS_TOP_BITS ;
for ( int i = 0 ; i < ( int ) Consensus : : MAX_VERSION_BITS_DEPLOYMENTS ; i + + ) {
2017-06-01 16:13:35 +02:00
ThresholdState state = VersionBitsState ( pindexPrev , params , static_cast < Consensus : : DeploymentPos > ( i ) , versionbitscache ) ;
2018-03-09 15:03:40 +01:00
if ( state = = ThresholdState : : LOCKED_IN | | state = = ThresholdState : : STARTED ) {
2017-06-01 16:13:35 +02:00
nVersion | = VersionBitsMask ( params , static_cast < Consensus : : DeploymentPos > ( i ) ) ;
2016-02-15 05:13:27 +01:00
}
}
return nVersion ;
}
/**
* Threshold condition checker that triggers when unknown versionbits are seen on the network .
*/
class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
{
private :
int bit ;
public :
2017-08-01 12:22:41 +02:00
explicit WarningBitsConditionChecker ( int bitIn ) : bit ( bitIn ) { }
2016-02-15 05:13:27 +01:00
2017-06-20 21:58:56 +02: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 05:13:27 +01:00
2017-06-20 21:58:56 +02:00
bool Condition ( const CBlockIndex * pindex , const Consensus : : Params & params ) const override
2016-02-15 05:13:27 +01:00
{
return ( ( pindex - > nVersion & VERSIONBITS_TOP_MASK ) = = VERSIONBITS_TOP_BITS ) & &
( ( pindex - > nVersion > > bit ) & 1 ) ! = 0 & &
( ( ComputeBlockVersion ( pindex - > pprev , params ) > > bit ) & 1 ) = = 0 ;
}
} ;
// Protected by cs_main
static ThresholdConditionCache warningcache [ VERSIONBITS_NUM_BITS ] ;
2017-09-13 16:13:57 +02:00
// 0.13.0 was shipped with a segwit deployment defined for testnet, but not for
// mainnet. We no longer need to support disabling the segwit deployment
// except for testing purposes, due to limitations of the functional test
// environment. See test/functional/p2p-segwit.py.
static bool IsScriptWitnessEnabled ( const Consensus : : Params & params )
{
return params . vDeployments [ Consensus : : DEPLOYMENT_SEGWIT ] . nTimeout ! = 0 ;
}
2017-04-11 22:04:37 +02:00
static unsigned int GetBlockScriptFlags ( const CBlockIndex * pindex , const Consensus : : Params & consensusparams ) {
AssertLockHeld ( cs_main ) ;
2017-10-13 17:35:18 +02:00
unsigned int flags = SCRIPT_VERIFY_NONE ;
2017-04-11 22:04:37 +02:00
2017-09-12 17:38:20 +02: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
// mainnet and testnet), so for simplicity, always leave P2SH
// on except for the one violating block.
if ( consensusparams . BIP16Exception . IsNull ( ) | | // no bip16 exception on this chain
pindex - > phashBlock = = nullptr | | // this is a new candidate block, eg from TestBlockValidity()
* pindex - > phashBlock ! = consensusparams . BIP16Exception ) // this block isn't the historical exception
{
2017-10-13 17:35:18 +02:00
flags | = SCRIPT_VERIFY_P2SH ;
}
2017-04-11 22:04:37 +02:00
2017-09-13 16:13:57 +02:00
// Enforce WITNESS rules whenever P2SH is in effect (and the segwit
// deployment is defined).
if ( flags & SCRIPT_VERIFY_P2SH & & IsScriptWitnessEnabled ( consensusparams ) ) {
flags | = SCRIPT_VERIFY_WITNESS ;
}
2017-04-11 22:04:37 +02:00
// Start enforcing the DERSIG (BIP66) rule
if ( pindex - > nHeight > = consensusparams . BIP66Height ) {
flags | = SCRIPT_VERIFY_DERSIG ;
}
// Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
if ( pindex - > nHeight > = consensusparams . BIP65Height ) {
flags | = SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY ;
}
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
2018-03-09 15:03:40 +01:00
if ( VersionBitsState ( pindex - > pprev , consensusparams , Consensus : : DEPLOYMENT_CSV , versionbitscache ) = = ThresholdState : : ACTIVE ) {
2017-04-11 22:04:37 +02:00
flags | = SCRIPT_VERIFY_CHECKSEQUENCEVERIFY ;
}
2017-09-12 18:40:29 +02:00
if ( IsNullDummyEnabled ( pindex - > pprev , consensusparams ) ) {
2017-04-11 22:04:37 +02:00
flags | = SCRIPT_VERIFY_NULLDUMMY ;
}
return flags ;
}
2015-11-07 00:12:30 +01:00
static int64_t nTimeCheck = 0 ;
static int64_t nTimeForks = 0 ;
2014-07-26 22:49:17 +02:00
static int64_t nTimeVerify = 0 ;
static int64_t nTimeConnect = 0 ;
static int64_t nTimeIndex = 0 ;
static int64_t nTimeCallbacks = 0 ;
static int64_t nTimeTotal = 0 ;
2017-04-28 09:16:33 +02:00
static int64_t nBlocksTotal = 0 ;
2014-07-26 22:49:17 +02:00
2017-01-17 22:01:48 +01: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 ) . */
2017-12-04 15:34:46 +01:00
bool CChainState : : ConnectBlock ( const CBlock & block , CValidationState & state , CBlockIndex * pindex ,
2018-08-06 21:40:20 +02:00
CCoinsViewCache & view , CClaimTrieCache & trieCache , const CChainParams & chainparams , bool fJustCheck )
2010-08-29 18:58:15 +02:00
{
2014-04-23 08:55:24 +02:00
AssertLockHeld ( cs_main ) ;
2016-09-09 04:51:08 +02:00
assert ( pindex ) ;
2017-12-12 19:30:22 +01:00
assert ( * pindex - > phashBlock = = block . GetHash ( ) ) ;
2015-11-07 00:12:30 +01:00
int64_t nTimeStart = GetTimeMicros ( ) ;
2010-08-29 18:58:15 +02:00
// Check it again in case a previous version let a bad block in
2017-11-20 20:13:12 +01: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
// change is potentially tricky and issue-specific (see RewindBlockIndex()
// for one general approach that was used for BIP 141 deployment).
// 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
// GetAdjustedTime() to go backward).
2018-03-05 16:42:26 +01:00
if ( ! CheckBlock ( block , state , chainparams . GetConsensus ( ) , ! fJustCheck , ! fJustCheck ) ) {
if ( state . CorruptionPossible ( ) ) {
// 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 " ) ;
}
2015-12-02 03:13:47 +01:00
return error ( " %s: Consensus::CheckBlock: %s " , __func__ , FormatStateMessage ( state ) ) ;
2018-03-05 16:42:26 +01:00
}
2010-08-29 18:58:15 +02: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 18:54:00 +02:00
// verify that the view's current state corresponds to the previous block
2017-08-07 07:36:37 +02:00
uint256 hashPrevBlock = pindex - > pprev = = nullptr ? uint256 ( ) : pindex - > pprev - > GetBlockHash ( ) ;
2013-11-05 02:27:39 +01: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 18:54:00 +02:00
2018-08-06 21:40:20 +02:00
// also verify that the trie cache's current state corresponds to the previous block
2019-07-01 20:42:45 +02:00
if ( pindex - > pprev ! = nullptr & & pindex - > pprev - > hashClaimTrie ! = trieCache . getMerkleHash ( ) ) {
LogPrintf ( " %s: Previous block claim hash doesn't match current: %s vs %s \n " ,
__func__ , pindex - > pprev - > hashClaimTrie . ToString ( ) , trieCache . getMerkleHash ( ) . ToString ( ) ) ;
assert ( false ) ;
}
2018-08-06 21:40:20 +02:00
2013-01-19 00:35:17 +01:00
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
2015-04-09 15:58:34 +02:00
if ( block . GetHash ( ) = = chainparams . GetConsensus ( ) . hashGenesisBlock ) {
2014-12-31 04:28:05 +01:00
if ( ! fJustCheck )
2018-08-06 21:40:20 +02:00
{
2014-12-31 04:28:05 +01:00
view . SetBestBlock ( pindex - > GetBlockHash ( ) ) ;
2018-08-06 21:40:20 +02:00
}
/* return true; */
2013-01-19 00:35:17 +01:00
}
2017-04-28 09:16:33 +02:00
nBlocksTotal + + ;
2015-03-19 13:34:06 +01:00
bool fScriptChecks = true ;
2017-01-06 12:49:59 +01: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.
BlockMap : : const_iterator it = mapBlockIndex . find ( hashAssumeValid ) ;
if ( it ! = mapBlockIndex . end ( ) ) {
if ( it - > second - > GetAncestor ( pindex - > nHeight ) = = pindex & &
pindexBestHeader - > GetAncestor ( pindex - > nHeight ) = = pindex & &
2017-05-07 20:10:19 +02:00
pindexBestHeader - > nChainWork > = nMinimumChainWork ) {
2017-01-06 12:49:59 +01:00
// This block is a member of the assumed verified chain and an ancestor of the best header.
2017-02-06 15:16:18 +01:00
// The equivalent time check discourages hash power from extorting the network via DOS attack
2017-01-06 12:49:59 +01: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.
fScriptChecks = ( GetBlockProofEquivalentTime ( * pindexBestHeader , * pindex , * pindexBestHeader , chainparams . GetConsensus ( ) ) < = 60 * 60 * 24 * 7 * 2 ) ;
}
2015-03-19 13:34:06 +01:00
}
}
2012-12-01 22:51:10 +01:00
2015-11-07 00:12:30 +01:00
int64_t nTime1 = GetTimeMicros ( ) ; nTimeCheck + = nTime1 - nTimeStart ;
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Sanity checks: %.2fms [%.2fs (%.2fms/blk)] \n " , MILLI * ( nTime1 - nTimeStart ) , nTimeCheck * MICRO , nTimeCheck * MILLI / nBlocksTotal ) ;
2015-11-07 00:12:30 +01:00
2012-02-17 17:58:02 +01: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.
// See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information.
// This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
2012-07-26 05:25:26 +02:00
// already refuses previously-known transaction ids entirely.
2015-04-28 16:48:28 +02:00
// This rule was originally applied to all blocks with a timestamp after March 15, 2012, 0:00 UTC.
2012-09-10 02:11:04 +02:00
// Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the
2015-04-28 16:47:17 +02:00
// two in the chain that violate it. This prevents exploiting the issue against nodes during their
2012-09-10 02:11:04 +02:00
// initial block download.
2017-12-12 19:30:22 +01:00
bool fEnforceBIP30 = ! ( ( pindex - > nHeight = = 91842 & & pindex - > GetBlockHash ( ) = = uint256S ( " 0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec " ) ) | |
2014-12-16 14:50:05 +01:00
( pindex - > nHeight = = 91880 & & pindex - > GetBlockHash ( ) = = uint256S ( " 0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721 " ) ) ) ;
2015-11-02 22:10:57 +01: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 15:26:45 +01:00
// before the first had been spent. Since those coinbases are sufficiently buried it's no longer possible to create further
2015-11-02 22:10:57 +01:00
// duplicate transactions descending from the known pairs either.
2015-11-02 22:41:55 +01: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 19:43:47 +02: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
// post BIP34 before approximately height 486,000,000 and presumably will
// be reset before it reaches block 1,983,702 and starts doing unnecessary
// BIP30 checking again.
2018-08-06 21:40:20 +02:00
/* assert(pindex->pprev); */
if ( pindex - > pprev )
{
CBlockIndex * pindexBIP34height = pindex - > pprev - > GetAncestor ( chainparams . GetConsensus ( ) . BIP34Height ) ;
//Only continue to enforce if we're below BIP34 activation height or the block hash at that height doesn't correspond.
fEnforceBIP30 = fEnforceBIP30 & & ( ! pindexBIP34height | | ! ( pindexBIP34height - > GetBlockHash ( ) = = chainparams . GetConsensus ( ) . BIP34Hash ) ) ;
// TODO: Remove BIP30 checking from block height 1,983,702 on, once we have a
// consensus change that ensures coinbases at those heights can not
// duplicate earlier coinbases.
if ( fEnforceBIP30 | | pindex - > nHeight > = BIP34_IMPLIES_BIP30_LIMIT ) {
for ( const auto & tx : block . vtx ) {
for ( size_t o = 0 ; o < tx - > vout . size ( ) ; o + + ) {
if ( view . HaveCoin ( COutPoint ( tx - > GetHash ( ) , o ) ) ) {
return state . DoS ( 100 , error ( " ConnectBlock(): tried to overwrite transaction " ) ,
REJECT_INVALID , " bad-txns-BIP30 " ) ;
}
2017-04-25 20:29:30 +02: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 18:54:00 +02:00
}
}
2012-02-17 17:58:02 +01:00
2016-02-16 17:37:43 +01:00
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
int nLockTimeFlags = 0 ;
2018-03-09 15:03:40 +01:00
if ( VersionBitsState ( pindex - > pprev , chainparams . GetConsensus ( ) , Consensus : : DEPLOYMENT_CSV , versionbitscache ) = = ThresholdState : : ACTIVE ) {
2016-02-16 17:37:43 +01:00
nLockTimeFlags | = LOCKTIME_VERIFY_SEQUENCE ;
2016-02-20 23:37:13 +01:00
}
2017-04-11 22:04:37 +02:00
// Get the script flags for this block
unsigned int flags = GetBlockScriptFlags ( pindex , chainparams . GetConsensus ( ) ) ;
2015-11-06 01:42:38 +01:00
2018-08-06 21:40:20 +02:00
// v 13 LBRYcrd hard fork to extend expiration time
if ( pindex - > nHeight = = Params ( ) . GetConsensus ( ) . nExtendedClaimExpirationForkHeight )
{
LogPrintf ( " Incremented past the extended claim expiration hard fork height \n " ) ;
2019-07-01 20:42:45 +02:00
trieCache . setExpirationTime ( chainparams . GetConsensus ( ) . GetExpirationTime ( pindex - > nHeight ) ) ;
2018-08-06 21:40:20 +02:00
trieCache . forkForExpirationChange ( true ) ;
}
2015-11-07 00:12:30 +01:00
int64_t nTime2 = GetTimeMicros ( ) ; nTimeForks + = nTime2 - nTime1 ;
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Fork checks: %.2fms [%.2fs (%.2fms/blk)] \n " , MILLI * ( nTime2 - nTime1 ) , nTimeForks * MICRO , nTimeForks * MILLI / nBlocksTotal ) ;
2015-11-07 00:12:30 +01:00
2012-06-23 14:17:13 +02:00
CBlockUndo blockundo ;
2017-08-07 07:36:37 +02:00
CCheckQueueControl < CScriptCheck > control ( fScriptChecks & & nScriptCheckThreads ? & scriptcheckqueue : nullptr ) ;
2012-12-01 23:04:14 +01:00
2015-12-07 21:44:16 +01:00
std : : vector < int > prevheights ;
2014-04-23 00:46:19 +02:00
CAmount nFees = 0 ;
2012-12-01 20:10:23 +01:00
int nInputs = 0 ;
2016-01-03 18:54:50 +01:00
int64_t nSigOpsCost = 0 ;
2018-08-06 21:40:20 +02:00
CDiskTxPos pos ( pindex - > GetBlockPos ( ) , GetSizeOfCompactSize ( block . vtx . size ( ) ) ) ;
std : : vector < std : : pair < uint256 , CDiskTxPos > > vPos ;
vPos . reserve ( block . vtx . size ( ) ) ;
2014-09-03 15:54:37 +02:00
blockundo . vtxundo . reserve ( block . vtx . size ( ) - 1 ) ;
2016-08-26 18:38:20 +02:00
std : : vector < PrecomputedTransactionData > txdata ;
txdata . reserve ( block . vtx . size ( ) ) ; // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
2013-06-24 03:50:06 +02:00
for ( unsigned int i = 0 ; i < block . vtx . size ( ) ; i + + )
2010-08-29 18:58:15 +02:00
{
2016-11-11 02:26:00 +01:00
const CTransaction & tx = * ( block . vtx [ i ] ) ;
2018-08-06 21:40:20 +02:00
std : : map < unsigned int , unsigned int > mClaimUndoHeights ;
2012-07-08 00:06:34 +02:00
2012-12-01 20:10:23 +01:00
nInputs + = tx . vin . size ( ) ;
2012-01-20 23:07:40 +01:00
2012-01-11 02:18:00 +01:00
if ( ! tx . IsCoinBase ( ) )
{
2016-08-11 04:42:36 +02:00
CAmount txfee = 0 ;
if ( ! Consensus : : CheckTxInputs ( tx , state , view , pindex - > nHeight , txfee ) ) {
return error ( " %s: Consensus::CheckTxInputs: %s, %s " , __func__ , tx . GetHash ( ) . ToString ( ) , FormatStateMessage ( state ) ) ;
}
nFees + = txfee ;
2017-07-04 17:45:46 +02:00
if ( ! MoneyRange ( nFees ) ) {
return state . DoS ( 100 , error ( " %s: accumulated fee in the block out of range. " , __func__ ) ,
REJECT_INVALID , " bad-txns-accumulated-fee-outofrange " ) ;
}
2012-01-05 03:40:52 +01:00
2015-12-07 21:44:16 +01: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 20:29:30 +02:00
prevheights [ j ] = view . AccessCoin ( tx . vin [ j ] . prevout ) . nHeight ;
2015-12-07 21:44:16 +01:00
}
if ( ! SequenceLocks ( tx , nLockTimeFlags , & prevheights , * pindex ) ) {
2016-02-11 21:34:04 +01:00
return state . DoS ( 100 , error ( " %s: contains a non-BIP68-final transaction " , __func__ ) ,
2015-12-07 21:44:16 +01:00
REJECT_INVALID , " bad-txns-nonfinal " ) ;
}
2016-01-03 18:54:50 +01:00
}
2015-12-07 21:44:16 +01:00
2016-01-03 18:54:50 +01: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 ) ;
if ( nSigOpsCost > MAX_BLOCK_SIGOPS_COST )
return state . DoS ( 100 , error ( " ConnectBlock(): too many sigops " ) ,
REJECT_INVALID , " bad-blk-sigops " ) ;
2012-01-05 03:40:52 +01:00
2016-08-26 18:38:20 +02:00
txdata . emplace_back ( tx ) ;
2016-01-03 18:54:50 +01:00
if ( ! tx . IsCoinBase ( ) )
{
2012-12-01 23:04:14 +01:00
std : : vector < CScriptCheck > vChecks ;
2015-11-02 02:01:45 +01:00
bool fCacheResults = fJustCheck ; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
2017-08-07 07:36:37 +02:00
if ( ! CheckInputs ( tx , state , view , fScriptChecks , flags , fCacheResults , fCacheResults , txdata [ i ] , nScriptCheckThreads ? & vChecks : nullptr ) )
2015-08-06 10:02:12 +02:00
return error ( " ConnectBlock(): CheckInputs on %s failed with %s " ,
2018-08-06 21:40:20 +02:00
tx . GetHash ( ) . ToString ( ) , FormatStateMessage ( state ) ) ;
2012-12-01 23:04:14 +01:00
control . Add ( vChecks ) ;
2018-08-06 21:40:20 +02:00
// To handle claim updates, stick all claims found in the inputs into a map of
// name: (txhash, nOut). When running through the outputs, if any claim's
// name is found in the map, send the name's txhash and nOut to the trie cache,
// and then remove the name: (txhash, nOut) mapping from the map.
// If there are two or more claims in the inputs with the same name, only
// use the first.
spentClaimsType spentClaims ;
for ( unsigned int j = 0 ; j < tx . vin . size ( ) ; j + + )
{
const CTxIn & txin = tx . vin [ j ] ;
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
2019-05-08 00:32:22 +02:00
if ( coin . out . scriptPubKey . empty ( ) )
continue ;
int nValidAtHeight ;
if ( SpendClaim ( trieCache , coin . out . scriptPubKey , COutPoint ( txin . prevout . hash , txin . prevout . n ) , coin . nHeight , nValidAtHeight , spentClaims ) )
mClaimUndoHeights [ j ] = nValidAtHeight ;
2018-08-06 21:40:20 +02:00
}
2019-05-08 00:32:22 +02:00
for ( unsigned int j = 0 ; j < tx . vout . size ( ) ; j + + ) {
2018-08-06 21:40:20 +02:00
const CTxOut & txout = tx . vout [ j ] ;
2019-05-08 00:32:22 +02:00
if ( ! txout . scriptPubKey . empty ( ) )
AddSpendClaim ( trieCache , txout . scriptPubKey , COutPoint ( tx . GetHash ( ) , j ) , txout . nValue , pindex - > nHeight , spentClaims ) ;
2018-08-06 21:40:20 +02:00
}
2012-01-11 02:18:00 +01:00
}
2014-09-03 15:54:37 +02:00
CTxUndo undoDummy ;
if ( i > 0 ) {
blockundo . vtxundo . push_back ( CTxUndo ( ) ) ;
}
2016-04-30 05:45:20 +02:00
UpdateCoins ( tx , view , i = = 0 ? undoDummy : blockundo . vtxundo . back ( ) , pindex - > nHeight ) ;
2018-08-06 21:40:20 +02:00
if ( i > 0 & & ! mClaimUndoHeights . empty ( ) )
{
2019-05-23 19:46:37 +02:00
auto & txinUndos = blockundo . vtxundo . back ( ) . vprevout ;
2018-08-06 21:40:20 +02:00
for ( std : : map < unsigned int , unsigned int > : : iterator itHeight = mClaimUndoHeights . begin ( ) ; itHeight ! = mClaimUndoHeights . end ( ) ; + + itHeight )
{
2019-05-23 19:46:37 +02:00
txinUndos [ itHeight - > first ] . nClaimValidHeight = itHeight - > second ;
txinUndos [ itHeight - > first ] . fIsClaim = true ;
2018-08-06 21:40:20 +02:00
}
}
2019-05-23 19:46:37 +02:00
2018-08-06 21:40:20 +02:00
// The CTxUndo vector contains the heights at which claims should be put into the trie.
// This is necessary because some claims are inserted immediately into the trie, and
// others are inserted after a delay, depending on the state of the claim trie at the time
// that the claim was originally inserted into the blockchain. That state will not be
// available when and if this block is disconnected.
// It also contains whether or not any given txin represents a claim that should
// be put back into the trie. If we didn't find a claim or support in the trie
// or cache when trying to spend it, we shouldn't try to put a claim or support back
// in. Some OP_UPDATE_CLAIM's, for example, may be invalid, and so may never have been
// inserted into the trie in the first place.
vPos . push_back ( std : : make_pair ( tx . GetHash ( ) , pos ) ) ;
pos . nTxOffset + = : : GetSerializeSize ( tx , SER_DISK , CLIENT_VERSION ) ;
2010-08-29 18:58:15 +02:00
}
2018-08-06 21:40:20 +02:00
2019-07-01 20:42:45 +02:00
// TODO: if the "just check" flag is set, we should reduce the work done here. Incrementing blocks twice per mine is not efficient.
2018-08-06 21:40:20 +02:00
const auto incremented = trieCache . incrementBlock ( blockundo . insertUndo , blockundo . expireUndo , blockundo . insertSupportUndo , blockundo . expireSupportUndo , blockundo . takeoverHeightUndo ) ;
assert ( incremented ) ;
if ( trieCache . getMerkleHash ( ) ! = block . hashClaimTrie )
{
2019-07-01 20:42:45 +02:00
if ( trieCache . checkConsistency ( ) )
trieCache . dumpToLog ( trieCache . begin ( ) ) ;
return state . DoS ( 100 , error ( " ConnectBlock() : the merkle root of the claim trie does not match "
" (actual=%s vs block=%s on height=%d) " , trieCache . getMerkleHash ( ) . GetHex ( ) ,
block . hashClaimTrie . GetHex ( ) , pindex - > nHeight ) , REJECT_INVALID , " bad-claim-merkle-hash " ) ;
2018-08-06 21:40:20 +02:00
}
2015-11-07 00:12:30 +01:00
int64_t nTime3 = GetTimeMicros ( ) ; nTimeConnect + = nTime3 - nTime2 ;
2017-06-01 04:42:34 +02: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 19:05:43 +02:00
2015-04-01 16:03:11 +02:00
CAmount blockReward = nFees + GetBlockSubsidy ( pindex - > nHeight , chainparams . GetConsensus ( ) ) ;
2016-11-11 02:26:00 +01:00
if ( block . vtx [ 0 ] - > GetValueOut ( ) > blockReward )
2013-10-28 07:36:11 +01:00
return state . DoS ( 100 ,
2015-01-08 11:44:25 +01:00
error ( " ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d) " ,
2016-11-11 02:26:00 +01:00
block . vtx [ 0 ] - > GetValueOut ( ) , blockReward ) ,
2014-02-10 16:31:06 +01:00
REJECT_INVALID , " bad-cb-amount " ) ;
2012-10-22 21:46:00 +02:00
2012-12-01 23:04:14 +01:00
if ( ! control . Wait ( ) )
2017-03-31 20:18:15 +02:00
return state . DoS ( 100 , error ( " %s: CheckQueue failed " , __func__ ) , REJECT_INVALID , " block-validation-failed " ) ;
2015-11-07 00:12:30 +01:00
int64_t nTime4 = GetTimeMicros ( ) ; nTimeVerify + = nTime4 - nTime2 ;
2017-06-01 04:42:34 +02: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 23:04:14 +01:00
2012-05-09 19:24:44 +02:00
if ( fJustCheck )
return true ;
2018-08-06 21:40:20 +02:00
if ( pindex - > pprev ! = nullptr & &
! WriteUndoDataForBlock ( blockundo , state , pindex , chainparams ) & &
! pblocktree - > WriteTxIndex ( vPos ) )
2016-12-03 01:54:15 +01:00
return false ;
2012-08-19 00:33:01 +02:00
2016-12-03 01:54:15 +01:00
if ( ! pindex - > IsValid ( BLOCK_VALID_SCRIPTS ) ) {
2014-03-13 03:48:27 +01:00
pindex - > RaiseValidity ( BLOCK_VALID_SCRIPTS ) ;
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 11:38:35 +01:00
setDirtyBlockIndex . insert ( pindex ) ;
2010-08-29 18:58:15 +02:00
}
2017-08-28 09:24:17 +02:00
assert ( pindex - > phashBlock ) ;
2012-10-05 19:22:21 +02:00
// add this block to the view's block chain
2014-09-03 09:25:32 +02: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 18:54:00 +02:00
2015-11-07 00:12:30 +01:00
int64_t nTime5 = GetTimeMicros ( ) ; nTimeIndex + = nTime5 - nTime4 ;
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Index writing: %.2fms [%.2fs (%.2fms/blk)] \n " , MILLI * ( nTime5 - nTime4 ) , nTimeIndex * MICRO , nTimeIndex * MILLI / nBlocksTotal ) ;
2014-07-26 22:49:17 +02:00
2015-11-07 00:12:30 +01:00
int64_t nTime6 = GetTimeMicros ( ) ; nTimeCallbacks + = nTime6 - nTime5 ;
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Callbacks: %.2fms [%.2fs (%.2fms/blk)] \n " , MILLI * ( nTime6 - nTime5 ) , nTimeCallbacks * MICRO , nTimeCallbacks * MILLI / nBlocksTotal ) ;
2014-07-26 22:49:17 +02:00
2010-08-29 18:58:15 +02:00
return true ;
}
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 11:38:35 +01:00
/**
* Update the on - disk chain state .
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 20:27:44 +01:00
* The caches and indexes are flushed depending on the mode we ' re called with
* if they ' re too large , if it ' s been a while since the last write ,
* or always and in all cases if we ' re in prune mode and are deleting files .
2018-04-11 12:45:59 +02:00
*
* If FlushStateMode : : NONE is used , then FlushStateToDisk ( . . . ) won ' t do anything
* besides checking if we need to prune .
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 11:38:35 +01:00
*/
2017-04-21 20:45:30 +02:00
bool static FlushStateToDisk ( const CChainParams & chainparams , CValidationState & state , FlushStateMode mode , int nManualPruneHeight ) {
2016-12-22 04:15:13 +01:00
int64_t nMempoolUsage = mempool . DynamicMemoryUsage ( ) ;
2017-07-24 17:24:12 +02:00
LOCK ( cs_main ) ;
2013-11-16 19:28:24 +01:00
static int64_t nLastWrite = 0 ;
2015-05-04 22:00:19 +02:00
static int64_t 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 20:27:44 +01:00
std : : set < int > setFilesToPrune ;
2018-04-27 20:08:39 +02:00
bool full_flush_completed = false ;
2015-01-04 19:11:44 +01:00
try {
2017-07-24 17:24:12 +02:00
{
2018-04-27 20:08:39 +02:00
bool fFlushForPrune = false ;
bool fDoFullFlush = false ;
2017-07-24 17:24:12 +02:00
LOCK ( cs_LastBlockFile ) ;
if ( fPruneMode & & ( fCheckForPruning | | nManualPruneHeight > 0 ) & & ! fReindex ) {
if ( nManualPruneHeight > 0 ) {
FindFilesToPruneManual ( setFilesToPrune , nManualPruneHeight ) ;
} else {
FindFilesToPrune ( setFilesToPrune , chainparams . PruneAfterHeight ( ) ) ;
fCheckForPruning = false ;
2014-11-25 16:26:20 +01:00
}
2017-07-24 17:24:12 +02:00
if ( ! setFilesToPrune . empty ( ) ) {
fFlushForPrune = true ;
if ( ! fHavePruned ) {
pblocktree - > WriteFlag ( " prunedblockfiles " , true ) ;
fHavePruned = true ;
}
2014-11-25 16:26:20 +01:00
}
2017-07-24 17:24:12 +02:00
}
2018-04-27 20:08:39 +02:00
int64_t nNow = GetTimeMicros ( ) ;
2017-07-24 17:24:12 +02:00
// Avoid writing/flushing immediately after startup.
if ( nLastWrite = = 0 ) {
nLastWrite = nNow ;
}
if ( nLastFlush = = 0 ) {
nLastFlush = nNow ;
}
2017-08-01 21:17:40 +02:00
int64_t nMempoolSizeMax = gArgs . GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ;
2017-07-24 17:24:12 +02:00
int64_t cacheSize = pcoinsTip - > DynamicMemoryUsage ( ) ;
int64_t nTotalSpace = nCoinCacheUsage + std : : max < int64_t > ( nMempoolSizeMax - nMempoolUsage , 0 ) ;
// 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).
2018-03-09 15:03:40 +01:00
bool fCacheLarge = mode = = FlushStateMode : : PERIODIC & & cacheSize > std : : max ( ( 9 * nTotalSpace ) / 10 , nTotalSpace - MAX_BLOCK_COINSDB_USAGE * 1024 * 1024 ) ;
2017-07-24 17:24:12 +02:00
// The cache is over the limit, we have to write now.
2018-03-09 15:03:40 +01:00
bool fCacheCritical = mode = = FlushStateMode : : IF_NEEDED & & cacheSize > nTotalSpace ;
2017-07-24 17:24:12 +02: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.
2018-03-09 15:03:40 +01:00
bool fPeriodicWrite = mode = = FlushStateMode : : PERIODIC & & nNow > nLastWrite + ( int64_t ) DATABASE_WRITE_INTERVAL * 1000000 ;
2017-07-24 17:24:12 +02:00
// It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
2018-03-09 15:03:40 +01:00
bool fPeriodicFlush = mode = = FlushStateMode : : PERIODIC & & nNow > nLastFlush + ( int64_t ) DATABASE_FLUSH_INTERVAL * 1000000 ;
2017-07-24 17:24:12 +02:00
// Combine all conditions that result in a full cache flush.
2018-03-09 15:03:40 +01:00
fDoFullFlush = ( mode = = FlushStateMode : : ALWAYS ) | | fCacheLarge | | fCacheCritical | | fPeriodicFlush | | fFlushForPrune ;
2017-07-24 17:24:12 +02:00
// Write blocks and block index to disk.
if ( fDoFullFlush | | fPeriodicWrite ) {
// Depend on nMinDiskSpace to ensure we can write block index
2018-03-09 05:12:43 +01:00
if ( ! CheckDiskSpace ( 0 , true ) )
2017-07-24 17:24:12 +02:00
return state . Error ( " out of disk space " ) ;
// First make sure all block and undo data is flushed to disk.
FlushBlockFile ( ) ;
// Then update all block file information (which may refer to block and undo files).
{
std : : vector < std : : pair < int , const CBlockFileInfo * > > vFiles ;
vFiles . reserve ( setDirtyFileInfo . size ( ) ) ;
for ( std : : set < int > : : iterator it = setDirtyFileInfo . begin ( ) ; it ! = setDirtyFileInfo . end ( ) ; ) {
vFiles . push_back ( std : : make_pair ( * it , & vinfoBlockFile [ * it ] ) ) ;
setDirtyFileInfo . erase ( it + + ) ;
}
std : : vector < const CBlockIndex * > vBlocks ;
vBlocks . reserve ( setDirtyBlockIndex . size ( ) ) ;
for ( std : : set < CBlockIndex * > : : iterator it = setDirtyBlockIndex . begin ( ) ; it ! = setDirtyBlockIndex . end ( ) ; ) {
vBlocks . push_back ( * it ) ;
setDirtyBlockIndex . erase ( it + + ) ;
}
if ( ! pblocktree - > WriteBatchSync ( vFiles , nLastBlockFile , vBlocks ) ) {
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 11:38:35 +01:00
}
2017-07-24 17:24:12 +02:00
// Finally remove any pruned files
if ( fFlushForPrune )
UnlinkPrunedFiles ( setFilesToPrune ) ;
nLastWrite = nNow ;
}
// Flush best chain related state. This can only be done if the blocks / block index write was also done.
2018-02-13 06:24:14 +01:00
if ( fDoFullFlush & & ! pcoinsTip - > GetBestBlock ( ) . IsNull ( ) ) {
2017-07-24 17:24:12 +02: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.
if ( ! CheckDiskSpace ( 48 * 2 * 2 * pcoinsTip - > GetCacheSize ( ) ) )
return state . Error ( " out of disk space " ) ;
2019-07-01 20:42:45 +02:00
if ( ! pclaimTrie - > SyncToDisk ( ) )
2018-08-06 21:40:20 +02:00
return state . Error ( " Failed to write to claim trie database " ) ;
2017-07-24 17:24:12 +02:00
// Flush the chainstate (which may refer to block index entries).
if ( ! pcoinsTip - > Flush ( ) )
return AbortNode ( state , " Failed to write to coin database " ) ;
nLastFlush = nNow ;
2018-04-27 20:08:39 +02:00
full_flush_completed = true ;
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 11:38:35 +01:00
}
2015-05-04 22:00:19 +02:00
}
2018-04-27 20:08:39 +02: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 11:38:35 +01:00
// Update best block in wallet (so we can detect restored wallets).
2018-04-27 20:01:02 +02:00
GetMainSignals ( ) . ChainStateFlushed ( chainActive . GetLocator ( ) ) ;
2012-09-06 03:21:18 +02:00
}
2015-01-04 19:11:44 +01:00
} catch ( const std : : runtime_error & e ) {
2015-01-17 00:57:14 +01:00
return AbortNode ( state , std : : string ( " System error while flushing: " ) + e . what ( ) ) ;
2015-01-04 19:11:44 +01:00
}
2013-11-16 18:40:55 +01: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 18:54:00 +02: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 11:38:35 +01:00
void FlushStateToDisk ( ) {
CValidationState state ;
2017-04-21 20:45:30 +02:00
const CChainParams & chainparams = Params ( ) ;
2018-04-18 15:58:13 +02:00
if ( ! FlushStateToDisk ( chainparams , state , FlushStateMode : : ALWAYS ) ) {
LogPrintf ( " %s: failed to flush state (%s) \n " , __func__ , FormatStateMessage ( state ) ) ;
}
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 11:38:35 +01: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 20:27:44 +01:00
void PruneAndFlush ( ) {
CValidationState state ;
fCheckForPruning = true ;
2017-04-21 20:45:30 +02:00
const CChainParams & chainparams = Params ( ) ;
2018-04-18 15:58:13 +02:00
if ( ! FlushStateToDisk ( chainparams , state , FlushStateMode : : NONE ) ) {
LogPrintf ( " %s: failed to flush state (%s) \n " , __func__ , FormatStateMessage ( state ) ) ;
}
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 20:27:44 +01:00
}
2017-05-27 05:31:04 +02:00
static void DoWarning ( const std : : string & strWarning )
{
static bool fWarned = false ;
SetMiscWarning ( strWarning ) ;
if ( ! fWarned ) {
AlertNotify ( strWarning ) ;
fWarned = true ;
}
}
2018-07-20 23:48:26 +02:00
/** Private helper function that concatenates warning messages. */
static void AppendWarning ( std : : string & res , const std : : string & warn )
{
if ( ! res . empty ( ) ) res + = " , " ;
res + = warn ;
}
2017-04-26 03:31:08 +02:00
/** Check warning conditions and do some notifications on new chain tip set. */
void static UpdateTip ( const CBlockIndex * pindexNew , const CChainParams & chainParams ) {
2010-08-29 18:58:15 +02:00
// New best block
2013-08-27 07:51:57 +02:00
mempool . AddTransactionsUpdated ( 1 ) ;
2012-05-13 06:43:24 +02:00
2018-03-21 05:04:27 +01:00
{
2018-04-04 06:53:07 +02:00
WaitableLock lock ( g_best_block_mutex ) ;
g_best_block = pindexNew - > GetBlockHash ( ) ;
g_best_block_cv . notify_all ( ) ;
2018-03-21 05:04:27 +01:00
}
2012-05-13 06:43:24 +02:00
2018-07-20 23:48:26 +02:00
std : : string warningMessages ;
2016-02-15 05:13:27 +01:00
if ( ! IsInitialBlockDownload ( ) )
2012-06-27 19:51:51 +02:00
{
int nUpgraded = 0 ;
2017-04-26 03:31:08 +02:00
const CBlockIndex * pindex = pindexNew ;
2016-02-15 05:13:27 +01:00
for ( int bit = 0 ; bit < VERSIONBITS_NUM_BITS ; bit + + ) {
WarningBitsConditionChecker checker ( bit ) ;
ThresholdState state = checker . GetStateFor ( pindex , chainParams . GetConsensus ( ) , warningcache [ bit ] ) ;
2018-03-09 15:03:40 +01:00
if ( state = = ThresholdState : : ACTIVE | | state = = ThresholdState : : LOCKED_IN ) {
2017-05-27 05:31:04 +02:00
const std : : string strWarning = strprintf ( _ ( " Warning: unknown new rules activated (versionbit %i) " ) , bit ) ;
2018-03-09 15:03:40 +01:00
if ( state = = ThresholdState : : ACTIVE ) {
2017-05-27 05:31:04 +02:00
DoWarning ( strWarning ) ;
2016-02-15 05:13:27 +01:00
} else {
2018-07-20 23:48:26 +02:00
AppendWarning ( warningMessages , strWarning ) ;
2016-02-15 05:13:27 +01:00
}
}
}
2016-04-03 12:08:14 +02:00
// Check the version of the last 100 blocks to see if we need to upgrade:
2017-08-07 07:36:37 +02:00
for ( int i = 0 ; i < 100 & & pindex ! = nullptr ; i + + )
2012-06-27 19:51:51 +02:00
{
2016-02-15 05:13:27 +01:00
int32_t nExpectedVersion = ComputeBlockVersion ( pindex - > pprev , chainParams . GetConsensus ( ) ) ;
if ( pindex - > nVersion > VERSIONBITS_LAST_OLD_BLOCK_VERSION & & ( pindex - > nVersion & ~ nExpectedVersion ) ! = 0 )
2012-06-27 19:51:51 +02:00
+ + nUpgraded ;
pindex = pindex - > pprev ;
}
if ( nUpgraded > 0 )
2018-07-20 23:48:26 +02:00
AppendWarning ( warningMessages , strprintf ( _ ( " %d of last 100 blocks have unexpected version " ) , nUpgraded ) ) ;
2012-06-27 19:51:51 +02:00
if ( nUpgraded > 100 / 2 )
2014-10-07 20:22:58 +02:00
{
2016-11-29 10:46:19 +01:00
std : : string strWarning = _ ( " Warning: Unknown block versions being mined! It's possible unknown rules are in effect " ) ;
// notify GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
2017-05-27 05:31:04 +02:00
DoWarning ( strWarning ) ;
2014-10-07 20:22:58 +02:00
}
2012-06-27 19:51:51 +02:00
}
2018-04-05 16:17:32 +02:00
LogPrintf ( " %s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo) " , __func__ , /* Continued */
2017-04-26 03:31:08 +02:00
pindexNew - > GetBlockHash ( ) . ToString ( ) , pindexNew - > nHeight , pindexNew - > nVersion ,
log ( pindexNew - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , ( unsigned long ) pindexNew - > nChainTx ,
2018-02-28 16:46:31 +01:00
FormatISO8601DateTime ( pindexNew - > GetBlockTime ( ) ) ,
2017-04-26 03:31:08 +02:00
GuessVerificationProgress ( chainParams . TxData ( ) , pindexNew ) , pcoinsTip - > DynamicMemoryUsage ( ) * ( 1.0 / ( 1 < < 20 ) ) , pcoinsTip - > GetCacheSize ( ) ) ;
2016-04-03 12:08:14 +02:00
if ( ! warningMessages . empty ( ) )
2018-07-20 23:48:26 +02:00
LogPrintf ( " warning='%s' " , warningMessages ) ; /* Continued */
2016-04-03 12:08:14 +02:00
LogPrintf ( " \n " ) ;
2013-11-16 19:28:24 +01:00
}
2012-06-27 19:51:51 +02:00
2016-11-03 19:45:10 +01:00
/** Disconnect chainActive's tip.
* After calling , the mempool will be in an inconsistent state , with
* transactions from disconnected blocks being added to disconnectpool . You
* should make the mempool consistent again by calling UpdateMempoolForReorg .
* with cs_main held .
*
2017-08-07 07:36:37 +02:00
* If disconnectpool is nullptr , then no disconnected transactions are added to
2016-11-03 19:45:10 +01:00
* disconnectpool ( note that the caller is responsible for mempool consistency
* in any case ) .
*/
2017-12-04 15:34:46 +01:00
bool CChainState : : DisconnectTip ( CValidationState & state , const CChainParams & chainparams , DisconnectedBlockTransactions * disconnectpool )
2015-04-17 14:19:21 +02:00
{
2013-11-16 19:28:24 +01:00
CBlockIndex * pindexDelete = chainActive . Tip ( ) ;
assert ( pindexDelete ) ;
// Read block from disk.
2017-03-30 03:12:42 +02:00
std : : shared_ptr < CBlock > pblock = std : : make_shared < CBlock > ( ) ;
CBlock & block = * pblock ;
2016-04-17 09:58:50 +02:00
if ( ! ReadBlockFromDisk ( block , pindexDelete , chainparams . GetConsensus ( ) ) )
2015-01-17 00:57:14 +01:00
return AbortNode ( state , " Failed to read block " ) ;
2013-11-16 19:28:24 +01:00
// Apply the block atomically to the chain state.
int64_t nStart = GetTimeMicros ( ) ;
2012-01-03 21:24:28 +01:00
{
2017-08-09 17:08:22 +02:00
CCoinsViewCache view ( pcoinsTip . get ( ) ) ;
2018-08-06 21:40:20 +02:00
CClaimTrieCache trieCache ( pclaimTrie ) ;
2017-04-19 18:34:30 +02:00
assert ( view . GetBestBlock ( ) = = pindexDelete - > GetBlockHash ( ) ) ;
2018-08-06 21:40:20 +02:00
if ( DisconnectBlock ( block , pindexDelete , view , trieCache ) ! = DISCONNECT_OK )
2015-01-08 11:44:25 +01:00
return error ( " DisconnectTip() : DisconnectBlock % s failed " , pindexDelete->GetBlockHash().ToString()) ;
2016-12-14 02:50:00 +01:00
bool flushed = view . Flush ( ) ;
assert ( flushed ) ;
2018-08-06 21:40:20 +02:00
assert ( trieCache . flush ( ) ) ;
assert ( pindexDelete - > pprev - > hashClaimTrie = = trieCache . getMerkleHash ( ) ) ;
2012-01-03 21:24:28 +01:00
}
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Disconnect block: %.2fms \n " , ( GetTimeMicros ( ) - nStart ) * MILLI ) ;
2013-11-16 19:28:24 +01:00
// Write the chain state to disk, if necessary.
2018-03-09 15:03:40 +01:00
if ( ! FlushStateToDisk ( chainparams , state , FlushStateMode : : IF_NEEDED ) )
2013-11-16 19:28:24 +01:00
return false ;
2016-03-18 17:20:12 +01:00
2016-11-03 19:45:10 +01:00
if ( disconnectpool ) {
// 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 ( ) ;
mempool . removeRecursive ( * * it , MemPoolRemovalReason : : REORG ) ;
disconnectpool - > removeEntry ( it ) ;
2015-07-15 20:47:45 +02:00
}
2013-11-16 19:28:24 +01:00
}
2016-03-18 17:20:12 +01:00
2017-04-26 03:31:08 +02:00
chainActive . SetTip ( pindexDelete - > pprev ) ;
2016-04-06 16:36:32 +02:00
UpdateTip ( pindexDelete - > pprev , chainparams ) ;
2014-02-15 22:38:28 +01:00
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
2017-03-30 03:12:42 +02:00
GetMainSignals ( ) . BlockDisconnected ( pblock ) ;
2013-11-16 19:28:24 +01:00
return true ;
2013-11-16 18:40:55 +01:00
}
2012-01-03 21:24:28 +01:00
2014-07-26 22:49:17 +02:00
static int64_t nTimeReadFromDisk = 0 ;
static int64_t nTimeConnectTotal = 0 ;
static int64_t nTimeFlush = 0 ;
static int64_t nTimeChainState = 0 ;
static int64_t nTimePostConnect = 0 ;
2017-03-07 20:43:35 +01:00
struct PerBlockConnectTrace {
2017-08-07 07:36:37 +02:00
CBlockIndex * pindex = nullptr ;
2017-03-07 20:43:35 +01:00
std : : shared_ptr < const CBlock > pblock ;
std : : shared_ptr < std : : vector < CTransactionRef > > conflictedTxs ;
PerBlockConnectTrace ( ) : conflictedTxs ( std : : make_shared < std : : vector < CTransactionRef > > ( ) ) { }
} ;
2016-10-25 19:20:45 +02:00
/**
2016-11-29 23:15:12 +01:00
* Used to track blocks whose transactions were applied to the UTXO state as a
* part of a single ActivateBestChainStep call .
2017-03-06 23:19:22 +01:00
*
* This class also tracks transactions that are removed from the mempool as
2017-03-06 23:22:50 +01:00
* conflicts ( per block ) and can be used to pass all those transactions
* through SyncTransaction .
2017-03-07 20:43:35 +01:00
*
* This class assumes ( and asserts ) that the conflicted transactions for a given
* block are added via mempool callbacks prior to the BlockConnected ( ) associated
* with those transactions . If any transactions are marked conflicted , it is
* assumed that an associated block will always be added .
*
* This class is single - use , once you call GetBlocksConnected ( ) you have to throw
* it away and make a new one .
2016-10-25 19:20:45 +02:00
*/
2017-03-06 23:19:22 +01:00
class ConnectTrace {
2017-03-06 23:14:53 +01:00
private :
2017-03-07 20:43:35 +01:00
std : : vector < PerBlockConnectTrace > blocksConnected ;
2017-03-06 23:19:22 +01:00
CTxMemPool & pool ;
2017-03-06 23:14:53 +01:00
public :
2017-08-01 12:22:41 +02:00
explicit ConnectTrace ( CTxMemPool & _pool ) : blocksConnected ( 1 ) , pool ( _pool ) {
2017-03-06 23:19:22 +01:00
pool . NotifyEntryRemoved . connect ( boost : : bind ( & ConnectTrace : : NotifyEntryRemoved , this , _1 , _2 ) ) ;
}
~ ConnectTrace ( ) {
pool . NotifyEntryRemoved . disconnect ( boost : : bind ( & ConnectTrace : : NotifyEntryRemoved , this , _1 , _2 ) ) ;
}
2017-03-06 23:14:53 +01:00
void BlockConnected ( CBlockIndex * pindex , std : : shared_ptr < const CBlock > pblock ) {
2017-03-07 20:43:35 +01: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 ) ;
assert ( blocksConnected . back ( ) . conflictedTxs - > empty ( ) ) ;
blocksConnected . pop_back ( ) ;
2017-03-06 23:14:53 +01:00
return blocksConnected ;
}
2017-03-06 23:19:22 +01:00
void NotifyEntryRemoved ( CTransactionRef txRemoved , MemPoolRemovalReason reason ) {
2017-03-07 20:43:35 +01:00
assert ( ! blocksConnected . back ( ) . pindex ) ;
2017-03-06 23:19:22 +01:00
if ( reason = = MemPoolRemovalReason : : CONFLICT ) {
2017-03-07 20:43:35 +01:00
blocksConnected . back ( ) . conflictedTxs - > emplace_back ( std : : move ( txRemoved ) ) ;
2017-03-06 23:19:22 +01:00
}
}
2016-10-25 19:20:45 +02:00
} ;
2015-05-31 15:36:44 +02:00
/**
2017-08-07 07:36:37 +02:00
* Connect a new block to chainActive . pblock is either nullptr or a pointer to a CBlock
2014-12-01 02:39:44 +01:00
* corresponding to pindexNew , to bypass loading it again from disk .
2016-11-30 06:25:39 +01:00
*
2017-03-06 23:11:33 +01:00
* The block is added to connectTrace if connection succeeds .
2014-12-01 02:39:44 +01:00
*/
2017-12-04 15:34:46 +01:00
bool CChainState : : ConnectTip ( CValidationState & state , const CChainParams & chainparams , CBlockIndex * pindexNew , const std : : shared_ptr < const CBlock > & pblock , ConnectTrace & connectTrace , DisconnectedBlockTransactions & disconnectpool )
2015-04-17 14:40:24 +02:00
{
2013-11-16 19:28:24 +01:00
assert ( pindexNew - > pprev = = chainActive . Tip ( ) ) ;
// Read block from disk.
2014-07-26 22:49:17 +02:00
int64_t nTime1 = GetTimeMicros ( ) ;
2017-03-06 23:11:33 +01:00
std : : shared_ptr < const CBlock > pthisBlock ;
2014-08-26 02:26:41 +02:00
if ( ! pblock ) {
2016-10-15 18:12:50 +02:00
std : : shared_ptr < CBlock > pblockNew = std : : make_shared < CBlock > ( ) ;
if ( ! ReadBlockFromDisk ( * pblockNew , pindexNew , chainparams . GetConsensus ( ) ) )
2015-01-17 00:57:14 +01:00
return AbortNode ( state , " Failed to read block " ) ;
2017-03-06 23:11:33 +01:00
pthisBlock = pblockNew ;
2016-10-15 18:12:50 +02:00
} else {
2017-03-06 23:11:33 +01:00
pthisBlock = pblock ;
2014-08-26 02:26:41 +02:00
}
2017-03-06 23:11:33 +01:00
const CBlock & blockConnecting = * pthisBlock ;
2013-11-16 19:28:24 +01:00
// Apply the block atomically to the chain state.
2014-07-26 22:49:17 +02:00
int64_t nTime2 = GetTimeMicros ( ) ; nTimeReadFromDisk + = nTime2 - nTime1 ;
int64_t nTime3 ;
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Load block from disk: %.2fms [%.2fs] \n " , ( nTime2 - nTime1 ) * MILLI , nTimeReadFromDisk * MICRO ) ;
2010-08-29 18:58:15 +02:00
{
2017-08-09 17:08:22 +02:00
CCoinsViewCache view ( pcoinsTip . get ( ) ) ;
2018-08-06 21:40:20 +02:00
CClaimTrieCache trieCache ( pclaimTrie ) ;
bool rv = ConnectBlock ( blockConnecting , state , pindexNew , view , trieCache , chainparams ) ;
2016-10-25 20:22:41 +02:00
GetMainSignals ( ) . BlockChecked ( blockConnecting , state ) ;
2014-10-20 05:55:04 +02:00
if ( ! rv ) {
2013-11-16 19:28:24 +01:00
if ( state . IsInvalid ( ) )
InvalidBlockFound ( pindexNew , state ) ;
2015-01-08 11:44:25 +01:00
return error ( " ConnectTip() : ConnectBlock % s failed " , pindexNew->GetBlockHash().ToString()) ;
2013-01-27 01:24:06 +01:00
}
2014-07-26 22:49:17 +02:00
nTime3 = GetTimeMicros ( ) ; nTimeConnectTotal + = nTime3 - nTime2 ;
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Connect total: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime3 - nTime2 ) * MILLI , nTimeConnectTotal * MICRO , nTimeConnectTotal * MILLI / nBlocksTotal ) ;
2016-12-14 02:50:00 +01:00
bool flushed = view . Flush ( ) ;
assert ( flushed ) ;
2018-08-06 21:40:20 +02:00
flushed = trieCache . flush ( ) ;
assert ( flushed ) ;
2010-08-29 18:58:15 +02:00
}
2014-07-26 22:49:17 +02:00
int64_t nTime4 = GetTimeMicros ( ) ; nTimeFlush + = nTime4 - nTime3 ;
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Flush: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime4 - nTime3 ) * MILLI , nTimeFlush * MICRO , nTimeFlush * MILLI / nBlocksTotal ) ;
2013-11-16 19:28:24 +01:00
// Write the chain state to disk, if necessary.
2018-03-09 15:03:40 +01:00
if ( ! FlushStateToDisk ( chainparams , state , FlushStateMode : : IF_NEEDED ) )
2013-11-16 19:28:24 +01:00
return false ;
2014-07-26 22:49:17 +02:00
int64_t nTime5 = GetTimeMicros ( ) ; nTimeChainState + = nTime5 - nTime4 ;
2017-06-01 04:42:34 +02:00
LogPrint ( BCLog : : BENCH , " - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)] \n " , ( nTime5 - nTime4 ) * MILLI , nTimeChainState * MICRO , nTimeChainState * MILLI / nBlocksTotal ) ;
2016-04-26 13:55:13 +02:00
// Remove conflicting transactions from the mempool.;
2016-11-11 19:14:45 +01:00
mempool . removeForBlock ( blockConnecting . vtx , pindexNew - > nHeight ) ;
2016-11-03 19:45:10 +01:00
disconnectpool . removeForBlock ( blockConnecting . vtx ) ;
2013-11-16 19:28:24 +01:00
// Update chainActive & related variables.
2017-04-26 03:31:08 +02:00
chainActive . SetTip ( pindexNew ) ;
2016-04-06 16:36:32 +02:00
UpdateTip ( pindexNew , chainparams ) ;
2016-04-26 13:55:13 +02:00
2014-07-26 22:49:17 +02:00
int64_t nTime6 = GetTimeMicros ( ) ; nTimePostConnect + = nTime6 - nTime5 ; nTimeTotal + = nTime6 - nTime1 ;
2017-06-01 04:42:34 +02: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 23:11:33 +01:00
2017-03-06 23:14:53 +01:00
connectTrace . BlockConnected ( pindexNew , std : : move ( pthisBlock ) ) ;
2010-08-29 18:58:15 +02:00
return true ;
}
2014-12-01 02:39:44 +01: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 ) .
*/
2017-12-04 15:34:46 +01:00
CBlockIndex * CChainState : : FindMostWorkChain ( ) {
2013-11-16 19:28:24 +01:00
do {
2017-08-07 07:36:37 +02:00
CBlockIndex * pindexNew = nullptr ;
2014-05-06 00:54:10 +02:00
2013-11-16 19:28:24 +01:00
// Find the best candidate header.
{
2014-10-06 08:31:33 +02:00
std : : set < CBlockIndex * , CBlockIndexWorkComparator > : : reverse_iterator it = setBlockIndexCandidates . rbegin ( ) ;
if ( it = = setBlockIndexCandidates . rend ( ) )
2017-08-07 07:36:37 +02:00
return nullptr ;
2013-11-16 19:28:24 +01: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 ;
while ( pindexTest & & ! chainActive . Contains ( pindexTest ) ) {
2014-07-12 00:02:35 +02:00
assert ( pindexTest - > nChainTx | | 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 20:27:44 +01: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)
2017-08-07 07:36:37 +02:00
if ( fFailedChain & & ( pindexBestInvalid = = nullptr | | pindexNew - > nChainWork > pindexBestInvalid - > nChainWork ) )
2014-03-13 03:48:27 +01:00
pindexBestInvalid = pindexNew ;
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 20:27:44 +01:00
// Remove the entire chain from the set.
2013-11-16 19:28:24 +01: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 20:27:44 +01:00
if ( fFailedChain ) {
pindexFailed - > nStatus | = BLOCK_FAILED_CHILD ;
} else if ( fMissingData ) {
// If we're missing data, then add back to mapBlocksUnlinked,
// so that if the block arrives in the future we can try adding
// to setBlockIndexCandidates again.
mapBlocksUnlinked . insert ( std : : make_pair ( pindexFailed - > pprev , pindexFailed ) ) ;
}
2014-10-06 08:31:33 +02:00
setBlockIndexCandidates . erase ( pindexFailed ) ;
2013-11-16 19:28:24 +01:00
pindexFailed = pindexFailed - > pprev ;
}
2014-10-06 08:31:33 +02:00
setBlockIndexCandidates . erase ( pindexTest ) ;
2013-11-16 19:28:24 +01:00
fInvalidAncestor = true ;
break ;
2013-01-27 00:14:11 +01:00
}
2013-11-16 19:28:24 +01:00
pindexTest = pindexTest - > pprev ;
2010-08-29 18:58:15 +02:00
}
2014-05-06 00:54:10 +02:00
if ( ! fInvalidAncestor )
return pindexNew ;
2013-11-16 19:28:24 +01:00
} while ( true ) ;
}
2010-08-29 18:58:15 +02:00
2014-12-01 02:39:44 +01:00
/** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
2017-12-04 15:34:46 +01:00
void CChainState : : PruneBlockIndexCandidates ( ) {
2014-11-01 22:42:12 +01: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 ( ) ;
2014-11-20 12:43:50 +01:00
while ( it ! = setBlockIndexCandidates . end ( ) & & setBlockIndexCandidates . value_comp ( ) ( * it , chainActive . Tip ( ) ) ) {
2014-11-01 22:42:12 +01:00
setBlockIndexCandidates . erase ( it + + ) ;
}
2014-11-20 12:43:50 +01:00
// Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
assert ( ! setBlockIndexCandidates . empty ( ) ) ;
2014-11-01 22:42:12 +01:00
}
2014-12-01 02:39:44 +01:00
/**
* Try to make some progress towards making pindexMostWork the active block .
2017-08-07 07:36:37 +02:00
* pblock is either nullptr or a pointer to a CBlock corresponding to pindexMostWork .
2014-12-01 02:39:44 +01:00
*/
2017-12-04 15:34:46 +01:00
bool CChainState : : ActivateBestChainStep ( CValidationState & state , const CChainParams & chainparams , CBlockIndex * pindexMostWork , const std : : shared_ptr < const CBlock > & pblock , bool & fInvalidFound , ConnectTrace & connectTrace )
2015-04-17 14:40:24 +02:00
{
2014-05-06 01:23:13 +02:00
AssertLockHeld ( cs_main ) ;
2018-05-10 21:57:16 +02:00
2014-08-03 18:12:19 +02:00
const CBlockIndex * pindexOldTip = chainActive . Tip ( ) ;
const CBlockIndex * pindexFork = chainActive . FindFork ( pindexMostWork ) ;
2010-08-29 18:58:15 +02:00
2014-05-06 01:23:13 +02:00
// Disconnect active blocks which are no longer in the best chain.
2015-10-02 23:20:38 +02:00
bool fBlocksDisconnected = false ;
2016-11-03 19:45:10 +01:00
DisconnectedBlockTransactions disconnectpool ;
2014-05-06 01:23:13 +02:00
while ( chainActive . Tip ( ) & & chainActive . Tip ( ) ! = pindexFork ) {
2016-11-03 19:45:10 +01:00
if ( ! DisconnectTip ( state , chainparams , & disconnectpool ) ) {
// This is likely a fatal error, but keep the mempool consistent,
// just in case. Only remove from the mempool in this case.
UpdateMempoolForReorg ( disconnectpool , false ) ;
2014-05-06 01:23:13 +02:00
return false ;
2016-11-03 19:45:10 +01:00
}
2015-10-02 23:20:38 +02:00
fBlocksDisconnected = true ;
2014-05-06 01:23:13 +02:00
}
2013-11-16 19:28:24 +01:00
2014-05-06 01:23:13 +02:00
// Build list of new blocks to connect.
std : : vector < CBlockIndex * > vpindexToConnect ;
2014-10-10 22:13:47 +02:00
bool fContinue = true ;
int nHeight = pindexFork ? pindexFork - > nHeight : - 1 ;
while ( fContinue & & nHeight ! = pindexMostWork - > nHeight ) {
2015-09-09 23:54:11 +02: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 ) ;
CBlockIndex * pindexIter = pindexMostWork - > GetAncestor ( nTargetHeight ) ;
while ( pindexIter & & pindexIter - > nHeight ! = nHeight ) {
vpindexToConnect . push_back ( pindexIter ) ;
pindexIter = pindexIter - > pprev ;
}
nHeight = nTargetHeight ;
// Connect new blocks.
2017-04-13 00:51:39 +02:00
for ( CBlockIndex * pindexConnect : reverse_iterate ( vpindexToConnect ) ) {
2016-11-03 19:45:10 +01:00
if ( ! ConnectTip ( state , chainparams , pindexConnect , pindexConnect = = pindexMostWork ? pblock : std : : shared_ptr < const CBlock > ( ) , connectTrace , disconnectpool ) ) {
2015-09-09 23:54:11 +02:00
if ( state . IsInvalid ( ) ) {
// The block violates a consensus rule.
2018-05-07 20:18:27 +02:00
if ( ! state . CorruptionPossible ( ) ) {
InvalidChainFound ( vpindexToConnect . front ( ) ) ;
}
2015-09-09 23:54:11 +02:00
state = CValidationState ( ) ;
fInvalidFound = true ;
fContinue = false ;
break ;
} else {
// A system error occurred (disk space, database error, ...).
2016-11-03 19:45:10 +01:00
// Make the mempool consistent with the current tip, just in case
// any observers try to use it before shutdown.
UpdateMempoolForReorg ( disconnectpool , false ) ;
2015-09-09 23:54:11 +02:00
return false ;
}
2014-05-06 01:23:13 +02:00
} else {
2015-09-09 23:54:11 +02:00
PruneBlockIndexCandidates ( ) ;
if ( ! pindexOldTip | | chainActive . Tip ( ) - > nChainWork > pindexOldTip - > nChainWork ) {
// We're in a better position than we were. Return temporarily to release the lock.
fContinue = false ;
break ;
}
2013-11-16 19:28:24 +01:00
}
}
2012-11-24 14:26:51 +01:00
}
2010-08-29 18:58:15 +02:00
2015-09-10 01:31:20 +02:00
if ( fBlocksDisconnected ) {
2016-11-03 19:45:10 +01:00
// If any blocks were disconnected, disconnectpool may be non empty. Add
// any disconnected transactions back to the mempool.
UpdateMempoolForReorg ( disconnectpool , true ) ;
2015-09-10 01:31:20 +02:00
}
2017-08-09 17:08:22 +02:00
mempool . check ( pcoinsTip . get ( ) ) ;
2015-10-02 23:20:38 +02:00
2014-05-07 16:45:33 +02:00
// Callbacks/notifications for a new best chain.
if ( fInvalidFound )
CheckForkWarningConditionsOnNewFork ( vpindexToConnect . back ( ) ) ;
else
CheckForkWarningConditions ( ) ;
2010-08-29 18:58:15 +02:00
return true ;
}
2018-06-05 00:25:13 +02:00
static void NotifyHeaderTip ( ) LOCKS_EXCLUDED ( cs_main ) {
2016-04-28 16:18:45 +02:00
bool fNotify = false ;
bool fInitialBlockDownload = false ;
2017-08-07 07:36:37 +02:00
static CBlockIndex * pindexHeaderOld = nullptr ;
CBlockIndex * pindexHeader = nullptr ;
2016-04-28 16:18:45 +02:00
{
LOCK ( cs_main ) ;
2016-10-20 18:53:05 +02:00
pindexHeader = pindexBestHeader ;
2016-04-28 16:18:45 +02:00
if ( pindexHeader ! = pindexHeaderOld ) {
fNotify = true ;
fInitialBlockDownload = IsInitialBlockDownload ( ) ;
pindexHeaderOld = pindexHeader ;
}
}
// Send block tip changed notifications without cs_main
if ( fNotify ) {
uiInterface . NotifyHeaderTip ( fInitialBlockDownload , pindexHeader ) ;
}
}
2014-12-01 02:39:44 +01:00
/**
* Make the best chain active , in multiple steps . The result is either failure
2017-08-07 07:36:37 +02:00
* or an activated best chain . pblock is either nullptr or a pointer to a block
2014-12-01 02:39:44 +01:00
* that is already loaded ( to avoid loading it again from disk ) .
2018-04-17 23:15:20 +02:00
*
* ActivateBestChain is split into steps ( see ActivateBestChainStep ) so that
* we avoid holding cs_main for an extended period of time ; the length of this
* call may be quite long during reindexing or a substantial reorg .
2014-12-01 02:39:44 +01:00
*/
2017-12-04 15:34:46 +01:00
bool CChainState : : ActivateBestChain ( CValidationState & state , const CChainParams & chainparams , std : : shared_ptr < const CBlock > pblock ) {
2017-01-12 21:15:17 +01: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!
2017-12-05 00:25:57 +01:00
AssertLockNotHeld ( cs_main ) ;
2017-01-12 21:15:17 +01:00
2018-05-10 21:57:16 +02: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
// we use m_cs_chainstate to enforce mutual exclusion so that only one caller may execute this function at a time
LOCK ( m_cs_chainstate ) ;
2017-08-07 07:36:37 +02:00
CBlockIndex * pindexMostWork = nullptr ;
CBlockIndex * pindexNewTip = nullptr ;
2017-08-01 21:17:40 +02:00
int nStopAtHeight = gArgs . GetArg ( " -stopatheight " , DEFAULT_STOPATHEIGHT ) ;
2014-05-06 01:23:13 +02:00
do {
boost : : this_thread : : interruption_point ( ) ;
2017-12-05 00:57:55 +01:00
if ( GetMainSignals ( ) . CallbacksPending ( ) > 10 ) {
// Block until the validation queue drains. This should largely
// never happen in normal operation, however may happen during
2018-01-28 13:14:54 +01:00
// reindex, causing memory blowup if we run too far ahead.
2018-05-11 22:56:19 +02:00
// 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.
2017-12-24 18:13:13 +01:00
SyncWithValidationInterfaceQueue ( ) ;
2017-12-05 00:57:55 +01:00
}
2014-05-07 16:45:33 +02:00
{
LOCK ( cs_main ) ;
2017-10-09 17:19:10 +02:00
CBlockIndex * starting_tip = chainActive . Tip ( ) ;
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).
ConnectTrace connectTrace ( mempool ) ; // Destructed before cs_main is unlocked
if ( pindexMostWork = = nullptr ) {
pindexMostWork = FindMostWorkChain ( ) ;
}
2017-03-06 23:19:22 +01:00
2017-10-09 17:19:10 +02:00
// Whether we have anything to do at all.
if ( pindexMostWork = = nullptr | | pindexMostWork = = chainActive . Tip ( ) ) {
break ;
}
2014-05-06 01:23:13 +02:00
2017-10-09 17:19:10 +02:00
bool fInvalidFound = false ;
std : : shared_ptr < const CBlock > nullBlockPtr ;
if ( ! ActivateBestChainStep ( state , chainparams , pindexMostWork , pblock & & pblock - > GetHash ( ) = = pindexMostWork - > GetBlockHash ( ) ? pblock : nullBlockPtr , fInvalidFound , connectTrace ) )
return false ;
blocks_connected = true ;
2014-05-06 01:23:13 +02:00
2017-10-09 17:19:10 +02:00
if ( fInvalidFound ) {
// Wipe cache, we may need another branch now.
pindexMostWork = nullptr ;
}
pindexNewTip = chainActive . Tip ( ) ;
2014-05-06 01:23:13 +02:00
2017-10-09 17:19:10 +02:00
for ( const PerBlockConnectTrace & trace : connectTrace . GetBlocksConnected ( ) ) {
assert ( trace . pblock & & trace . pindex ) ;
GetMainSignals ( ) . BlockConnected ( trace . pblock , trace . pindex , trace . conflictedTxs ) ;
}
} while ( ! chainActive . Tip ( ) | | ( starting_tip & & CBlockIndexWorkComparator ( ) ( chainActive . Tip ( ) , starting_tip ) ) ) ;
if ( ! blocks_connected ) return true ;
2017-01-19 17:03:36 +01:00
2017-10-09 17:19:10 +02:00
const CBlockIndex * pindexFork = chainActive . FindFork ( starting_tip ) ;
bool fInitialDownload = IsInitialBlockDownload ( ) ;
2014-05-07 16:45:33 +02:00
2018-04-15 17:22:28 +02: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 17:19:10 +02:00
// Notify ValidationInterface subscribers
GetMainSignals ( ) . UpdatedBlockTip ( pindexNewTip , pindexFork , fInitialDownload ) ;
// Always notify the UI if a new block tip was connected
2018-04-15 17:22:28 +02:00
uiInterface . NotifyBlockTip ( fInitialDownload , pindexNewTip ) ;
}
2014-05-07 16:45:33 +02:00
}
2018-04-15 17:22:28 +02:00
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
2017-06-09 20:38:30 +02:00
if ( nStopAtHeight & & pindexNewTip & & pindexNewTip - > nHeight > = nStopAtHeight ) StartShutdown ( ) ;
2018-02-06 19:38:54 +01: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.
if ( ShutdownRequested ( ) )
break ;
2016-04-25 21:31:32 +02:00
} while ( pindexNewTip ! = pindexMostWork ) ;
2015-04-17 14:19:21 +02:00
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
2014-05-06 01:23:13 +02: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 11:38:35 +01:00
// Write changes periodically to disk, after relay.
2018-03-09 15:03:40 +01:00
if ( ! FlushStateToDisk ( chainparams , 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 11:38:35 +01:00
return false ;
}
2014-05-06 01:23:13 +02:00
return true ;
}
2017-10-09 17:19:10 +02:00
2017-12-04 15:34:46 +01:00
bool ActivateBestChain ( CValidationState & state , const CChainParams & chainparams , std : : shared_ptr < const CBlock > pblock ) {
return g_chainstate . ActivateBestChain ( state , chainparams , std : : move ( pblock ) ) ;
}
2014-03-13 03:48:27 +01:00
2017-12-04 15:34:46 +01:00
bool CChainState : : PreciousBlock ( CValidationState & state , const CChainParams & params , CBlockIndex * pindex )
2016-08-26 23:05:09 +02:00
{
{
LOCK ( cs_main ) ;
if ( pindex - > nChainWork < chainActive . Tip ( ) - > nChainWork ) {
// Nothing to do, this block is not at the tip.
return true ;
}
if ( chainActive . Tip ( ) - > nChainWork > nLastPreciousChainwork ) {
// The chain has been extended since the last call, reset the counter.
nBlockReverseSequenceId = - 1 ;
}
nLastPreciousChainwork = chainActive . Tip ( ) - > nChainWork ;
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 - - ;
}
if ( pindex - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & & pindex - > nChainTx ) {
setBlockIndexCandidates . insert ( pindex ) ;
PruneBlockIndexCandidates ( ) ;
}
}
2017-12-04 15:34:46 +01:00
return ActivateBestChain ( state , params , std : : shared_ptr < const CBlock > ( ) ) ;
}
bool PreciousBlock ( CValidationState & state , const CChainParams & params , CBlockIndex * pindex ) {
return g_chainstate . PreciousBlock ( state , params , pindex ) ;
2016-08-26 23:05:09 +02:00
}
2017-12-04 15:34:46 +01:00
bool CChainState : : InvalidateBlock ( CValidationState & state , const CChainParams & chainparams , CBlockIndex * pindex )
2015-04-17 14:19:21 +02:00
{
2014-11-19 09:39:42 +01:00
AssertLockHeld ( cs_main ) ;
2017-10-19 22:55:31 +02:00
// We first disconnect backwards and then mark the 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).
bool pindex_was_in_chain = false ;
CBlockIndex * invalid_walk_tip = chainActive . Tip ( ) ;
2014-11-19 09:39:42 +01:00
2016-11-03 19:45:10 +01:00
DisconnectedBlockTransactions disconnectpool ;
2014-11-19 09:39:42 +01:00
while ( chainActive . Contains ( pindex ) ) {
2017-10-19 22:55:31 +02:00
pindex_was_in_chain = true ;
2014-11-19 09:39:42 +01:00
// ActivateBestChain considers blocks already in chainActive
// unconditionally valid already, so force disconnect away from it.
2016-11-03 19:45:10 +01:00
if ( ! DisconnectTip ( state , chainparams , & disconnectpool ) ) {
// It's probably hopeless to try to make the mempool consistent
// here if DisconnectTip failed, but we can try.
UpdateMempoolForReorg ( disconnectpool , false ) ;
2014-11-19 09:39:42 +01:00
return false ;
}
}
2017-10-19 22:55:31 +02:00
// Now mark the blocks we just disconnected as descendants invalid
// (note this may not be all descendants).
while ( pindex_was_in_chain & & invalid_walk_tip ! = pindex ) {
invalid_walk_tip - > nStatus | = BLOCK_FAILED_CHILD ;
setDirtyBlockIndex . insert ( invalid_walk_tip ) ;
setBlockIndexCandidates . erase ( invalid_walk_tip ) ;
invalid_walk_tip = invalid_walk_tip - > pprev ;
}
// Mark the block itself as invalid.
pindex - > nStatus | = BLOCK_FAILED_VALID ;
setDirtyBlockIndex . insert ( pindex ) ;
setBlockIndexCandidates . erase ( pindex ) ;
2018-04-18 13:57:18 +02:00
m_failed_blocks . insert ( pindex ) ;
2017-10-19 22:55:31 +02:00
2016-11-03 19:45:10 +01:00
// DisconnectTip will add transactions to disconnectpool; try to add these
// back to the mempool.
UpdateMempoolForReorg ( disconnectpool , true ) ;
2015-10-02 23:20:38 +02:00
2014-11-19 09:39:42 +01:00
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
2015-04-28 16:47:17 +02:00
// add it again.
2014-11-19 09:39:42 +01:00
BlockMap : : iterator it = mapBlockIndex . begin ( ) ;
while ( it ! = mapBlockIndex . end ( ) ) {
2015-03-12 21:03:23 +01:00
if ( it - > second - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & & it - > second - > nChainTx & & ! setBlockIndexCandidates . value_comp ( ) ( it - > second , chainActive . Tip ( ) ) ) {
2015-03-11 16:56:44 +01:00
setBlockIndexCandidates . insert ( it - > second ) ;
2014-11-19 09:39:42 +01:00
}
it + + ;
}
InvalidChainFound ( pindex ) ;
2018-02-14 04:39:04 +01:00
// Only notify about a new block tip if the active chain was modified.
if ( pindex_was_in_chain ) {
uiInterface . NotifyBlockTip ( IsInitialBlockDownload ( ) , pindex - > pprev ) ;
}
2014-11-19 09:39:42 +01:00
return true ;
}
2017-12-04 15:34:46 +01:00
bool InvalidateBlock ( CValidationState & state , const CChainParams & chainparams , CBlockIndex * pindex ) {
return g_chainstate . InvalidateBlock ( state , chainparams , pindex ) ;
}
2014-11-19 09:39:42 +01:00
2018-07-27 08:22:42 +02:00
void CChainState : : ResetBlockFailureFlags ( CBlockIndex * pindex ) {
2014-11-19 09:39:42 +01:00
AssertLockHeld ( cs_main ) ;
int nHeight = pindex - > nHeight ;
// Remove the invalidity flag from this block and all its descendants.
BlockMap : : iterator it = mapBlockIndex . begin ( ) ;
while ( it ! = mapBlockIndex . end ( ) ) {
if ( ! it - > second - > IsValid ( ) & & it - > second - > GetAncestor ( nHeight ) = = pindex ) {
it - > second - > nStatus & = ~ BLOCK_FAILED_MASK ;
2014-11-25 12:33:43 +01:00
setDirtyBlockIndex . insert ( it - > second ) ;
2014-11-19 09:39:42 +01:00
if ( it - > second - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & & it - > second - > nChainTx & & setBlockIndexCandidates . value_comp ( ) ( chainActive . Tip ( ) , it - > second ) ) {
setBlockIndexCandidates . insert ( it - > second ) ;
}
if ( it - > second = = pindexBestInvalid ) {
// Reset invalid block marker if it was pointing to one of those.
2017-08-07 07:36:37 +02:00
pindexBestInvalid = nullptr ;
2014-11-19 09:39:42 +01:00
}
2018-04-18 13:57:18 +02:00
m_failed_blocks . erase ( it - > second ) ;
2014-11-19 09:39:42 +01:00
}
it + + ;
}
// Remove the invalidity flag from all ancestors too.
2017-08-07 07:36:37 +02:00
while ( pindex ! = nullptr ) {
2014-11-25 12:33:43 +01:00
if ( pindex - > nStatus & BLOCK_FAILED_MASK ) {
pindex - > nStatus & = ~ BLOCK_FAILED_MASK ;
setDirtyBlockIndex . insert ( pindex ) ;
2018-05-09 15:03:35 +02:00
m_failed_blocks . erase ( pindex ) ;
2014-11-19 09:39:42 +01:00
}
pindex = pindex - > pprev ;
}
}
2018-07-27 08:22:42 +02:00
void ResetBlockFailureFlags ( CBlockIndex * pindex ) {
2017-12-04 15:34:46 +01:00
return g_chainstate . ResetBlockFailureFlags ( pindex ) ;
}
2014-11-19 09:39:42 +01:00
2017-12-04 15:34:46 +01:00
CBlockIndex * CChainState : : AddToBlockIndex ( const CBlockHeader & block )
2010-08-29 18:58:15 +02:00
{
2018-01-12 00:32:32 +01:00
AssertLockHeld ( cs_main ) ;
2010-08-29 18:58:15 +02:00
// Check for duplicate
2013-06-24 04:00:18 +02:00
uint256 hash = block . GetHash ( ) ;
2014-09-04 02:02:44 +02:00
BlockMap : : iterator it = mapBlockIndex . find ( hash ) ;
2014-03-13 03:48:27 +01:00
if ( it ! = mapBlockIndex . end ( ) )
return it - > second ;
2010-08-29 18:58:15 +02:00
// Construct new block index object
2013-06-24 04:00:18 +02:00
CBlockIndex * pindexNew = new CBlockIndex ( block ) ;
2014-07-12 00:02:35 +02:00
// We assign the sequence id to blocks only when the full data is available,
// to avoid miners withholding blocks but broadcasting headers, to get a
// competitive advantage.
pindexNew - > nSequenceId = 0 ;
2017-01-27 09:43:41 +01:00
BlockMap : : iterator mi = mapBlockIndex . insert ( std : : make_pair ( hash , pindexNew ) ) . first ;
2010-08-29 18:58:15 +02:00
pindexNew - > phashBlock = & ( ( * mi ) . first ) ;
2014-09-04 02:02:44 +02:00
BlockMap : : iterator miPrev = mapBlockIndex . find ( block . hashPrevBlock ) ;
2010-08-29 18:58:15 +02:00
if ( miPrev ! = mapBlockIndex . end ( ) )
{
pindexNew - > pprev = ( * miPrev ) . second ;
pindexNew - > nHeight = pindexNew - > pprev - > nHeight + 1 ;
2014-06-25 00:56:47 +02:00
pindexNew - > BuildSkip ( ) ;
2010-08-29 18:58:15 +02:00
}
2017-01-08 05:05:14 +01:00
pindexNew - > nTimeMax = ( pindexNew - > pprev ? std : : max ( pindexNew - > pprev - > nTimeMax , pindexNew - > nTime ) : pindexNew - > nTime ) ;
2014-10-29 17:00:02 +01:00
pindexNew - > nChainWork = ( pindexNew - > pprev ? pindexNew - > pprev - > nChainWork : 0 ) + GetBlockProof ( * pindexNew ) ;
2014-03-13 03:48:27 +01:00
pindexNew - > RaiseValidity ( BLOCK_VALID_TREE ) ;
2017-08-07 07:36:37 +02:00
if ( pindexBestHeader = = nullptr | | pindexBestHeader - > nChainWork < pindexNew - > nChainWork )
2014-07-12 00:02:35 +02:00
pindexBestHeader = pindexNew ;
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 11:38:35 +01:00
setDirtyBlockIndex . insert ( pindexNew ) ;
2014-03-13 03:48:27 +01:00
return pindexNew ;
}
2014-12-01 02:39:44 +01:00
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
2018-06-07 17:10:48 +02:00
void CChainState : : ReceivedBlockTransactions ( const CBlock & block , CBlockIndex * pindexNew , const CDiskBlockPos & pos , const Consensus : : Params & consensusParams )
2014-03-13 03:48:27 +01:00
{
pindexNew - > nTx = block . vtx . size ( ) ;
2014-07-12 00:02:35 +02:00
pindexNew - > nChainTx = 0 ;
2012-08-19 00:33:01 +02:00
pindexNew - > nFile = pos . nFile ;
pindexNew - > nDataPos = pos . nPos ;
2012-08-13 19:11:05 +02:00
pindexNew - > nUndoPos = 0 ;
2014-03-13 03:48:27 +01:00
pindexNew - > nStatus | = BLOCK_HAVE_DATA ;
2017-04-13 16:37:46 +02:00
if ( IsWitnessEnabled ( pindexNew - > pprev , consensusParams ) ) {
2016-03-18 17:20:12 +01:00
pindexNew - > nStatus | = BLOCK_OPT_WITNESS ;
}
2014-07-12 00:02:35 +02:00
pindexNew - > RaiseValidity ( BLOCK_VALID_TRANSACTIONS ) ;
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 11:38:35 +01:00
setDirtyBlockIndex . insert ( pindexNew ) ;
2014-03-13 03:48:27 +01:00
2017-08-07 07:36:37 +02:00
if ( pindexNew - > pprev = = nullptr | | pindexNew - > pprev - > nChainTx ) {
2014-07-12 00:02:35 +02:00
// If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
2017-01-27 09:43:41 +01:00
std : : deque < CBlockIndex * > queue ;
2014-07-12 00:02:35 +02:00
queue . push_back ( pindexNew ) ;
2010-08-29 18:58:15 +02:00
2014-07-12 00:02:35 +02: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 ;
2015-04-13 18:26:28 +02:00
{
LOCK ( cs_nBlockSequenceId ) ;
pindex - > nSequenceId = nBlockSequenceId + + ;
}
2017-08-07 07:36:37 +02:00
if ( chainActive . Tip ( ) = = nullptr | | ! setBlockIndexCandidates . value_comp ( ) ( pindex , chainActive . Tip ( ) ) ) {
2015-03-13 17:25:34 +01:00
setBlockIndexCandidates . insert ( pindex ) ;
}
2014-07-12 00:02:35 +02:00
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > range = mapBlocksUnlinked . equal_range ( pindex ) ;
while ( range . first ! = range . second ) {
std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator it = range . first ;
queue . push_back ( it - > second ) ;
range . first + + ;
mapBlocksUnlinked . erase ( it ) ;
}
}
} else {
if ( pindexNew - > pprev & & pindexNew - > pprev - > IsValid ( BLOCK_VALID_TREE ) ) {
mapBlocksUnlinked . insert ( std : : make_pair ( pindexNew - > pprev , pindexNew ) ) ;
}
}
2010-08-29 18:58:15 +02:00
}
2017-04-26 03:35:02 +02:00
static bool FindBlockPos ( CDiskBlockPos & pos , unsigned int nAddSize , unsigned int nHeight , uint64_t nTime , bool fKnown = false )
2012-08-13 19:11:05 +02:00
{
LOCK ( cs_LastBlockFile ) ;
2014-09-25 08:21:21 +02:00
unsigned int nFile = fKnown ? pos . nFile : nLastBlockFile ;
if ( vinfoBlockFile . size ( ) < = nFile ) {
vinfoBlockFile . resize ( nFile + 1 ) ;
}
if ( ! fKnown ) {
while ( vinfoBlockFile [ nFile ] . nSize + nAddSize > = MAX_BLOCKFILE_SIZE ) {
nFile + + ;
if ( vinfoBlockFile . size ( ) < = nFile ) {
vinfoBlockFile . resize ( nFile + 1 ) ;
}
2012-10-21 21:23:13 +02:00
}
2014-09-25 08:21:21 +02:00
pos . nFile = nFile ;
pos . nPos = vinfoBlockFile [ nFile ] . nSize ;
2012-08-13 19:11:05 +02:00
}
2015-11-16 02:13:30 +01:00
if ( ( int ) nFile ! = nLastBlockFile ) {
2015-11-05 00:16:49 +01:00
if ( ! fKnown ) {
2015-11-18 04:23:39 +01:00
LogPrintf ( " Leaving block file %i: %s \n " , nLastBlockFile , vinfoBlockFile [ nLastBlockFile ] . ToString ( ) ) ;
2015-11-05 00:16:49 +01:00
}
FlushBlockFile ( ! fKnown ) ;
nLastBlockFile = nFile ;
}
2014-09-25 08:21:21 +02:00
vinfoBlockFile [ nFile ] . AddBlock ( nHeight , nTime ) ;
2015-03-07 02:26:09 +01:00
if ( fKnown )
vinfoBlockFile [ nFile ] . nSize = std : : max ( pos . nPos + nAddSize , vinfoBlockFile [ nFile ] . nSize ) ;
else
vinfoBlockFile [ nFile ] . nSize + = nAddSize ;
2012-08-13 19:11:05 +02:00
2012-10-21 21:23:13 +02:00
if ( ! fKnown ) {
unsigned int nOldChunks = ( pos . nPos + BLOCKFILE_CHUNK_SIZE - 1 ) / BLOCKFILE_CHUNK_SIZE ;
2014-09-25 08:21:21 +02:00
unsigned int nNewChunks = ( vinfoBlockFile [ nFile ] . nSize + BLOCKFILE_CHUNK_SIZE - 1 ) / BLOCKFILE_CHUNK_SIZE ;
2012-10-21 21:23:13 +02:00
if ( nNewChunks > nOldChunks ) {
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 20:27:44 +01:00
if ( fPruneMode )
fCheckForPruning = true ;
2018-03-09 05:12:43 +01:00
if ( CheckDiskSpace ( nNewChunks * BLOCKFILE_CHUNK_SIZE - pos . nPos , true ) ) {
2012-12-04 07:48:57 +01:00
FILE * file = OpenBlockFile ( pos ) ;
if ( file ) {
2013-09-18 12:38:08 +02:00
LogPrintf ( " Pre-allocating up to position 0x%x in blk%05u.dat \n " , nNewChunks * BLOCKFILE_CHUNK_SIZE , pos . nFile ) ;
2012-12-04 07:48:57 +01:00
AllocateFileRange ( file , pos . nPos , nNewChunks * BLOCKFILE_CHUNK_SIZE - pos . nPos ) ;
fclose ( file ) ;
}
2012-10-21 21:23:13 +02:00
}
2012-12-04 07:48:57 +01:00
else
2017-04-26 03:35:02 +02:00
return error ( " out of disk space " ) ;
2012-08-16 02:21:28 +02: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 11:38:35 +01:00
setDirtyFileInfo . insert ( nFile ) ;
2012-08-13 19:11:05 +02:00
return true ;
}
2017-04-21 20:45:30 +02:00
static bool FindUndoPos ( CValidationState & state , int nFile , CDiskBlockPos & pos , unsigned int nAddSize )
2012-08-13 19:11:05 +02:00
{
pos . nFile = nFile ;
LOCK ( cs_LastBlockFile ) ;
2012-08-16 02:21:28 +02:00
unsigned int nNewSize ;
2014-09-25 08:21:21 +02:00
pos . nPos = vinfoBlockFile [ nFile ] . nUndoSize ;
nNewSize = vinfoBlockFile [ nFile ] . nUndoSize + = nAddSize ;
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 11:38:35 +01:00
setDirtyFileInfo . insert ( nFile ) ;
2012-08-16 02:21:28 +02:00
unsigned int nOldChunks = ( pos . nPos + UNDOFILE_CHUNK_SIZE - 1 ) / UNDOFILE_CHUNK_SIZE ;
unsigned int nNewChunks = ( nNewSize + UNDOFILE_CHUNK_SIZE - 1 ) / UNDOFILE_CHUNK_SIZE ;
if ( nNewChunks > nOldChunks ) {
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 20:27:44 +01:00
if ( fPruneMode )
fCheckForPruning = true ;
2018-03-09 05:12:43 +01:00
if ( CheckDiskSpace ( nNewChunks * UNDOFILE_CHUNK_SIZE - pos . nPos , true ) ) {
2012-12-04 07:48:57 +01:00
FILE * file = OpenUndoFile ( pos ) ;
if ( file ) {
2013-09-18 12:38:08 +02:00
LogPrintf ( " Pre-allocating up to position 0x%x in rev%05u.dat \n " , nNewChunks * UNDOFILE_CHUNK_SIZE , pos . nFile ) ;
2012-12-04 07:48:57 +01:00
AllocateFileRange ( file , pos . nPos , nNewChunks * UNDOFILE_CHUNK_SIZE - pos . nPos ) ;
fclose ( file ) ;
}
2012-08-16 02:21:28 +02:00
}
2012-12-04 07:48:57 +01:00
else
2012-09-10 04:02:35 +02:00
return state . Error ( " out of disk space " ) ;
2012-08-13 19:11:05 +02:00
}
return true ;
}
2017-04-21 20:45:30 +02:00
static bool CheckBlockHeader ( const CBlockHeader & block , CValidationState & state , const Consensus : : Params & consensusParams , bool fCheckPOW = true )
2010-08-29 18:58:15 +02:00
{
2010-09-19 23:20:34 +02:00
// Check proof of work matches claimed amount
2018-08-06 21:40:20 +02:00
if ( fCheckPOW & & ! CheckProofOfWork ( block . GetPoWHash ( ) , block . nBits , consensusParams ) )
2015-12-02 03:13:47 +01:00
return state . DoS ( 50 , false , REJECT_INVALID , " high-hash " , false , " proof of work failed " ) ;
2010-09-19 23:20:34 +02:00
2014-03-11 17:36:21 +01:00
return true ;
}
2016-06-09 01:12:52 +02:00
bool CheckBlock ( const CBlock & block , CValidationState & state , const Consensus : : Params & consensusParams , bool fCheckPOW , bool fCheckMerkleRoot )
2010-08-29 18:58:15 +02:00
{
2014-07-12 00:02:35 +02:00
// These are checks that are independent of context.
2010-08-29 18:58:15 +02:00
2015-08-15 23:32:38 +02:00
if ( block . fChecked )
return true ;
2014-11-20 08:28:19 +01:00
// Check that the header is valid (particularly PoW). This is mostly
// redundant with the call in AcceptBlockHeader.
2016-06-09 01:12:52 +02:00
if ( ! CheckBlockHeader ( block , state , consensusParams , fCheckPOW ) )
2014-03-11 17:36:21 +01:00
return false ;
2014-07-12 00:02:35 +02:00
// Check the merkle root.
if ( fCheckMerkleRoot ) {
bool mutated ;
2015-11-17 17:35:44 +01:00
uint256 hashMerkleRoot2 = BlockMerkleRoot ( block , & mutated ) ;
2014-07-12 00:02:35 +02:00
if ( block . hashMerkleRoot ! = hashMerkleRoot2 )
2015-12-02 03:13:47 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txnmrklroot " , true , " hashMerkleRoot mismatch " ) ;
2014-07-12 00:02:35 +02: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 )
2015-12-02 03:13:47 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-duplicate " , true , " duplicate transaction " ) ;
2014-07-12 00:02:35 +02: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 18:54:50 +01:00
// Note that witness malleability is checked in ContextualCheckBlock, so no
// checks that use witness data may be performed here.
2014-07-12 00:02:35 +02:00
2010-08-29 18:58:15 +02:00
// Size limits
2017-06-17 02:18:42 +02:00
if ( block . vtx . empty ( ) | | block . vtx . size ( ) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT | | : : GetSerializeSize ( block , SER_NETWORK , PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS ) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT )
2015-12-02 03:13:47 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-blk-length " , false , " size limits failed " ) ;
2010-08-29 18:58:15 +02:00
// First transaction must be coinbase, the rest must not be
2016-11-11 02:26:00 +01:00
if ( block . vtx . empty ( ) | | ! block . vtx [ 0 ] - > IsCoinBase ( ) )
2015-12-02 03:13:47 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-cb-missing " , false , " first tx is not coinbase " ) ;
2013-06-24 04:14:11 +02:00
for ( unsigned int i = 1 ; i < block . vtx . size ( ) ; i + + )
2016-11-11 02:26:00 +01:00
if ( block . vtx [ i ] - > IsCoinBase ( ) )
2015-12-02 03:13:47 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-cb-multiple " , false , " more than one coinbase " ) ;
2010-08-29 18:58:15 +02:00
// Check transactions
2016-07-15 07:20:13 +02:00
for ( const auto & tx : block . vtx )
2018-09-17 22:13:37 +02:00
if ( ! CheckTransaction ( * tx , state , true ) )
2015-12-02 03:13:47 +01:00
return state . Invalid ( false , state . GetRejectCode ( ) , state . GetRejectReason ( ) ,
2016-11-11 02:26:00 +01:00
strprintf ( " Transaction check failed (tx hash %s) %s " , tx - > GetHash ( ) . ToString ( ) , state . GetDebugMessage ( ) ) ) ;
2010-08-29 18:58:15 +02:00
2012-04-23 20:14:03 +02:00
unsigned int nSigOps = 0 ;
2016-07-15 07:20:13 +02:00
for ( const auto & tx : block . vtx )
2011-10-03 19:05:43 +02:00
{
2016-11-11 02:26:00 +01:00
nSigOps + = GetLegacySigOpCount ( * tx ) ;
2011-10-03 19:05:43 +02:00
}
2016-01-03 18:54:50 +01:00
if ( nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST )
2015-12-02 03:13:47 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-blk-sigops " , false , " out-of-bounds SigOpCount " ) ;
2010-08-29 18:58:15 +02:00
2015-08-15 23:32:38 +02:00
if ( fCheckPOW & & fCheckMerkleRoot )
block . fChecked = true ;
2010-08-29 18:58:15 +02:00
return true ;
}
2015-11-06 01:42:38 +01:00
bool IsWitnessEnabled ( const CBlockIndex * pindexPrev , const Consensus : : Params & params )
{
LOCK ( cs_main ) ;
2018-03-09 15:03:40 +01:00
return ( VersionBitsState ( pindexPrev , params , Consensus : : DEPLOYMENT_SEGWIT , versionbitscache ) = = ThresholdState : : ACTIVE ) ;
2015-11-06 01:42:38 +01:00
}
2017-09-12 18:40:29 +02:00
bool IsNullDummyEnabled ( const CBlockIndex * pindexPrev , const Consensus : : Params & params )
{
LOCK ( cs_main ) ;
return ( VersionBitsState ( pindexPrev , params , Consensus : : DEPLOYMENT_SEGWIT , versionbitscache ) = = ThresholdState : : ACTIVE ) ;
}
2015-11-06 01:42:38 +01:00
// Compute at which vout of the block's coinbase transaction the witness
// commitment occurs, or -1 if not found.
static int GetWitnessCommitmentIndex ( const CBlock & block )
{
int commitpos = - 1 ;
2017-04-02 23:28:17 +02:00
if ( ! block . vtx . empty ( ) ) {
for ( size_t o = 0 ; o < block . vtx [ 0 ] - > vout . size ( ) ; o + + ) {
if ( block . vtx [ 0 ] - > vout [ o ] . scriptPubKey . size ( ) > = 38 & & block . vtx [ 0 ] - > vout [ o ] . scriptPubKey [ 0 ] = = OP_RETURN & & block . vtx [ 0 ] - > vout [ o ] . scriptPubKey [ 1 ] = = 0x24 & & block . vtx [ 0 ] - > vout [ o ] . scriptPubKey [ 2 ] = = 0xaa & & block . vtx [ 0 ] - > vout [ o ] . scriptPubKey [ 3 ] = = 0x21 & & block . vtx [ 0 ] - > vout [ o ] . scriptPubKey [ 4 ] = = 0xa9 & & block . vtx [ 0 ] - > vout [ o ] . scriptPubKey [ 5 ] = = 0xed ) {
commitpos = o ;
}
2015-11-06 01:42:38 +01:00
}
}
return commitpos ;
}
void UpdateUncommittedBlockStructures ( CBlock & block , const CBlockIndex * pindexPrev , const Consensus : : Params & consensusParams )
{
int commitpos = GetWitnessCommitmentIndex ( block ) ;
static const std : : vector < unsigned char > nonce ( 32 , 0x00 ) ;
2016-08-04 02:49:16 +02:00
if ( commitpos ! = - 1 & & IsWitnessEnabled ( pindexPrev , consensusParams ) & & ! block . vtx [ 0 ] - > HasWitness ( ) ) {
2016-11-11 02:26:00 +01:00
CMutableTransaction tx ( * block . vtx [ 0 ] ) ;
2016-08-04 02:49:16 +02:00
tx . vin [ 0 ] . scriptWitness . stack . resize ( 1 ) ;
tx . vin [ 0 ] . scriptWitness . stack [ 0 ] = nonce ;
2016-11-11 02:34:17 +01:00
block . vtx [ 0 ] = MakeTransactionRef ( std : : move ( tx ) ) ;
2015-11-06 01:42:38 +01:00
}
}
std : : vector < unsigned char > GenerateCoinbaseCommitment ( CBlock & block , const CBlockIndex * pindexPrev , const Consensus : : Params & consensusParams )
{
std : : vector < unsigned char > commitment ;
int commitpos = GetWitnessCommitmentIndex ( block ) ;
std : : vector < unsigned char > ret ( 32 , 0x00 ) ;
2016-11-18 21:15:01 +01:00
if ( consensusParams . vDeployments [ Consensus : : DEPLOYMENT_SEGWIT ] . nTimeout ! = 0 ) {
2015-11-06 01:42:38 +01:00
if ( commitpos = = - 1 ) {
2017-08-07 07:36:37 +02:00
uint256 witnessroot = BlockWitnessMerkleRoot ( block , nullptr ) ;
2017-03-28 17:37:06 +02:00
CHash256 ( ) . Write ( witnessroot . begin ( ) , 32 ) . Write ( ret . data ( ) , 32 ) . Finalize ( witnessroot . begin ( ) ) ;
2015-11-06 01:42:38 +01:00
CTxOut out ;
out . nValue = 0 ;
out . scriptPubKey . resize ( 38 ) ;
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 ( ) ) ;
2016-11-12 01:23:17 +01:00
CMutableTransaction tx ( * block . vtx [ 0 ] ) ;
tx . vout . push_back ( out ) ;
block . vtx [ 0 ] = MakeTransactionRef ( std : : move ( tx ) ) ;
2015-11-06 01:42:38 +01:00
}
}
UpdateUncommittedBlockStructures ( block , pindexPrev , consensusParams ) ;
return commitment ;
}
2017-04-21 20:45:30 +02:00
/** Context-dependent validity checks.
* By " context " , we mean only the previous block headers , but not the UTXO
2017-11-20 20:13:12 +01: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 !
*/
2017-08-10 02:48:38 +02:00
static bool ContextualCheckBlockHeader ( const CBlockHeader & block , CValidationState & state , const CChainParams & params , const CBlockIndex * pindexPrev , int64_t nAdjustedTime )
2015-03-30 13:48:04 +02:00
{
2017-08-07 07:36:37 +02:00
assert ( pindexPrev ! = nullptr ) ;
2016-09-05 08:55:04 +02:00
const int nHeight = pindexPrev - > nHeight + 1 ;
2017-08-10 02:48:38 +02:00
2014-10-20 01:09:50 +02:00
// Check proof of work
2017-08-10 02:48:38 +02:00
const Consensus : : Params & consensusParams = params . GetConsensus ( ) ;
2015-04-23 00:19:11 +02:00
if ( block . nBits ! = GetNextWorkRequired ( pindexPrev , & block , consensusParams ) )
2015-12-02 03:13:47 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-diffbits " , false , " incorrect proof of work " ) ;
2014-10-20 01:09:50 +02:00
2017-08-10 02:48:38 +02: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
// MapBlockIndex.
CBlockIndex * pcheckpoint = Checkpoints : : GetLastCheckpoint ( params . Checkpoints ( ) ) ;
if ( pcheckpoint & & nHeight < pcheckpoint - > nHeight )
return state . DoS ( 100 , error ( " %s: forked chain older than last checkpoint (height %d) " , __func__ , nHeight ) , REJECT_CHECKPOINT , " bad-fork-prior-to-checkpoint " ) ;
}
2014-10-20 01:09:50 +02:00
// Check timestamp against prev
if ( block . GetBlockTime ( ) < = pindexPrev - > GetMedianTimePast ( ) )
2015-12-02 03:13:47 +01:00
return state . Invalid ( false , REJECT_INVALID , " time-too-old " , " block's timestamp is too early " ) ;
2015-01-20 00:37:21 +01:00
2016-06-09 01:12:52 +02:00
// Check timestamp
2017-03-02 18:20:34 +01:00
if ( block . GetBlockTime ( ) > nAdjustedTime + MAX_FUTURE_BLOCK_TIME )
2016-06-09 01:12:52 +02:00
return state . Invalid ( false , REJECT_INVALID , " time-too-new " , " block timestamp too far in the future " ) ;
2015-12-02 03:13:47 +01:00
// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
2016-07-22 01:27:55 +02:00
// check for version 2, 3 and 4 upgrades
if ( ( block . nVersion < 2 & & nHeight > = consensusParams . BIP34Height ) | |
( block . nVersion < 3 & & nHeight > = consensusParams . BIP66Height ) | |
( block . nVersion < 4 & & nHeight > = consensusParams . BIP65Height ) )
return state . Invalid ( false , REJECT_OBSOLETE , strprintf ( " bad-version(0x%08x) " , block . nVersion ) ,
strprintf ( " rejected nVersion=0x%08x block " , block . nVersion ) ) ;
2015-01-20 00:37:21 +01:00
2014-10-20 01:09:50 +02:00
return true ;
}
2017-11-20 20:13:12 +01: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 !
*/
2017-04-21 20:45:30 +02:00
static bool ContextualCheckBlock ( const CBlock & block , CValidationState & state , const Consensus : : Params & consensusParams , const CBlockIndex * pindexPrev )
2014-10-20 01:09:50 +02:00
{
2017-08-07 07:36:37 +02:00
const int nHeight = pindexPrev = = nullptr ? 0 : pindexPrev - > nHeight + 1 ;
2014-10-20 01:09:50 +02:00
2016-02-16 17:33:31 +01:00
// Start enforcing BIP113 (Median Time Past) using versionbits logic.
int nLockTimeFlags = 0 ;
2018-03-09 15:03:40 +01:00
if ( VersionBitsState ( pindexPrev , consensusParams , Consensus : : DEPLOYMENT_CSV , versionbitscache ) = = ThresholdState : : ACTIVE ) {
2016-02-16 17:33:31 +01:00
nLockTimeFlags | = LOCKTIME_MEDIAN_TIME_PAST ;
}
int64_t nLockTimeCutoff = ( nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST )
? pindexPrev - > GetMedianTimePast ( )
: block . GetBlockTime ( ) ;
2014-10-20 01:09:50 +02:00
// Check that all transactions are finalized
2016-07-15 07:20:13 +02:00
for ( const auto & tx : block . vtx ) {
2016-11-11 02:26:00 +01:00
if ( ! IsFinalTx ( * tx , nHeight , nLockTimeCutoff ) ) {
2015-12-02 03:13:47 +01:00
return state . DoS ( 10 , false , REJECT_INVALID , " bad-txns-nonfinal " , false , " non-final transaction " ) ;
2014-10-20 01:09:50 +02:00
}
2015-11-03 18:12:36 +01:00
}
2014-10-20 01:09:50 +02:00
2016-07-22 01:27:55 +02:00
// Enforce rule that the coinbase starts with serialized block height
if ( nHeight > = consensusParams . BIP34Height )
2014-10-20 01:09:50 +02:00
{
CScript expect = CScript ( ) < < nHeight ;
2016-11-11 02:26:00 +01:00
if ( block . vtx [ 0 ] - > vin [ 0 ] . scriptSig . size ( ) < expect . size ( ) | |
! std : : equal ( expect . begin ( ) , expect . end ( ) , block . vtx [ 0 ] - > vin [ 0 ] . scriptSig . begin ( ) ) ) {
2015-12-02 03:13:47 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-cb-height " , false , " block height mismatch in coinbase " ) ;
2014-10-20 01:09:50 +02:00
}
}
2015-11-06 01:42:38 +01: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 23:24:17 +02:00
// * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness reserved value (unconstrained).
2015-11-06 01:42:38 +01: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 23:24:17 +02:00
// {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are
2015-11-06 01:42:38 +01:00
// multiple, the last one is used.
bool fHaveWitness = false ;
2018-03-09 15:03:40 +01:00
if ( VersionBitsState ( pindexPrev , consensusParams , Consensus : : DEPLOYMENT_SEGWIT , versionbitscache ) = = ThresholdState : : ACTIVE ) {
2015-11-06 01:42:38 +01:00
int commitpos = GetWitnessCommitmentIndex ( block ) ;
if ( commitpos ! = - 1 ) {
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-04 02:49:16 +02:00
if ( block . vtx [ 0 ] - > vin [ 0 ] . scriptWitness . stack . size ( ) ! = 1 | | block . vtx [ 0 ] - > vin [ 0 ] . scriptWitness . stack [ 0 ] . size ( ) ! = 32 ) {
2018-03-26 23:24:17 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-witness-nonce-size " , true , strprintf ( " %s : invalid witness reserved value size " , __func__ ) ) ;
2015-11-06 01:42:38 +01:00
}
2016-08-04 02:49:16 +02:00
CHash256 ( ) . Write ( hashWitness . begin ( ) , 32 ) . Write ( & block . vtx [ 0 ] - > vin [ 0 ] . scriptWitness . stack [ 0 ] [ 0 ] , 32 ) . Finalize ( hashWitness . begin ( ) ) ;
2016-11-11 02:26:00 +01:00
if ( memcmp ( hashWitness . begin ( ) , & block . vtx [ 0 ] - > vout [ commitpos ] . scriptPubKey [ 6 ] , 32 ) ) {
2016-07-14 17:02:59 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-witness-merkle-match " , true , strprintf ( " %s : witness merkle commitment mismatch " , __func__ ) ) ;
2015-11-06 01:42:38 +01: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 09:42:14 +02:00
for ( const auto & tx : block . vtx ) {
if ( tx - > HasWitness ( ) ) {
2016-07-14 17:02:59 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " unexpected-witness " , true , strprintf ( " %s : unexpected witness data found " , __func__ ) ) ;
2015-11-06 01:42:38 +01:00
}
}
}
2018-03-26 23:24:17 +02:00
// After the coinbase witness reserved value and commitment are verified,
2016-07-18 19:28:26 +02: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 18:54:50 +01: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 19:28:26 +02:00
if ( GetBlockWeight ( block ) > MAX_BLOCK_WEIGHT ) {
2016-07-14 17:02:59 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-blk-weight " , false , strprintf ( " %s : weight limit failed " , __func__ ) ) ;
2016-01-03 18:54:50 +01:00
}
2014-10-20 01:09:50 +02:00
return true ;
}
2017-12-04 15:34:46 +01:00
bool CChainState : : AcceptBlockHeader ( const CBlockHeader & block , CValidationState & state , const CChainParams & chainparams , CBlockIndex * * ppindex )
2010-08-29 18:58:15 +02:00
{
2014-04-15 12:43:17 +02:00
AssertLockHeld ( cs_main ) ;
2010-08-29 18:58:15 +02:00
// Check for duplicate
2013-06-24 04:27:02 +02:00
uint256 hash = block . GetHash ( ) ;
2014-09-04 02:02:44 +02:00
BlockMap : : iterator miSelf = mapBlockIndex . find ( hash ) ;
2017-08-07 07:36:37 +02:00
CBlockIndex * pindex = nullptr ;
2015-06-17 21:23:53 +02:00
if ( hash ! = chainparams . GetConsensus ( ) . hashGenesisBlock ) {
if ( miSelf ! = mapBlockIndex . end ( ) ) {
// Block header is already known.
pindex = miSelf - > second ;
if ( ppindex )
* ppindex = pindex ;
if ( pindex - > nStatus & BLOCK_FAILED_MASK )
2016-04-26 22:22:59 +02:00
return state . Invalid ( error ( " %s: block %s is marked invalid " , __func__ , hash . ToString ( ) ) , 0 , " duplicate " ) ;
2015-06-17 21:23:53 +02:00
return true ;
}
2014-11-20 08:28:19 +01:00
2016-06-09 01:12:52 +02:00
if ( ! CheckBlockHeader ( block , state , chainparams . GetConsensus ( ) ) )
2015-12-02 03:13:47 +01:00
return error ( " %s: Consensus::CheckBlockHeader: %s, %s " , __func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
2015-06-17 21:23:53 +02:00
// Get prev block index
2017-08-07 07:36:37 +02:00
CBlockIndex * pindexPrev = nullptr ;
2014-09-04 02:02:44 +02:00
BlockMap : : iterator mi = mapBlockIndex . find ( block . hashPrevBlock ) ;
2012-11-10 14:26:34 +01:00
if ( mi = = mapBlockIndex . end ( ) )
2017-03-31 20:18:15 +02:00
return state . DoS ( 10 , error ( " %s: prev block not found " , __func__ ) , 0 , " prev-blk-not-found " ) ;
2012-11-10 14:26:34 +01:00
pindexPrev = ( * mi ) . second ;
2014-12-11 13:35:14 +01:00
if ( pindexPrev - > nStatus & BLOCK_FAILED_MASK )
2015-01-08 11:44:25 +01:00
return state . DoS ( 100 , error ( " %s: prev block invalid " , __func__ ) , REJECT_INVALID , " bad-prevblk " ) ;
2017-08-10 02:48:38 +02:00
if ( ! ContextualCheckBlockHeader ( block , state , chainparams , pindexPrev , GetAdjustedTime ( ) ) )
2015-12-02 03:13:47 +01:00
return error ( " %s: Consensus::ContextualCheckBlockHeader: %s, %s " , __func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
2017-10-19 22:55:31 +02:00
2018-04-17 23:15:20 +02:00
// If the previous block index isn't valid, determine if it descends from any block which
2018-06-05 00:25:13 +02:00
// has been found invalid (m_failed_blocks), then mark pindexPrev and any blocks
2018-04-17 23:15:20 +02:00
// between them as failed.
2017-10-19 22:55:31 +02:00
if ( ! pindexPrev - > IsValid ( BLOCK_VALID_SCRIPTS ) ) {
2018-04-18 13:57:18 +02:00
for ( const CBlockIndex * failedit : m_failed_blocks ) {
2017-10-19 22:55:31 +02: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 ;
setDirtyBlockIndex . insert ( invalid_walk ) ;
invalid_walk = invalid_walk - > pprev ;
}
return state . DoS ( 100 , error ( " %s: prev block invalid " , __func__ ) , REJECT_INVALID , " bad-prevblk " ) ;
}
}
}
2015-06-17 21:23:53 +02:00
}
2017-08-07 07:36:37 +02:00
if ( pindex = = nullptr )
2014-03-13 03:48:27 +01:00
pindex = AddToBlockIndex ( block ) ;
if ( ppindex )
* ppindex = pindex ;
2016-10-02 18:45:24 +02:00
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
2014-03-13 03:48:27 +01:00
return true ;
}
2016-10-02 18:22:05 +02:00
// Exposed wrapper for AcceptBlockHeader
2017-10-26 20:54:33 +02:00
bool ProcessNewBlockHeaders ( const std : : vector < CBlockHeader > & headers , CValidationState & state , const CChainParams & chainparams , const CBlockIndex * * ppindex , CBlockHeader * first_invalid )
2016-10-02 18:22:05 +02:00
{
2017-10-26 20:54:33 +02:00
if ( first_invalid ! = nullptr ) first_invalid - > SetNull ( ) ;
2016-10-02 18:22:05 +02:00
{
LOCK ( cs_main ) ;
for ( const CBlockHeader & header : headers ) {
2017-08-07 07:36:37 +02:00
CBlockIndex * pindex = nullptr ; // Use a temp pindex instead of ppindex to avoid a const_cast
2017-12-04 15:34:46 +01:00
if ( ! g_chainstate . AcceptBlockHeader ( header , state , chainparams , & pindex ) ) {
2017-10-26 20:54:33 +02:00
if ( first_invalid ) * first_invalid = header ;
2016-10-02 18:22:05 +02:00
return false ;
}
2017-01-11 23:47:52 +01:00
if ( ppindex ) {
* ppindex = pindex ;
}
2016-10-02 18:22:05 +02:00
}
}
NotifyHeaderTip ( ) ;
return true ;
}
2017-08-07 07:36:37 +02:00
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
2017-04-26 03:35:02 +02:00
static CDiskBlockPos SaveBlockToDisk ( const CBlock & block , int nHeight , const CChainParams & chainparams , const CDiskBlockPos * dbp ) {
unsigned int nBlockSize = : : GetSerializeSize ( block , SER_DISK , CLIENT_VERSION ) ;
CDiskBlockPos blockPos ;
if ( dbp ! = nullptr )
blockPos = * dbp ;
if ( ! FindBlockPos ( blockPos , nBlockSize + 8 , nHeight , block . GetBlockTime ( ) , dbp ! = nullptr ) ) {
error ( " %s: FindBlockPos failed " , __func__ ) ;
return CDiskBlockPos ( ) ;
}
if ( dbp = = nullptr ) {
if ( ! WriteBlockToDisk ( block , blockPos , chainparams . MessageStart ( ) ) ) {
AbortNode ( " Failed to write block " ) ;
return CDiskBlockPos ( ) ;
}
}
return blockPos ;
}
2017-08-07 07:36:37 +02:00
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
2017-12-04 15:34:46 +01:00
bool CChainState : : AcceptBlock ( const std : : shared_ptr < const CBlock > & pblock , CValidationState & state , const CChainParams & chainparams , CBlockIndex * * ppindex , bool fRequested , const CDiskBlockPos * dbp , bool * fNewBlock )
2014-03-13 03:48:27 +01:00
{
2016-12-19 08:24:11 +01:00
const CBlock & block = * pblock ;
2016-05-22 07:55:15 +02:00
if ( fNewBlock ) * fNewBlock = false ;
2014-03-13 03:48:27 +01:00
AssertLockHeld ( cs_main ) ;
2017-08-07 07:36:37 +02:00
CBlockIndex * pindexDummy = nullptr ;
2016-04-20 15:45:41 +02:00
CBlockIndex * & pindex = ppindex ? * ppindex : pindexDummy ;
2014-03-13 03:48:27 +01:00
2015-11-10 19:28:56 +01:00
if ( ! AcceptBlockHeader ( block , state , chainparams , & pindex ) )
2014-03-13 03:48:27 +01:00
return false ;
2015-04-09 19:21:11 +02: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 21:17:36 +02:00
// advance our tip, and isn't too many blocks ahead.
2015-04-09 19:21:11 +02:00
bool fAlreadyHave = pindex - > nStatus & BLOCK_HAVE_DATA ;
2017-10-11 22:04:13 +02:00
bool fHasMoreOrSameWork = ( chainActive . Tip ( ) ? pindex - > nChainWork > = chainActive . Tip ( ) - > nChainWork : true ) ;
2015-06-02 21:17:36 +02: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.
2015-07-11 12:52:35 +02:00
bool fTooFarAhead = ( pindex - > nHeight > int ( chainActive . Height ( ) + MIN_BLOCKS_TO_KEEP ) ) ;
2015-04-09 19:21:11 +02:00
2016-10-02 05:44:40 +02:00
// TODO: Decouple this function from the block download logic by removing fRequested
2017-03-21 19:49:08 +01:00
// This requires some new chain data structure to efficiently look up if a
2016-10-02 05:44:40 +02:00
// block is in a chain leading to a candidate for best tip, despite not
// being such a candidate itself.
2015-04-09 19:21:11 +02: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 22:04:13 +02: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 20:11:43 +02: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-12 00:02:35 +02:00
}
2017-02-13 23:28:39 +01:00
if ( ! CheckBlock ( block , state , chainparams . GetConsensus ( ) ) | |
2016-07-17 05:49:46 +02:00
! ContextualCheckBlock ( block , state , chainparams . GetConsensus ( ) , pindex - > pprev ) ) {
2014-07-15 03:24:21 +02:00
if ( state . IsInvalid ( ) & & ! state . CorruptionPossible ( ) ) {
2014-03-13 03:48:27 +01:00
pindex - > nStatus | = BLOCK_FAILED_VALID ;
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 11:38:35 +01:00
setDirtyBlockIndex . insert ( pindex ) ;
2014-03-13 03:48:27 +01:00
}
2015-12-02 03:13:47 +01:00
return error ( " %s: %s " , __func__ , FormatStateMessage ( state ) ) ;
2014-03-13 03:48:27 +01:00
}
2016-12-19 08:26:20 +01: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)
if ( ! IsInitialBlockDownload ( ) & & chainActive . Tip ( ) = = pindex - > pprev )
GetMainSignals ( ) . NewPoWValidBlock ( pindex , pblock ) ;
2010-08-29 18:58:15 +02:00
// Write block to history file
2018-06-11 21:13:04 +02:00
if ( fNewBlock ) * fNewBlock = true ;
2013-01-29 01:44:19 +01:00
try {
2017-04-26 03:35:02 +02:00
CDiskBlockPos blockPos = SaveBlockToDisk ( block , pindex - > nHeight , chainparams , dbp ) ;
if ( blockPos . IsNull ( ) ) {
state . Error ( strprintf ( " %s: Failed to find position to write new block to disk " , __func__ ) ) ;
return false ;
}
2018-06-07 17:10:48 +02:00
ReceivedBlockTransactions ( block , pindex , blockPos , chainparams . GetConsensus ( ) ) ;
2014-12-07 13:29:06 +01:00
} catch ( const std : : runtime_error & e ) {
2015-01-17 00:57:14 +01:00
return AbortNode ( state , std : : string ( " System error: " ) + e . what ( ) ) ;
2013-01-29 01:44:19 +01:00
}
2010-08-29 18:58:15 +02:00
2017-11-06 11:21:15 +01:00
FlushStateToDisk ( chainparams , 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 20:27:44 +01:00
2017-12-04 15:34:46 +01:00
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
2010-08-29 18:58:15 +02:00
return true ;
}
2016-12-04 09:23:17 +01:00
bool ProcessNewBlock ( const CChainParams & chainparams , const std : : shared_ptr < const CBlock > pblock , bool fForceProcessing , bool * fNewBlock )
2010-08-29 18:58:15 +02:00
{
2017-12-05 00:25:57 +01:00
AssertLockNotHeld ( cs_main ) ;
2010-08-29 18:58:15 +02:00
{
2017-08-07 07:36:37 +02:00
CBlockIndex * pindex = nullptr ;
2016-10-02 17:04:49 +02:00
if ( fNewBlock ) * fNewBlock = false ;
2016-10-27 22:30:17 +02:00
CValidationState state ;
2017-02-13 23:28:39 +01:00
// Ensure that CheckBlock() passes before calling AcceptBlock, as
// belt-and-suspenders.
bool ret = CheckBlock ( * pblock , state , chainparams . GetConsensus ( ) ) ;
LOCK ( cs_main ) ;
if ( ret ) {
// Store to disk
2017-12-04 15:34:46 +01:00
ret = g_chainstate . AcceptBlock ( pblock , state , chainparams , & pindex , fForceProcessing , nullptr , fNewBlock ) ;
2017-02-13 23:28:39 +01:00
}
2016-10-27 22:30:17 +02:00
if ( ! ret ) {
GetMainSignals ( ) . BlockChecked ( * pblock , state ) ;
2018-04-18 15:58:13 +02:00
return error ( " %s: AcceptBlock FAILED (%s) " , __func__, FormatStateMessage(state)) ;
2016-10-27 22:30:17 +02:00
}
2014-05-07 17:10:35 +02:00
}
2016-04-28 16:18:45 +02:00
NotifyHeaderTip ( ) ;
2016-10-27 22:30:17 +02:00
CValidationState state ; // Only used to report errors, not invalidity - ignore it
2018-08-06 21:40:20 +02:00
if ( ! g_chainstate . ActivateBestChain ( state , chainparams , pblock ) ) {
2018-04-18 15:58:13 +02:00
return error ( " %s: ActivateBestChain failed (%s) " , __func__, FormatStateMessage(state)) ;
2018-08-06 21:40:20 +02:00
}
2014-05-07 17:10:35 +02:00
2010-08-29 18:58:15 +02:00
return true ;
}
2015-04-20 00:17:11 +02:00
bool TestBlockValidity ( CValidationState & state , const CChainParams & chainparams , const CBlock & block , CBlockIndex * pindexPrev , bool fCheckPOW , bool fCheckMerkleRoot )
2014-10-20 04:10:03 +02:00
{
AssertLockHeld ( cs_main ) ;
2015-03-30 13:48:04 +02:00
assert ( pindexPrev & & pindexPrev = = chainActive . Tip ( ) ) ;
2017-08-09 17:08:22 +02:00
CCoinsViewCache viewNew ( pcoinsTip . get ( ) ) ;
2018-08-06 21:40:20 +02:00
CClaimTrieCache trieCache ( pclaimTrie ) ;
2017-12-12 19:30:22 +01:00
uint256 block_hash ( block . GetHash ( ) ) ;
2014-10-20 04:10:03 +02:00
CBlockIndex indexDummy ( block ) ;
indexDummy . pprev = pindexPrev ;
indexDummy . nHeight = pindexPrev - > nHeight + 1 ;
2017-12-12 19:30:22 +01:00
indexDummy . phashBlock = & block_hash ;
2014-10-20 04:10:03 +02:00
// NOTE: CheckBlockHeader is called by CheckBlock
2017-08-10 02:48:38 +02:00
if ( ! ContextualCheckBlockHeader ( block , state , chainparams , pindexPrev , GetAdjustedTime ( ) ) )
2015-12-02 03:13:47 +01:00
return error ( " %s: Consensus::ContextualCheckBlockHeader: %s " , __func__ , FormatStateMessage ( state ) ) ;
2016-06-09 01:12:52 +02:00
if ( ! CheckBlock ( block , state , chainparams . GetConsensus ( ) , fCheckPOW , fCheckMerkleRoot ) )
2015-12-02 03:13:47 +01:00
return error ( " %s: Consensus::CheckBlock: %s " , __func__ , FormatStateMessage ( state ) ) ;
2016-07-17 05:49:46 +02:00
if ( ! ContextualCheckBlock ( block , state , chainparams . GetConsensus ( ) , pindexPrev ) )
2015-12-02 03:13:47 +01:00
return error ( " %s: Consensus::ContextualCheckBlock: %s " , __func__ , FormatStateMessage ( state ) ) ;
2018-08-06 21:40:20 +02:00
if ( ! g_chainstate . ConnectBlock ( block , state , & indexDummy , viewNew , trieCache , chainparams , true ) )
2014-10-20 04:10:03 +02:00
return false ;
assert ( state . IsValid ( ) ) ;
return true ;
}
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 20:27:44 +01:00
/**
* BLOCK PRUNING CODE
*/
/* Calculate the amount of disk space the block & undo files currently use */
2017-09-21 01:52:20 +02:00
uint64_t CalculateCurrentUsage ( )
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 20:27:44 +01:00
{
2017-09-21 01:52:20 +02:00
LOCK ( cs_LastBlockFile ) ;
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 20:27:44 +01:00
uint64_t retval = 0 ;
2017-06-02 03:18:57 +02:00
for ( const CBlockFileInfo & file : vinfoBlockFile ) {
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 20:27:44 +01:00
retval + = file . nSize + file . nUndoSize ;
}
return retval ;
}
/* Prune a block file (modify associated database entries)*/
void PruneOneBlockFile ( const int fileNumber )
{
2017-09-21 01:52:20 +02:00
LOCK ( cs_LastBlockFile ) ;
2017-06-04 22:02:43 +02:00
for ( const auto & entry : mapBlockIndex ) {
CBlockIndex * pindex = entry . second ;
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 20:27:44 +01:00
if ( pindex - > nFile = = fileNumber ) {
pindex - > nStatus & = ~ BLOCK_HAVE_DATA ;
pindex - > nStatus & = ~ BLOCK_HAVE_UNDO ;
pindex - > nFile = 0 ;
pindex - > nDataPos = 0 ;
pindex - > nUndoPos = 0 ;
setDirtyBlockIndex . insert ( pindex ) ;
// Prune from mapBlocksUnlinked -- any block we prune would have
// to be downloaded again in order to consider its chain, at which
// point it would be considered as a candidate for
// mapBlocksUnlinked or setBlockIndexCandidates.
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > range = mapBlocksUnlinked . equal_range ( pindex - > pprev ) ;
while ( range . first ! = range . second ) {
2016-09-02 18:19:01 +02:00
std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator _it = range . first ;
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 20:27:44 +01:00
range . first + + ;
2016-09-02 18:19:01 +02:00
if ( _it - > second = = pindex ) {
mapBlocksUnlinked . erase ( _it ) ;
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 20:27:44 +01:00
}
}
}
}
vinfoBlockFile [ fileNumber ] . SetNull ( ) ;
setDirtyFileInfo . insert ( fileNumber ) ;
}
2017-02-16 16:49:03 +01:00
void UnlinkPrunedFiles ( const std : : set < int > & setFilesToPrune )
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 20:27:44 +01:00
{
2017-01-27 09:43:41 +01:00
for ( std : : set < int > : : iterator it = setFilesToPrune . begin ( ) ; it ! = setFilesToPrune . end ( ) ; + + it ) {
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 20:27:44 +01:00
CDiskBlockPos pos ( * it , 0 ) ;
2017-03-01 17:05:50 +01:00
fs : : remove ( GetBlockPosFilename ( pos , " blk " ) ) ;
fs : : remove ( GetBlockPosFilename ( pos , " rev " ) ) ;
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 20:27:44 +01:00
LogPrintf ( " Prune: %s deleted blk/rev (%05u) \n " , __func__ , * it ) ;
}
}
2016-11-29 18:39:19 +01:00
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
2017-04-21 20:45:30 +02:00
static void FindFilesToPruneManual ( std : : set < int > & setFilesToPrune , int nManualPruneHeight )
2016-11-29 18:39:19 +01:00
{
assert ( fPruneMode & & nManualPruneHeight > 0 ) ;
LOCK2 ( cs_main , cs_LastBlockFile ) ;
2017-08-07 07:36:37 +02:00
if ( chainActive . Tip ( ) = = nullptr )
2016-11-29 18:39:19 +01:00
return ;
// last block to prune is the lesser of (user-specified height, MIN_BLOCKS_TO_KEEP from the tip)
2017-01-27 09:43:41 +01:00
unsigned int nLastBlockWeCanPrune = std : : min ( ( unsigned ) nManualPruneHeight , chainActive . Tip ( ) - > nHeight - MIN_BLOCKS_TO_KEEP ) ;
2016-11-29 18:39:19 +01:00
int count = 0 ;
for ( int fileNumber = 0 ; fileNumber < nLastBlockFile ; fileNumber + + ) {
if ( vinfoBlockFile [ fileNumber ] . nSize = = 0 | | vinfoBlockFile [ fileNumber ] . nHeightLast > nLastBlockWeCanPrune )
continue ;
PruneOneBlockFile ( fileNumber ) ;
setFilesToPrune . insert ( fileNumber ) ;
count + + ;
}
LogPrintf ( " Prune (Manual): prune_height=%d removed %d blk/rev pairs \n " , nLastBlockWeCanPrune , count ) ;
}
/* This function is called from the RPC code for pruneblockchain */
void PruneBlockFilesManual ( int nManualPruneHeight )
{
CValidationState state ;
2017-04-21 20:45:30 +02:00
const CChainParams & chainparams = Params ( ) ;
2018-04-18 15:58:13 +02:00
if ( ! FlushStateToDisk ( chainparams , state , FlushStateMode : : NONE , nManualPruneHeight ) ) {
LogPrintf ( " %s: failed to flush state (%s) \n " , __func__ , FormatStateMessage ( state ) ) ;
}
2016-11-29 18:39:19 +01:00
}
2017-04-21 20:45:30 +02:00
/**
* Prune block and undo files ( blk ? ? ? . dat and undo ? ? ? . dat ) so that the disk space used is less than a user - defined target .
* The user sets the target ( in MB ) on the command line or in config file . This will be run on startup and whenever new
* space is allocated in a block or undo file , staying below the target . Changing back to unpruned requires a reindex
* ( which in this case means the blockchain must be re - downloaded . )
*
* Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set .
* Block and undo files are deleted in lock - step ( when blk00003 . dat is deleted , so is rev00003 . dat . )
* Pruning cannot take place until the longest chain is at least a certain length ( 100000 on mainnet , 1000 on testnet , 1000 on regtest ) .
* Pruning will never delete a block within a defined distance ( currently 288 ) from the active chain ' s tip .
* The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files .
* A db flag records the fact that at least some block files have been pruned .
*
* @ param [ out ] setFilesToPrune The set of file indices that can be unlinked will be returned
*/
static void FindFilesToPrune ( std : : set < int > & setFilesToPrune , uint64_t nPruneAfterHeight )
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 20:27:44 +01:00
{
LOCK2 ( cs_main , cs_LastBlockFile ) ;
2017-08-07 07:36:37 +02:00
if ( chainActive . Tip ( ) = = nullptr | | nPruneTarget = = 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 20:27:44 +01:00
return ;
}
2015-11-27 15:12:08 +01:00
if ( ( uint64_t ) chainActive . Tip ( ) - > nHeight < = nPruneAfterHeight ) {
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 20:27:44 +01:00
return ;
}
2015-04-23 15:40:21 +02:00
unsigned int nLastBlockWeCanPrune = chainActive . Tip ( ) - > nHeight - MIN_BLOCKS_TO_KEEP ;
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 20:27:44 +01:00
uint64_t nCurrentUsage = CalculateCurrentUsage ( ) ;
// We don't check to prune until after we've allocated new space for files
// So we should leave a buffer under our target to account for another allocation
// before the next pruning.
uint64_t nBuffer = BLOCKFILE_CHUNK_SIZE + UNDOFILE_CHUNK_SIZE ;
uint64_t nBytesToPrune ;
int count = 0 ;
if ( nCurrentUsage + nBuffer > = nPruneTarget ) {
2017-11-11 10:05:36 +01:00
// On a prune event, the chainstate DB is flushed.
// To avoid excessive prune events negating the benefit of high dbcache
// values, we should not prune too rapidly.
// So when pruning in IBD, increase the buffer a bit to avoid a re-prune too soon.
if ( IsInitialBlockDownload ( ) ) {
// Since this is only relevant during IBD, we use a fixed 10%
nBuffer + = nPruneTarget / 10 ;
}
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 20:27:44 +01:00
for ( int fileNumber = 0 ; fileNumber < nLastBlockFile ; fileNumber + + ) {
nBytesToPrune = vinfoBlockFile [ fileNumber ] . nSize + vinfoBlockFile [ fileNumber ] . nUndoSize ;
if ( vinfoBlockFile [ fileNumber ] . nSize = = 0 )
continue ;
if ( nCurrentUsage + nBuffer < nPruneTarget ) // are we below our target?
break ;
2015-06-02 21:24:53 +02:00
// don't prune files that could have a block within MIN_BLOCKS_TO_KEEP of the main chain's tip but keep scanning
2015-04-23 15:40:21 +02:00
if ( vinfoBlockFile [ fileNumber ] . nHeightLast > nLastBlockWeCanPrune )
2015-06-02 21:24:53 +02:00
continue ;
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 20:27:44 +01:00
PruneOneBlockFile ( fileNumber ) ;
// Queue up the files for removal
setFilesToPrune . insert ( fileNumber ) ;
nCurrentUsage - = nBytesToPrune ;
count + + ;
}
}
2016-12-25 21:19:40 +01:00
LogPrint ( BCLog : : PRUNE , " Prune: target=%dMiB actual=%dMiB diff=%dMiB max_prune_height=%d removed %d blk/rev pairs \n " ,
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 20:27:44 +01:00
nPruneTarget / 1024 / 1024 , nCurrentUsage / 1024 / 1024 ,
( ( int64_t ) nPruneTarget - ( int64_t ) nCurrentUsage ) / 1024 / 1024 ,
2015-04-23 15:40:21 +02:00
nLastBlockWeCanPrune , count ) ;
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 20:27:44 +01:00
}
2018-03-09 05:12:43 +01:00
bool CheckDiskSpace ( uint64_t nAdditionalBytes , bool blocks_dir )
2010-08-29 18:58:15 +02:00
{
2018-03-09 05:12:43 +01:00
uint64_t nFreeBytesAvailable = fs : : space ( blocks_dir ? GetBlocksDir ( ) : GetDataDir ( ) ) . available ;
2010-08-29 18:58:15 +02:00
2012-05-14 07:49:17 +02:00
// Check for nMinDiskSpace bytes (currently 50MB)
if ( nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes )
2014-10-02 22:17:57 +02:00
return AbortNode ( " Disk space is low! " , _ ( " Error: Disk space is low! " ) ) ;
2013-01-27 01:24:06 +01:00
2010-08-29 18:58:15 +02:00
return true ;
}
2017-04-21 20:45:30 +02:00
static FILE * OpenDiskFile ( const CDiskBlockPos & pos , const char * prefix , bool fReadOnly )
2012-09-05 03:40:26 +02: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 18:54:00 +02:00
if ( pos . IsNull ( ) )
2017-08-07 07:36:37 +02:00
return nullptr ;
2017-03-01 17:05:50 +01:00
fs : : path path = GetBlockPosFilename ( pos , prefix ) ;
fs : : create_directories ( path . parent_path ( ) ) ;
2017-11-21 20:35:06 +01:00
FILE * file = fsbridge : : fopen ( path , fReadOnly ? " rb " : " rb+ " ) ;
2012-08-13 19:11:05 +02:00
if ( ! file & & ! fReadOnly )
2017-03-01 17:28:39 +01:00
file = fsbridge : : fopen ( path , " wb+ " ) ;
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 18:54:00 +02:00
if ( ! file ) {
2014-01-16 16:15:27 +01:00
LogPrintf ( " Unable to open file %s \n " , path . string ( ) ) ;
2017-08-07 07:36:37 +02:00
return nullptr ;
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 18:54:00 +02:00
}
2012-08-13 19:11:05 +02:00
if ( pos . nPos ) {
if ( fseek ( file , pos . nPos , SEEK_SET ) ) {
2014-01-16 16:15:27 +01:00
LogPrintf ( " Unable to seek to position %u of %s \n " , pos . nPos , path . string ( ) ) ;
2012-08-13 19:11:05 +02:00
fclose ( file ) ;
2017-08-07 07:36:37 +02:00
return nullptr ;
2012-08-13 19:11:05 +02:00
}
}
2010-08-29 18:58:15 +02:00
return file ;
}
2012-08-13 19:11:05 +02:00
FILE * OpenBlockFile ( const CDiskBlockPos & pos , bool fReadOnly ) {
return OpenDiskFile ( pos , " blk " , fReadOnly ) ;
}
2017-04-21 20:45:30 +02:00
/** Open an undo file (rev?????.dat) */
static FILE * OpenUndoFile ( const CDiskBlockPos & pos , bool fReadOnly ) {
2012-08-13 19:11:05 +02:00
return OpenDiskFile ( pos , " rev " , fReadOnly ) ;
}
2017-03-01 17:05:50 +01:00
fs : : path GetBlockPosFilename ( const CDiskBlockPos & pos , const char * prefix )
2014-09-08 19:29:14 +02:00
{
2018-03-09 05:12:43 +01:00
return GetBlocksDir ( ) / strprintf ( " %s%05u.dat " , prefix , pos . nFile ) ;
2014-09-08 19:29:14 +02:00
}
2017-12-04 15:34:46 +01:00
CBlockIndex * CChainState : : InsertBlockIndex ( const uint256 & hash )
2012-09-03 21:14:03 +02:00
{
2018-01-12 00:32:32 +01:00
AssertLockHeld ( cs_main ) ;
2014-12-15 09:11:16 +01:00
if ( hash . IsNull ( ) )
2017-08-07 07:36:37 +02:00
return nullptr ;
2012-09-03 21:14:03 +02:00
// Return existing
2014-09-04 02:02:44 +02:00
BlockMap : : iterator mi = mapBlockIndex . find ( hash ) ;
2012-09-03 21:14:03 +02:00
if ( mi ! = mapBlockIndex . end ( ) )
return ( * mi ) . second ;
// Create new
CBlockIndex * pindexNew = new CBlockIndex ( ) ;
2017-01-27 09:43:41 +01:00
mi = mapBlockIndex . insert ( std : : make_pair ( hash , pindexNew ) ) . first ;
2012-09-03 21:14:03 +02:00
pindexNew - > phashBlock = & ( ( * mi ) . first ) ;
return pindexNew ;
}
2017-12-04 15:34:46 +01:00
bool CChainState : : LoadBlockIndex ( const Consensus : : Params & consensus_params , CBlockTreeDB & blocktree )
2012-09-03 21:14:03 +02:00
{
2018-06-05 00:25:13 +02:00
if ( ! blocktree . LoadBlockIndexGuts ( consensus_params , [ this ] ( const uint256 & hash ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) { return this - > InsertBlockIndex ( hash ) ; } ) )
2012-09-03 21:14:03 +02:00
return false ;
2013-03-09 18:02:57 +01:00
boost : : this_thread : : interruption_point ( ) ;
2012-09-03 21:14:03 +02:00
2013-03-28 23:51:50 +01:00
// Calculate nChainWork
2017-01-27 09:43:41 +01:00
std : : vector < std : : pair < int , CBlockIndex * > > vSortedByHeight ;
2012-09-03 21:14:03 +02:00
vSortedByHeight . reserve ( mapBlockIndex . size ( ) ) ;
2018-05-16 00:41:53 +02:00
for ( const std : : pair < const uint256 , CBlockIndex * > & item : mapBlockIndex )
2012-09-03 21:14:03 +02:00
{
CBlockIndex * pindex = item . second ;
2017-01-27 09:43:41 +01:00
vSortedByHeight . push_back ( std : : make_pair ( pindex - > nHeight , pindex ) ) ;
2012-09-03 21:14:03 +02:00
}
sort ( vSortedByHeight . begin ( ) , vSortedByHeight . end ( ) ) ;
2017-06-02 03:28:42 +02:00
for ( const std : : pair < int , CBlockIndex * > & item : vSortedByHeight )
2012-09-03 21:14:03 +02:00
{
CBlockIndex * pindex = item . second ;
2014-10-29 17:00:02 +01:00
pindex - > nChainWork = ( pindex - > pprev ? pindex - > pprev - > nChainWork : 0 ) + GetBlockProof ( * pindex ) ;
2017-01-08 05:05:14 +01:00
pindex - > nTimeMax = ( pindex - > pprev ? std : : max ( pindex - > pprev - > nTimeMax , pindex - > nTime ) : pindex - > nTime ) ;
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 20:27:44 +01:00
// We can link the chain of blocks for which we've received transactions at some point.
// Pruned nodes may have deleted the block.
if ( pindex - > nTx > 0 ) {
2014-07-12 00:02:35 +02:00
if ( pindex - > pprev ) {
if ( pindex - > pprev - > nChainTx ) {
pindex - > nChainTx = pindex - > pprev - > nChainTx + pindex - > nTx ;
} else {
pindex - > nChainTx = 0 ;
mapBlocksUnlinked . insert ( std : : make_pair ( pindex - > pprev , pindex ) ) ;
}
} else {
pindex - > nChainTx = pindex - > nTx ;
}
}
2017-10-19 22:55:31 +02:00
if ( ! ( pindex - > nStatus & BLOCK_FAILED_MASK ) & & pindex - > pprev & & ( pindex - > pprev - > nStatus & BLOCK_FAILED_MASK ) ) {
pindex - > nStatus | = BLOCK_FAILED_CHILD ;
setDirtyBlockIndex . insert ( pindex ) ;
}
2017-08-07 07:36:37 +02:00
if ( pindex - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & & ( pindex - > nChainTx | | pindex - > pprev = = nullptr ) )
2014-10-06 08:31:33 +02:00
setBlockIndexCandidates . insert ( pindex ) ;
2013-10-13 22:15:48 +02:00
if ( pindex - > nStatus & BLOCK_FAILED_MASK & & ( ! pindexBestInvalid | | pindex - > nChainWork > pindexBestInvalid - > nChainWork ) )
pindexBestInvalid = pindex ;
2014-06-25 00:56:47 +02:00
if ( pindex - > pprev )
pindex - > BuildSkip ( ) ;
2017-08-07 07:36:37 +02:00
if ( pindex - > IsValid ( BLOCK_VALID_TREE ) & & ( pindexBestHeader = = nullptr | | CBlockIndexWorkComparator ( ) ( pindexBestHeader , pindex ) ) )
2014-07-12 00:02:35 +02:00
pindexBestHeader = pindex ;
2012-09-03 21:14:03 +02:00
}
2017-12-04 15:34:46 +01:00
return true ;
}
2018-06-05 00:25:13 +02:00
bool static LoadBlockIndexDB ( const CChainParams & chainparams ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main )
2017-12-04 15:34:46 +01:00
{
if ( ! g_chainstate . LoadBlockIndex ( chainparams . GetConsensus ( ) , * pblocktree ) )
return false ;
2012-09-03 21:14:03 +02:00
// Load block file info
pblocktree - > ReadLastBlockFile ( nLastBlockFile ) ;
2014-09-25 08:21:21 +02:00
vinfoBlockFile . resize ( nLastBlockFile + 1 ) ;
2014-10-22 01:17:13 +02:00
LogPrintf ( " %s: last block file = %i \n " , __func__ , nLastBlockFile ) ;
2014-09-25 08:21:21 +02:00
for ( int nFile = 0 ; nFile < = nLastBlockFile ; nFile + + ) {
pblocktree - > ReadBlockFileInfo ( nFile , vinfoBlockFile [ nFile ] ) ;
}
2014-10-22 01:17:13 +02:00
LogPrintf ( " %s: last block file info: %s \n " , __func__ , vinfoBlockFile [ nLastBlockFile ] . ToString ( ) ) ;
2014-09-25 08:21:21 +02:00
for ( int nFile = nLastBlockFile + 1 ; true ; nFile + + ) {
CBlockFileInfo info ;
if ( pblocktree - > ReadBlockFileInfo ( nFile , info ) ) {
vinfoBlockFile . push_back ( info ) ;
} else {
break ;
}
}
2012-10-05 19:22:21 +02:00
2014-05-11 14:05:04 +02:00
// Check presence of blk files
LogPrintf ( " Checking all blk files are present... \n " ) ;
2017-01-27 09:43:41 +01:00
std : : set < int > setBlkDataFiles ;
2018-05-16 00:41:53 +02:00
for ( const std : : pair < const uint256 , CBlockIndex * > & item : mapBlockIndex )
2014-05-11 14:05:04 +02:00
{
CBlockIndex * pindex = item . second ;
if ( pindex - > nStatus & BLOCK_HAVE_DATA ) {
setBlkDataFiles . insert ( pindex - > nFile ) ;
}
}
for ( std : : set < int > : : iterator it = setBlkDataFiles . begin ( ) ; it ! = setBlkDataFiles . end ( ) ; it + + )
{
CDiskBlockPos pos ( * it , 0 ) ;
2014-10-20 12:45:50 +02:00
if ( CAutoFile ( OpenBlockFile ( pos , true ) , SER_DISK , CLIENT_VERSION ) . IsNull ( ) ) {
2014-05-11 14:05:04 +02:00
return false ;
}
}
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 20:27:44 +01:00
// Check whether we have ever pruned block & undo files
pblocktree - > ReadFlag ( " prunedblockfiles " , fHavePruned ) ;
if ( fHavePruned )
LogPrintf ( " LoadBlockIndexDB(): Block files have previously been pruned \n " ) ;
2012-12-02 21:59:22 +01:00
// Check whether we need to continue reindexing
bool fReindexing = false ;
pblocktree - > ReadReindexing ( fReindexing ) ;
2017-08-24 03:45:26 +02:00
if ( fReindexing ) fReindex = true ;
2012-12-02 21:59:22 +01:00
2017-04-19 18:34:30 +02:00
return true ;
}
2017-07-07 02:00:11 +02:00
bool LoadChainTip ( const CChainParams & chainparams )
2017-04-19 18:34:30 +02:00
{
2018-01-12 00:32:32 +01:00
AssertLockHeld ( cs_main ) ;
2017-07-07 02:00:11 +02:00
if ( chainActive . Tip ( ) & & chainActive . Tip ( ) - > GetBlockHash ( ) = = pcoinsTip - > GetBestBlock ( ) ) return true ;
if ( pcoinsTip - > GetBestBlock ( ) . IsNull ( ) & & mapBlockIndex . size ( ) = = 1 ) {
// In case we just added the genesis block, connect it now, so
// that we always have a chainActive.Tip() when we return.
LogPrintf ( " %s: Connecting genesis block... \n " , __func__ ) ;
CValidationState state ;
if ( ! ActivateBestChain ( state , chainparams ) ) {
2018-04-18 15:58:13 +02:00
LogPrintf ( " %s: failed to activate chain (%s) \n " , __func__ , FormatStateMessage ( state ) ) ;
2017-07-07 02:00:11 +02:00
return false ;
}
}
2017-04-19 18:34:30 +02:00
2013-10-13 22:15:48 +02:00
// Load pointer to end of best chain
2018-01-12 01:23:09 +01:00
CBlockIndex * pindex = LookupBlockIndex ( pcoinsTip - > GetBestBlock ( ) ) ;
if ( ! pindex ) {
2017-07-07 02:00:11 +02:00
return false ;
2018-01-12 01:23:09 +01:00
}
chainActive . SetTip ( pindex ) ;
2014-11-01 22:42:12 +01:00
2017-12-04 15:34:46 +01:00
g_chainstate . PruneBlockIndexCandidates ( ) ;
2014-11-01 22:42:12 +01:00
2017-04-19 18:34:30 +02:00
LogPrintf ( " Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f \n " ,
2014-01-16 16:15:27 +01:00
chainActive . Tip ( ) - > GetBlockHash ( ) . ToString ( ) , chainActive . Height ( ) ,
2018-02-28 16:46:31 +01:00
FormatISO8601DateTime ( chainActive . Tip ( ) - > GetBlockTime ( ) ) ,
2017-01-04 16:31:56 +01:00
GuessVerificationProgress ( chainparams . TxData ( ) , chainActive . Tip ( ) ) ) ;
2017-07-07 02:00:11 +02:00
return true ;
2013-01-03 15:29:07 +01:00
}
2014-05-23 18:04:09 +02:00
CVerifyDB : : CVerifyDB ( )
{
2017-07-07 23:09:55 +02:00
uiInterface . ShowProgress ( _ ( " Verifying blocks... " ) , 0 , false ) ;
2014-05-23 18:04:09 +02:00
}
CVerifyDB : : ~ CVerifyDB ( )
{
2017-07-07 23:09:55 +02:00
uiInterface . ShowProgress ( " " , 100 , false ) ;
2014-05-23 18:04:09 +02:00
}
2015-04-17 14:40:24 +02:00
bool CVerifyDB : : VerifyDB ( const CChainParams & chainparams , CCoinsView * coinsview , int nCheckLevel , int nCheckDepth )
2013-06-19 17:32:49 +02:00
{
2014-05-07 15:12:31 +02:00
LOCK ( cs_main ) ;
2017-08-07 07:36:37 +02:00
if ( chainActive . Tip ( ) = = nullptr | | chainActive . Tip ( ) - > pprev = = nullptr )
2013-01-03 15:29:07 +01:00
return true ;
2012-09-03 21:14:03 +02:00
// Verify blocks in the best chain
2017-07-08 18:44:03 +02:00
if ( nCheckDepth < = 0 | | nCheckDepth > chainActive . Height ( ) )
2013-10-10 23:07:44 +02:00
nCheckDepth = chainActive . Height ( ) ;
2013-01-03 15:29:07 +01:00
nCheckLevel = std : : max ( 0 , std : : min ( 4 , nCheckLevel ) ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " Verifying last %i blocks at level %i \n " , nCheckDepth , nCheckLevel ) ;
2014-09-24 03:19:04 +02:00
CCoinsViewCache coins ( coinsview ) ;
2018-08-06 21:40:20 +02:00
CClaimTrieCache trieCache ( pclaimTrie ) ;
2018-06-11 09:14:35 +02:00
CBlockIndex * pindex ;
2017-08-07 07:36:37 +02:00
CBlockIndex * pindexFailure = nullptr ;
2013-01-03 15:29:07 +01:00
int nGoodTransactions = 0 ;
2013-01-27 00:14:11 +01:00
CValidationState state ;
2016-06-02 13:52:09 +02:00
int reportDone = 0 ;
2018-04-05 16:17:32 +02:00
LogPrintf ( " [0%%]... " ) ; /* Continued */
2018-06-11 09:14:35 +02:00
for ( pindex = chainActive . Tip ( ) ; pindex & & pindex - > pprev ; pindex = pindex - > pprev ) {
2013-03-09 18:02:57 +01:00
boost : : this_thread : : interruption_point ( ) ;
2016-06-02 13:52:09 +02:00
int percentageDone = std : : max ( 1 , std : : min ( 99 , ( int ) ( ( ( double ) ( chainActive . Height ( ) - pindex - > nHeight ) ) / ( double ) nCheckDepth * ( nCheckLevel > = 4 ? 50 : 100 ) ) ) ) ;
if ( reportDone < percentageDone / 10 ) {
// report every 10% step
2018-04-05 16:17:32 +02:00
LogPrintf ( " [%d%%]... " , percentageDone ) ; /* Continued */
2016-06-02 13:52:09 +02:00
reportDone = percentageDone / 10 ;
}
2017-07-07 23:09:55 +02:00
uiInterface . ShowProgress ( _ ( " Verifying blocks... " ) , percentageDone , false ) ;
2018-06-11 07:16:51 +02:00
if ( pindex - > nHeight < = chainActive . Height ( ) - nCheckDepth )
2012-09-03 21:14:03 +02:00
break ;
2016-05-20 10:59:57 +02:00
if ( fPruneMode & & ! ( pindex - > nStatus & BLOCK_HAVE_DATA ) ) {
// If pruning, only go back as far as we have data.
LogPrintf ( " VerifyDB(): block verification stopping at height %d (pruning, no data) \n " , pindex - > nHeight ) ;
break ;
}
2012-09-03 21:14:03 +02:00
CBlock block ;
2013-01-03 15:29:07 +01:00
// check level 0: read from disk
2015-04-17 14:19:21 +02:00
if ( ! ReadBlockFromDisk ( block , pindex , chainparams . GetConsensus ( ) ) )
2015-01-08 11:44:25 +01:00
return error ( " VerifyDB() : * * * ReadBlockFromDisk failed at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2012-09-03 21:14:03 +02:00
// check level 1: verify block validity
2016-06-09 01:12:52 +02:00
if ( nCheckLevel > = 1 & & ! CheckBlock ( block , state , chainparams . GetConsensus ( ) ) )
2016-03-26 16:44:50 +01:00
return error ( " %s: *** found bad block at %d, hash=%s (%s) \n " , __func__ ,
2015-12-02 03:13:47 +01:00
pindex - > nHeight , pindex - > GetBlockHash ( ) . ToString ( ) , FormatStateMessage ( state ) ) ;
2013-01-03 15:29:07 +01:00
// check level 2: verify undo validity
if ( nCheckLevel > = 2 & & pindex ) {
CBlockUndo undo ;
2017-06-09 18:57:23 +02:00
if ( ! pindex - > GetUndoPos ( ) . IsNull ( ) ) {
if ( ! UndoReadFromDisk ( undo , pindex ) ) {
2015-01-08 11:44:25 +01:00
return error ( " VerifyDB() : * * * found bad undo data at % d , hash = % s \ n " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2017-06-09 18:57:23 +02:00
}
2013-01-03 15:29:07 +01:00
}
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
2018-06-11 09:14:35 +02:00
if ( nCheckLevel > = 3 & & ( coins . DynamicMemoryUsage ( ) + pcoinsTip - > DynamicMemoryUsage ( ) ) < = nCoinCacheUsage ) {
2017-04-19 18:34:30 +02:00
assert ( coins . GetBestBlock ( ) = = pindex - > GetBlockHash ( ) ) ;
2018-08-06 21:40:20 +02:00
DisconnectResult res = g_chainstate . DisconnectBlock ( block , pindex , coins , trieCache ) ;
2017-04-29 01:08:39 +02:00
if ( res = = DISCONNECT_FAILED ) {
2015-01-08 11:44:25 +01:00
return error ( " VerifyDB() : * * * irrecoverable inconsistency in block data at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2017-04-29 01:08:39 +02:00
}
if ( res = = DISCONNECT_UNCLEAN ) {
2013-01-03 15:29:07 +01:00
nGoodTransactions = 0 ;
pindexFailure = pindex ;
2017-04-29 01:08:39 +02:00
} else {
2013-01-03 15:29:07 +01:00
nGoodTransactions + = block . vtx . size ( ) ;
2017-04-29 01:08:39 +02:00
}
2012-09-03 21:14:03 +02:00
}
2014-12-28 22:39:53 +01:00
if ( ShutdownRequested ( ) )
return true ;
2012-09-03 21:14:03 +02:00
}
2013-01-03 15:29:07 +01:00
if ( pindexFailure )
2015-01-08 11:44:25 +01:00
return error ( " VerifyDB() : * * * coin database inconsistencies found ( last % i blocks , % i good transactions before that ) \ n " , chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions) ;
2013-01-03 15:29:07 +01:00
2018-06-11 09:14:35 +02:00
// store block count as we move pindex at check level >= 4
int block_count = chainActive . Height ( ) - pindex - > nHeight ;
2013-01-03 15:29:07 +01:00
// check level 4: try reconnecting blocks
if ( nCheckLevel > = 4 ) {
2013-10-10 23:07:44 +02:00
while ( pindex ! = chainActive . Tip ( ) ) {
2013-03-09 18:02:57 +01:00
boost : : this_thread : : interruption_point ( ) ;
2017-07-07 23:09:55 +02:00
uiInterface . ShowProgress ( _ ( " Verifying blocks... " ) , std : : max ( 1 , std : : min ( 99 , 100 - ( int ) ( ( ( double ) ( chainActive . Height ( ) - pindex - > nHeight ) ) / ( double ) nCheckDepth * 50 ) ) ) , false ) ;
2013-10-10 23:07:44 +02:00
pindex = chainActive . Next ( pindex ) ;
2013-04-04 11:30:55 +02:00
CBlock block ;
2015-04-17 14:19:21 +02:00
if ( ! ReadBlockFromDisk ( block , pindex , chainparams . GetConsensus ( ) ) )
2015-01-08 11:44:25 +01:00
return error ( " VerifyDB() : * * * ReadBlockFromDisk failed at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2018-08-06 21:40:20 +02:00
if ( ! g_chainstate . ConnectBlock ( block , state , pindex , coins , trieCache , chainparams ) )
2018-04-18 15:58:13 +02:00
return error ( " VerifyDB() : * * * found unconnectable block at % d , hash = % s ( % s ) " , pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)) ;
2013-01-03 15:29:07 +01:00
}
2012-09-03 21:14:03 +02:00
}
2016-06-02 13:52:09 +02:00
LogPrintf ( " [DONE]. \n " ) ;
2018-06-11 09:14:35 +02:00
LogPrintf ( " No coin database inconsistencies in last %i blocks (%i transactions) \n " , block_count , nGoodTransactions ) ;
2013-01-03 15:29:07 +01:00
2012-09-03 21:14:03 +02:00
return true ;
}
2017-04-19 18:34:30 +02:00
/** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */
2017-12-04 15:34:46 +01:00
bool CChainState : : RollforwardBlock ( const CBlockIndex * pindex , CCoinsViewCache & inputs , const CChainParams & params )
2017-04-19 18:34:30 +02:00
{
// TODO: merge with ConnectBlock
CBlock block ;
if ( ! ReadBlockFromDisk ( block , pindex , params . GetConsensus ( ) ) ) {
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 ;
}
2017-12-04 15:34:46 +01:00
bool CChainState : : ReplayBlocks ( const CChainParams & params , CCoinsView * view )
2017-04-19 18:34:30 +02:00
{
LOCK ( cs_main ) ;
CCoinsViewCache cache ( view ) ;
2018-08-06 21:40:20 +02:00
CClaimTrieCache trieCache ( pclaimTrie ) ;
2017-04-19 18:34:30 +02:00
std : : vector < uint256 > hashHeads = view - > GetHeadBlocks ( ) ;
if ( hashHeads . empty ( ) ) return true ; // We're already in a consistent state.
if ( hashHeads . size ( ) ! = 2 ) return error ( " ReplayBlocks(): unknown inconsistent state " ) ;
2017-07-07 23:09:55 +02:00
uiInterface . ShowProgress ( _ ( " Replaying blocks... " ) , 0 , false ) ;
2017-04-19 18:34:30 +02: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.
if ( mapBlockIndex . count ( hashHeads [ 0 ] ) = = 0 ) {
return error ( " ReplayBlocks() : reorganization to unknown block requested " ) ;
}
pindexNew = mapBlockIndex [ hashHeads [ 0 ] ] ;
if ( ! hashHeads [ 1 ] . IsNull ( ) ) { // The old tip is allowed to be 0, indicating it's the first flush.
if ( mapBlockIndex . count ( hashHeads [ 1 ] ) = = 0 ) {
return error ( " ReplayBlocks() : reorganization from unknown block requested " ) ;
}
pindexOld = mapBlockIndex [ hashHeads [ 1 ] ] ;
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 ;
if ( ! ReadBlockFromDisk ( block , pindexOld , params . GetConsensus ( ) ) ) {
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 ) ;
2018-08-06 21:40:20 +02:00
DisconnectResult res = DisconnectBlock ( block , pindexOld , cache , trieCache ) ;
2017-04-19 18:34:30 +02:00
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 ) {
const CBlockIndex * pindex = pindexNew - > GetAncestor ( nHeight ) ;
LogPrintf ( " Rolling forward %s (%i) \n " , pindex - > GetBlockHash ( ) . ToString ( ) , nHeight ) ;
if ( ! RollforwardBlock ( pindex , cache , params ) ) return false ;
}
cache . SetBestBlock ( pindexNew - > GetBlockHash ( ) ) ;
cache . Flush ( ) ;
2018-08-06 21:40:20 +02:00
trieCache . flush ( ) ;
2017-07-07 23:09:55 +02:00
uiInterface . ShowProgress ( " " , 100 , false ) ;
2017-04-19 18:34:30 +02:00
return true ;
}
2017-12-04 15:34:46 +01:00
bool ReplayBlocks ( const CChainParams & params , CCoinsView * view ) {
return g_chainstate . ReplayBlocks ( params , view ) ;
}
bool CChainState : : RewindBlockIndex ( const CChainParams & params )
2016-03-18 17:20:12 +01:00
{
LOCK ( cs_main ) ;
2017-07-07 03:29:46 +02:00
// Note that during -reindex-chainstate we are called with an empty chainActive!
2016-03-18 17:20:12 +01:00
int nHeight = 1 ;
while ( nHeight < = chainActive . Height ( ) ) {
2017-09-13 16:13:57 +02:00
// Although SCRIPT_VERIFY_WITNESS is now generally enforced on all
// blocks in ConnectBlock, we don't need to go back and
// re-download/re-verify blocks from before segwit actually activated.
2016-03-18 17:20:12 +01:00
if ( IsWitnessEnabled ( chainActive [ nHeight - 1 ] , params . GetConsensus ( ) ) & & ! ( chainActive [ nHeight ] - > nStatus & BLOCK_OPT_WITNESS ) ) {
break ;
}
nHeight + + ;
}
// nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
CValidationState state ;
CBlockIndex * pindex = chainActive . Tip ( ) ;
while ( chainActive . Height ( ) > = nHeight ) {
if ( fPruneMode & & ! ( chainActive . Tip ( ) - > nStatus & BLOCK_HAVE_DATA ) ) {
// If pruning, don't try rewinding past the HAVE_DATA point;
// since older blocks can't be served anyway, there's
// no need to walk further, and trying to DisconnectTip()
// will fail (and require a needless reindex/redownload
// of the blockchain).
break ;
}
2017-08-07 07:36:37 +02:00
if ( ! DisconnectTip ( state , params , nullptr ) ) {
2018-04-18 15:58:13 +02:00
return error ( " RewindBlockIndex: unable to disconnect block at height %i (%s) " , pindex->nHeight, FormatStateMessage(state)) ;
2016-03-18 17:20:12 +01:00
}
// Occasionally flush state to disk.
2018-04-18 15:58:13 +02:00
if ( ! FlushStateToDisk ( params , state , FlushStateMode : : PERIODIC ) ) {
LogPrintf ( " RewindBlockIndex: unable to flush state to disk (%s) \n " , FormatStateMessage ( state ) ) ;
2016-03-18 17:20:12 +01:00
return false ;
2018-04-18 15:58:13 +02:00
}
2016-03-18 17:20:12 +01:00
}
// Reduce validity flag and have-data flags.
// We do this after actual disconnecting, otherwise we'll end up writing the lack of data
// to disk before writing the chainstate, resulting in a failure to continue if interrupted.
2017-06-04 22:02:43 +02:00
for ( const auto & entry : mapBlockIndex ) {
CBlockIndex * pindexIter = entry . second ;
2016-03-18 17:20:12 +01:00
// Note: If we encounter an insufficiently validated block that
// is on chainActive, it must be because we are a pruning node, and
// this block or some successor doesn't HAVE_DATA, so we were unable to
// rewind all the way. Blocks remaining on chainActive at this point
// must not have their validity reduced.
if ( IsWitnessEnabled ( pindexIter - > pprev , params . GetConsensus ( ) ) & & ! ( pindexIter - > nStatus & BLOCK_OPT_WITNESS ) & & ! chainActive . Contains ( pindexIter ) ) {
// Reduce validity
pindexIter - > nStatus = std : : min < unsigned int > ( pindexIter - > nStatus & BLOCK_VALID_MASK , BLOCK_VALID_TREE ) | ( pindexIter - > nStatus & ~ BLOCK_VALID_MASK ) ;
// Remove have-data flags.
pindexIter - > nStatus & = ~ ( BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO ) ;
// Remove storage location.
pindexIter - > nFile = 0 ;
pindexIter - > nDataPos = 0 ;
pindexIter - > nUndoPos = 0 ;
// Remove various other things
pindexIter - > nTx = 0 ;
pindexIter - > nChainTx = 0 ;
pindexIter - > nSequenceId = 0 ;
// Make sure it gets written.
setDirtyBlockIndex . insert ( pindexIter ) ;
// Update indexes
setBlockIndexCandidates . erase ( pindexIter ) ;
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > ret = mapBlocksUnlinked . equal_range ( pindexIter - > pprev ) ;
while ( ret . first ! = ret . second ) {
if ( ret . first - > second = = pindexIter ) {
mapBlocksUnlinked . erase ( ret . first + + ) ;
} else {
+ + ret . first ;
}
}
} else if ( pindexIter - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & & pindexIter - > nChainTx ) {
setBlockIndexCandidates . insert ( pindexIter ) ;
}
}
2017-08-07 07:36:37 +02:00
if ( chainActive . Tip ( ) ! = nullptr ) {
2017-07-07 03:29:46 +02:00
// We can't prune block index candidates based on our tip if we have
// no tip due to chainActive being empty!
PruneBlockIndexCandidates ( ) ;
2016-03-18 17:20:12 +01:00
2017-07-07 03:29:46 +02:00
CheckBlockIndex ( params . GetConsensus ( ) ) ;
2017-12-04 15:34:46 +01:00
}
2016-03-18 17:20:12 +01:00
2017-12-04 15:34:46 +01:00
return true ;
}
bool RewindBlockIndex ( const CChainParams & params ) {
if ( ! g_chainstate . RewindBlockIndex ( params ) ) {
return false ;
}
2016-03-18 17:20:12 +01:00
2017-12-04 15:34:46 +01:00
if ( chainActive . Tip ( ) ! = nullptr ) {
2017-07-07 03:29:46 +02:00
// FlushStateToDisk can possibly read chainActive. Be conservative
// and skip it here, we're about to -reindex-chainstate anyway, so
// it'll get called a bunch real soon.
2017-12-04 15:34:46 +01:00
CValidationState state ;
2018-03-09 15:03:40 +01:00
if ( ! FlushStateToDisk ( params , state , FlushStateMode : : ALWAYS ) ) {
2018-04-18 15:58:13 +02:00
LogPrintf ( " RewindBlockIndex: unable to flush state to disk (%s) \n " , FormatStateMessage ( state ) ) ;
2017-07-07 03:29:46 +02:00
return false ;
}
2016-03-18 17:20:12 +01:00
}
return true ;
}
2017-12-04 15:34:46 +01:00
void CChainState : : UnloadBlockIndex ( ) {
2017-04-26 03:31:08 +02:00
nBlockSequenceId = 1 ;
2018-04-18 13:57:18 +02:00
m_failed_blocks . clear ( ) ;
2017-12-04 15:34:46 +01:00
setBlockIndexCandidates . clear ( ) ;
}
2016-10-02 17:29:35 +02:00
// May NOT be used after any connections are up as much
// of the peer-processing logic assumes a consistent
// block index state
2013-02-16 17:58:45 +01:00
void UnloadBlockIndex ( )
{
2015-03-03 16:49:12 +01:00
LOCK ( cs_main ) ;
2017-08-07 07:36:37 +02:00
chainActive . SetTip ( nullptr ) ;
pindexBestInvalid = nullptr ;
pindexBestHeader = nullptr ;
2015-03-03 16:49:12 +01:00
mempool . clear ( ) ;
mapBlocksUnlinked . clear ( ) ;
vinfoBlockFile . clear ( ) ;
nLastBlockFile = 0 ;
setDirtyBlockIndex . clear ( ) ;
setDirtyFileInfo . clear ( ) ;
2016-02-15 05:13:27 +01:00
versionbitscache . Clear ( ) ;
for ( int b = 0 ; b < VERSIONBITS_NUM_BITS ; b + + ) {
warningcache [ b ] . clear ( ) ;
}
2015-03-03 16:49:12 +01:00
2017-06-02 03:18:57 +02:00
for ( BlockMap : : value_type & entry : mapBlockIndex ) {
2015-03-03 16:49:12 +01:00
delete entry . second ;
}
mapBlockIndex . clear ( ) ;
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 20:27:44 +01:00
fHavePruned = false ;
2017-12-04 15:34:46 +01:00
g_chainstate . UnloadBlockIndex ( ) ;
2013-02-16 17:58:45 +01:00
}
2016-10-25 16:35:26 +02:00
bool LoadBlockIndex ( const CChainParams & chainparams )
2010-08-29 18:58:15 +02:00
{
2012-09-03 15:26:57 +02:00
// Load block index from databases
2017-07-07 01:57:20 +02:00
bool needs_init = fReindex ;
if ( ! fReindex ) {
bool ret = LoadBlockIndexDB ( chainparams ) ;
if ( ! ret ) return false ;
needs_init = mapBlockIndex . empty ( ) ;
}
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 21:43:36 +01:00
return true ;
}
2013-01-11 01:47:57 +01:00
2017-12-04 15:34:46 +01:00
bool CChainState : : LoadGenesisBlock ( const CChainParams & chainparams )
2015-04-17 14:40:24 +02:00
{
2014-04-15 17:38:25 +02:00
LOCK ( cs_main ) ;
2015-07-31 17:55:05 +02:00
2017-07-07 01:57:20 +02:00
// Check whether we're already initialized by checking for genesis in
// mapBlockIndex. Note that we can't use chainActive here, since it is
// set based on the coins db, not the block index db, which is the only
// thing loaded at this point.
if ( mapBlockIndex . count ( chainparams . GenesisBlock ( ) . GetHash ( ) ) )
2013-01-30 21:43:36 +01:00
return true ;
2017-07-07 01:57:20 +02:00
try {
CBlock & block = const_cast < CBlock & > ( chainparams . GenesisBlock ( ) ) ;
2017-04-26 03:35:02 +02:00
CDiskBlockPos blockPos = SaveBlockToDisk ( block , 0 , chainparams , nullptr ) ;
if ( blockPos . IsNull ( ) )
2017-07-07 01:57:20 +02:00
return error ( " %s: writing genesis block to disk failed " , __func__ ) ;
CBlockIndex * pindex = AddToBlockIndex ( block ) ;
2018-06-07 17:10:48 +02:00
ReceivedBlockTransactions ( block , pindex , blockPos , chainparams . GetConsensus ( ) ) ;
2017-07-07 01:57:20 +02:00
} catch ( const std : : runtime_error & e ) {
return error ( " %s: failed to write genesis block: %s " , __func__ , e . what ( ) ) ;
2010-08-29 18:58:15 +02:00
}
return true ;
}
2017-12-04 15:34:46 +01:00
bool LoadGenesisBlock ( const CChainParams & chainparams )
{
return g_chainstate . LoadGenesisBlock ( chainparams ) ;
}
2015-04-17 14:40:24 +02:00
bool LoadExternalBlockFile ( const CChainParams & chainparams , FILE * fileIn , CDiskBlockPos * dbp )
2012-02-20 20:50:26 +01:00
{
2014-10-07 18:06:30 +02:00
// Map of disk positions for blocks with unknown parent (only used for reindex)
static std : : multimap < uint256 , CDiskBlockPos > mapBlocksUnknownParent ;
2013-04-13 07:13:08 +02:00
int64_t nStart = GetTimeMillis ( ) ;
2012-08-17 00:14:40 +02:00
2012-02-20 20:50:26 +01:00
int nLoaded = 0 ;
2013-01-29 01:44:19 +01:00
try {
2014-09-25 08:53:43 +02:00
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
2016-01-03 18:54:50 +01:00
CBufferedFile blkdat ( fileIn , 2 * MAX_BLOCK_SERIALIZED_SIZE , MAX_BLOCK_SERIALIZED_SIZE + 8 , SER_DISK , CLIENT_VERSION ) ;
2013-04-13 07:13:08 +02:00
uint64_t nRewind = blkdat . GetPos ( ) ;
2014-08-01 22:57:55 +02:00
while ( ! blkdat . eof ( ) ) {
2013-03-07 04:31:26 +01:00
boost : : this_thread : : interruption_point ( ) ;
2012-10-27 22:01:38 +02:00
blkdat . SetPos ( nRewind ) ;
nRewind + + ; // start one byte further next time, in case of failure
blkdat . SetLimit ( ) ; // remove former limit
2012-10-21 21:23:13 +02:00
unsigned int nSize = 0 ;
2012-10-27 22:01:38 +02:00
try {
// locate a header
2016-10-04 13:12:23 +02:00
unsigned char buf [ CMessageHeader : : MESSAGE_START_SIZE ] ;
2015-04-17 14:40:24 +02:00
blkdat . FindByte ( chainparams . MessageStart ( ) [ 0 ] ) ;
2012-10-27 22:01:38 +02:00
nRewind = blkdat . GetPos ( ) + 1 ;
2018-03-21 01:37:32 +01:00
blkdat > > buf ;
2016-10-04 13:12:23 +02:00
if ( memcmp ( buf , chainparams . MessageStart ( ) , CMessageHeader : : MESSAGE_START_SIZE ) )
2012-10-27 22:01:38 +02:00
continue ;
// read size
2012-02-20 20:50:26 +01:00
blkdat > > nSize ;
2016-01-03 18:54:50 +01:00
if ( nSize < 80 | | nSize > MAX_BLOCK_SERIALIZED_SIZE )
2012-10-27 22:01:38 +02:00
continue ;
2014-12-07 13:29:06 +01:00
} catch ( const std : : exception & ) {
2012-10-21 21:23:13 +02:00
// no valid block header found; don't complain
break ;
}
try {
2012-10-27 22:01:38 +02:00
// read block
2013-04-13 07:13:08 +02:00
uint64_t nBlockPos = blkdat . GetPos ( ) ;
2014-10-07 18:06:30 +02:00
if ( dbp )
dbp - > nPos = nBlockPos ;
2012-10-21 21:23:13 +02:00
blkdat . SetLimit ( nBlockPos + nSize ) ;
2014-10-07 21:15:32 +02:00
blkdat . SetPos ( nBlockPos ) ;
2016-12-19 08:24:11 +01:00
std : : shared_ptr < CBlock > pblock = std : : make_shared < CBlock > ( ) ;
CBlock & block = * pblock ;
2014-10-07 21:15:32 +02:00
blkdat > > block ;
2014-10-07 18:06:30 +02:00
nRewind = blkdat . GetPos ( ) ;
2014-10-07 21:15:32 +02:00
uint256 hash = block . GetHash ( ) ;
2018-01-12 00:40:43 +01:00
{
2016-04-20 15:45:41 +02:00
LOCK ( cs_main ) ;
2018-01-12 00:40:43 +01:00
// detect out of order blocks, and store them for later
2018-01-12 01:23:09 +01:00
if ( hash ! = chainparams . GetConsensus ( ) . hashGenesisBlock & & ! LookupBlockIndex ( block . hashPrevBlock ) ) {
2018-01-12 00:40:43 +01: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
2018-01-12 01:23:09 +01:00
CBlockIndex * pindex = LookupBlockIndex ( hash ) ;
if ( ! pindex | | ( pindex - > nStatus & BLOCK_HAVE_DATA ) = = 0 ) {
CValidationState state ;
if ( g_chainstate . AcceptBlock ( pblock , state , chainparams , nullptr , true , dbp , nullptr ) ) {
nLoaded + + ;
}
if ( state . IsError ( ) ) {
break ;
}
} else if ( hash ! = chainparams . 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-12 00:40:43 +01:00
}
2014-10-07 21:15:32 +02:00
}
2014-10-07 18:06:30 +02:00
2016-04-28 16:18:45 +02:00
// Activate the genesis block so normal node progress can continue
if ( hash = = chainparams . GetConsensus ( ) . hashGenesisBlock ) {
CValidationState state ;
if ( ! ActivateBestChain ( state , chainparams ) ) {
break ;
}
2014-10-07 21:15:32 +02:00
}
2014-10-07 18:06:30 +02:00
2016-04-28 16:18:45 +02:00
NotifyHeaderTip ( ) ;
2014-10-07 18:06:30 +02:00
// Recursively process earlier encountered successors of this block
2017-01-27 09:43:41 +01:00
std : : deque < uint256 > queue ;
2014-10-07 18:06:30 +02:00
queue . push_back ( hash ) ;
while ( ! queue . empty ( ) ) {
uint256 head = queue . front ( ) ;
queue . pop_front ( ) ;
std : : pair < std : : multimap < uint256 , CDiskBlockPos > : : iterator , std : : multimap < uint256 , CDiskBlockPos > : : iterator > range = mapBlocksUnknownParent . equal_range ( head ) ;
while ( range . first ! = range . second ) {
std : : multimap < uint256 , CDiskBlockPos > : : iterator it = range . first ;
2016-12-19 08:24:11 +01:00
std : : shared_ptr < CBlock > pblockrecursive = std : : make_shared < CBlock > ( ) ;
if ( ReadBlockFromDisk ( * pblockrecursive , it - > second , chainparams . GetConsensus ( ) ) )
2014-10-07 18:06:30 +02:00
{
2016-12-25 21:19:40 +01:00
LogPrint ( BCLog : : REINDEX , " %s: Processing out of order child %s of %s \n " , __func__ , pblockrecursive - > GetHash ( ) . ToString ( ) ,
2014-10-07 18:06:30 +02:00
head . ToString ( ) ) ;
2016-04-20 15:45:41 +02:00
LOCK ( cs_main ) ;
2014-10-07 18:06:30 +02:00
CValidationState dummy ;
2017-12-04 15:34:46 +01:00
if ( g_chainstate . AcceptBlock ( pblockrecursive , dummy , chainparams , nullptr , true , & it - > second , nullptr ) )
2014-10-07 18:06:30 +02:00
{
nLoaded + + ;
2016-12-19 08:24:11 +01:00
queue . push_back ( pblockrecursive - > GetHash ( ) ) ;
2014-10-07 18:06:30 +02:00
}
}
range . first + + ;
mapBlocksUnknownParent . erase ( it ) ;
2016-04-28 16:18:45 +02:00
NotifyHeaderTip ( ) ;
2014-10-07 18:06:30 +02:00
}
2012-02-20 20:50:26 +01:00
}
2014-12-07 13:29:06 +01:00
} catch ( const std : : exception & e ) {
2015-07-31 16:41:06 +02:00
LogPrintf ( " %s: Deserialize or I/O error - %s \n " , __func__ , e . what ( ) ) ;
2012-02-20 20:50:26 +01:00
}
}
2014-12-07 13:29:06 +01:00
} catch ( const std : : runtime_error & e ) {
2014-10-02 22:17:57 +02:00
AbortNode ( std : : string ( " System error: " ) + e . what ( ) ) ;
2012-02-20 20:50:26 +01:00
}
2012-10-21 21:23:13 +02:00
if ( nLoaded > 0 )
2014-02-24 09:08:56 +01:00
LogPrintf ( " Loaded %i blocks from external file in %dms \n " , nLoaded , GetTimeMillis ( ) - nStart ) ;
2012-02-20 20:50:26 +01:00
return nLoaded > 0 ;
}
2010-08-29 18:58:15 +02:00
2017-12-04 15:34:46 +01:00
void CChainState : : CheckBlockIndex ( const Consensus : : Params & consensusParams )
2015-03-13 17:25:34 +01:00
{
if ( ! fCheckBlockIndex ) {
return ;
}
LOCK ( cs_main ) ;
2015-04-09 17:08:39 +02:00
// During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain,
// so we have the genesis block in mapBlockIndex but no active chain. (A few of the tests when
// iterating the block tree require that chainActive has been initialized.)
if ( chainActive . Height ( ) < 0 ) {
assert ( mapBlockIndex . size ( ) < = 1 ) ;
return ;
}
2015-03-13 17:25:34 +01:00
// Build forward-pointing map of the entire block tree.
std : : multimap < CBlockIndex * , CBlockIndex * > forward ;
2017-06-04 22:02:43 +02:00
for ( auto & entry : mapBlockIndex ) {
forward . insert ( std : : make_pair ( entry . second - > pprev , entry . second ) ) ;
2015-03-13 17:25:34 +01:00
}
assert ( forward . size ( ) = = mapBlockIndex . size ( ) ) ;
2017-08-07 07:36:37 +02:00
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > rangeGenesis = forward . equal_range ( nullptr ) ;
2015-03-13 17:25:34 +01:00
CBlockIndex * pindex = rangeGenesis . first - > second ;
rangeGenesis . first + + ;
2017-08-07 07:36:37 +02:00
assert ( rangeGenesis . first = = rangeGenesis . second ) ; // There is only one index entry with parent nullptr.
2015-03-13 17:25:34 +01: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 07:36:37 +02: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 17:25:34 +01:00
nNodes + + ;
2017-08-07 07:36:37 +02:00
if ( pindexFirstInvalid = = nullptr & & pindex - > nStatus & BLOCK_FAILED_VALID ) pindexFirstInvalid = pindex ;
if ( pindexFirstMissing = = nullptr & & ! ( pindex - > nStatus & BLOCK_HAVE_DATA ) ) pindexFirstMissing = pindex ;
if ( pindexFirstNeverProcessed = = nullptr & & pindex - > nTx = = 0 ) pindexFirstNeverProcessed = pindex ;
if ( pindex - > pprev ! = nullptr & & pindexFirstNotTreeValid = = nullptr & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_TREE ) pindexFirstNotTreeValid = pindex ;
if ( pindex - > pprev ! = nullptr & & pindexFirstNotTransactionsValid = = nullptr & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_TRANSACTIONS ) pindexFirstNotTransactionsValid = pindex ;
if ( pindex - > pprev ! = nullptr & & pindexFirstNotChainValid = = nullptr & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_CHAIN ) pindexFirstNotChainValid = pindex ;
if ( pindex - > pprev ! = nullptr & & pindexFirstNotScriptsValid = = nullptr & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_SCRIPTS ) pindexFirstNotScriptsValid = pindex ;
2015-03-13 17:25:34 +01:00
// Begin: actual consistency checks.
2017-08-07 07:36:37 +02:00
if ( pindex - > pprev = = nullptr ) {
2015-03-13 17:25:34 +01:00
// Genesis block checks.
2015-04-09 15:58:34 +02:00
assert ( pindex - > GetBlockHash ( ) = = consensusParams . hashGenesisBlock ) ; // Genesis block's hash must match.
2015-03-13 17:25:34 +01:00
assert ( pindex = = chainActive . Genesis ( ) ) ; // The current active chain's genesis block must be this block.
}
2016-08-26 23:05:09 +02:00
if ( pindex - > nChainTx = = 0 ) 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 20:27:44 +01: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.
if ( ! fHavePruned ) {
// 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 ) ;
assert ( ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_TRANSACTIONS ) = = ( pindex - > nTx > 0 ) ) ; // This is pruning-independent.
// All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to nChainTx being set.
2017-08-07 07:36:37 +02:00
assert ( ( pindexFirstNeverProcessed ! = nullptr ) = = ( pindex - > nChainTx = = 0 ) ) ; // nChainTx != 0 is used to signal that all parent blocks have been processed (but may have been pruned).
assert ( ( pindexFirstNotTransactionsValid ! = nullptr ) = = ( pindex - > nChainTx = = 0 ) ) ;
2015-03-13 17:25:34 +01:00
assert ( pindex - > nHeight = = nHeight ) ; // nHeight must be consistent.
2017-08-07 07:36:37 +02: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 17:25:34 +01:00
assert ( nHeight < 2 | | ( pindex - > pskip & & ( pindex - > pskip - > nHeight < nHeight ) ) ) ; // The pskip pointer must point back for all but the first 2 blocks.
2017-08-07 07:36:37 +02:00
assert ( pindexFirstNotTreeValid = = nullptr ) ; // All mapBlockIndex entries must at least be TREE valid
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 17:25:34 +01:00
// Checks for not-invalid blocks.
assert ( ( pindex - > nStatus & BLOCK_FAILED_MASK ) = = 0 ) ; // The failed mask cannot be set for blocks without invalid parents.
}
2017-08-07 07:36:37 +02:00
if ( ! CBlockIndexWorkComparator ( ) ( pindex , chainActive . Tip ( ) ) & & pindexFirstNeverProcessed = = nullptr ) {
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 20:27:44 +01: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
// setBlockIndexCandidates. chainActive.Tip() must also be there
// even if some data has been pruned.
2017-08-07 07:36:37 +02:00
if ( pindexFirstMissing = = nullptr | | pindex = = chainActive . 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 20:27:44 +01: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.
// In this case it must be in mapBlocksUnlinked -- see test below.
2015-03-13 17:25:34 +01: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 20:27:44 +01: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 17:25:34 +01:00
assert ( setBlockIndexCandidates . count ( pindex ) = = 0 ) ;
}
// Check whether this block is in mapBlocksUnlinked.
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > rangeUnlinked = mapBlocksUnlinked . equal_range ( pindex - > pprev ) ;
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 07:36:37 +02:00
if ( pindex - > pprev & & ( pindex - > nStatus & BLOCK_HAVE_DATA ) & & pindexFirstNeverProcessed ! = nullptr & & 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 20:27:44 +01:00
// If this block has block data available, some parent was never received, and has no invalid parents, it must be in mapBlocksUnlinked.
assert ( foundInUnlinked ) ;
}
if ( ! ( pindex - > nStatus & BLOCK_HAVE_DATA ) ) assert ( ! foundInUnlinked ) ; // Can't be in mapBlocksUnlinked if we don't HAVE_DATA
2017-08-07 07:36:37 +02:00
if ( pindexFirstMissing = = nullptr ) assert ( ! foundInUnlinked ) ; // We aren't missing data for any parent -- cannot be in mapBlocksUnlinked.
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 20:27:44 +01: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.
assert ( fHavePruned ) ; // We must have pruned.
// This block may have entered mapBlocksUnlinked if:
// - it has a descendant that at some point had more work than the
// tip, and
// - we tried switching to that descendant but were missing
// data for some intermediate block between chainActive and the
// tip.
// So if this block is itself better than chainActive.Tip() and it wasn't in
// setBlockIndexCandidates, then it must be in mapBlocksUnlinked.
if ( ! CBlockIndexWorkComparator ( ) ( pindex , chainActive . Tip ( ) ) & & setBlockIndexCandidates . count ( pindex ) = = 0 ) {
2017-08-07 07:36:37 +02: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 20:27:44 +01:00
assert ( foundInUnlinked ) ;
}
2015-03-13 17:25:34 +01: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 07:36:37 +02: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 17:25:34 +01: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 ( ) ) ;
}
2016-11-29 02:00:11 +01:00
std : : string CBlockFileInfo : : ToString ( ) const
2010-08-29 18:58:15 +02:00
{
2018-02-28 16:46:31 +01:00
return strprintf ( " CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s) " , nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast)) ;
2016-11-29 02:00:11 +01:00
}
2010-08-29 18:58:15 +02:00
2017-02-16 16:49:03 +01:00
CBlockFileInfo * GetBlockFileInfo ( size_t n )
{
2017-09-21 01:52:20 +02:00
LOCK ( cs_LastBlockFile ) ;
2017-02-16 16:49:03 +01:00
return & vinfoBlockFile . at ( n ) ;
}
2016-12-02 00:45:50 +01:00
ThresholdState VersionBitsTipState ( const Consensus : : Params & params , Consensus : : DeploymentPos pos )
{
2016-11-03 19:58:29 +01:00
LOCK ( cs_main ) ;
2016-12-02 00:45:50 +01:00
return VersionBitsState ( chainActive . Tip ( ) , params , pos , versionbitscache ) ;
2016-10-04 19:49:44 +02:00
}
2017-01-14 02:06:50 +01:00
BIP9Stats VersionBitsTipStatistics ( const Consensus : : Params & params , Consensus : : DeploymentPos pos )
{
LOCK ( cs_main ) ;
return VersionBitsStatistics ( chainActive . Tip ( ) , params , pos ) ;
}
2016-12-02 00:45:50 +01:00
int VersionBitsTipStateSinceHeight ( const Consensus : : Params & params , Consensus : : DeploymentPos pos )
{
2016-10-04 19:54:29 +02:00
LOCK ( cs_main ) ;
2016-12-02 00:45:50 +01:00
return VersionBitsStateSinceHeight ( chainActive . Tip ( ) , params , pos , versionbitscache ) ;
2016-10-04 19:54:29 +02:00
}
2016-12-02 00:45:50 +01:00
static const uint64_t MEMPOOL_DUMP_VERSION = 1 ;
2010-08-29 18:58:15 +02:00
2016-12-02 00:45:50 +01:00
bool LoadMempool ( void )
2016-10-31 07:53:38 +01:00
{
2017-04-21 20:45:30 +02:00
const CChainParams & chainparams = Params ( ) ;
2017-08-01 21:17:40 +02:00
int64_t nExpiryTimeout = gArgs . GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ;
2017-03-01 17:28:39 +01:00
FILE * filestr = fsbridge : : fopen ( GetDataDir ( ) / " mempool.dat " , " rb " ) ;
2016-10-31 07:53:38 +01: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 10:19:02 +02:00
int64_t expired = 0 ;
2016-10-31 07:53:38 +01:00
int64_t failed = 0 ;
2017-08-16 10:19:02 +02:00
int64_t already_there = 0 ;
2016-10-31 07:53:38 +01:00
int64_t nNow = GetTime ( ) ;
try {
uint64_t version ;
file > > version ;
if ( version ! = MEMPOOL_DUMP_VERSION ) {
return false ;
}
uint64_t num ;
file > > num ;
while ( num - - ) {
2016-11-11 07:29:19 +01:00
CTransactionRef tx ;
2016-10-31 07:53:38 +01:00
int64_t nTime ;
int64_t nFeeDelta ;
2016-11-11 07:29:19 +01:00
file > > tx ;
2016-10-31 07:53:38 +01:00
file > > nTime ;
file > > nFeeDelta ;
CAmount amountdelta = nFeeDelta ;
if ( amountdelta ) {
2017-01-20 05:37:15 +01:00
mempool . PrioritiseTransaction ( tx - > GetHash ( ) , amountdelta ) ;
2016-10-31 07:53:38 +01:00
}
CValidationState state ;
if ( nTime + nExpiryTimeout > nNow ) {
LOCK ( cs_main ) ;
2017-09-12 18:30:26 +02:00
AcceptToMemoryPoolWithTime ( chainparams , mempool , state , tx , nullptr /* pfMissingInputs */ , nTime ,
2017-11-17 18:54:39 +01:00
nullptr /* plTxnReplaced */ , false /* bypass_limits */ , 0 /* nAbsurdFee */ ,
false /* test_accept */ ) ;
2016-10-31 07:53:38 +01:00
if ( state . IsValid ( ) ) {
+ + count ;
} else {
2017-08-16 10:19:02 +02: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'
if ( mempool . exists ( tx - > GetHash ( ) ) ) {
+ + already_there ;
} else {
+ + failed ;
}
2016-10-31 07:53:38 +01:00
}
} else {
2017-08-16 10:19:02 +02:00
+ + expired ;
2016-10-31 07:53:38 +01:00
}
2016-12-22 20:11:26 +01:00
if ( ShutdownRequested ( ) )
return false ;
2016-10-31 07:53:38 +01:00
}
std : : map < uint256 , CAmount > mapDeltas ;
file > > mapDeltas ;
for ( const auto & i : mapDeltas ) {
2017-01-20 05:37:15 +01:00
mempool . PrioritiseTransaction ( i . first , i . second ) ;
2016-10-31 07:53:38 +01:00
}
} catch ( const std : : exception & e ) {
LogPrintf ( " Failed to deserialize mempool data on disk: %s. Continuing anyway. \n " , e . what ( ) ) ;
return false ;
}
2017-08-16 10:19:02 +02:00
LogPrintf ( " Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there \n " , count , failed , expired , already_there ) ;
2016-10-31 07:53:38 +01:00
return true ;
}
2017-08-21 13:22:23 +02:00
bool DumpMempool ( void )
2016-10-31 07:53:38 +01:00
{
int64_t start = GetTimeMicros ( ) ;
std : : map < uint256 , CAmount > mapDeltas ;
std : : vector < TxMempoolInfo > vinfo ;
{
LOCK ( mempool . cs ) ;
for ( const auto & i : mempool . mapDeltas ) {
2017-01-20 05:37:15 +01:00
mapDeltas [ i . first ] = i . second ;
2016-10-31 07:53:38 +01:00
}
vinfo = mempool . infoAll ( ) ;
}
int64_t mid = GetTimeMicros ( ) ;
try {
2017-03-01 17:28:39 +01:00
FILE * filestr = fsbridge : : fopen ( GetDataDir ( ) / " mempool.dat.new " , " wb " ) ;
2016-10-31 07:53:38 +01:00
if ( ! filestr ) {
2017-08-21 13:22:23 +02:00
return false ;
2016-10-31 07:53:38 +01: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 ) ;
file < < ( int64_t ) i . nTime ;
file < < ( int64_t ) i . nFeeDelta ;
mapDeltas . erase ( i . tx - > GetHash ( ) ) ;
}
file < < mapDeltas ;
2018-04-20 11:21:08 +02:00
if ( ! FileCommit ( file . Get ( ) ) )
throw std : : runtime_error ( " FileCommit failed " ) ;
2016-10-31 07:53:38 +01:00
file . fclose ( ) ;
RenameOver ( GetDataDir ( ) / " mempool.dat.new " , GetDataDir ( ) / " mempool.dat " ) ;
int64_t last = GetTimeMicros ( ) ;
2017-06-01 04:42:34 +02:00
LogPrintf ( " Dumped mempool: %gs to copy, %gs to dump \n " , ( mid - start ) * MICRO , ( last - mid ) * MICRO ) ;
2016-10-31 07:53:38 +01:00
} catch ( const std : : exception & e ) {
LogPrintf ( " Failed to dump mempool: %s. Continuing anyway. \n " , e . what ( ) ) ;
2017-08-21 13:22:23 +02:00
return false ;
2016-10-31 07:53:38 +01:00
}
2017-08-21 13:22:23 +02:00
return true ;
2016-10-31 07:53:38 +01:00
}
2017-01-04 16:09:02 +01:00
//! Guess how far we are in the verification process at the given block index
2018-01-28 20:15:18 +01:00
//! require cs_main if pindex has not been validated yet (because nChainTx might be unset)
2017-04-26 03:31:08 +02:00
double GuessVerificationProgress ( const ChainTxData & data , const CBlockIndex * pindex ) {
2017-08-07 07:36:37 +02:00
if ( pindex = = nullptr )
2017-01-04 16:09:02 +01:00
return 0.0 ;
2017-08-07 07:36:37 +02:00
int64_t nNow = time ( nullptr ) ;
2017-01-04 16:09:02 +01:00
2017-01-04 22:09:20 +01:00
double fTxTotal ;
2017-01-04 16:09:02 +01:00
2017-01-04 16:35:39 +01:00
if ( pindex - > nChainTx < = data . nTxCount ) {
fTxTotal = data . nTxCount + ( nNow - data . nTime ) * data . dTxRate ;
2017-01-04 16:09:02 +01:00
} else {
2017-01-04 16:35:39 +01:00
fTxTotal = pindex - > nChainTx + ( nNow - pindex - > GetBlockTime ( ) ) * data . dTxRate ;
2017-01-04 16:09:02 +01:00
}
2017-01-04 22:09:20 +01:00
return pindex - > nChainTx / fTxTotal ;
2017-01-04 16:09:02 +01:00
}
2013-03-29 02:17:10 +01:00
class CMainCleanup
{
public :
CMainCleanup ( ) { }
~ CMainCleanup ( ) {
// block headers
2014-09-04 02:02:44 +02:00
BlockMap : : iterator it1 = mapBlockIndex . begin ( ) ;
2013-03-29 02:17:10 +01:00
for ( ; it1 ! = mapBlockIndex . end ( ) ; it1 + + )
delete ( * it1 ) . second ;
mapBlockIndex . clear ( ) ;
}
} instance_of_cmaincleanup ;