2010-08-29 18:58:15 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2015-12-13 14:51:43 +01:00
// Copyright (c) 2009-2015 The Bitcoin Core developers
2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash 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-08-09 02:19:06 +02:00
# include "validation.h"
2013-08-27 07:51:57 +02:00
2012-08-28 23:04:54 +02:00
# include "alert.h"
2015-02-05 01:11:44 +01:00
# include "arith_uint256.h"
Backport compact blocks functionality from bitcoin (#1966)
* Merge #8068: Compact Blocks
48efec8 Fix some minor compact block issues that came up in review (Matt Corallo)
ccd06b9 Elaborate bucket size math (Pieter Wuille)
0d4cb48 Use vTxHashes to optimize InitData significantly (Matt Corallo)
8119026 Provide a flat list of txid/terators to txn in CTxMemPool (Matt Corallo)
678ee97 Add BIP 152 to implemented BIPs list (Matt Corallo)
56ba516 Add reconstruction debug logging (Matt Corallo)
2f34a2e Get our "best three" peers to announce blocks using cmpctblocks (Matt Corallo)
927f8ee Add ability to fetch CNode by NodeId (Matt Corallo)
d25cd3e Add receiver-side protocol implementation for CMPCTBLOCK stuff (Matt Corallo)
9c837d5 Add sender-side protocol implementation for CMPCTBLOCK stuff (Matt Corallo)
00c4078 Add protocol messages for short-ids blocks (Matt Corallo)
e3b2222 Add some blockencodings tests (Matt Corallo)
f4f8f14 Add TestMemPoolEntryHelper::FromTx version for CTransaction (Matt Corallo)
85ad31e Add partial-block block encodings API (Matt Corallo)
5249dac Add COMPACTSIZE wrapper similar to VARINT for serialization (Matt Corallo)
cbda71c Move context-required checks from CheckBlockHeader to Contextual... (Matt Corallo)
7c29ec9 If AcceptBlockHeader returns true, pindex will be set. (Matt Corallo)
96806c3 Stop trimming when mapTx is empty (Pieter Wuille)
* Merge #8408: Prevent fingerprinting, disk-DoS with compact blocks
1d06e49 Ignore CMPCTBLOCK messages for pruned blocks (Suhas Daftuar)
1de2a46 Ignore GETBLOCKTXN requests for unknown blocks (Suhas Daftuar)
* Merge #8418: Add tests for compact blocks
45c7ddd Add p2p test for BIP 152 (compact blocks) (Suhas Daftuar)
9a22a6c Add support for compactblocks to mininode (Suhas Daftuar)
a8689fd Tests: refactor compact size serialization in mininode (Suhas Daftuar)
9c8593d Implement SipHash in Python (Pieter Wuille)
56c87e9 Allow changing BIP9 parameters on regtest (Suhas Daftuar)
* Merge #8505: Trivial: Fix typos in various files
1aacfc2 various typos (leijurv)
* Merge #8449: [Trivial] Do not shadow local variable, cleanup
a159f25 Remove redundand (and shadowing) declaration (Pavel Janík)
cce3024 Do not shadow local variable, cleanup (Pavel Janík)
* Merge #8739: [qa] Fix broken sendcmpct test in p2p-compactblocks.py
157254a Fix broken sendcmpct test in p2p-compactblocks.py (Suhas Daftuar)
* Merge #8854: [qa] Fix race condition in p2p-compactblocks test
b5fd666 [qa] Fix race condition in p2p-compactblocks test (Suhas Daftuar)
* Merge #8393: Support for compact blocks together with segwit
27acfc1 [qa] Update p2p-compactblocks.py for compactblocks v2 (Suhas Daftuar)
422fac6 [qa] Add support for compactblocks v2 to mininode (Suhas Daftuar)
f5b9b8f [qa] Fix bug in mininode witness deserialization (Suhas Daftuar)
6aa28ab Use cmpctblock type 2 for segwit-enabled transfer (Pieter Wuille)
be7555f Fix overly-prescriptive p2p-segwit test for new fetch logic (Matt Corallo)
06128da Make GetFetchFlags always request witness objects from witness peers (Matt Corallo)
* Merge #8882: [qa] Fix race conditions in p2p-compactblocks.py and sendheaders.py
b55d941 [qa] Fix race condition in sendheaders.py (Suhas Daftuar)
6976db2 [qa] Another attempt to fix race condition in p2p-compactblocks.py (Suhas Daftuar)
* Merge #8904: [qa] Fix compact block shortids for a test case
4cdece4 [qa] Fix compact block shortids for a test case (Dagur Valberg Johannsson)
* Merge #8637: Compact Block Tweaks (rebase of #8235)
3ac6de0 Align constant names for maximum compact block / blocktxn depth (Pieter Wuille)
b2e93a3 Add cmpctblock to debug help list (instagibbs)
fe998e9 More agressively filter compact block requests (Matt Corallo)
02a337d Dont remove a "preferred" cmpctblock peer if they provide a block (Matt Corallo)
* Merge #8975: Chainparams: Trivial: In AppInit2(), s/Params()/chainparams/
6f2f639 Chainparams: Trivial: In AppInit2(), s/Params()/chainparams/ (Jorge Timón)
* Merge #8968: Don't hold cs_main when calling ProcessNewBlock from a cmpctblock
72ca7d9 Don't hold cs_main when calling ProcessNewBlock from a cmpctblock (Matt Corallo)
* Merge #8995: Add missing cs_main lock to ::GETBLOCKTXN processing
dfe7906 Add missing cs_main lock to ::GETBLOCKTXN processing (Matt Corallo)
* Merge #8515: A few mempool removal optimizations
0334430 Add some missing includes (Pieter Wuille)
4100499 Return shared_ptr<CTransaction> from mempool removes (Pieter Wuille)
51f2783 Make removed and conflicted arguments optional to remove (Pieter Wuille)
f48211b Bypass removeRecursive in removeForReorg (Pieter Wuille)
* Merge #9026: Fix handling of invalid compact blocks
d4833ff Bump the protocol version to distinguish new banning behavior. (Suhas Daftuar)
88c3549 Fix compact block handling to not ban if block is invalid (Suhas Daftuar)
c93beac [qa] Test that invalid compactblocks don't result in ban (Suhas Daftuar)
* Merge #9039: Various serialization simplifcations and optimizations
d59a518 Use fixed preallocation instead of costly GetSerializeSize (Pieter Wuille)
25a211a Add optimized CSizeComputer serializers (Pieter Wuille)
a2929a2 Make CSerAction's ForRead() constexpr (Pieter Wuille)
a603925 Avoid -Wshadow errors (Pieter Wuille)
5284721 Get rid of nType and nVersion (Pieter Wuille)
657e05a Make GetSerializeSize a wrapper on top of CSizeComputer (Pieter Wuille)
fad9b66 Make nType and nVersion private and sometimes const (Pieter Wuille)
c2c5d42 Make streams' read and write return void (Pieter Wuille)
50e8a9c Remove unused ReadVersion and WriteVersion (Pieter Wuille)
* Merge #9058: Fixes for p2p-compactblocks.py test timeouts on travis (#8842)
dac53b5 Modify getblocktxn handler not to drop requests for old blocks (Russell Yanofsky)
55bfddc [qa] Fix stale data bug in test_compactblocks_not_at_tip (Russell Yanofsky)
47e9659 [qa] Fix bug in compactblocks v2 merge (Russell Yanofsky)
* Merge #9160: [trivial] Fix hungarian variable name
ec34648 [trivial] Fix hungarian variable name (Russell Yanofsky)
* Merge #9159: [qa] Wait for specific block announcement in p2p-compactblocks
dfa44d1 [qa] Wait for specific block announcement in p2p-compactblocks (Russell Yanofsky)
* Merge #9125: Make CBlock a vector of shared_ptr of CTransactions
b4e4ba4 Introduce convenience type CTransactionRef (Pieter Wuille)
1662b43 Make CBlock::vtx a vector of shared_ptr<CTransaction> (Pieter Wuille)
da60506 Add deserializing constructors to CTransaction and CMutableTransaction (Pieter Wuille)
0e85204 Add serialization for unique_ptr and shared_ptr (Pieter Wuille)
* Merge #8872: Remove block-request logic from INV message processing
037159c Remove block-request logic from INV message processing (Matt Corallo)
3451203 [qa] Respond to getheaders and do not assume a getdata on inv (Matt Corallo)
d768f15 [qa] Make comptool push blocks instead of relying on inv-fetch (mrbandrews)
* Merge #9199: Always drop the least preferred HB peer when adding a new one.
ca8549d Always drop the least preferred HB peer when adding a new one. (Gregory Maxwell)
* Merge #9233: Fix some typos
15fa95d Fix some typos (fsb4000)
* Merge #9260: Mrs Peacock in The Library with The Candlestick (killed main.{h,cpp})
76faa3c Rename the remaining main.{h,cpp} to validation.{h,cpp} (Matt Corallo)
e736772 Move network-msg-processing code out of main to its own file (Matt Corallo)
87c35f5 Remove orphan state wipe from UnloadBlockIndex. (Matt Corallo)
* Merge #9014: Fix block-connection performance regression
dd0df81 Document ConnectBlock connectTrace postconditions (Matt Corallo)
2d6e561 Switch pblock in ProcessNewBlock to a shared_ptr (Matt Corallo)
2736c44 Make the optional pblock in ActivateBestChain a shared_ptr (Matt Corallo)
ae4db44 Create a shared_ptr for the block we're connecting in ActivateBCS (Matt Corallo)
fd9d890 Keep blocks as shared_ptrs, instead of copying txn in ConnectTip (Matt Corallo)
6fdd43b Add struct to track block-connect-time-generated info for callbacks (Matt Corallo)
* Merge #9240: Remove txConflicted
a874ab5 remove internal tracking of mempool conflicts for reporting to wallet (Alex Morcos)
bf663f8 remove external usage of mempool conflict tracking (Alex Morcos)
* Merge #9344: Do not run functions with necessary side-effects in assert()
da9cdd2 Do not run functions with necessary side-effects in assert() (Gregory Maxwell)
* Merge #9273: Remove unused CDiskBlockPos* argument from ProcessNewBlock
a13fa4c Remove unused CDiskBlockPos* argument from ProcessNewBlock (Matt Corallo)
* Merge #9352: Attempt reconstruction from all compact block announcements
813ede9 [qa] Update compactblocks test for multi-peer reconstruction (Suhas Daftuar)
7017298 Allow compactblock reconstruction when block is in flight (Suhas Daftuar)
* Merge #9252: Release cs_main before calling ProcessNewBlock, or processing headers (cmpctblock handling)
bd02bdd Release cs_main before processing cmpctblock as header (Suhas Daftuar)
680b0c0 Release cs_main before calling ProcessNewBlock (cmpctblock handling) (Suhas Daftuar)
* Merge #9283: A few more CTransactionRef optimizations
91335ba Remove unused MakeTransactionRef overloads (Pieter Wuille)
6713f0f Make FillBlock consume txn_available to avoid shared_ptr copies (Pieter Wuille)
62607d7 Convert COrphanTx to keep a CTransactionRef (Pieter Wuille)
c44e4c4 Make AcceptToMemoryPool take CTransactionRef (Pieter Wuille)
* Merge #9375: Relay compact block messages prior to full block connection
02ee4eb Make most_recent_compact_block a pointer to a const (Matt Corallo)
73666ad Add comment to describe callers to ActivateBestChain (Matt Corallo)
962f7f0 Call ActivateBestChain without cs_main/with most_recent_block (Matt Corallo)
0df777d Use a temp pindex to avoid a const_cast in ProcessNewBlockHeaders (Matt Corallo)
c1ae4fc Avoid holding cs_most_recent_block while calling ReadBlockFromDisk (Matt Corallo)
9eb67f5 Ensure we meet the BIP 152 old-relay-types response requirements (Matt Corallo)
5749a85 Cache most-recently-connected compact block (Matt Corallo)
9eaec08 Cache most-recently-announced block's shared_ptr (Matt Corallo)
c802092 Relay compact block messages prior to full block connection (Matt Corallo)
6987219 Add a CValidationInterface::NewPoWValidBlock callback (Matt Corallo)
180586f Call AcceptBlock with the block's shared_ptr instead of CBlock& (Matt Corallo)
8baaba6 [qa] Avoid race in preciousblock test. (Matt Corallo)
9a0b2f4 [qa] Make compact blocks test construction using fetch methods (Matt Corallo)
8017547 Make CBlockIndex*es in net_processing const (Matt Corallo)
* Merge #9486: Make peer=%d log prints consistent
e6111b2 Make peer id logging consistent ("peer=%d" instead of "peer %d") (Matt Corallo)
* Merge #9400: Set peers as HB peers upon full block validation
d4781ac Set peers as HB peers upon full block validation (Gregory Sanders)
* Merge #9499: Use recent-rejects, orphans, and recently-replaced txn for compact-block-reconstruction
c594580 Add braces around AddToCompactExtraTransactions (Matt Corallo)
1ccfe9b Clarify comment about mempool/extra conflicts (Matt Corallo)
fac4c78 Make PartiallyDownloadedBlock::InitData's second param const (Matt Corallo)
b55b416 Add extra_count lower bound to compact reconstruction debug print (Matt Corallo)
863edb4 Consider all (<100k memusage) txn for compact-block-extra-txn cache (Matt Corallo)
7f8c8ca Consider all orphan txn for compact-block-extra-txn cache (Matt Corallo)
93380c5 Use replaced transactions in compact block reconstruction (Matt Corallo)
1531652 Keep shared_ptrs to recently-replaced txn for compact blocks (Matt Corallo)
edded80 Make ATMP optionally return the CTransactionRefs it replaced (Matt Corallo)
c735540 Move ORPHAN constants from validation.h to net_processing.h (Matt Corallo)
* Merge #9587: Do not shadow local variable named `tx`.
44f2baa Do not shadow local variable named `tx`. (Pavel Janík)
* Merge #9510: [trivial] Fix typos in comments
cc16d99 [trivial] Fix typos in comments (practicalswift)
* Merge #9604: [Trivial] add comment about setting peer as HB peer.
dd5b011 [Trivial] add comment about setting peer as HB peer. (John Newbery)
* Fix using of AcceptToMemoryPool in PrivateSend code
* add `override`
* fSupportsDesiredCmpctVersion
* bring back tx ressurection in DisconnectTip
* Fix delayed headers
* Remove unused CConnman::FindNode overload
* Fix typos and comments
* Fix minor code differences
* Don't use rejection cache for corrupted transactions
Partly based on https://github.com/bitcoin/bitcoin/pull/8525
* Backport missed cs_main locking changes
Missed from https://github.com/bitcoin/bitcoin/commit/58a215ce8c13b900cf982c39f8ee4879290d1a95
* Backport missed comments and mapBlockSource.emplace call
Missed from two commits:
https://github.com/bitcoin/bitcoin/commit/88c35491ab19f9afdf9b3fa9356a072f70ef2f55
https://github.com/bitcoin/bitcoin/commit/7c98ce584ec23bcddcba8cdb33efa6547212f6ef
* Add CheckPeerHeaders() helper and check in (nCount == 0) too
2018-04-11 13:06:01 +02:00
# include "blockencodings.h"
2013-08-27 07:51:57 +02:00
# include "chainparams.h"
2011-09-08 22:50:58 +02:00
# include "checkpoints.h"
2013-08-27 07:51:57 +02:00
# include "checkqueue.h"
2015-06-24 07:25:30 +02:00
# include "consensus/consensus.h"
2015-11-17 17:35:44 +01:00
# include "consensus/merkle.h"
2015-01-24 15:57:12 +01:00
# include "consensus/validation.h"
2015-07-05 14:17:46 +02:00
# include "hash.h"
2011-05-15 23:52:31 +02:00
# include "init.h"
2015-06-24 07:25:30 +02:00
# include "policy/policy.h"
2014-03-10 16:46:53 +01:00
# include "pow.h"
2015-07-05 14:30:07 +02:00
# include "primitives/block.h"
# include "primitives/transaction.h"
# include "script/script.h"
# include "script/sigcache.h"
# include "script/standard.h"
2017-08-09 02:19:06 +02:00
# include "timedata.h"
2015-07-05 14:30:07 +02:00
# include "tinyformat.h"
2013-08-27 07:51:57 +02:00
# include "txdb.h"
# include "txmempool.h"
2012-04-15 22:10:54 +02:00
# include "ui_interface.h"
2014-10-27 14:42:49 +01:00
# include "undo.h"
2013-04-13 07:13:08 +02:00
# include "util.h"
2015-02-09 20:28:29 +01:00
# include "spork.h"
2013-08-06 03:27:09 +02:00
# include "utilmoneystr.h"
2015-07-05 14:17:46 +02:00
# include "utilstrencodings.h"
2015-02-05 01:11:44 +01:00
# include "validationinterface.h"
2016-02-15 05:13:27 +01:00
# include "versionbits.h"
2016-12-19 12:38:35 +01:00
# include "warnings.h"
2013-04-13 07:13:08 +02:00
2016-12-20 14:27:59 +01:00
# include "instantx.h"
2017-09-11 16:13:30 +02:00
# include "masternodeman.h"
2016-12-20 14:27:59 +01:00
# include "masternode-payments.h"
2018-02-13 13:34:35 +01:00
# include "evo/specialtx.h"
2018-02-13 13:36:36 +01:00
# include "evo/providertx.h"
2018-02-14 14:43:03 +01:00
# include "evo/deterministicmns.h"
2018-04-06 11:00:10 +02:00
# include "evo/cbtx.h"
2018-02-13 13:34:35 +01:00
2016-06-06 15:45:25 +02:00
# include <atomic>
2013-10-28 07:36:11 +01:00
# include <sstream>
2013-04-13 07:13:08 +02:00
# include <boost/algorithm/string/replace.hpp>
2016-05-25 18:17:47 +02:00
# include <boost/algorithm/string/join.hpp>
2013-04-13 07:13:08 +02:00
# include <boost/filesystem.hpp>
# include <boost/filesystem/fstream.hpp>
2015-02-02 12:42:41 +01:00
# include <boost/lexical_cast.hpp>
2015-03-26 16:20:59 +01:00
# include <boost/math/distributions/poisson.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)
2016-07-29 07:30:19 +02:00
# error "Dash Core cannot be compiled without assertions."
2013-12-02 20:33:44 +01:00
# endif
2014-12-01 02:39:44 +01:00
/**
* Global state
*/
2010-08-29 18:58:15 +02:00
CCriticalSection cs_main ;
2014-09-04 02:02:44 +02:00
BlockMap mapBlockIndex ;
2013-10-10 23:07:44 +02:00
CChain chainActive ;
2014-07-12 00:03:10 +02:00
CBlockIndex * pindexBestHeader = NULL ;
2012-05-13 06:43:24 +02:00
CWaitableCriticalSection csBestBlock ;
CConditionVariable cvBlockChange ;
2012-12-01 23:04:14 +01:00
int nScriptCheckThreads = 0 ;
2016-11-29 12:38:12 +01:00
std : : atomic_bool fImporting ( false ) ;
2012-10-21 21:23:13 +02:00
bool fReindex = false ;
2015-07-16 16:34:40 +02:00
bool fTxIndex = true ;
2016-03-05 22:31:10 +01:00
bool fAddressIndex = false ;
2016-03-22 23:11:04 +01:00
bool fTimestampIndex = false ;
2016-04-05 21:53:38 +02:00
bool fSpentIndex = 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 ;
2014-02-22 03:41:01 +01:00
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP ;
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-06-12 12:00:39 +02:00
bool fAlerts = DEFAULT_ALERTS ;
2016-01-18 11:55:52 +01:00
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE ;
2014-07-12 00:03:10 +02:00
2017-09-15 20:08:03 +02:00
std : : atomic < bool > fDIP0001ActiveAtTip { false } ;
2018-02-14 21:31:42 +01:00
std : : atomic < bool > fDIP0003ActiveAtTip { false } ;
2017-09-15 20:08:03 +02:00
2017-08-23 16:21:08 +02:00
uint256 hashAssumeValid ;
2017-12-07 10:43:23 +01:00
CFeeRate minRelayTxFee = CFeeRate ( DEFAULT_MIN_RELAY_TX_FEE ) ;
2016-02-02 15:17:51 +01:00
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE ;
2013-04-26 02:11:27 +02:00
2014-07-03 20:25:32 +02:00
CTxMemPool mempool ( : : minRelayTxFee ) ;
2018-02-21 20:26:53 +01:00
std : : map < uint256 , int64_t > mapRejectedBlocks GUARDED_BY ( cs_main ) ;
2015-08-05 02:58:41 +02:00
2015-04-17 14:19:21 +02:00
static void CheckBlockIndex ( const Consensus : : Params & consensusParams ) ;
2015-03-13 17:25:34 +01: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
2017-01-30 13:13:07 +01:00
const std : : string strMessageMagic = " DarkCoin Signed Message: \n " ;
2011-12-23 16:14:57 +01:00
2013-10-14 02:13:44 +02:00
// Internal stuff
namespace {
2014-06-24 14:17:43 +02:00
2014-04-30 08:57:11 +02:00
struct CBlockIndexWorkComparator
{
2015-03-13 17:25:34 +01:00
bool operator ( ) ( CBlockIndex * pa , CBlockIndex * pb ) const {
2014-04-30 08:57:11 +02:00
// First sort by most total work, ...
if ( pa - > nChainWork > pb - > nChainWork ) return false ;
if ( pa - > nChainWork < pb - > nChainWork ) return true ;
// ... then by earliest time received, ...
if ( pa - > nSequenceId < pb - > nSequenceId ) return false ;
if ( pa - > nSequenceId > pb - > nSequenceId ) return true ;
// Use pointer address as tie breaker (should only happen with blocks
// loaded from disk, as those all have id 0).
if ( pa < pb ) return false ;
if ( pa > pb ) return true ;
// Identical blocks.
return false ;
}
} ;
CBlockIndex * pindexBestInvalid ;
2014-07-09 18:04:18 +02:00
2014-12-01 02:39:44 +01:00
/**
2015-03-13 17:25:34 +01:00
* The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS ( for itself and all ancestors ) and
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
* as good as our current tip or better . Entries may be failed , though , and pruning nodes may be
* missing the data for the block .
2014-12-01 02:39:44 +01:00
*/
2017-01-30 13:13:07 +01:00
std : : set < CBlockIndex * , CBlockIndexWorkComparator > setBlockIndexCandidates ;
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-01-30 13:13:07 +01:00
std : : multimap < CBlockIndex * , CBlockIndex * > 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
/**
* Every received block is assigned a unique and increasing identifier , so we
* know which one to give priority in case of a fork .
*/
2014-04-30 08:57:11 +02:00
CCriticalSection cs_nBlockSequenceId ;
2014-12-01 02:39:44 +01:00
/** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
2016-10-18 21:35:27 +02:00
int32_t nBlockSequenceId = 1 ;
/** Decreasing counter (used by subsequent preciousblock calls). */
int32_t nBlockReverseSequenceId = - 1 ;
/** chainwork for the last block that preciousblock has been applied to. */
arith_uint256 nLastPreciousChainwork = 0 ;
2014-04-30 08:57:11 +02:00
2014-12-01 02:39:44 +01:00
/** Dirty block index entries. */
2017-01-30 13:13:07 +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-30 13:13:07 +01:00
std : : set < int > setDirtyFileInfo ;
2014-06-24 14:17:43 +02:00
} // anon namespace
2013-11-18 01:25:17 +01:00
2017-01-24 10:07:50 +01:00
/* Use this class to start tracking transactions that are removed from the
* mempool and pass all those transactions through SyncTransaction when the
* object goes out of scope . This is currently only used to call SyncTransaction
* on conflicts removed from the mempool during block connection . Applied in
* ActivateBestChain around ActivateBestStep which in turn calls :
* ConnectTip - > removeForBlock - > removeConflicts
*/
class MemPoolConflictRemovalTracker
{
private :
std : : vector < CTransactionRef > conflictedTxs ;
CTxMemPool & pool ;
public :
MemPoolConflictRemovalTracker ( CTxMemPool & _pool ) : pool ( _pool ) {
pool . NotifyEntryRemoved . connect ( boost : : bind ( & MemPoolConflictRemovalTracker : : NotifyEntryRemoved , this , _1 , _2 ) ) ;
}
void NotifyEntryRemoved ( CTransactionRef txRemoved , MemPoolRemovalReason reason ) {
if ( reason = = MemPoolRemovalReason : : CONFLICT ) {
conflictedTxs . push_back ( txRemoved ) ;
}
}
~ MemPoolConflictRemovalTracker ( ) {
pool . NotifyEntryRemoved . disconnect ( boost : : bind ( & MemPoolConflictRemovalTracker : : NotifyEntryRemoved , this , _1 , _2 ) ) ;
for ( const auto & tx : conflictedTxs ) {
GetMainSignals ( ) . SyncTransaction ( * tx , NULL , CMainSignals : : SYNC_TRANSACTION_NOT_IN_BLOCK ) ;
}
conflictedTxs . clear ( ) ;
}
} ;
2014-09-03 02:52:01 +02:00
CBlockIndex * FindForkInGlobalIndex ( const CChain & chain , const CBlockLocator & locator )
{
2013-05-07 13:59:29 +02:00
// Find the first block the caller has in the main chain
2013-10-12 15:18:08 +02:00
BOOST_FOREACH ( const uint256 & hash , locator . vHave ) {
2014-09-04 02:02:44 +02:00
BlockMap : : iterator mi = mapBlockIndex . find ( hash ) ;
2013-05-07 13:59:29 +02:00
if ( mi ! = mapBlockIndex . end ( ) )
{
CBlockIndex * pindex = ( * mi ) . second ;
2014-09-03 02:52:01 +02:00
if ( chain . Contains ( pindex ) )
2013-05-07 13:59:29 +02:00
return pindex ;
}
}
2014-09-03 02:52:01 +02:00
return chain . Genesis ( ) ;
2013-10-10 23:07:44 +02:00
}
2017-06-12 16:19:08 +02:00
CCoinsViewDB * pcoinsdbview = NULL ;
2012-07-06 16:33:34 +02:00
CCoinsViewCache * pcoinsTip = NULL ;
2012-09-03 15:26:57 +02:00
CBlockTreeDB * pblocktree = NULL ;
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-08-01 17:11:32 +02:00
enum FlushStateMode {
FLUSH_STATE_NONE ,
FLUSH_STATE_IF_NEEDED ,
FLUSH_STATE_PERIODIC ,
FLUSH_STATE_ALWAYS
} ;
// See definition for documentation
2017-01-11 14:16:11 +01:00
bool static FlushStateToDisk ( CValidationState & state , FlushStateMode mode , int nManualPruneHeight = 0 ) ;
void FindFilesToPruneManual ( std : : set < int > & setFilesToPrune , int nManualPruneHeight ) ;
2017-08-01 17:11:32 +02:00
2013-04-13 07:13:08 +02:00
bool IsFinalTx ( const CTransaction & tx , int nBlockHeight , int64_t nBlockTime )
2013-01-08 13:17:15 +01:00
{
if ( tx . nLockTime = = 0 )
return true ;
2013-04-13 07:13:08 +02:00
if ( ( int64_t ) tx . nLockTime < ( ( int64_t ) tx . nLockTime < LOCKTIME_THRESHOLD ? ( int64_t ) nBlockHeight : nBlockTime ) )
2013-01-08 13:17:15 +01:00
return true ;
2016-07-21 11:43:43 +02:00
for ( const auto & txin : tx . vin ) {
2015-12-07 21:44:16 +01:00
if ( ! ( txin . nSequence = = CTxIn : : SEQUENCE_FINAL ) )
2013-01-08 13:17:15 +01:00
return false ;
2015-12-07 21:44:16 +01:00
}
2013-01-08 13:17:15 +01:00
return true ;
}
2015-11-03 18:12:36 +01:00
bool CheckFinalTx ( const CTransaction & tx , int flags )
2011-10-03 19:05:43 +02:00
{
2015-05-25 06:48:33 +02:00
AssertLockHeld ( cs_main ) ;
2011-10-03 19:05:43 +02:00
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 ;
2015-11-13 22:36:54 +01:00
// BIP113 will require that time-locked transactions have nLockTime set to
// 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 ) ;
2011-10-03 19:05:43 +02:00
}
2015-12-07 21:44:16 +01:00
/**
* Calculates the block height and previous block ' s median time past at
* which the transaction will be considered final in the context of BIP 68.
* Also removes from the vector of input heights any entries which did not
* correspond to sequence locked inputs as they do not affect the calculation .
*/
static std : : pair < int , int64_t > CalculateSequenceLocks ( const CTransaction & tx , int flags , std : : vector < int > * prevHeights , const CBlockIndex & block )
{
assert ( prevHeights - > size ( ) = = tx . vin . size ( ) ) ;
// Will be set to the equivalent height- and time-based nLockTime
// values that would be necessary to satisfy all relative lock-
// time constraints given our view of block chain history.
// The semantics of nLockTime are the last invalid height/time, so
// use -1 to have the effect of any height or time being valid.
int nMinHeight = - 1 ;
int64_t nMinTime = - 1 ;
// tx.nVersion is signed integer so requires cast to unsigned otherwise
// we would be doing a signed comparison and half the range of nVersion
// wouldn't support BIP 68.
bool fEnforceBIP68 = static_cast < uint32_t > ( tx . nVersion ) > = 2
& & flags & LOCKTIME_VERIFY_SEQUENCE ;
// Do not enforce sequence numbers as a relative lock time
// unless we have been instructed to
if ( ! fEnforceBIP68 ) {
return std : : make_pair ( nMinHeight , nMinTime ) ;
}
for ( size_t txinIndex = 0 ; txinIndex < tx . vin . size ( ) ; txinIndex + + ) {
const CTxIn & txin = tx . vin [ txinIndex ] ;
// Sequence numbers with the most significant bit set are not
// treated as relative lock-times, nor are they given any
// consensus-enforced meaning at this point.
if ( txin . nSequence & CTxIn : : SEQUENCE_LOCKTIME_DISABLE_FLAG ) {
// The height of this input is not relevant for sequence locks
( * prevHeights ) [ txinIndex ] = 0 ;
continue ;
}
int nCoinHeight = ( * prevHeights ) [ txinIndex ] ;
if ( txin . nSequence & CTxIn : : SEQUENCE_LOCKTIME_TYPE_FLAG ) {
int64_t nCoinTime = block . GetAncestor ( std : : max ( nCoinHeight - 1 , 0 ) ) - > GetMedianTimePast ( ) ;
// NOTE: Subtract 1 to maintain nLockTime semantics
// BIP 68 relative lock times have the semantics of calculating
// the first block or time at which the transaction would be
// valid. When calculating the effective block time or height
// for the entire transaction, we switch to using the
// semantics of nLockTime which is the last invalid block
// time or height. Thus we subtract 1 from the calculated
// time or height.
// Time-based relative lock-times are measured from the
// smallest allowed timestamp of the block containing the
// txout being spent, which is the median time past of the
// block prior.
2017-09-21 15:58:23 +02:00
nMinTime = std : : max ( nMinTime , nCoinTime + ( int64_t ) ( ( txin . nSequence & CTxIn : : SEQUENCE_LOCKTIME_MASK ) < < CTxIn : : SEQUENCE_LOCKTIME_GRANULARITY ) - 1 ) ;
2015-12-07 21:44:16 +01:00
} else {
2017-09-21 15:58:23 +02:00
nMinHeight = std : : max ( nMinHeight , nCoinHeight + ( int ) ( txin . nSequence & CTxIn : : SEQUENCE_LOCKTIME_MASK ) - 1 ) ;
2015-12-07 21:44:16 +01:00
}
}
return std : : make_pair ( nMinHeight , nMinTime ) ;
}
static bool EvaluateSequenceLocks ( const CBlockIndex & block , std : : pair < int , int64_t > lockPair )
{
assert ( block . pprev ) ;
int64_t nBlockTime = block . pprev - > GetMedianTimePast ( ) ;
if ( lockPair . first > = block . nHeight | | lockPair . second > = nBlockTime )
return false ;
return true ;
}
bool SequenceLocks ( const CTransaction & tx , int flags , std : : vector < int > * prevHeights , const CBlockIndex & block )
{
return EvaluateSequenceLocks ( block , CalculateSequenceLocks ( tx , flags , prevHeights , block ) ) ;
}
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 ( ) ;
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()
CCoinsViewMemPool viewMemPool ( pcoinsTip , mempool ) ;
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-06-02 00:47:58 +02:00
Coin coin ;
if ( ! viewMemPool . GetCoin ( txin . prevout , coin ) ) {
2015-12-04 21:01:22 +01:00
return error ( " %s: Missing input " , __func__ ) ;
}
2017-06-02 00:47:58 +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-06-02 00:47:58 +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 ;
BOOST_FOREACH ( int height , prevheights ) {
// 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 ) ;
}
2013-01-08 13:17:15 +01:00
unsigned int GetLegacySigOpCount ( const CTransaction & tx )
2012-01-05 03:40:52 +01:00
{
2012-04-23 20:14:03 +02:00
unsigned int nSigOps = 0 ;
2016-07-21 11:43:43 +02:00
for ( const auto & txin : tx . vin )
2012-01-05 03:40:52 +01:00
{
nSigOps + = txin . scriptSig . GetSigOpCount ( false ) ;
}
2016-07-21 11:43:43 +02:00
for ( const auto & txout : tx . vout )
2012-01-05 03:40:52 +01:00
{
nSigOps + = txout . scriptPubKey . GetSigOpCount ( false ) ;
}
return nSigOps ;
}
2010-08-29 18:58:15 +02:00
2014-07-19 17:14:23 +02:00
unsigned int GetP2SHSigOpCount ( const CTransaction & tx , const CCoinsViewCache & inputs )
2013-01-08 13:17:15 +01:00
{
if ( tx . IsCoinBase ( ) )
return 0 ;
unsigned int nSigOps = 0 ;
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + )
{
2017-06-21 03:18:09 +02:00
const Coin & coin = inputs . AccessCoin ( tx . vin [ i ] . prevout ) ;
assert ( ! coin . IsSpent ( ) ) ;
const CTxOut & prevout = coin . out ;
2013-01-08 13:17:15 +01:00
if ( prevout . scriptPubKey . IsPayToScriptHash ( ) )
nSigOps + = prevout . scriptPubKey . GetSigOpCount ( tx . vin [ i ] . scriptSig ) ;
}
return nSigOps ;
}
2010-08-29 18:58:15 +02:00
2017-09-26 16:33:46 +02:00
bool GetUTXOCoin ( const COutPoint & outpoint , Coin & coin )
2017-01-29 09:22:14 +01:00
{
LOCK ( cs_main ) ;
2017-09-26 16:33:46 +02:00
if ( ! pcoinsTip - > GetCoin ( outpoint , coin ) )
return false ;
if ( coin . IsSpent ( ) )
return false ;
return true ;
2014-12-09 02:17:57 +01:00
}
2010-08-29 18:58:15 +02:00
2017-08-25 14:56:48 +02:00
int GetUTXOHeight ( const COutPoint & outpoint )
2016-03-23 15:49:35 +01:00
{
2017-08-25 14:56:48 +02:00
// -1 means UTXO is yet unknown or already spent
2017-09-26 16:33:46 +02:00
Coin coin ;
return GetUTXOCoin ( outpoint , coin ) ? coin . nHeight : - 1 ;
2015-07-13 01:37:55 +02:00
}
2010-08-29 18:58:15 +02:00
2017-08-25 14:56:48 +02:00
int GetUTXOConfirmations ( const COutPoint & outpoint )
2016-03-23 15:49:35 +01:00
{
2017-08-25 14:56:48 +02:00
// -1 means UTXO is yet unknown or already spent
LOCK ( cs_main ) ;
int nPrevoutHeight = GetUTXOHeight ( outpoint ) ;
return ( nPrevoutHeight > - 1 & & chainActive . Tip ( ) ) ? chainActive . Height ( ) - nPrevoutHeight + 1 : - 1 ;
2015-07-14 05:03:08 +02:00
}
2018-09-19 14:04:35 +02:00
bool CheckTransaction ( const CTransaction & tx , CValidationState & state )
2010-09-30 18:23:07 +02:00
{
// Basic checks that don't depend on any context
2013-01-08 13:17:15 +01:00
if ( tx . vin . empty ( ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 10 , false , REJECT_INVALID , " bad-txns-vin-empty " ) ;
2013-01-08 13:17:15 +01:00
if ( tx . vout . empty ( ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 10 , false , REJECT_INVALID , " bad-txns-vout-empty " ) ;
2010-09-30 18:23:07 +02:00
// Size limits
2017-09-11 16:13:30 +02:00
if ( : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) > MAX_LEGACY_BLOCK_SIZE )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-oversize " ) ;
2018-02-13 13:33:23 +01:00
if ( tx . vExtraPayload . size ( ) > MAX_TX_EXTRA_PAYLOAD )
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-payload-oversize " ) ;
2010-09-30 18:23:07 +02:00
// Check for negative or overflow output values
2014-04-23 00:46:19 +02:00
CAmount nValueOut = 0 ;
2016-07-21 11:43:43 +02:00
for ( const auto & txout : tx . vout )
2010-09-30 18:23:07 +02:00
{
if ( txout . nValue < 0 )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-vout-negative " ) ;
2010-09-30 18:23:07 +02:00
if ( txout . nValue > MAX_MONEY )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-vout-toolarge " ) ;
2010-09-30 18:23:07 +02:00
nValueOut + = txout . nValue ;
if ( ! MoneyRange ( nValueOut ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-txouttotal-toolarge " ) ;
2010-09-30 18:23:07 +02:00
}
2018-09-19 14:04:35 +02:00
// Check for duplicate inputs
std : : set < COutPoint > vInOutPoints ;
for ( const auto & txin : tx . vin )
{
if ( ! vInOutPoints . insert ( txin . prevout ) . second )
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-inputs-duplicate " ) ;
2011-07-30 23:01:45 +02:00
}
2013-01-08 13:17:15 +01:00
if ( tx . IsCoinBase ( ) )
2010-09-30 18:23:07 +02:00
{
2018-09-28 09:55:11 +02:00
size_t minCbSize = 2 ;
2018-04-06 11:00:10 +02:00
if ( tx . nType = = TRANSACTION_COINBASE ) {
// With the introduction of CbTx, coinbase scripts are not required anymore to hold a valid block height
minCbSize = 1 ;
}
if ( tx . vin [ 0 ] . scriptSig . size ( ) < minCbSize | | tx . vin [ 0 ] . scriptSig . size ( ) > 100 )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-cb-length " ) ;
2010-09-30 18:23:07 +02:00
}
else
{
2016-07-21 11:43:43 +02:00
for ( const auto & txin : tx . vin )
2010-09-30 18:23:07 +02:00
if ( txin . prevout . IsNull ( ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 10 , false , REJECT_INVALID , " bad-txns-prevout-null " ) ;
2010-09-30 18:23:07 +02:00
}
return true ;
}
2018-08-28 13:43:58 +02:00
bool ContextualCheckTransaction ( const CTransaction & tx , CValidationState & state , const Consensus : : Params & consensusParams , const CBlockIndex * pindexPrev )
2017-09-11 16:13:30 +02:00
{
2018-03-08 13:18:24 +01:00
int nHeight = pindexPrev = = NULL ? 0 : pindexPrev - > nHeight + 1 ;
2018-08-28 13:43:58 +02:00
bool fDIP0001Active_context = nHeight > = consensusParams . DIP0001Height ;
2018-02-13 13:33:23 +01:00
bool fDIP0003Active_context = VersionBitsState ( pindexPrev , consensusParams , Consensus : : DEPLOYMENT_DIP0003 , versionbitscache ) = = THRESHOLD_ACTIVE ;
if ( fDIP0003Active_context ) {
// check version 3 transaction types
if ( tx . nVersion > = 3 ) {
2018-02-13 13:36:36 +01:00
if ( tx . nType ! = TRANSACTION_NORMAL & &
2018-03-12 12:14:11 +01:00
tx . nType ! = TRANSACTION_PROVIDER_REGISTER & &
2018-03-19 08:44:00 +01:00
tx . nType ! = TRANSACTION_PROVIDER_UPDATE_SERVICE & &
2018-03-19 12:29:59 +01:00
tx . nType ! = TRANSACTION_PROVIDER_UPDATE_REGISTRAR & &
2018-04-06 11:00:10 +02:00
tx . nType ! = TRANSACTION_PROVIDER_UPDATE_REVOKE & &
tx . nType ! = TRANSACTION_COINBASE ) {
2018-02-13 13:33:23 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-type " ) ;
}
2018-04-06 11:00:10 +02:00
if ( tx . IsCoinBase ( ) & & tx . nType ! = TRANSACTION_COINBASE )
2018-02-13 13:33:23 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-cb-type " ) ;
} else if ( tx . nType ! = TRANSACTION_NORMAL ) {
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-type " ) ;
}
}
2017-09-11 16:13:30 +02:00
// Size limits
if ( fDIP0001Active_context & & : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) > MAX_STANDARD_TX_SIZE )
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-oversize " ) ;
return true ;
}
2015-10-22 20:52:55 +02:00
void LimitMempoolSize ( CTxMemPool & pool , size_t limit , unsigned long age ) {
int expired = pool . Expire ( GetTime ( ) - age ) ;
if ( expired ! = 0 )
LogPrint ( " mempool " , " Expired %i transactions from the memory pool \n " , expired ) ;
2012-09-09 22:39:45 +02:00
2017-06-02 00:47:58 +02:00
std : : vector < COutPoint > vNoSpendsRemaining ;
2015-10-22 20:52:55 +02:00
pool . TrimToSize ( limit , & vNoSpendsRemaining ) ;
2017-06-02 00:47:58 +02:00
BOOST_FOREACH ( const COutPoint & removed , vNoSpendsRemaining )
2015-10-22 20:52:55 +02:00
pcoinsTip - > Uncache ( removed ) ;
2012-09-09 22:39:45 +02:00
}
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
2017-01-05 23:14:23 +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 ;
}
2017-01-04 12:22:49 +01:00
bool AcceptToMemoryPoolWorker ( CTxMemPool & pool , CValidationState & state , const CTransactionRef & ptx , bool fLimitFree ,
2018-09-20 14:39:34 +02:00
bool * pfMissingInputs , int64_t nAcceptTime , bool fOverrideMempoolLimit ,
const CAmount & nAbsurdFee , std : : vector < COutPoint > & coins_to_uncache , bool fDryRun )
2010-08-29 18:58:15 +02:00
{
2017-01-04 12:22:49 +01:00
const CTransaction & tx = * ptx ;
2016-02-01 10:21:27 +01:00
const uint256 hash = tx . GetHash ( ) ;
2014-04-15 12:43:17 +02:00
AssertLockHeld ( cs_main ) ;
2010-08-29 18:58:15 +02:00
if ( pfMissingInputs )
* pfMissingInputs = false ;
2016-02-01 10:21:27 +01:00
if ( ! CheckTransaction ( tx , state ) )
2016-03-11 08:20:24 +01:00
return false ; // state filled in by CheckTransaction
2016-02-01 10:21:27 +01:00
2018-08-28 13:43:58 +02:00
if ( ! ContextualCheckTransaction ( tx , state , Params ( ) . GetConsensus ( ) , chainActive . Tip ( ) ) )
2016-02-01 10:21:27 +01:00
return error ( " %s: ContextualCheckTransaction: %s, %s " , __func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
2010-09-30 18:23:07 +02:00
2018-02-13 13:34:35 +01:00
if ( ! CheckSpecialTx ( tx , chainActive . Tip ( ) , state ) )
return false ;
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
2013-07-23 17:46:05 +02:00
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
2017-01-30 13:13:07 +01:00
std : : string reason ;
2015-06-24 05:36:22 +02:00
if ( fRequireStandard & & ! IsStandardTx ( tx , reason ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 0 , false , REJECT_NONSTANDARD , reason ) ;
2010-12-12 19:20:36 +01:00
2018-02-14 14:42:06 +01:00
if ( pool . existsProviderTxConflict ( tx ) ) {
return state . DoS ( 0 , false , REJECT_DUPLICATE , " protx-dup " ) ;
}
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 " ) ;
2010-12-12 19:20:36 +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?
2013-08-27 07:51:57 +02:00
if ( pool . exists ( hash ) )
2015-08-06 09:51:36 +02:00
return state . Invalid ( false , REJECT_ALREADY_KNOWN , " txn-already-in-mempool " ) ;
2010-08-29 18:58:15 +02:00
2017-01-29 09:22:14 +01:00
// If this is a Transaction Lock Request check to see if it's valid
if ( instantsend . HasTxLockRequest ( hash ) & & ! CTxLockRequest ( tx ) . IsValid ( ) )
return state . DoS ( 10 , error ( " AcceptToMemoryPool : CTxLockRequest %s is invalid " , hash . ToString ( ) ) ,
REJECT_INVALID , " bad-txlockrequest " ) ;
2015-02-04 22:59:19 +01:00
2017-01-29 09:22:14 +01:00
// Check for conflicts with a completed Transaction Lock
BOOST_FOREACH ( const CTxIn & txin , tx . vin )
{
uint256 hashLocked ;
if ( instantsend . GetLockedOutPointTxHash ( txin . prevout , hashLocked ) & & hash ! = hashLocked )
return state . DoS ( 10 , error ( " AcceptToMemoryPool : Transaction %s conflicts with completed Transaction Lock %s " ,
hash . ToString ( ) , hashLocked . ToString ( ) ) ,
REJECT_INVALID , " tx-txlock-conflict " ) ;
2015-02-04 22:59:19 +01:00
}
2010-08-29 18:58:15 +02:00
// Check for conflicts with in-memory transactions
2013-08-27 07:51:57 +02:00
{
LOCK ( pool . cs ) ; // protect pool.mapNextTx
2015-10-22 20:13:18 +02:00
BOOST_FOREACH ( const CTxIn & txin , tx . vin )
2010-08-29 18:58:15 +02:00
{
2016-06-03 01:11:02 +02:00
auto itConflicting = pool . mapNextTx . find ( txin . prevout ) ;
if ( itConflicting ! = pool . mapNextTx . end ( ) )
2010-08-29 18:58:15 +02:00
{
2016-06-03 01:11:02 +02:00
const CTransaction * ptxConflicting = itConflicting - > second ;
2018-09-20 14:39:34 +02:00
// InstantSend txes are not replacable
if ( instantsend . HasTxLockRequest ( ptxConflicting - > GetHash ( ) ) ) {
// this tx conflicts with a Transaction Lock Request candidate
return state . DoS ( 0 , error ( " AcceptToMemoryPool : Transaction %s conflicts with Transaction Lock Request %s " ,
hash . ToString ( ) , ptxConflicting - > GetHash ( ) . ToString ( ) ) ,
REJECT_INVALID , " tx-txlockreq-mempool-conflict " ) ;
} else if ( instantsend . HasTxLockRequest ( hash ) ) {
// this tx is a tx lock request and it conflicts with a normal tx
return state . DoS ( 0 , error ( " AcceptToMemoryPool : Transaction Lock Request %s conflicts with transaction %s " ,
hash . ToString ( ) , ptxConflicting - > GetHash ( ) . ToString ( ) ) ,
REJECT_INVALID , " txlockreq-tx-mempool-conflict " ) ;
2015-10-22 20:13:18 +02:00
}
2018-09-20 14:39:34 +02:00
// Transaction conflicts with mempool and RBF doesn't exist in Dash
return state . Invalid ( false , REJECT_CONFLICT , " txn-mempool-conflict " ) ;
2010-08-29 18:58:15 +02:00
}
}
2013-08-27 07:51:57 +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
2014-04-23 00:46:19 +02:00
CAmount nValueIn = 0 ;
2015-12-04 21:01:22 +01:00
LockPoints lp ;
2012-10-23 01:16:26 +02:00
{
2013-08-27 07:51:57 +02:00
LOCK ( pool . cs ) ;
2014-09-24 03:19:04 +02:00
CCoinsViewMemPool viewMemPool ( pcoinsTip , 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 we already have it?
2017-06-02 00:47:58 +02:00
for ( size_t out = 0 ; out < tx . vout . size ( ) ; out + + ) {
COutPoint outpoint ( hash , out ) ;
bool had_coin_in_cache = pcoinsTip - > HaveCoinInCache ( outpoint ) ;
if ( view . HaveCoin ( outpoint ) ) {
if ( ! had_coin_in_cache ) {
coins_to_uncache . push_back ( outpoint ) ;
}
return state . Invalid ( false , REJECT_ALREADY_KNOWN , " txn-already-known " ) ;
}
2015-10-23 00:50:33 +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
// do all inputs exist?
BOOST_FOREACH ( const CTxIn txin , tx . vin ) {
2017-06-02 00:47:58 +02:00
if ( ! pcoinsTip - > HaveCoinInCache ( txin . prevout ) ) {
coins_to_uncache . push_back ( txin . prevout ) ;
}
if ( ! view . HaveCoin ( txin . prevout ) ) {
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-06-02 00:47:58 +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 ( ) ;
2014-03-17 13:19:54 +01:00
nValueIn = view . GetValueIn ( tx ) ;
2012-10-23 01:16:26 +02:00
// 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 " ) ;
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
2014-05-08 06:18:57 +02:00
unsigned int nSigOps = GetLegacySigOpCount ( tx ) ;
nSigOps + = GetP2SHSigOpCount ( tx , view ) ;
2012-01-20 23:07:40 +01:00
2014-04-23 00:46:19 +02:00
CAmount nValueOut = tx . GetValueOut ( ) ;
CAmount nFees = nValueIn - nValueOut ;
2015-11-19 17:18:28 +01:00
// nModifiedFees includes any fee deltas from PrioritiseTransaction
CAmount nModifiedFees = nFees ;
double nPriorityDummy = 0 ;
pool . ApplyDeltas ( hash , nPriorityDummy , nModifiedFees ) ;
2015-11-13 16:05:21 +01:00
CAmount inChainInputValue ;
double dPriority = view . GetPriority ( tx , chainActive . Height ( ) , inChainInputValue ) ;
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 ;
BOOST_FOREACH ( const CTxIn & txin , tx . vin ) {
2017-06-02 00:47:58 +02:00
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
if ( coin . IsCoinBase ( ) ) {
2015-10-29 19:06:13 +01:00
fSpendsCoinbase = true ;
break ;
}
}
2013-11-11 08:35:14 +01:00
2017-01-05 23:14:23 +01:00
CTxMemPoolEntry entry ( ptx , nFees , nAcceptTime , dPriority , chainActive . Height ( ) ,
inChainInputValue , fSpendsCoinbase , nSigOps , 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.
if ( ( nSigOps > MAX_STANDARD_TX_SIGOPS ) | | ( nBytesPerSigOp & & nSigOps > nSize / nBytesPerSigOp ) )
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " bad-txns-too-many-sigops " , false ,
strprintf ( " %d " , nSigOps ) ) ;
2015-10-02 23:19:55 +02:00
CAmount mempoolRejectFee = pool . GetMinFee ( GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ) . GetFee ( nSize ) ;
2015-11-19 17:18:28 +01:00
if ( mempoolRejectFee > 0 & & nModifiedFees < mempoolRejectFee ) {
2015-10-02 23:19:55 +02:00
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " mempool min fee not met " , false , strprintf ( " %d < %d " , nFees , mempoolRejectFee ) ) ;
2015-11-19 17:18:28 +01:00
} else if ( GetBoolArg ( " -relaypriority " , DEFAULT_RELAYPRIORITY ) & & nModifiedFees < : : minRelayTxFee . GetFee ( nSize ) & & ! AllowFree ( entry . GetPriority ( chainActive . Height ( ) + 1 ) ) ) {
2015-04-03 00:51:08 +02:00
// Require that free transactions have sufficient priority to be mined in the next block.
2014-12-23 23:50:21 +01:00
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " insufficient priority " ) ;
2010-12-12 19:20:36 +01:00
}
2012-01-11 02:18:00 +01:00
2014-11-25 18:54:36 +01:00
// Continuously rate-limit free (really, very-low-fee) transactions
2011-03-13 19:38:07 +01:00
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
2012-07-26 05:25:26 +02:00
// be annoying or make others' transactions take longer to confirm.
2015-11-19 17:18:28 +01:00
if ( fLimitFree & & nModifiedFees < : : minRelayTxFee . GetFee ( nSize ) )
2012-01-11 02:18:00 +01:00
{
2014-07-17 14:09:55 +02:00
static CCriticalSection csFreeLimiter ;
2011-03-11 17:50:16 +01:00
static double dFreeCount ;
2014-07-17 14:09:55 +02:00
static int64_t nLastTime ;
int64_t nNow = GetTime ( ) ;
LOCK ( csFreeLimiter ) ;
2013-01-14 22:52:33 +01:00
2014-07-17 14:09:55 +02:00
// Use an exponentially decaying ~10-minute window:
dFreeCount * = pow ( 1.0 - 1.0 / 600.0 , ( double ) ( nNow - nLastTime ) ) ;
nLastTime = nNow ;
// -limitfreerelay unit is thousand-bytes-per-minute
// At default rate it would take over a month to fill 1GB
2016-01-29 13:11:57 +01:00
if ( dFreeCount + nSize > = GetArg ( " -limitfreerelay " , DEFAULT_LIMITFREERELAY ) * 10 * 1000 )
2015-08-06 09:59:09 +02:00
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " rate limited free transaction " ) ;
2013-08-27 07:51:57 +02:00
LogPrint ( " mempool " , " Rate limit dFreeCount: %g => %g \n " , dFreeCount , dFreeCount + nSize ) ;
2014-07-17 14:09:55 +02:00
dFreeCount + = nSize ;
2010-12-12 19:20:36 +01:00
}
2012-01-11 02:18:00 +01:00
2016-02-04 14:38:58 +01:00
if ( nAbsurdFee & & nFees > nAbsurdFee )
2015-08-06 09:59:09 +02:00
return state . Invalid ( false ,
REJECT_HIGHFEE , " absurdly-high-fee " ,
2016-02-04 14:38:58 +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 ;
size_t nLimitAncestors = GetArg ( " -limitancestorcount " , DEFAULT_ANCESTOR_LIMIT ) ;
size_t nLimitAncestorSize = GetArg ( " -limitancestorsize " , DEFAULT_ANCESTOR_SIZE_LIMIT ) * 1000 ;
size_t nLimitDescendants = GetArg ( " -limitdescendantcount " , DEFAULT_DESCENDANT_LIMIT ) ;
size_t nLimitDescendantSize = GetArg ( " -limitdescendantsize " , DEFAULT_DESCENDANT_SIZE_LIMIT ) * 1000 ;
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 ) ;
}
2016-02-06 15:27:33 +01:00
// If we aren't going to actually accept it but just were verifying it, we are fine already
if ( fDryRun ) return true ;
2014-12-09 02:17:57 +01:00
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
2014-09-14 04:48:32 +02:00
if ( ! CheckInputs ( tx , state , view , true , STANDARD_SCRIPT_VERIFY_FLAGS , true ) )
2016-03-11 08:20:24 +01:00
return false ; // state filled in by CheckInputs
2015-02-01 16:53:49 +01:00
2015-04-03 00:51:08 +02:00
// Check again against just the consensus-critical mandatory script
// verification flags, in case of bugs in the standard flags that cause
// transactions to pass as valid when they're actually invalid. For
// instance the STRICTENC flag was incorrectly allowing certain
// CHECKSIG NOT scripts to pass, even though they were invalid.
//
// There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks, however allowing such transactions into the mempool
// can be exploited as a DoS attack.
2014-11-10 08:52:28 +01:00
if ( ! CheckInputs ( tx , state , view , true , MANDATORY_SCRIPT_VERIFY_FLAGS , true ) )
2016-02-14 05:51:06 +01:00
{
2015-08-06 09:59:09 +02:00
return error ( " %s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s " ,
__func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
2016-02-14 05:51:06 +01:00
}
2015-02-01 16:53:49 +01:00
2018-09-20 14:39:34 +02:00
// This transaction should only count for fee estimation if the
2017-01-26 10:53:07 +01:00
// node is not behind, and the transaction is not dependent on any other
// transactions in the mempool.
2018-09-20 14:39:34 +02:00
bool validForFeeEstimation = IsCurrentForFeeEstimation ( ) & & pool . HasNoInputsOf ( tx ) ;
2017-01-05 23:14:23 +01:00
2014-07-17 14:08:01 +02:00
// Store transaction in memory
2017-01-05 23:14:23 +01:00
pool . addUnchecked ( hash , entry , setAncestors , validForFeeEstimation ) ;
2015-10-02 23:19:55 +02:00
2016-05-16 20:23:01 +02:00
// Add memory address index
2016-04-04 22:37:43 +02:00
if ( fAddressIndex ) {
pool . addAddressIndex ( entry , view ) ;
}
2015-10-02 23:19:55 +02:00
2016-05-16 20:23:01 +02:00
// Add memory spent index
if ( fSpentIndex ) {
pool . addSpentIndex ( entry , view ) ;
}
2015-10-02 23:19:55 +02:00
// trim mempool and check if tx was trimmed
2015-10-02 23:20:38 +02:00
if ( ! fOverrideMempoolLimit ) {
2015-10-22 20:52:55 +02:00
LimitMempoolSize ( pool , GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 , GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ) ;
if ( ! pool . exists ( hash ) )
2015-10-02 23:20:38 +02:00
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " mempool full " ) ;
}
2015-02-01 16:53:49 +01:00
}
2017-07-28 16:10:10 +02:00
if ( ! fDryRun )
2017-09-18 18:01:52 +02:00
GetMainSignals ( ) . SyncTransaction ( tx , NULL , CMainSignals : : SYNC_TRANSACTION_NOT_IN_BLOCK ) ;
2010-08-29 18:58:15 +02:00
2015-04-03 00:51:08 +02:00
return true ;
2010-08-29 18:58:15 +02:00
}
2017-01-04 12:22:49 +01:00
bool AcceptToMemoryPoolWithTime ( CTxMemPool & pool , CValidationState & state , const CTransactionRef & tx , bool fLimitFree ,
2018-09-20 14:39:34 +02:00
bool * pfMissingInputs , int64_t nAcceptTime , bool fOverrideMempoolLimit ,
const CAmount nAbsurdFee , bool fDryRun )
2015-10-23 00:50:33 +02:00
{
2017-06-02 00:47:58 +02:00
std : : vector < COutPoint > coins_to_uncache ;
2018-09-20 14:39:34 +02:00
bool res = AcceptToMemoryPoolWorker ( pool , state , tx , fLimitFree , pfMissingInputs , nAcceptTime , fOverrideMempoolLimit , nAbsurdFee , coins_to_uncache , fDryRun ) ;
2016-02-02 16:28:56 +01:00
if ( ! res | | fDryRun ) {
2018-02-26 12:10:20 +01:00
if ( ! res ) LogPrint ( " mempool " , " %s: %s %s (%s) \n " , __func__ , tx - > GetHash ( ) . ToString ( ) , state . GetRejectReason ( ) , state . GetDebugMessage ( ) ) ;
2017-06-02 00:47:58 +02:00
BOOST_FOREACH ( const COutPoint & hashTx , coins_to_uncache )
2015-10-23 00:50:33 +02:00
pcoinsTip - > Uncache ( hashTx ) ;
}
2017-08-01 17:11:32 +02:00
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
CValidationState stateDummy ;
FlushStateToDisk ( stateDummy , FLUSH_STATE_PERIODIC ) ;
2015-10-23 00:50:33 +02:00
return res ;
}
2017-01-04 12:22:49 +01:00
bool AcceptToMemoryPool ( CTxMemPool & pool , CValidationState & state , const CTransactionRef & tx , bool fLimitFree ,
2018-09-20 14:39:34 +02:00
bool * pfMissingInputs , bool fOverrideMempoolLimit , const CAmount nAbsurdFee , bool fDryRun )
2016-11-02 11:12:48 +01:00
{
2018-09-20 14:39:34 +02:00
return AcceptToMemoryPoolWithTime ( pool , state , tx , fLimitFree , pfMissingInputs , GetTime ( ) , fOverrideMempoolLimit , nAbsurdFee , fDryRun ) ;
2016-11-02 11:12:48 +01:00
}
2016-03-22 23:11:04 +01:00
bool GetTimestampIndex ( const unsigned int & high , const unsigned int & low , std : : vector < uint256 > & hashes )
{
if ( ! fTimestampIndex )
return error ( " Timestamp index not enabled " ) ;
if ( ! pblocktree - > ReadTimestampIndex ( high , low , hashes ) )
return error ( " Unable to get hashes for timestamps " ) ;
return true ;
}
2016-04-05 21:53:38 +02:00
bool GetSpentIndex ( CSpentIndexKey & key , CSpentIndexValue & value )
{
if ( ! fSpentIndex )
2016-04-12 18:31:21 +02:00
return false ;
2016-04-05 21:53:38 +02:00
2016-05-16 20:23:01 +02:00
if ( mempool . getSpentIndex ( key , value ) )
return true ;
2016-04-05 21:53:38 +02:00
if ( ! pblocktree - > ReadSpentIndex ( key , value ) )
2016-06-01 20:57:39 +02:00
return false ;
2016-04-05 21:53:38 +02:00
return true ;
}
2016-03-24 20:44:23 +01:00
bool GetAddressIndex ( uint160 addressHash , int type ,
std : : vector < std : : pair < CAddressIndexKey , CAmount > > & addressIndex , int start , int end )
2016-03-05 22:31:10 +01:00
{
if ( ! fAddressIndex )
2016-03-24 20:44:23 +01:00
return error ( " address index not enabled " ) ;
2016-03-05 22:31:10 +01:00
2016-03-24 20:44:23 +01:00
if ( ! pblocktree - > ReadAddressIndex ( addressHash , type , addressIndex , start , end ) )
return error ( " unable to get txids for address " ) ;
2016-03-05 22:31:10 +01:00
return true ;
}
2016-03-29 21:17:30 +02:00
bool GetAddressUnspent ( uint160 addressHash , int type ,
std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > & unspentOutputs )
{
if ( ! fAddressIndex )
return error ( " address index not enabled " ) ;
if ( ! pblocktree - > ReadAddressUnspentIndex ( addressHash , type , unspentOutputs ) )
return error ( " unable to get txids for address " ) ;
return true ;
}
2016-10-24 09:18:16 +02:00
/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */
2016-12-05 08:01:20 +01:00
bool GetTransaction ( const uint256 & hash , CTransactionRef & txOut , const Consensus : : Params & consensusParams , uint256 & hashBlock , bool fAllowSlow )
2012-02-15 17:49:04 +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
CBlockIndex * pindexSlow = NULL ;
2015-09-17 23:43:34 +02:00
LOCK ( cs_main ) ;
2016-11-21 10:51:32 +01:00
CTransactionRef ptx = mempool . get ( hash ) ;
2016-06-08 14:01:05 +02:00
if ( ptx )
2012-02-15 17:49:04 +01:00
{
2016-12-05 08:01:20 +01:00
txOut = ptx ;
2015-09-17 23:43:34 +02: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
2015-09-17 23:43:34 +02:00
if ( fTxIndex ) {
CDiskTxPos postx ;
if ( pblocktree - > ReadTxIndex ( hash , postx ) ) {
CAutoFile file ( OpenBlockFile ( postx , true ) , SER_DISK , CLIENT_VERSION ) ;
if ( file . IsNull ( ) )
return error ( " %s: OpenBlockFile failed " , __func__ ) ;
CBlockHeader header ;
try {
file > > header ;
fseek ( file . Get ( ) , postx . nTxOffset , SEEK_CUR ) ;
file > > txOut ;
} catch ( const std : : exception & e ) {
return error ( " %s: Deserialize or I/O error - %s " , __func__ , e . what ( ) ) ;
2013-01-11 01:47:57 +01:00
}
2015-09-17 23:43:34 +02:00
hashBlock = header . GetHash ( ) ;
2016-12-05 08:01:20 +01:00
if ( txOut - > GetHash ( ) ! = hash )
2015-09-17 23:43:34 +02:00
return error ( " %s: txid mismatch " , __func__ ) ;
return true ;
2013-01-11 01:47:57 +01:00
}
2017-10-19 20:04:44 +02:00
// transaction not found in index, nothing more can be done
return false ;
2015-09-17 23:43:34 +02:00
}
2013-01-11 01:47:57 +01:00
2015-09-17 23:43:34 +02:00
if ( fAllowSlow ) { // use coin database to locate block that contains transaction, and scan it
2017-06-02 00:47:58 +02:00
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-21 10:51:32 +01:00
for ( const auto & tx : block . vtx ) {
if ( tx - > GetHash ( ) = = hash ) {
2016-12-05 08:01:20 +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
//
2015-08-08 18:18:41 +02:00
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-11-09 12:32:57 +01:00
unsigned int nSize = GetSerializeSize ( fileout , block ) ;
2015-04-19 23:48:25 +02:00
fileout < < FLATDATA ( 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
2015-04-17 14:19:21 +02:00
if ( ! CheckProofOfWork ( block . GetHash ( ) , 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
{
2015-04-17 14:19:21 +02:00
if ( ! ReadBlockFromDisk ( block , pindex - > GetBlockPos ( ) , 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 ;
}
2014-12-02 09:16:52 +01:00
double ConvertBitsToDouble ( unsigned int nBits )
2010-08-29 18:58:15 +02:00
{
2014-12-02 09:16:52 +01:00
int nShift = ( nBits > > 24 ) & 0xff ;
2014-03-11 01:02:36 +01:00
2016-08-23 13:25:03 +02:00
double dDiff = ( double ) 0x0000ffff / ( double ) ( nBits & 0x00ffffff ) ;
2010-08-29 18:58:15 +02:00
2014-12-02 09:16:52 +01:00
while ( nShift < 29 )
{
dDiff * = 256.0 ;
nShift + + ;
}
while ( nShift > 29 )
{
dDiff / = 256.0 ;
nShift - - ;
}
return dDiff ;
}
2016-02-15 14:59:15 +01:00
/*
NOTE : unlike bitcoin we are using PREVIOUS block height here ,
might be a good idea to change this to use prev bits
but current height to avoid confusion .
*/
2016-08-22 03:41:40 +02:00
CAmount GetBlockSubsidy ( int nPrevBits , int nPrevHeight , const Consensus : : Params & consensusParams , bool fSuperblockPartOnly )
2014-12-02 09:16:52 +01:00
{
2016-08-23 13:25:03 +02:00
double dDiff ;
CAmount nSubsidyBase ;
if ( nPrevHeight < = 4500 & & Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN ) {
/* a bug which caused diff to not be correctly calculated */
dDiff = ( double ) 0x0000ffff / ( double ) ( nPrevBits & 0x00ffffff ) ;
} else {
dDiff = ConvertBitsToDouble ( nPrevBits ) ;
}
if ( nPrevHeight < 5465 ) {
// Early ages...
// 1111/((x+1)^2)
nSubsidyBase = ( 1111.0 / ( pow ( ( dDiff + 1.0 ) , 2.0 ) ) ) ;
if ( nSubsidyBase > 500 ) nSubsidyBase = 500 ;
else if ( nSubsidyBase < 1 ) nSubsidyBase = 1 ;
} else if ( nPrevHeight < 17000 | | ( dDiff < = 75 & & nPrevHeight < 24000 ) ) {
// CPU mining era
// 11111/(((x+51)/6)^2)
nSubsidyBase = ( 11111.0 / ( pow ( ( dDiff + 51.0 ) / 6.0 , 2.0 ) ) ) ;
if ( nSubsidyBase > 500 ) nSubsidyBase = 500 ;
else if ( nSubsidyBase < 25 ) nSubsidyBase = 25 ;
2014-12-02 09:16:52 +01:00
} else {
2016-08-23 13:25:03 +02:00
// GPU/ASIC mining era
// 2222222/(((x+2600)/9)^2)
nSubsidyBase = ( 2222222.0 / ( pow ( ( dDiff + 2600.0 ) / 9.0 , 2.0 ) ) ) ;
if ( nSubsidyBase > 25 ) nSubsidyBase = 25 ;
else if ( nSubsidyBase < 5 ) nSubsidyBase = 5 ;
2014-12-02 09:16:52 +01:00
}
2016-08-23 13:25:03 +02:00
// LogPrintf("height %u diff %4.2f reward %d\n", nPrevHeight, dDiff, nSubsidyBase);
CAmount nSubsidy = nSubsidyBase * COIN ;
2014-12-02 09:16:52 +01:00
2016-08-23 13:25:03 +02:00
// yearly decline of production by ~7.1% per year, projected ~18M coins max by year 2050+.
for ( int i = consensusParams . nSubsidyHalvingInterval ; i < = nPrevHeight ; i + = consensusParams . nSubsidyHalvingInterval ) {
nSubsidy - = nSubsidy / 14 ;
}
2010-08-29 18:58:15 +02:00
2018-10-25 09:16:38 +02:00
// this is only active on devnets
if ( nPrevHeight < consensusParams . nHighSubsidyBlocks ) {
nSubsidy * = consensusParams . nHighSubsidyFactor ;
}
2016-08-23 13:25:03 +02:00
// Hard fork to reduce the block reward by 10 extra percent (allowing budget/superblocks)
2016-08-22 03:41:40 +02:00
CAmount nSuperblockPart = ( nPrevHeight > consensusParams . nBudgetPaymentsStartBlock ) ? nSubsidy / 10 : 0 ;
2015-07-28 15:40:48 +02:00
2016-08-22 03:41:40 +02:00
return fSuperblockPartOnly ? nSuperblockPart : nSubsidy - nSuperblockPart ;
2010-08-29 18:58:15 +02:00
}
2016-01-24 05:21:14 +01:00
CAmount GetMasternodePayment ( int nHeight , CAmount blockValue )
2014-12-02 09:16:52 +01:00
{
2016-01-24 05:21:14 +01:00
CAmount ret = blockValue / 5 ; // start at 20%
2014-12-02 09:16:52 +01:00
2016-02-17 17:29:36 +01:00
int nMNPIBlock = Params ( ) . GetConsensus ( ) . nMasternodePaymentsIncreaseBlock ;
int nMNPIPeriod = Params ( ) . GetConsensus ( ) . nMasternodePaymentsIncreasePeriod ;
// mainnet:
if ( nHeight > nMNPIBlock ) ret + = blockValue / 20 ; // 158000 - 25.0% - 2014-10-24
if ( nHeight > nMNPIBlock + ( nMNPIPeriod * 1 ) ) ret + = blockValue / 20 ; // 175280 - 30.0% - 2014-11-25
if ( nHeight > nMNPIBlock + ( nMNPIPeriod * 2 ) ) ret + = blockValue / 20 ; // 192560 - 35.0% - 2014-12-26
if ( nHeight > nMNPIBlock + ( nMNPIPeriod * 3 ) ) ret + = blockValue / 40 ; // 209840 - 37.5% - 2015-01-26
if ( nHeight > nMNPIBlock + ( nMNPIPeriod * 4 ) ) ret + = blockValue / 40 ; // 227120 - 40.0% - 2015-02-27
if ( nHeight > nMNPIBlock + ( nMNPIPeriod * 5 ) ) ret + = blockValue / 40 ; // 244400 - 42.5% - 2015-03-30
if ( nHeight > nMNPIBlock + ( nMNPIPeriod * 6 ) ) ret + = blockValue / 40 ; // 261680 - 45.0% - 2015-05-01
if ( nHeight > nMNPIBlock + ( nMNPIPeriod * 7 ) ) ret + = blockValue / 40 ; // 278960 - 47.5% - 2015-06-01
if ( nHeight > nMNPIBlock + ( nMNPIPeriod * 9 ) ) ret + = blockValue / 40 ; // 313520 - 50.0% - 2015-08-03
2014-12-02 09:16:52 +01:00
return ret ;
}
2010-08-29 18:58:15 +02:00
bool IsInitialBlockDownload ( )
{
2016-06-06 15:45:25 +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 ;
LOCK ( cs_main ) ;
if ( latchToFalse . load ( std : : memory_order_relaxed ) )
2016-05-31 06:57:05 +02:00
return false ;
2015-04-23 05:22:36 +02:00
if ( fImporting | | fReindex )
return true ;
2016-05-31 06:57:05 +02:00
const CChainParams & chainParams = Params ( ) ;
2017-08-23 16:21:08 +02:00
if ( chainActive . Tip ( ) = = NULL )
return true ;
if ( chainActive . Tip ( ) - > nChainWork < UintToArith256 ( chainParams . GetConsensus ( ) . nMinimumChainWork ) )
return true ;
2016-01-18 11:55:52 +01:00
if ( chainActive . Tip ( ) - > GetBlockTime ( ) < ( GetTime ( ) - nMaxTipAge ) )
2010-08-29 18:58:15 +02:00
return true ;
2016-06-06 15:45:25 +02:00
latchToFalse . store ( true , std : : memory_order_relaxed ) ;
2017-08-23 16:21:08 +02:00
return false ;
2010-08-29 18:58:15 +02:00
}
2013-05-07 18:33:52 +02:00
CBlockIndex * pindexBestForkTip = NULL , * pindexBestForkBase = NULL ;
void CheckForkWarningConditions ( )
{
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
2017-08-23 16:21:08 +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 ;
2015-02-11 01:07:52 +01:00
// If our best fork is no longer within 72 blocks (+/- 3 hours if no one mines it)
2013-05-07 18:33:52 +02:00
// of our head, drop it
2013-10-10 23:07:44 +02:00
if ( pindexBestForkTip & & chainActive . Height ( ) - pindexBestForkTip - > nHeight > = 72 )
2013-05-07 18:33:52 +02:00
pindexBestForkTip = NULL ;
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-12-19 12:38:35 +01:00
if ( ! GetfLargeWorkForkFound ( ) & & pindexBestForkBase )
2013-05-07 18:37:37 +02:00
{
2015-01-23 19:29:29 +01:00
if ( pindexBestForkBase - > phashBlock ) {
2015-01-23 14:29:06 +01:00
std : : string warning = std : : string ( " 'Warning: Large-work fork detected, forking after block " ) +
pindexBestForkBase - > phashBlock - > ToString ( ) + std : : string ( " ' " ) ;
2017-12-21 18:50:08 +01:00
CAlert : : Notify ( warning ) ;
2015-01-23 14:29:06 +01:00
}
2013-05-07 18:37:37 +02:00
}
2015-01-23 19:29:29 +01:00
if ( pindexBestForkTip & & pindexBestForkBase )
2013-05-18 03:09:28 +02:00
{
2015-01-23 19:29:29 +01:00
if ( pindexBestForkBase - > phashBlock ) {
2016-02-02 16:28:56 +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__ ,
2015-01-23 19:29:29 +01:00
pindexBestForkBase - > nHeight , pindexBestForkBase - > phashBlock - > ToString ( ) ,
pindexBestForkTip - > nHeight , pindexBestForkTip - > phashBlock - > ToString ( ) ) ;
2016-12-19 12:38:35 +01:00
SetfLargeWorkForkFound ( true ) ;
2015-01-23 19:29:29 +01:00
}
2013-05-18 03:09:28 +02:00
}
else
{
2017-01-01 11:18:05 +01:00
if ( pindexBestInvalid - > nHeight > chainActive . Height ( ) + 6 )
LogPrintf ( " %s: Warning: Found invalid chain at least ~6 blocks longer than our best chain. \n Chain state database corruption likely. \n " , __func__ ) ;
else
LogPrintf ( " %s: Warning: Found invalid chain which has higher work (at least ~6 blocks worth of work) than our best chain. \n Chain state database corruption likely. \n " , __func__ ) ;
2016-12-19 12:38:35 +01:00
SetfLargeWorkInvalidChainFound ( true ) ;
2013-05-18 03:09:28 +02:00
}
}
else
{
2016-12-19 12:38:35 +01:00
SetfLargeWorkForkFound ( false ) ;
SetfLargeWorkInvalidChainFound ( false ) ;
2013-05-18 03:09:28 +02:00
}
2013-05-07 18:33:52 +02:00
}
void CheckForkWarningConditionsOnNewFork ( CBlockIndex * pindexNewForkTip )
{
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
2016-02-02 16:28:56 +01:00
// with a tip within 72 blocks (+/- 3 hours if no one mines it) of ours
2015-07-07 14:47:22 +02:00
// or a chain that is entirely longer than ours and invalid (note that this should be detected by both)
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.
// 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
if ( pfork & & ( ! pindexBestForkTip | | ( 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
2018-02-26 12:10:20 +01:00
LogPrintf ( " %s: invalid block=%s height=%d log2_work=%.8f date=%s \n " , __func__ ,
2014-01-16 16:15:27 +01:00
pindexNew - > GetBlockHash ( ) . ToString ( ) , pindexNew - > nHeight ,
2013-03-28 23:51:50 +01:00
log ( pindexNew - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " ,
2014-01-16 16:15:27 +01:00
pindexNew - > GetBlockTime ( ) ) ) ;
2015-07-04 21:14:03 +02:00
CBlockIndex * tip = chainActive . Tip ( ) ;
assert ( tip ) ;
2018-02-26 12:10:20 +01:00
LogPrintf ( " %s: current best=%s height=%d log2_work=%.8f date=%s \n " , __func__ ,
2015-07-04 21:14:03 +02:00
tip - > GetBlockHash ( ) . ToString ( ) , chainActive . Height ( ) , log ( tip - > nChainWork . getdouble ( ) ) / log ( 2.0 ) ,
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , tip - > GetBlockTime ( ) ) ) ;
2013-05-07 18:33:52 +02:00
CheckForkWarningConditions ( ) ;
2010-08-29 18:58:15 +02:00
}
2013-11-16 19:28:24 +01:00
void static InvalidBlockFound ( CBlockIndex * pindex , const CValidationState & state ) {
if ( ! state . CorruptionPossible ( ) ) {
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-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-05-09 11:57:16 +02:00
void UpdateCoins ( const CTransaction & tx , CCoinsViewCache & inputs , CTxUndo & txundo , int nHeight )
2012-02-16 16:22:31 +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
// 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 ( ) ) ;
2013-01-08 13:17:15 +01:00
BOOST_FOREACH ( const CTxIn & txin , tx . vin ) {
2017-06-02 00:47:58 +02:00
txundo . vprevout . emplace_back ( ) ;
2017-06-21 03:18:09 +02:00
bool is_spent = inputs . SpendCoin ( txin . prevout , & txundo . vprevout . back ( ) ) ;
assert ( is_spent ) ;
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 18:54:00 +02:00
}
}
2016-01-22 14:15:45 +01:00
// add outputs
2017-06-02 00:47:58 +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-05-09 11:57:16 +02:00
void UpdateCoins ( const CTransaction & tx , CCoinsViewCache & inputs , int nHeight )
2014-10-27 16:07:50 +01:00
{
CTxUndo txundo ;
2016-05-09 11:57:16 +02:00
UpdateCoins ( tx , inputs , txundo , 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
}
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 ;
2015-01-27 15:01:31 +01:00
if ( ! VerifyScript ( scriptSig , scriptPubKey , nFlags , CachingTransactionSignatureChecker ( ptxTo , nIn , cacheStore ) , & error ) ) {
2015-08-06 09:59:09 +02:00
return false ;
2014-11-29 16:01:37 +01:00
}
2012-12-01 22:30:06 +01:00
return true ;
}
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 ) ;
CBlockIndex * pindexPrev = mapBlockIndex . find ( inputs . GetBestBlock ( ) ) - > second ;
return pindexPrev - > nHeight + 1 ;
}
2012-12-01 23:04:14 +01:00
2015-04-24 16:45:16 +02:00
namespace Consensus {
bool CheckTxInputs ( const CTransaction & tx , CValidationState & state , const CCoinsViewCache & inputs , int nSpendHeight )
{
2012-07-08 19:04:05 +02:00
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
// for an attacker to attempt to split the network.
2013-01-08 13:17:15 +01:00
if ( ! inputs . HaveInputs ( tx ) )
2015-08-06 09:59:09 +02:00
return state . Invalid ( false , 0 , " " , " Inputs unavailable " ) ;
2012-07-08 19:04:05 +02:00
2014-04-23 00:46:19 +02:00
CAmount nValueIn = 0 ;
CAmount nFees = 0 ;
2013-01-08 13:17:15 +01:00
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + )
2010-08-29 18:58:15 +02:00
{
2013-01-08 13:17:15 +01:00
const COutPoint & prevout = tx . vin [ i ] . prevout ;
2017-06-02 00:47:58 +02:00
const Coin & coin = inputs . AccessCoin ( prevout ) ;
assert ( ! coin . IsSpent ( ) ) ;
2010-08-29 18:58:15 +02:00
// If prev is coinbase, check that it's matured
2017-06-02 00:47:58 +02:00
if ( coin . IsCoinBase ( ) ) {
if ( nSpendHeight - coin . nHeight < COINBASE_MATURITY )
2015-08-06 09:59:09 +02:00
return state . Invalid ( false ,
REJECT_INVALID , " bad-txns-premature-spend-of-coinbase " ,
2017-06-02 00:47:58 +02:00
strprintf ( " tried to spend coinbase at depth %d " , nSpendHeight - 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
}
2010-08-29 18:58:15 +02:00
2012-05-16 17:26:56 +02:00
// Check for negative or overflow input values
2017-06-02 00:47:58 +02:00
nValueIn + = coin . out . nValue ;
if ( ! MoneyRange ( coin . out . nValue ) | | ! MoneyRange ( nValueIn ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-inputvalues-outofrange " ) ;
2012-05-16 17:26:56 +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
2013-11-11 07:03:51 +01:00
if ( nValueIn < tx . GetValueOut ( ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-in-belowout " , false ,
strprintf ( " value in (%s) < value out (%s) " , FormatMoney ( nValueIn ) , FormatMoney ( tx . GetValueOut ( ) ) ) ) ;
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
// Tally transaction fees
2014-04-23 00:46:19 +02:00
CAmount nTxFee = nValueIn - tx . GetValueOut ( ) ;
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 ( nTxFee < 0 )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-fee-negative " ) ;
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
nFees + = nTxFee ;
if ( ! MoneyRange ( nFees ) )
2015-08-06 09:59:09 +02:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-txns-fee-outofrange " ) ;
2015-04-24 16:45:16 +02:00
return true ;
}
} // namespace Consensus
bool CheckInputs ( const CTransaction & tx , CValidationState & state , const CCoinsViewCache & inputs , bool fScriptChecks , unsigned int flags , bool cacheStore , std : : vector < CScriptCheck > * pvChecks )
{
if ( ! tx . IsCoinBase ( ) )
{
if ( ! Consensus : : CheckTxInputs ( tx , state , inputs , GetSpendHeight ( inputs ) ) )
return false ;
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-08-23 16:21:08 +02:00
// Skip script verification when connecting blocks under the
// assumedvalid block. Assuming the assumedvalid block is valid this
// is safe because block merkle hashes are still computed and checked,
// Of course, if an assumed valid block is invalid due to false scriptSigs
// this optimization would allow an invalid chain to be accepted.
2012-12-01 22:51:10 +01:00
if ( fScriptChecks ) {
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-06-02 00:47:58 +02:00
const Coin & coin = inputs . AccessCoin ( prevout ) ;
assert ( ! coin . IsSpent ( ) ) ;
// 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.
const CScript & scriptPubKey = coin . out . scriptPubKey ;
const CAmount amount = coin . out . nValue ;
2012-01-11 02:18:00 +01:00
2011-09-02 22:59:47 +02:00
// Verify signature
2017-06-02 00:47:58 +02:00
CScriptCheck check ( scriptPubKey , amount , tx , i , flags , cacheStore ) ;
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-06-02 00:47:58 +02:00
CScriptCheck check2 ( scriptPubKey , amount , tx , i ,
2014-09-14 04:48:32 +02:00
flags & ~ STANDARD_NOT_MANDATORY_VERIFY_FLAGS , cacheStore ) ;
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
// invalid in new blocks, e.g. a invalid P2SH. We DoS ban
// 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-04 16:01:24 +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
}
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-11-09 12:32:57 +01:00
unsigned int nSize = GetSerializeSize ( fileout , blockundo ) ;
2015-04-19 23:48:25 +02:00
fileout < < FLATDATA ( 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 ;
}
bool UndoReadFromDisk ( CBlockUndo & blockundo , const CDiskBlockPos & pos , const uint256 & hashBlock )
{
// Open history file to read
CAutoFile filein ( OpenUndoFile ( pos , true ) , SER_DISK , CLIENT_VERSION ) ;
if ( filein . IsNull ( ) )
2016-09-19 16:54:13 +02:00
return error ( " %s: OpenUndoFile failed " , __func__ ) ;
2014-12-03 00:39:03 +01:00
// Read block
uint256 hashChecksum ;
2017-06-02 00:47:58 +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-02 00:47:58 +02:00
verifier < < hashBlock ;
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-06-02 00:47:58 +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 */
bool AbortNode ( const std : : string & strMessage , const std : : string & userMessage = " " )
{
2016-12-19 12:38:35 +01:00
SetMiscWarning ( strMessage ) ;
2015-01-17 00:57:14 +01:00
LogPrintf ( " *** %s \n " , strMessage ) ;
uiInterface . ThreadSafeMessageBox (
2015-08-09 01:17:27 +02:00
userMessage . empty ( ) ? _ ( " Error: A fatal internal error occurred, see debug.log for details " ) : userMessage ,
2015-01-17 00:57:14 +01:00
" " , CClientUIInterface : : MSG_ERROR ) ;
StartShutdown ( ) ;
return false ;
}
bool AbortNode ( CValidationState & state , const std : : string & strMessage , const std : : string & userMessage = " " )
{
AbortNode ( strMessage , userMessage ) ;
return state . Error ( strMessage ) ;
}
2014-12-03 00:39:03 +01:00
} // anon namespace
2010-08-29 18:58:15 +02:00
2017-06-02 00:47:58 +02:00
enum DisconnectResult
{
DISCONNECT_OK , // All good.
DISCONNECT_UNCLEAN , // Rolled back, but UTXO set was inconsistent with block.
DISCONNECT_FAILED // Something else went wrong.
} ;
2015-02-03 15:44:39 +01:00
/**
2017-06-02 00:47:58 +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 .
* @ param out The out point that corresponds to the tx input .
2017-06-02 00:47:58 +02:00
* @ return A DisconnectResult as an int
2015-02-03 15:44:39 +01:00
*/
2017-06-02 00:47:58 +02:00
int ApplyTxInUndo ( Coin & & undo , CCoinsViewCache & view , const COutPoint & out )
2015-02-03 15:44:39 +01:00
{
bool fClean = true ;
2017-06-02 00:47:58 +02:00
if ( view . HaveCoin ( out ) ) fClean = false ; // overwriting transaction output
if ( undo . nHeight = = 0 ) {
// Missing undo metadata (height and coinbase). Older versions included this
// information only in undo records for the last spend of a transactions'
// outputs. This implies that it must be present for some other output of the same tx.
const Coin & alternate = AccessByTxid ( view , out . hash ) ;
if ( ! alternate . IsSpent ( ) ) {
undo . nHeight = alternate . nHeight ;
undo . fCoinBase = alternate . fCoinBase ;
} else {
return DISCONNECT_FAILED ; // adding output for transaction without known metadata
}
2015-02-03 15:44:39 +01:00
}
2017-06-02 00:47:58 +02:00
view . AddCoin ( out , std : : move ( undo ) , undo . fCoinBase ) ;
2015-02-03 15:44:39 +01:00
2017-06-02 00:47:58 +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-05-03 05:35:05 +02:00
* When UNCLEAN or FAILED is returned , view is left in an indeterminate state . */
static DisconnectResult DisconnectBlock ( const CBlock & block , CValidationState & state , const CBlockIndex * pindex , CCoinsViewCache & view )
2010-08-29 18:58:15 +02:00
{
2013-11-05 02:27:39 +01:00
assert ( pindex - > GetBlockHash ( ) = = view . GetBestBlock ( ) ) ;
2010-08-29 18:58:15 +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 ;
2012-12-30 23:41:41 +01:00
CDiskBlockPos pos = pindex - > GetUndoPos ( ) ;
2017-05-03 05:35:05 +02:00
if ( pos . IsNull ( ) ) {
error ( " DisconnectBlock(): no undo data available " ) ;
return DISCONNECT_FAILED ;
}
if ( ! UndoReadFromDisk ( blockUndo , pos , pindex - > pprev - > GetBlockHash ( ) ) ) {
error ( " DisconnectBlock(): failure reading undo data " ) ;
return DISCONNECT_FAILED ;
}
2010-08-29 18:58:15 +02:00
2017-05-03 05:35:05 +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
2016-03-29 15:13:31 +02:00
std : : vector < std : : pair < CAddressIndexKey , CAmount > > addressIndex ;
2016-03-29 23:56:57 +02:00
std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > addressUnspentIndex ;
2016-04-05 21:53:38 +02:00
std : : vector < std : : pair < CSpentIndexKey , CSpentIndexValue > > spentIndex ;
2016-03-29 15:13:31 +02:00
2018-02-13 13:34:35 +01:00
if ( ! UndoSpecialTxsInBlock ( block , pindex ) ) {
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
// 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-21 10:51:32 +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-28 20:23:11 +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
2016-03-29 15:13:31 +02:00
if ( fAddressIndex ) {
for ( unsigned int k = tx . vout . size ( ) ; k - - > 0 ; ) {
const CTxOut & out = tx . vout [ k ] ;
if ( out . scriptPubKey . IsPayToScriptHash ( ) ) {
2018-02-21 20:26:53 +01:00
std : : vector < unsigned char > hashBytes ( out . scriptPubKey . begin ( ) + 2 , out . scriptPubKey . begin ( ) + 22 ) ;
2016-03-29 23:56:57 +02:00
// undo receiving activity
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 2 , uint160 ( hashBytes ) , pindex - > nHeight , i , hash , k , false ) , out . nValue ) ) ;
2016-03-29 23:56:57 +02:00
// undo unspent index
2018-02-21 20:26:53 +01:00
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 2 , uint160 ( hashBytes ) , hash , k ) , CAddressUnspentValue ( ) ) ) ;
2016-03-29 23:56:57 +02:00
2016-03-29 15:13:31 +02:00
} else if ( out . scriptPubKey . IsPayToPublicKeyHash ( ) ) {
2018-02-21 20:26:53 +01:00
std : : vector < unsigned char > hashBytes ( out . scriptPubKey . begin ( ) + 3 , out . scriptPubKey . begin ( ) + 23 ) ;
2016-03-29 23:56:57 +02:00
// undo receiving activity
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 1 , uint160 ( hashBytes ) , pindex - > nHeight , i , hash , k , false ) , out . nValue ) ) ;
2016-03-29 23:56:57 +02:00
// undo unspent index
2018-02-21 20:26:53 +01:00
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 1 , uint160 ( hashBytes ) , hash , k ) , CAddressUnspentValue ( ) ) ) ;
2016-03-29 23:56:57 +02:00
2018-01-09 12:23:46 +01:00
} else if ( out . scriptPubKey . IsPayToPublicKey ( ) ) {
uint160 hashBytes ( Hash160 ( out . scriptPubKey . begin ( ) + 1 , out . scriptPubKey . end ( ) - 1 ) ) ;
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 1 , hashBytes , pindex - > nHeight , i , hash , k , false ) , out . nValue ) ) ;
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 1 , hashBytes , hash , k ) , CAddressUnspentValue ( ) ) ) ;
2016-03-29 15:13:31 +02:00
} else {
continue ;
}
}
}
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-06-02 00:47:58 +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-21 03:18:09 +02:00
bool is_spent = view . SpendCoin ( out , & coin ) ;
2017-06-28 20:23:11 +02:00
if ( ! is_spent | | tx . vout [ o ] ! = coin . out | | pindex - > nHeight ! = coin . nHeight | | is_coinbase ! = coin . fCoinBase ) {
2017-06-02 00:47:58 +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
// restore inputs
if ( i > 0 ) { // not coinbases
2017-06-02 00:47:58 +02:00
CTxUndo & txundo = blockUndo . vtxundo [ i - 1 ] ;
2017-05-03 05:35:05 +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 ;
2017-09-26 17:58:49 +02:00
int undoHeight = txundo . vprevout [ j ] . nHeight ;
2017-06-02 00:47:58 +02:00
int res = ApplyTxInUndo ( std : : move ( txundo . vprevout [ j ] ) , view , out ) ;
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
2016-04-05 21:53:38 +02:00
const CTxIn input = tx . vin [ j ] ;
if ( fSpentIndex ) {
// undo and delete the spent index
2018-02-21 20:26:53 +01:00
spentIndex . push_back ( std : : make_pair ( CSpentIndexKey ( input . prevout . hash , input . prevout . n ) , CSpentIndexValue ( ) ) ) ;
2016-04-05 21:53:38 +02:00
}
2016-03-29 15:13:31 +02:00
if ( fAddressIndex ) {
2017-09-26 17:58:49 +02:00
const Coin & coin = view . AccessCoin ( tx . vin [ j ] . prevout ) ;
const CTxOut & prevout = coin . out ;
2016-03-28 22:47:20 +02:00
if ( prevout . scriptPubKey . IsPayToScriptHash ( ) ) {
2018-02-21 20:26:53 +01:00
std : : vector < unsigned char > hashBytes ( prevout . scriptPubKey . begin ( ) + 2 , prevout . scriptPubKey . begin ( ) + 22 ) ;
2016-03-29 23:56:57 +02:00
// undo spending activity
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 2 , uint160 ( hashBytes ) , pindex - > nHeight , i , hash , j , true ) , prevout . nValue * - 1 ) ) ;
2016-03-29 23:56:57 +02:00
// restore unspent index
2018-02-21 20:26:53 +01:00
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 2 , uint160 ( hashBytes ) , input . prevout . hash , input . prevout . n ) , CAddressUnspentValue ( prevout . nValue , prevout . scriptPubKey , undoHeight ) ) ) ;
2016-03-29 23:56:57 +02:00
2016-03-28 22:47:20 +02:00
} else if ( prevout . scriptPubKey . IsPayToPublicKeyHash ( ) ) {
2018-02-21 20:26:53 +01:00
std : : vector < unsigned char > hashBytes ( prevout . scriptPubKey . begin ( ) + 3 , prevout . scriptPubKey . begin ( ) + 23 ) ;
2016-03-29 23:56:57 +02:00
// undo spending activity
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 1 , uint160 ( hashBytes ) , pindex - > nHeight , i , hash , j , true ) , prevout . nValue * - 1 ) ) ;
2016-03-29 23:56:57 +02:00
// restore unspent index
2018-02-21 20:26:53 +01:00
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 1 , uint160 ( hashBytes ) , input . prevout . hash , input . prevout . n ) , CAddressUnspentValue ( prevout . nValue , prevout . scriptPubKey , undoHeight ) ) ) ;
2016-03-29 23:56:57 +02:00
2018-01-09 12:23:46 +01:00
} else if ( prevout . scriptPubKey . IsPayToPublicKey ( ) ) {
uint160 hashBytes ( Hash160 ( prevout . scriptPubKey . begin ( ) + 1 , prevout . scriptPubKey . end ( ) - 1 ) ) ;
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 1 , hashBytes , pindex - > nHeight , i , hash , j , false ) , prevout . nValue ) ) ;
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 1 , hashBytes , hash , j ) , CAddressUnspentValue ( ) ) ) ;
2016-03-28 22:47:20 +02:00
} else {
continue ;
}
}
2016-04-05 21:53:38 +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
}
2017-06-02 00:47:58 +02:00
// At this point, all of txundo.vprevout should have been moved out.
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 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 ( ) ) ;
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-03-29 15:13:31 +02:00
if ( fAddressIndex ) {
2016-03-28 22:47:20 +02:00
if ( ! pblocktree - > EraseAddressIndex ( addressIndex ) ) {
2017-05-03 05:35:05 +02:00
AbortNode ( state , " Failed to delete address index " ) ;
return DISCONNECT_FAILED ;
2016-03-28 22:47:20 +02:00
}
2016-03-29 23:56:57 +02:00
if ( ! pblocktree - > UpdateAddressUnspentIndex ( addressUnspentIndex ) ) {
2017-05-03 05:35:05 +02:00
AbortNode ( state , " Failed to write address unspent index " ) ;
return DISCONNECT_FAILED ;
2016-03-29 23:56:57 +02:00
}
2016-03-28 22:47:20 +02:00
}
2018-10-26 07:03:33 +02:00
// make sure the flag is reset in case of a chain reorg
2018-10-26 18:42:52 +02:00
// (we reused the DIP3 deployment)
2018-10-26 07:03:33 +02:00
instantsend . isAutoLockBip9Active =
2018-10-26 18:42:52 +02:00
( VersionBitsState ( pindex - > pprev , Params ( ) . GetConsensus ( ) , Consensus : : DEPLOYMENT_DIP0003 , versionbitscache ) = = THRESHOLD_ACTIVE ) ;
2018-10-26 07:03:33 +02:00
2017-05-03 05:35:05 +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 ) ;
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 )
2014-09-25 08:21:21 +02:00
TruncateFile ( fileOld , vinfoBlockFile [ nLastBlockFile ] . nSize ) ;
2012-12-01 11:36:53 +01:00
FileCommit ( fileOld ) ;
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 )
2014-09-25 08:21:21 +02:00
TruncateFile ( fileOld , vinfoBlockFile [ nLastBlockFile ] . nUndoSize ) ;
2012-12-01 11:36:53 +01:00
FileCommit ( fileOld ) ;
fclose ( fileOld ) ;
}
2012-09-06 03:21:18 +02:00
}
2013-01-27 00:14:11 +01:00
bool FindUndoPos ( CValidationState & state , int nFile , CDiskBlockPos & pos , unsigned int nAddSize ) ;
2012-08-13 19:11:05 +02:00
2012-12-01 23:04:14 +01:00
static CCheckQueue < CScriptCheck > scriptcheckqueue ( 128 ) ;
2013-03-07 04:31:26 +01:00
void ThreadScriptCheck ( ) {
2015-03-19 15:15:08 +01:00
RenameThread ( " dash-scriptch " ) ;
2012-12-01 23:04:14 +01:00
scriptcheckqueue . Thread ( ) ;
}
2016-02-15 05:13:27 +01:00
// Protected by cs_main
2017-04-11 12:53:54 +02:00
VersionBitsCache versionbitscache ;
2016-02-15 05:13:27 +01:00
2018-10-26 18:42:52 +02:00
int32_t ComputeBlockVersion ( const CBlockIndex * pindexPrev , const Consensus : : Params & params , bool fCheckMasternodesUpgraded )
2016-02-15 05:13:27 +01:00
{
LOCK ( cs_main ) ;
int32_t nVersion = VERSIONBITS_TOP_BITS ;
for ( int i = 0 ; i < ( int ) Consensus : : MAX_VERSION_BITS_DEPLOYMENTS ; i + + ) {
2017-09-11 16:13:30 +02:00
Consensus : : DeploymentPos pos = Consensus : : DeploymentPos ( i ) ;
ThresholdState state = VersionBitsState ( pindexPrev , params , pos , versionbitscache ) ;
const struct BIP9DeploymentInfo & vbinfo = VersionBitsDeploymentInfo [ pos ] ;
2018-10-26 18:42:52 +02:00
if ( vbinfo . check_mn_protocol & & state = = THRESHOLD_STARTED & & fCheckMasternodesUpgraded ) {
2018-08-14 11:58:38 +02:00
std : : vector < CTxOut > voutMasternodePayments ;
2017-09-11 16:13:30 +02:00
masternode_info_t mnInfo ;
2018-08-14 11:58:38 +02:00
if ( ! mnpayments . GetBlockTxOuts ( pindexPrev - > nHeight + 1 , 0 , voutMasternodePayments ) ) {
2017-09-20 22:31:23 +02:00
// no votes for this block
continue ;
}
2018-08-14 11:58:38 +02:00
bool mnKnown = false ;
for ( const auto & txout : voutMasternodePayments ) {
if ( mnodeman . GetMasternodeInfo ( txout . scriptPubKey , mnInfo ) ) {
mnKnown = true ;
break ;
}
}
if ( ! mnKnown ) {
2017-09-20 22:31:23 +02:00
// unknown masternode
continue ;
}
2018-10-26 18:42:52 +02:00
if ( mnInfo . nProtocolVersion < DMN_PROTO_VERSION ) {
2017-09-20 22:31:23 +02:00
// masternode is not upgraded yet
2017-09-11 16:13:30 +02:00
continue ;
}
}
2016-02-15 05:13:27 +01:00
if ( state = = THRESHOLD_LOCKED_IN | | state = = THRESHOLD_STARTED ) {
nVersion | = VersionBitsMask ( params , ( Consensus : : DeploymentPos ) i ) ;
}
}
return nVersion ;
}
2016-08-06 16:31:51 +02:00
bool GetBlockHash ( uint256 & hashRet , int nBlockHeight )
{
LOCK ( cs_main ) ;
if ( chainActive . Tip ( ) = = NULL ) return false ;
if ( nBlockHeight < - 1 | | nBlockHeight > chainActive . Height ( ) ) return false ;
if ( nBlockHeight = = - 1 ) nBlockHeight = chainActive . Height ( ) ;
hashRet = chainActive [ nBlockHeight ] - > GetBlockHash ( ) ;
return true ;
}
2016-02-15 05:13:27 +01:00
/**
* Threshold condition checker that triggers when unknown versionbits are seen on the network .
*/
class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
{
private :
int bit ;
public :
WarningBitsConditionChecker ( int bitIn ) : bit ( bitIn ) { }
2018-02-15 08:29:15 +01: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
2018-02-15 08:29:15 +01: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 & &
2018-10-26 18:42:52 +02:00
( ( ComputeBlockVersion ( pindex - > pprev , params ) > > bit ) & 1 ) = = 0 ;
2016-02-15 05:13:27 +01:00
}
} ;
// Protected by cs_main
static ThresholdConditionCache warningcache [ VERSIONBITS_NUM_BITS ] ;
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-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 ) . */
2016-04-21 14:35:51 +02:00
static bool ConnectBlock ( const CBlock & block , CValidationState & state , CBlockIndex * pindex ,
CCoinsViewCache & view , const CChainParams & chainparams , bool fJustCheck = false )
2010-08-29 18:58:15 +02:00
{
2014-04-23 08:55:24 +02:00
AssertLockHeld ( cs_main ) ;
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
2016-06-09 01:12:52 +02:00
if ( ! CheckBlock ( block , state , chainparams . GetConsensus ( ) , ! fJustCheck , ! fJustCheck ) )
2016-02-01 10:21:27 +01:00
return error ( " %s: Consensus::CheckBlock: %s " , __func__ , FormatStateMessage ( state ) ) ;
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
2014-12-15 09:11:16 +01:00
uint256 hashPrevBlock = pindex - > pprev = = NULL ? 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
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 )
view . SetBestBlock ( pindex - > GetBlockHash ( ) ) ;
2013-01-19 00:35:17 +01:00
return true ;
}
2015-03-19 13:34:06 +01:00
bool fScriptChecks = true ;
2017-08-23 16:21:08 +02: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 & &
pindexBestHeader - > nChainWork > = UintToArith256 ( chainparams . GetConsensus ( ) . nMinimumChainWork ) ) {
// This block is a member of the assumed verified chain and an ancestor of the best header.
// The equivalent time check discourages hashpower from extorting the network via DOS attack
// 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 ;
LogPrint ( " bench " , " - Sanity checks: %.2fms [%.2fs] \n " , 0.001 * ( nTime1 - nTimeStart ) , nTimeCheck * 0.000001 ) ;
2012-12-01 22:51:10 +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.
2012-10-24 07:41:52 +02:00
bool fEnforceBIP30 = ( ! pindex - > phashBlock ) | | // Enforce on CreateNewBlock invocations which don't have a hash.
2014-12-16 14:50:05 +01:00
! ( ( pindex - > nHeight = = 91842 & & pindex - > GetBlockHash ( ) = = uint256S ( " 0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec " ) ) | |
( 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
// before the first had been spent. Since those coinbases are sufficiently buried its no longer possible to create further
// 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.
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 ) ) ;
2015-11-02 22:10:57 +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
if ( fEnforceBIP30 ) {
2016-11-21 10:51:32 +01:00
for ( const auto & tx : block . vtx ) {
for ( size_t o = 0 ; o < tx - > vout . size ( ) ; o + + ) {
if ( view . HaveCoin ( COutPoint ( tx - > GetHash ( ) , o ) ) ) {
2017-06-02 00:47:58 +02:00
return state . DoS ( 100 , error ( " ConnectBlock(): tried to overwrite transaction " ) ,
REJECT_INVALID , " bad-txns-BIP30 " ) ;
}
}
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
2018-02-01 13:42:21 +01:00
/// DASH: Check superblock start
// make sure old budget is the real one
if ( pindex - > nHeight = = chainparams . GetConsensus ( ) . nSuperblockStartBlock & &
chainparams . GetConsensus ( ) . nSuperblockStartHash ! = uint256 ( ) & &
block . GetHash ( ) ! = chainparams . GetConsensus ( ) . nSuperblockStartHash )
return state . DoS ( 100 , error ( " ConnectBlock(): invalid superblock start " ) ,
REJECT_INVALID , " bad-sb-start " ) ;
/// END DASH
2012-06-22 17:50:52 +02:00
// BIP16 didn't become active until Apr 1 2012
2013-04-13 07:13:08 +02:00
int64_t nBIP16SwitchTime = 1333238400 ;
2014-06-28 23:36:06 +02:00
bool fStrictPayToScriptHash = ( pindex - > GetBlockTime ( ) > = nBIP16SwitchTime ) ;
2012-01-20 23:07:40 +01:00
2014-09-14 04:48:32 +02:00
unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE ;
2012-12-08 22:49:04 +01:00
2016-08-04 11:55:25 +02:00
// Start enforcing the DERSIG (BIP66) rule
if ( pindex - > nHeight > = chainparams . GetConsensus ( ) . BIP66Height ) {
2015-02-06 05:56:10 +01:00
flags | = SCRIPT_VERIFY_DERSIG ;
}
2016-08-04 11:55:25 +02:00
// Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
if ( pindex - > nHeight > = chainparams . GetConsensus ( ) . BIP65Height ) {
2015-06-28 20:30:50 +02:00
flags | = SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY ;
}
2016-02-16 17:37:43 +01:00
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
int nLockTimeFlags = 0 ;
2016-02-20 23:37:13 +01:00
if ( VersionBitsState ( pindex - > pprev , chainparams . GetConsensus ( ) , Consensus : : DEPLOYMENT_CSV , versionbitscache ) = = THRESHOLD_ACTIVE ) {
flags | = SCRIPT_VERIFY_CHECKSEQUENCEVERIFY ;
2016-02-16 17:37:43 +01:00
nLockTimeFlags | = LOCKTIME_VERIFY_SEQUENCE ;
2016-02-20 23:37:13 +01:00
}
2018-01-30 20:18:51 +01:00
if ( VersionBitsState ( pindex - > pprev , chainparams . GetConsensus ( ) , Consensus : : DEPLOYMENT_BIP147 , versionbitscache ) = = THRESHOLD_ACTIVE ) {
flags | = SCRIPT_VERIFY_NULLDUMMY ;
}
2015-11-07 00:12:30 +01:00
int64_t nTime2 = GetTimeMicros ( ) ; nTimeForks + = nTime2 - nTime1 ;
LogPrint ( " bench " , " - Fork checks: %.2fms [%.2fs] \n " , 0.001 * ( nTime2 - nTime1 ) , nTimeForks * 0.000001 ) ;
2012-06-23 14:17:13 +02:00
CBlockUndo blockundo ;
2012-12-01 23:04:14 +01:00
CCheckQueueControl < CScriptCheck > control ( fScriptChecks & & nScriptCheckThreads ? & scriptcheckqueue : NULL ) ;
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 ;
2012-04-23 20:14:03 +02:00
unsigned int nSigOps = 0 ;
2013-06-24 03:50:06 +02:00
CDiskTxPos pos ( pindex - > GetBlockPos ( ) , GetSizeOfCompactSize ( block . vtx . size ( ) ) ) ;
2013-01-11 01:47:57 +01:00
std : : vector < std : : pair < uint256 , CDiskTxPos > > vPos ;
2013-06-24 03:50:06 +02:00
vPos . reserve ( block . vtx . size ( ) ) ;
2014-09-03 15:54:37 +02:00
blockundo . vtxundo . reserve ( block . vtx . size ( ) - 1 ) ;
2016-03-05 22:31:10 +01:00
std : : vector < std : : pair < CAddressIndexKey , CAmount > > addressIndex ;
2016-03-29 21:17:30 +02:00
std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > addressUnspentIndex ;
2016-04-05 21:53:38 +02:00
std : : vector < std : : pair < CSpentIndexKey , CSpentIndexValue > > spentIndex ;
2016-03-05 22:31:10 +01:00
2018-03-08 13:18:24 +01:00
bool fDIP0001Active_context = pindex - > nHeight > = Params ( ) . GetConsensus ( ) . DIP0001Height ;
2017-09-11 16:13:30 +02:00
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-21 10:51:32 +01:00
const CTransaction & tx = * ( block . vtx [ i ] ) ;
2016-03-05 22:31:10 +01:00
const uint256 txhash = tx . GetHash ( ) ;
2012-07-08 00:06:34 +02:00
2012-12-01 20:10:23 +01:00
nInputs + = tx . vin . size ( ) ;
2013-01-08 13:17:15 +01:00
nSigOps + = GetLegacySigOpCount ( tx ) ;
2017-09-11 16:13:30 +02:00
if ( nSigOps > MaxBlockSigOps ( fDIP0001Active_context ) )
2015-01-08 11:44:25 +01:00
return state . DoS ( 100 , error ( " ConnectBlock(): too many sigops " ) ,
2012-09-10 04:02:35 +02:00
REJECT_INVALID , " bad-blk-sigops " ) ;
2012-01-20 23:07:40 +01:00
2012-01-11 02:18:00 +01:00
if ( ! tx . IsCoinBase ( ) )
{
2013-01-08 13:17:15 +01:00
if ( ! view . HaveInputs ( tx ) )
2015-01-08 11:44:25 +01:00
return state . DoS ( 100 , error ( " ConnectBlock(): inputs missing/spent " ) ,
2012-09-10 04:02:35 +02:00
REJECT_INVALID , " bad-txns-inputs-missingorspent " ) ;
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-06-02 00:47:58 +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-04-05 21:53:38 +02:00
if ( fAddressIndex | | fSpentIndex )
2016-03-05 22:31:10 +01:00
{
for ( size_t j = 0 ; j < tx . vin . size ( ) ; j + + ) {
2016-03-30 21:12:19 +02:00
const CTxIn input = tx . vin [ j ] ;
2017-09-26 17:58:49 +02:00
const Coin & coin = view . AccessCoin ( tx . vin [ j ] . prevout ) ;
const CTxOut & prevout = coin . out ;
2016-05-13 17:43:01 +02:00
uint160 hashBytes ;
int addressType ;
2016-03-29 21:17:30 +02:00
2016-05-13 17:43:01 +02:00
if ( prevout . scriptPubKey . IsPayToScriptHash ( ) ) {
2018-02-21 20:26:53 +01:00
hashBytes = uint160 ( std : : vector < unsigned char > ( prevout . scriptPubKey . begin ( ) + 2 , prevout . scriptPubKey . begin ( ) + 22 ) ) ;
2016-05-13 17:43:01 +02:00
addressType = 2 ;
} else if ( prevout . scriptPubKey . IsPayToPublicKeyHash ( ) ) {
2018-02-21 20:26:53 +01:00
hashBytes = uint160 ( std : : vector < unsigned char > ( prevout . scriptPubKey . begin ( ) + 3 , prevout . scriptPubKey . begin ( ) + 23 ) ) ;
2016-05-13 17:43:01 +02:00
addressType = 1 ;
2018-01-09 12:23:46 +01:00
} else if ( prevout . scriptPubKey . IsPayToPublicKey ( ) ) {
hashBytes = Hash160 ( prevout . scriptPubKey . begin ( ) + 1 , prevout . scriptPubKey . end ( ) - 1 ) ;
addressType = 1 ;
2016-05-13 17:43:01 +02:00
} else {
hashBytes . SetNull ( ) ;
addressType = 0 ;
2016-04-05 21:53:38 +02:00
}
2016-03-29 21:17:30 +02:00
2016-05-13 17:43:01 +02:00
if ( fAddressIndex & & addressType > 0 ) {
// record spending activity
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( addressType , hashBytes , pindex - > nHeight , i , txhash , j , true ) , prevout . nValue * - 1 ) ) ;
2016-04-05 21:53:38 +02:00
2016-05-13 17:43:01 +02:00
// remove address from unspent index
2018-02-21 20:26:53 +01:00
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( addressType , hashBytes , input . prevout . hash , input . prevout . n ) , CAddressUnspentValue ( ) ) ) ;
2016-03-05 22:31:10 +01:00
}
2016-04-05 21:53:38 +02:00
2016-05-13 17:43:01 +02:00
if ( fSpentIndex ) {
// add the spent index to determine the txid and input that spent an output
// and to find the amount and address from an input
2018-02-21 20:26:53 +01:00
spentIndex . push_back ( std : : make_pair ( CSpentIndexKey ( input . prevout . hash , input . prevout . n ) , CSpentIndexValue ( txhash , j , pindex - > nHeight , prevout . nValue , addressType , hashBytes ) ) ) ;
2016-05-13 17:43:01 +02:00
}
2016-03-05 22:31:10 +01:00
}
2016-05-13 17:43:01 +02:00
2016-03-05 22:31:10 +01:00
}
2012-01-20 23:07:40 +01:00
if ( fStrictPayToScriptHash )
{
// Add in sigops done by pay-to-script-hash inputs;
// this is to prevent a "rogue miner" from creating
// an incredibly-expensive-to-validate block.
2013-01-08 13:17:15 +01:00
nSigOps + = GetP2SHSigOpCount ( tx , view ) ;
2017-09-11 16:13:30 +02:00
if ( nSigOps > MaxBlockSigOps ( fDIP0001Active_context ) )
2015-01-08 11:44:25 +01:00
return state . DoS ( 100 , error ( " ConnectBlock(): too many sigops " ) ,
2012-09-10 04:02:35 +02:00
REJECT_INVALID , " bad-blk-sigops " ) ;
2012-01-20 23:07:40 +01:00
}
2012-01-05 03:40:52 +01:00
2013-11-11 07:03:51 +01:00
nFees + = view . GetValueIn ( tx ) - tx . GetValueOut ( ) ;
2012-06-23 14:17:13 +02:00
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) */
if ( ! CheckInputs ( tx , state , view , fScriptChecks , flags , fCacheResults , nScriptCheckThreads ? & vChecks : NULL ) )
2015-08-06 10:02:12 +02:00
return error ( " ConnectBlock(): CheckInputs on %s failed with %s " ,
tx . GetHash ( ) . ToString ( ) , FormatStateMessage ( state ) ) ;
2012-12-01 23:04:14 +01:00
control . Add ( vChecks ) ;
2012-01-11 02:18:00 +01:00
}
2016-03-05 22:31:10 +01:00
if ( fAddressIndex ) {
for ( unsigned int k = 0 ; k < tx . vout . size ( ) ; k + + ) {
const CTxOut & out = tx . vout [ k ] ;
if ( out . scriptPubKey . IsPayToScriptHash ( ) ) {
2018-02-21 20:26:53 +01:00
std : : vector < unsigned char > hashBytes ( out . scriptPubKey . begin ( ) + 2 , out . scriptPubKey . begin ( ) + 22 ) ;
2016-03-29 21:17:30 +02:00
// record receiving activity
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 2 , uint160 ( hashBytes ) , pindex - > nHeight , i , txhash , k , false ) , out . nValue ) ) ;
2016-03-29 21:17:30 +02:00
// record unspent output
2018-02-21 20:26:53 +01:00
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 2 , uint160 ( hashBytes ) , txhash , k ) , CAddressUnspentValue ( out . nValue , out . scriptPubKey , pindex - > nHeight ) ) ) ;
2016-03-29 21:17:30 +02:00
2016-03-05 22:31:10 +01:00
} else if ( out . scriptPubKey . IsPayToPublicKeyHash ( ) ) {
2018-02-21 20:26:53 +01:00
std : : vector < unsigned char > hashBytes ( out . scriptPubKey . begin ( ) + 3 , out . scriptPubKey . begin ( ) + 23 ) ;
2016-03-29 21:17:30 +02:00
// record receiving activity
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 1 , uint160 ( hashBytes ) , pindex - > nHeight , i , txhash , k , false ) , out . nValue ) ) ;
2016-03-29 21:17:30 +02:00
// record unspent output
2018-02-21 20:26:53 +01:00
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 1 , uint160 ( hashBytes ) , txhash , k ) , CAddressUnspentValue ( out . nValue , out . scriptPubKey , pindex - > nHeight ) ) ) ;
2016-03-29 21:17:30 +02:00
2018-01-09 12:23:46 +01:00
} else if ( out . scriptPubKey . IsPayToPublicKey ( ) ) {
uint160 hashBytes ( Hash160 ( out . scriptPubKey . begin ( ) + 1 , out . scriptPubKey . end ( ) - 1 ) ) ;
2018-02-21 20:26:53 +01:00
addressIndex . push_back ( std : : make_pair ( CAddressIndexKey ( 1 , hashBytes , pindex - > nHeight , i , txhash , k , false ) , out . nValue ) ) ;
addressUnspentIndex . push_back ( std : : make_pair ( CAddressUnspentKey ( 1 , hashBytes , txhash , k ) , CAddressUnspentValue ( out . nValue , out . scriptPubKey , pindex - > nHeight ) ) ) ;
2016-03-05 22:31:10 +01:00
} else {
continue ;
}
}
}
2014-09-03 15:54:37 +02:00
CTxUndo undoDummy ;
if ( i > 0 ) {
blockundo . vtxundo . push_back ( CTxUndo ( ) ) ;
}
2016-05-09 11:57:16 +02:00
UpdateCoins ( tx , view , i = = 0 ? undoDummy : blockundo . vtxundo . back ( ) , pindex - > nHeight ) ;
2012-12-01 20:10:23 +01:00
2014-06-09 10:02:00 +02:00
vPos . push_back ( std : : make_pair ( tx . GetHash ( ) , pos ) ) ;
2013-01-11 01:47:57 +01:00
pos . nTxOffset + = : : GetSerializeSize ( tx , SER_DISK , CLIENT_VERSION ) ;
2010-08-29 18:58:15 +02:00
}
2015-11-07 00:12:30 +01:00
int64_t nTime3 = GetTimeMicros ( ) ; nTimeConnect + = nTime3 - nTime2 ;
LogPrint ( " bench " , " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs] \n " , ( unsigned ) block . vtx . size ( ) , 0.001 * ( nTime3 - nTime2 ) , 0.001 * ( nTime3 - nTime2 ) / block . vtx . size ( ) , nInputs < = 1 ? 0 : 0.001 * ( nTime3 - nTime2 ) / ( nInputs - 1 ) , nTimeConnect * 0.000001 ) ;
2011-10-03 19:05:43 +02:00
2018-02-13 13:34:35 +01:00
if ( ! ProcessSpecialTxsInBlock ( block , pindex , state ) )
return false ;
2017-01-30 07:01:08 +01:00
// DASH : MODIFIED TO CHECK MASTERNODE PAYMENTS AND SUPERBLOCKS
// It's possible that we simply don't have enough data and this could fail
// (i.e. block itself could be a correct one and we need to store it),
// that's why this is in ConnectBlock. Could be the other way around however -
// the peer who sent us this block is missing some data and wasn't able
// to recognize that block is actually invalid.
// TODO: resync data (both ways?) and try to reprocess this block later.
2016-02-15 14:09:43 +01:00
CAmount blockReward = nFees + GetBlockSubsidy ( pindex - > pprev - > nBits , pindex - > pprev - > nHeight , chainparams . GetConsensus ( ) ) ;
2016-12-01 22:58:55 +01:00
std : : string strError = " " ;
if ( ! IsBlockValueValid ( block , pindex - > nHeight , blockReward , strError ) ) {
2017-01-30 07:01:08 +01:00
return state . DoS ( 0 , error ( " ConnectBlock(DASH): %s " , strError ) , REJECT_INVALID , " bad-cb-amount " ) ;
2016-12-01 14:58:17 +01:00
}
2016-08-22 03:41:40 +02:00
2016-11-21 10:51:32 +01:00
if ( ! IsBlockPayeeValid ( * block . vtx [ 0 ] , pindex - > nHeight , blockReward ) ) {
2018-02-21 20:26:53 +01:00
mapRejectedBlocks . insert ( std : : make_pair ( block . GetHash ( ) , GetTime ( ) ) ) ;
2017-01-30 07:01:08 +01:00
return state . DoS ( 0 , error ( " ConnectBlock(DASH): couldn't find masternode or superblock payments " ) ,
2016-08-22 03:41:40 +02:00
REJECT_INVALID , " bad-cb-payee " ) ;
}
// END DASH
2012-10-22 21:46:00 +02:00
2012-12-01 23:04:14 +01:00
if ( ! control . Wait ( ) )
2013-01-27 00:14:11 +01:00
return state . DoS ( 100 , false ) ;
2015-11-07 00:12:30 +01:00
int64_t nTime4 = GetTimeMicros ( ) ; nTimeVerify + = nTime4 - nTime2 ;
LogPrint ( " bench " , " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs] \n " , nInputs - 1 , 0.001 * ( nTime4 - nTime2 ) , nInputs < = 1 ? 0 : 0.001 * ( nTime4 - nTime2 ) / ( nInputs - 1 ) , nTimeVerify * 0.000001 ) ;
2012-12-01 23:04:14 +01:00
2012-05-09 19:24:44 +02:00
if ( fJustCheck )
return true ;
2012-08-13 19:11:05 +02:00
// Write undo information to disk
2014-03-13 03:48:27 +01:00
if ( pindex - > GetUndoPos ( ) . IsNull ( ) | | ! pindex - > IsValid ( BLOCK_VALID_SCRIPTS ) )
2012-08-13 19:11:05 +02:00
{
2012-08-19 00:33:01 +02:00
if ( pindex - > GetUndoPos ( ) . IsNull ( ) ) {
2016-09-27 13:25:42 +02:00
CDiskBlockPos _pos ;
if ( ! FindUndoPos ( state , pindex - > nFile , _pos , : : GetSerializeSize ( blockundo , SER_DISK , CLIENT_VERSION ) + 40 ) )
2015-01-08 11:44:25 +01:00
return error ( " ConnectBlock() : FindUndoPos failed " ) ;
2016-09-27 13:25:42 +02:00
if ( ! UndoWriteToDisk ( blockundo , _pos , pindex - > pprev - > GetBlockHash ( ) , chainparams . MessageStart ( ) ) )
2015-01-17 00:57:14 +01:00
return AbortNode ( state , " Failed to write undo data " ) ;
2012-08-19 00:33:01 +02:00
// update nUndoPos in block index
2016-09-27 13:25:42 +02:00
pindex - > nUndoPos = _pos . nPos ;
2012-08-19 00:33:01 +02:00
pindex - > nStatus | = BLOCK_HAVE_UNDO ;
}
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
}
2013-01-11 01:47:57 +01:00
if ( fTxIndex )
2013-01-27 00:14:11 +01:00
if ( ! pblocktree - > WriteTxIndex ( vPos ) )
2015-01-17 00:57:14 +01:00
return AbortNode ( state , " Failed to write transaction index " ) ;
2013-01-11 01:47:57 +01:00
2016-03-29 21:17:30 +02:00
if ( fAddressIndex ) {
if ( ! pblocktree - > WriteAddressIndex ( addressIndex ) ) {
2016-03-22 23:11:04 +01:00
return AbortNode ( state , " Failed to write address index " ) ;
2016-03-29 21:17:30 +02:00
}
if ( ! pblocktree - > UpdateAddressUnspentIndex ( addressUnspentIndex ) ) {
return AbortNode ( state , " Failed to write address unspent index " ) ;
}
}
2016-03-22 23:11:04 +01:00
2016-04-05 21:53:38 +02:00
if ( fSpentIndex )
if ( ! pblocktree - > UpdateSpentIndex ( spentIndex ) )
return AbortNode ( state , " Failed to write transaction index " ) ;
2016-03-22 23:11:04 +01:00
if ( fTimestampIndex )
if ( ! pblocktree - > WriteTimestampIndex ( CTimestampIndexKey ( pindex - > nTime , pindex - > GetBlockHash ( ) ) ) )
return AbortNode ( state , " Failed to write timestamp index " ) ;
2016-03-05 22:31:10 +01:00
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
2018-10-26 07:03:33 +02:00
if ( ! fJustCheck ) {
// check if previous block had DIP3 disabled and the new block has it enabled
if ( VersionBitsState ( pindex - > pprev , chainparams . GetConsensus ( ) , Consensus : : DEPLOYMENT_DIP0003 , versionbitscache ) ! = THRESHOLD_ACTIVE & &
VersionBitsState ( pindex , chainparams . GetConsensus ( ) , Consensus : : DEPLOYMENT_DIP0003 , versionbitscache ) = = THRESHOLD_ACTIVE ) {
LogPrintf ( " %s -- DIP0003 got activated at height %d \n " , __func__ , pindex - > nHeight ) ;
}
}
2015-11-07 00:12:30 +01:00
int64_t nTime5 = GetTimeMicros ( ) ; nTimeIndex + = nTime5 - nTime4 ;
LogPrint ( " bench " , " - Index writing: %.2fms [%.2fs] \n " , 0.001 * ( nTime5 - nTime4 ) , nTimeIndex * 0.000001 ) ;
2014-07-26 22:49:17 +02:00
2014-05-07 16:45:33 +02:00
// Watch for changes to the previous coinbase transaction.
static uint256 hashPrevBestCoinBase ;
2015-02-05 01:11:44 +01:00
GetMainSignals ( ) . UpdatedTransaction ( hashPrevBestCoinBase ) ;
2016-11-21 10:51:32 +01:00
hashPrevBestCoinBase = block . vtx [ 0 ] - > GetHash ( ) ;
2014-05-07 16:45:33 +02:00
2016-06-20 14:45:34 +02:00
2015-11-07 00:12:30 +01:00
int64_t nTime6 = GetTimeMicros ( ) ; nTimeCallbacks + = nTime6 - nTime5 ;
LogPrint ( " bench " , " - Callbacks: %.2fms [%.2fs] \n " , 0.001 * ( nTime6 - nTime5 ) , nTimeCallbacks * 0.000001 ) ;
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 .
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-01-11 14:16:11 +01:00
bool static FlushStateToDisk ( CValidationState & state , FlushStateMode mode , int nManualPruneHeight ) {
2017-01-05 22:46:10 +01:00
int64_t nMempoolUsage = mempool . DynamicMemoryUsage ( ) ;
2015-04-17 14:40:24 +02:00
const CChainParams & chainparams = Params ( ) ;
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 ) ;
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 ;
static int64_t nLastSetChain = 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 ;
bool fFlushForPrune = false ;
2015-01-04 19:11:44 +01:00
try {
2017-01-11 14:16:11 +01:00
if ( fPruneMode & & ( fCheckForPruning | | nManualPruneHeight > 0 ) & & ! fReindex ) {
if ( nManualPruneHeight > 0 ) {
FindFilesToPruneManual ( setFilesToPrune , nManualPruneHeight ) ;
} else {
FindFilesToPrune ( setFilesToPrune , chainparams . PruneAfterHeight ( ) ) ;
fCheckForPruning = 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
if ( ! setFilesToPrune . empty ( ) ) {
fFlushForPrune = true ;
if ( ! fHavePruned ) {
pblocktree - > WriteFlag ( " prunedblockfiles " , true ) ;
fHavePruned = true ;
}
}
}
2015-05-04 22:00:19 +02:00
int64_t nNow = GetTimeMicros ( ) ;
// Avoid writing/flushing immediately after startup.
if ( nLastWrite = = 0 ) {
nLastWrite = nNow ;
}
if ( nLastFlush = = 0 ) {
nLastFlush = nNow ;
}
if ( nLastSetChain = = 0 ) {
nLastSetChain = nNow ;
}
2017-01-05 22:46:10 +01:00
int64_t nMempoolSizeMax = GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ;
2017-04-05 08:08:02 +02:00
int64_t cacheSize = pcoinsTip - > DynamicMemoryUsage ( ) * DB_PEAK_USAGE_FACTOR ;
2017-01-05 22:46:10 +01:00
int64_t nTotalSpace = nCoinCacheUsage + std : : max < int64_t > ( nMempoolSizeMax - nMempoolUsage , 0 ) ;
2017-06-02 00:47:58 +02:00
// 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).
bool fCacheLarge = mode = = FLUSH_STATE_PERIODIC & & cacheSize > std : : max ( ( 9 * nTotalSpace ) / 10 , nTotalSpace - MAX_BLOCK_COINSDB_USAGE * 1024 * 1024 ) ;
2015-05-04 22:00:19 +02:00
// The cache is over the limit, we have to write now.
2017-06-02 00:47:58 +02:00
bool fCacheCritical = mode = = FLUSH_STATE_IF_NEEDED & & cacheSize > nCoinCacheUsage ;
2015-05-04 22:00:19 +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.
bool fPeriodicWrite = mode = = FLUSH_STATE_PERIODIC & & nNow > nLastWrite + ( int64_t ) DATABASE_WRITE_INTERVAL * 1000000 ;
// It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
bool fPeriodicFlush = mode = = FLUSH_STATE_PERIODIC & & nNow > nLastFlush + ( int64_t ) DATABASE_FLUSH_INTERVAL * 1000000 ;
// Combine all conditions that result in a full cache flush.
bool fDoFullFlush = ( mode = = FLUSH_STATE_ALWAYS ) | | fCacheLarge | | fCacheCritical | | fPeriodicFlush | | fFlushForPrune ;
// Write blocks and block index to disk.
if ( fDoFullFlush | | fPeriodicWrite ) {
2015-05-11 17:18:39 +02:00
// Depend on nMinDiskSpace to ensure we can write block index
if ( ! CheckDiskSpace ( 0 ) )
2012-09-10 04:02:35 +02:00
return state . Error ( " out of disk space " ) ;
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
// First make sure all block and undo data is flushed to disk.
2012-09-06 03:21:18 +02:00
FlushBlockFile ( ) ;
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
// Then update all block file information (which may refer to block and undo files).
2014-11-25 16:26:20 +01:00
{
std : : vector < std : : pair < int , const CBlockFileInfo * > > vFiles ;
vFiles . reserve ( setDirtyFileInfo . size ( ) ) ;
2017-01-30 13:13:07 +01:00
for ( std : : set < int > : : iterator it = setDirtyFileInfo . begin ( ) ; it ! = setDirtyFileInfo . end ( ) ; ) {
vFiles . push_back ( std : : make_pair ( * it , & vinfoBlockFile [ * it ] ) ) ;
2014-11-25 16:26:20 +01:00
setDirtyFileInfo . erase ( it + + ) ;
}
std : : vector < const CBlockIndex * > vBlocks ;
vBlocks . reserve ( setDirtyBlockIndex . size ( ) ) ;
2017-01-30 13:13:07 +01:00
for ( std : : set < CBlockIndex * > : : iterator it = setDirtyBlockIndex . begin ( ) ; it ! = setDirtyBlockIndex . end ( ) ; ) {
2014-11-25 16:26:20 +01:00
vBlocks . push_back ( * it ) ;
setDirtyBlockIndex . erase ( it + + ) ;
}
if ( ! pblocktree - > WriteBatchSync ( vFiles , nLastBlockFile , vBlocks ) ) {
2017-01-24 21:16:27 +01:00
return AbortNode ( state , " Failed to write to block index database " ) ;
Improve chainstate/blockindex disk writing policy
There are 3 pieces of data that are maintained on disk. The actual block
and undo data, the block index (which can refer to positions on disk),
and the chainstate (which refers to the best block hash).
Earlier, there was no guarantee that blocks were written to disk before
block index entries referring to them were written. This commit introduces
dirty flags for block index data, and delays writing entries until the actual
block data is flushed.
With this stricter ordering in writes, it is now safe to not always flush
after every block, so there is no need for the IsInitialBlockDownload()
check there - instead we just write whenever enough time has passed or
the cache size grows too large. Also updating the wallet's best known block
is delayed until this is done, otherwise the wallet may end up referring to an
unknown block.
In addition, only do a write inside the block processing loop if necessary
(because of cache size exceeded). Otherwise, move the writing to a point
after processing is done, after relaying.
2014-11-07 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
// Finally remove any pruned files
2015-05-13 17:13:13 +02:00
if ( fFlushForPrune )
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
UnlinkPrunedFiles ( setFilesToPrune ) ;
2015-05-04 22:00:19 +02:00
nLastWrite = nNow ;
}
// Flush best chain related state. This can only be done if the blocks / block index write was also done.
if ( fDoFullFlush ) {
2017-06-02 00:47:58 +02:00
// Typical Coin structures on disk are around 48 bytes in size.
2015-05-11 17:18:39 +02:00
// 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.
2017-06-02 00:47:58 +02:00
if ( ! CheckDiskSpace ( 48 * 2 * 2 * pcoinsTip - > GetCacheSize ( ) ) )
2015-05-11 17:18:39 +02:00
return state . Error ( " out of disk space " ) ;
2015-05-04 22:00:19 +02:00
// Flush the chainstate (which may refer to block index entries).
2012-12-01 16:46:23 +01:00
if ( ! pcoinsTip - > Flush ( ) )
2015-01-17 00:57:14 +01:00
return AbortNode ( state , " Failed to write to coin database " ) ;
2015-05-04 22:00:19 +02:00
nLastFlush = nNow ;
}
2016-02-10 15:47:06 +01:00
if ( fDoFullFlush | | ( ( mode = = FLUSH_STATE_ALWAYS | | mode = = FLUSH_STATE_PERIODIC ) & & nNow > nLastSetChain + ( int64_t ) DATABASE_WRITE_INTERVAL * 1000000 ) ) {
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).
2015-05-04 22:00:19 +02:00
GetMainSignals ( ) . SetBestChain ( chainActive . GetLocator ( ) ) ;
nLastSetChain = nNow ;
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 ;
2014-11-14 18:19:26 +01:00
FlushStateToDisk ( state , FLUSH_STATE_ALWAYS ) ;
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 ;
FlushStateToDisk ( state , FLUSH_STATE_NONE ) ;
}
2014-12-01 02:39:44 +01:00
/** Update chainActive and related internal data structures. */
2016-04-21 14:35:51 +02:00
void static UpdateTip ( CBlockIndex * pindexNew , const CChainParams & chainParams ) {
2013-10-10 23:07:44 +02:00
chainActive . SetTip ( pindexNew ) ;
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
cvBlockChange . notify_all ( ) ;
2010-08-29 18:58:15 +02:00
2014-10-07 20:22:58 +02:00
static bool fWarned = false ;
2016-05-25 18:17:47 +02:00
std : : vector < std : : string > warningMessages ;
2016-02-15 05:13:27 +01:00
if ( ! IsInitialBlockDownload ( ) )
2012-06-27 19:51:51 +02:00
{
int nUpgraded = 0 ;
2013-10-10 23:07:44 +02:00
const CBlockIndex * pindex = chainActive . Tip ( ) ;
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 ] ) ;
if ( state = = THRESHOLD_ACTIVE | | state = = THRESHOLD_LOCKED_IN ) {
if ( state = = THRESHOLD_ACTIVE ) {
2016-12-19 12:38:35 +01:00
std : : string strWarning = strprintf ( _ ( " Warning: unknown new rules activated (versionbit %i) " ) , bit ) ;
SetMiscWarning ( strWarning ) ;
2016-02-15 05:13:27 +01:00
if ( ! fWarned ) {
2016-12-19 12:38:35 +01:00
CAlert : : Notify ( strWarning ) ;
2016-02-15 05:13:27 +01:00
fWarned = true ;
}
} else {
2016-05-25 18:17:47 +02:00
warningMessages . push_back ( strprintf ( " unknown new rules are about to activate (versionbit %i) " , bit ) ) ;
2016-02-15 05:13:27 +01:00
}
}
}
2016-05-25 18:17:47 +02:00
// Check the version of the last 100 blocks to see if we need to upgrade:
2012-06-27 19:51:51 +02:00
for ( int i = 0 ; i < 100 & & pindex ! = NULL ; i + + )
{
2018-10-26 18:42:52 +02:00
int32_t nExpectedVersion = ComputeBlockVersion ( pindex - > pprev , chainParams . GetConsensus ( ) ) ;
2016-02-15 05:13:27 +01:00
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 )
2016-05-25 18:17:47 +02:00
warningMessages . push_back ( 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-12-19 12:38:35 +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:
SetMiscWarning ( strWarning ) ;
2016-02-15 05:13:27 +01:00
if ( ! fWarned ) {
2016-12-19 12:38:35 +01:00
CAlert : : Notify ( strWarning ) ;
2016-02-15 05:13:27 +01:00
fWarned = true ;
}
2014-10-07 20:22:58 +02:00
}
2012-06-27 19:51:51 +02:00
}
2018-02-26 12:10:20 +01:00
LogPrintf ( " %s: new best=%s height=%d version=0x%08x log2_work=%.8f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo) " , __func__ ,
2016-05-25 18:17:47 +02:00
chainActive . Tip ( ) - > GetBlockHash ( ) . ToString ( ) , chainActive . Height ( ) , chainActive . Tip ( ) - > nVersion ,
log ( chainActive . Tip ( ) - > nChainWork . getdouble ( ) ) / log ( 2.0 ) , ( unsigned long ) chainActive . Tip ( ) - > nChainTx ,
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , chainActive . Tip ( ) - > GetBlockTime ( ) ) ,
2017-01-12 12:12:56 +01:00
GuessVerificationProgress ( chainParams . TxData ( ) , chainActive . Tip ( ) ) , pcoinsTip - > DynamicMemoryUsage ( ) * ( 1.0 / ( 1 < < 20 ) ) , pcoinsTip - > GetCacheSize ( ) ) ;
2016-05-25 18:17:47 +02:00
if ( ! warningMessages . empty ( ) )
LogPrintf ( " warning='%s' " , boost : : algorithm : : join ( warningMessages , " , " ) ) ;
LogPrintf ( " \n " ) ;
2013-11-16 19:28:24 +01:00
}
2012-06-27 19:51:51 +02:00
2015-09-10 01:31:20 +02:00
/** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */
2016-04-21 14:35:51 +02:00
bool static DisconnectTip ( CValidationState & state , const CChainParams & chainparams )
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.
CBlock block ;
2016-04-21 14:35:51 +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
{
2018-05-24 14:28:23 +02:00
auto dbTx = evoDb - > BeginTransaction ( ) ;
2014-09-24 03:19:04 +02:00
CCoinsViewCache view ( pcoinsTip ) ;
2017-05-03 05:35:05 +02:00
if ( DisconnectBlock ( block , state , pindexDelete , view ) ! = DISCONNECT_OK )
2015-01-08 11:44:25 +01:00
return error ( " DisconnectTip() : DisconnectBlock % s failed " , pindexDelete->GetBlockHash().ToString()) ;
2016-12-14 09:33:14 +01:00
bool flushed = view . Flush ( ) ;
assert ( flushed ) ;
2018-05-24 14:28:23 +02:00
bool committed = dbTx - > Commit ( ) ;
assert ( committed ) ;
2012-01-03 21:24:28 +01:00
}
2014-07-26 22:49:17 +02:00
LogPrint ( " bench " , " - Disconnect block: %.2fms \n " , ( GetTimeMicros ( ) - nStart ) * 0.001 ) ;
2013-11-16 19:28:24 +01:00
// Write the chain state to disk, if necessary.
2014-11-14 18:19:26 +01:00
if ( ! FlushStateToDisk ( state , FLUSH_STATE_IF_NEEDED ) )
2013-11-16 19:28:24 +01:00
return false ;
2014-02-15 22:38:28 +01:00
// Resurrect mempool transactions from the disconnected block.
2015-07-15 20:47:45 +02:00
std : : vector < uint256 > vHashUpdate ;
2016-11-21 10:51:32 +01:00
for ( const auto & it : block . vtx ) {
const CTransaction & tx = * it ;
2013-11-16 19:28:24 +01:00
// ignore validation errors in resurrected transactions
2014-12-02 09:16:52 +01:00
CValidationState stateDummy ;
2018-09-20 14:39:34 +02:00
if ( tx . IsCoinBase ( ) | | ! AcceptToMemoryPool ( mempool , stateDummy , it , false , NULL , true ) ) {
2017-01-24 10:07:50 +01:00
mempool . removeRecursive ( tx , MemPoolRemovalReason : : REORG ) ;
2015-07-15 20:47:45 +02:00
} else if ( mempool . exists ( tx . GetHash ( ) ) ) {
vHashUpdate . push_back ( tx . GetHash ( ) ) ;
}
2013-11-16 19:28:24 +01:00
}
2015-07-15 20:47:45 +02:00
// 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 this
// block that were added back and cleans up the mempool state.
mempool . UpdateTransactionsFromBlock ( vHashUpdate ) ;
2013-11-16 19:28:24 +01:00
// Update chainActive and related variables.
2016-04-21 14:35:51 +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:
2016-11-21 10:51:32 +01:00
for ( const auto & tx : block . vtx ) {
GetMainSignals ( ) . SyncTransaction ( * tx , pindexDelete - > pprev , CMainSignals : : SYNC_TRANSACTION_NOT_IN_BLOCK ) ;
2014-02-15 22:38:28 +01:00
}
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 ;
2016-12-05 08:07:22 +01:00
/**
2016-12-10 01:22:33 +01:00
* Used to track blocks whose transactions were applied to the UTXO state as a
* part of a single ActivateBestChainStep call .
2016-12-05 08:07:22 +01:00
*/
struct ConnectTrace {
std : : vector < std : : pair < CBlockIndex * , std : : shared_ptr < const CBlock > > > blocksConnected ;
} ;
2015-06-24 01:44:31 +02:00
/**
2014-12-01 02:39:44 +01:00
* Connect a new block to chainActive . pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew , to bypass loading it again from disk .
2016-12-05 08:07:22 +01:00
*
* The block is always added to connectTrace ( either after loading from disk or by copying
* pblock ) - if that is not intended , care must be taken to remove the last entry in
* blocksConnected in case of failure .
2014-12-01 02:39:44 +01:00
*/
2016-12-05 08:07:22 +01:00
bool static ConnectTip ( CValidationState & state , const CChainParams & chainparams , CBlockIndex * pindexNew , const std : : shared_ptr < const CBlock > & pblock , ConnectTrace & connectTrace )
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 ( ) ;
2014-08-26 02:26:41 +02:00
if ( ! pblock ) {
2016-12-05 08:07:22 +01:00
std : : shared_ptr < CBlock > pblockNew = std : : make_shared < CBlock > ( ) ;
connectTrace . blocksConnected . emplace_back ( pindexNew , pblockNew ) ;
if ( ! ReadBlockFromDisk ( * pblockNew , pindexNew , chainparams . GetConsensus ( ) ) )
2015-01-17 00:57:14 +01:00
return AbortNode ( state , " Failed to read block " ) ;
2016-12-05 08:07:22 +01:00
} else {
connectTrace . blocksConnected . emplace_back ( pindexNew , pblock ) ;
2014-08-26 02:26:41 +02:00
}
2016-12-05 08:07:22 +01:00
const CBlock & blockConnecting = * connectTrace . blocksConnected . back ( ) . second ;
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 ;
LogPrint ( " bench " , " - Load block from disk: %.2fms [%.2fs] \n " , ( nTime2 - nTime1 ) * 0.001 , nTimeReadFromDisk * 0.000001 ) ;
2010-08-29 18:58:15 +02:00
{
2018-05-24 14:28:23 +02:00
auto dbTx = evoDb - > BeginTransaction ( ) ;
2014-09-24 03:19:04 +02:00
CCoinsViewCache view ( pcoinsTip ) ;
2016-12-05 08:07:22 +01:00
bool rv = ConnectBlock ( blockConnecting , state , pindexNew , view , chainparams ) ;
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 ;
LogPrint ( " bench " , " - Connect total: %.2fms [%.2fs] \n " , ( nTime3 - nTime2 ) * 0.001 , nTimeConnectTotal * 0.000001 ) ;
2016-12-14 09:33:14 +01:00
bool flushed = view . Flush ( ) ;
assert ( flushed ) ;
2018-05-24 14:28:23 +02:00
bool committed = dbTx - > Commit ( ) ;
assert ( committed ) ;
2010-08-29 18:58:15 +02:00
}
2014-07-26 22:49:17 +02:00
int64_t nTime4 = GetTimeMicros ( ) ; nTimeFlush + = nTime4 - nTime3 ;
LogPrint ( " bench " , " - Flush: %.2fms [%.2fs] \n " , ( nTime4 - nTime3 ) * 0.001 , nTimeFlush * 0.000001 ) ;
2013-11-16 19:28:24 +01:00
// Write the chain state to disk, if necessary.
2014-11-14 18:19:26 +01:00
if ( ! FlushStateToDisk ( state , FLUSH_STATE_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 ;
LogPrint ( " bench " , " - Writing chainstate: %.2fms [%.2fs] \n " , ( nTime5 - nTime4 ) * 0.001 , nTimeChainState * 0.000001 ) ;
2016-08-15 11:49:12 +02:00
// Remove conflicting transactions from the mempool.;
2017-01-05 23:14:23 +01:00
mempool . removeForBlock ( blockConnecting . vtx , pindexNew - > nHeight ) ;
2013-11-16 19:28:24 +01:00
// Update chainActive & related variables.
2016-04-21 14:35:51 +02:00
UpdateTip ( pindexNew , chainparams ) ;
2016-08-15 11:49:12 +02:00
2014-07-26 22:49:17 +02:00
int64_t nTime6 = GetTimeMicros ( ) ; nTimePostConnect + = nTime6 - nTime5 ; nTimeTotal + = nTime6 - nTime1 ;
LogPrint ( " bench " , " - Connect postprocess: %.2fms [%.2fs] \n " , ( nTime6 - nTime5 ) * 0.001 , nTimePostConnect * 0.000001 ) ;
LogPrint ( " bench " , " - Connect block: %.2fms [%.2fs] \n " , ( nTime6 - nTime1 ) * 0.001 , nTimeTotal * 0.000001 ) ;
2010-08-29 18:58:15 +02:00
return true ;
}
2016-07-30 13:04:27 +02:00
bool DisconnectBlocks ( int blocks )
2015-02-12 05:05:09 +01:00
{
LOCK ( cs_main ) ;
CValidationState state ;
2016-02-02 16:28:56 +01:00
const CChainParams & chainparams = Params ( ) ;
2015-02-12 05:05:09 +01:00
2016-07-30 13:04:27 +02:00
LogPrintf ( " DisconnectBlocks -- Got command to replay %d blocks \n " , blocks ) ;
2017-02-04 01:41:32 +01:00
for ( int i = 0 ; i < blocks ; i + + ) {
2016-04-21 14:35:51 +02:00
if ( ! DisconnectTip ( state , chainparams ) | | ! state . IsValid ( ) ) {
2017-01-30 07:01:08 +01:00
return false ;
}
}
2015-02-04 17:39:45 +01:00
return true ;
}
2016-07-30 13:04:27 +02:00
void ReprocessBlocks ( int nBlocks )
{
2017-01-30 07:01:08 +01:00
LOCK ( cs_main ) ;
2016-07-30 13:04:27 +02:00
std : : map < uint256 , int64_t > : : iterator it = mapRejectedBlocks . begin ( ) ;
while ( it ! = mapRejectedBlocks . end ( ) ) {
//use a window twice as large as is usual for the nBlocks we want to reset
if ( ( * it ) . second > GetTime ( ) - ( nBlocks * 60 * 5 ) ) {
BlockMap : : iterator mi = mapBlockIndex . find ( ( * it ) . first ) ;
if ( mi ! = mapBlockIndex . end ( ) & & ( * mi ) . second ) {
CBlockIndex * pindex = ( * mi ) . second ;
2017-12-22 06:07:40 +01:00
LogPrintf ( " ReprocessBlocks -- %s \n " , ( * it ) . first . ToString ( ) ) ;
2016-07-30 13:04:27 +02:00
2016-05-10 12:43:19 +02:00
ResetBlockFailureFlags ( pindex ) ;
2016-07-30 13:04:27 +02:00
}
}
+ + it ;
}
2017-01-30 07:01:08 +01:00
DisconnectBlocks ( nBlocks ) ;
2016-07-30 13:04:27 +02:00
2017-01-30 07:01:08 +01:00
CValidationState state ;
ActivateBestChain ( state , Params ( ) ) ;
2016-07-30 13:04:27 +02:00
}
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 ) .
*/
2014-05-06 00:54:10 +02:00
static CBlockIndex * FindMostWorkChain ( ) {
2013-11-16 19:28:24 +01:00
do {
2014-05-06 00:54:10 +02:00
CBlockIndex * pindexNew = NULL ;
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 ( ) )
2014-05-06 00:54:10 +02:00
return NULL ;
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 ) ;
2015-08-11 21:06:07 +02: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)
if ( fFailedChain & & ( pindexBestInvalid = = NULL | | pindexNew - > nChainWork > pindexBestInvalid - > nChainWork ) )
2014-03-13 03:48:27 +01:00
pindexBestInvalid = pindexNew ;
CBlockIndex * pindexFailed = pindexNew ;
2015-08-11 21:06:07 +02:00
// Remove the entire chain from the set.
2013-11-16 19:28:24 +01:00
while ( pindexTest ! = pindexFailed ) {
2015-08-11 21:06:07 +02: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. */
2014-11-01 22:42:12 +01:00
static void PruneBlockIndexCandidates ( ) {
// 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 .
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork .
*/
2016-12-05 08:07:22 +01:00
static bool 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 ) ;
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 ;
2014-05-06 01:23:13 +02:00
while ( chainActive . Tip ( ) & & chainActive . Tip ( ) ! = pindexFork ) {
2016-04-21 14:35:51 +02:00
if ( ! DisconnectTip ( state , chainparams ) )
2014-05-06 01:23:13 +02:00
return false ;
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.
BOOST_REVERSE_FOREACH ( CBlockIndex * pindexConnect , vpindexToConnect ) {
2016-12-05 08:07:22 +01:00
if ( ! ConnectTip ( state , chainparams , pindexConnect , pindexConnect = = pindexMostWork ? pblock : std : : shared_ptr < const CBlock > ( ) , connectTrace ) ) {
2015-09-09 23:54:11 +02:00
if ( state . IsInvalid ( ) ) {
// The block violates a consensus rule.
if ( ! state . CorruptionPossible ( ) )
InvalidChainFound ( vpindexToConnect . back ( ) ) ;
state = CValidationState ( ) ;
fInvalidFound = true ;
fContinue = false ;
2016-12-05 08:07:22 +01:00
// If we didn't actually connect the block, don't notify listeners about it
connectTrace . blocksConnected . pop_back ( ) ;
2015-09-09 23:54:11 +02:00
break ;
} else {
// A system error occurred (disk space, database error, ...).
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 ) {
2015-11-23 22:06:12 +01:00
mempool . removeForReorg ( pcoinsTip , chainActive . Tip ( ) - > nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS ) ;
2015-10-22 20:52:55 +02:00
LimitMempoolSize ( mempool , GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 , GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ) ;
2014-10-10 22:13:47 +02:00
}
2015-09-10 01:31:20 +02:00
mempool . check ( pcoinsTip ) ;
2012-12-01 16:46:23 +01: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 ;
2013-11-16 19:28:24 +01:00
}
2010-08-29 18:58:15 +02:00
2017-07-10 16:41:14 +02:00
static void NotifyHeaderTip ( ) {
bool fNotify = false ;
bool fInitialBlockDownload = false ;
static CBlockIndex * pindexHeaderOld = NULL ;
CBlockIndex * pindexHeader = NULL ;
{
LOCK ( cs_main ) ;
2017-09-11 15:38:14 +02:00
pindexHeader = pindexBestHeader ;
2017-07-10 16:41:14 +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 ) ;
2017-09-03 15:30:08 +02:00
GetMainSignals ( ) . NotifyHeaderTip ( pindexHeader , fInitialBlockDownload ) ;
2017-07-10 16:41:14 +02:00
}
}
2014-12-01 02:39:44 +01:00
/**
* Make the best chain active , in multiple steps . The result is either failure
* or an activated best chain . pblock is either NULL or a pointer to a block
* that is already loaded ( to avoid loading it again from disk ) .
*/
2016-12-05 08:07:22 +01:00
bool ActivateBestChain ( CValidationState & state , const CChainParams & chainparams , std : : shared_ptr < const CBlock > pblock ) {
Backport compact blocks functionality from bitcoin (#1966)
* Merge #8068: Compact Blocks
48efec8 Fix some minor compact block issues that came up in review (Matt Corallo)
ccd06b9 Elaborate bucket size math (Pieter Wuille)
0d4cb48 Use vTxHashes to optimize InitData significantly (Matt Corallo)
8119026 Provide a flat list of txid/terators to txn in CTxMemPool (Matt Corallo)
678ee97 Add BIP 152 to implemented BIPs list (Matt Corallo)
56ba516 Add reconstruction debug logging (Matt Corallo)
2f34a2e Get our "best three" peers to announce blocks using cmpctblocks (Matt Corallo)
927f8ee Add ability to fetch CNode by NodeId (Matt Corallo)
d25cd3e Add receiver-side protocol implementation for CMPCTBLOCK stuff (Matt Corallo)
9c837d5 Add sender-side protocol implementation for CMPCTBLOCK stuff (Matt Corallo)
00c4078 Add protocol messages for short-ids blocks (Matt Corallo)
e3b2222 Add some blockencodings tests (Matt Corallo)
f4f8f14 Add TestMemPoolEntryHelper::FromTx version for CTransaction (Matt Corallo)
85ad31e Add partial-block block encodings API (Matt Corallo)
5249dac Add COMPACTSIZE wrapper similar to VARINT for serialization (Matt Corallo)
cbda71c Move context-required checks from CheckBlockHeader to Contextual... (Matt Corallo)
7c29ec9 If AcceptBlockHeader returns true, pindex will be set. (Matt Corallo)
96806c3 Stop trimming when mapTx is empty (Pieter Wuille)
* Merge #8408: Prevent fingerprinting, disk-DoS with compact blocks
1d06e49 Ignore CMPCTBLOCK messages for pruned blocks (Suhas Daftuar)
1de2a46 Ignore GETBLOCKTXN requests for unknown blocks (Suhas Daftuar)
* Merge #8418: Add tests for compact blocks
45c7ddd Add p2p test for BIP 152 (compact blocks) (Suhas Daftuar)
9a22a6c Add support for compactblocks to mininode (Suhas Daftuar)
a8689fd Tests: refactor compact size serialization in mininode (Suhas Daftuar)
9c8593d Implement SipHash in Python (Pieter Wuille)
56c87e9 Allow changing BIP9 parameters on regtest (Suhas Daftuar)
* Merge #8505: Trivial: Fix typos in various files
1aacfc2 various typos (leijurv)
* Merge #8449: [Trivial] Do not shadow local variable, cleanup
a159f25 Remove redundand (and shadowing) declaration (Pavel Janík)
cce3024 Do not shadow local variable, cleanup (Pavel Janík)
* Merge #8739: [qa] Fix broken sendcmpct test in p2p-compactblocks.py
157254a Fix broken sendcmpct test in p2p-compactblocks.py (Suhas Daftuar)
* Merge #8854: [qa] Fix race condition in p2p-compactblocks test
b5fd666 [qa] Fix race condition in p2p-compactblocks test (Suhas Daftuar)
* Merge #8393: Support for compact blocks together with segwit
27acfc1 [qa] Update p2p-compactblocks.py for compactblocks v2 (Suhas Daftuar)
422fac6 [qa] Add support for compactblocks v2 to mininode (Suhas Daftuar)
f5b9b8f [qa] Fix bug in mininode witness deserialization (Suhas Daftuar)
6aa28ab Use cmpctblock type 2 for segwit-enabled transfer (Pieter Wuille)
be7555f Fix overly-prescriptive p2p-segwit test for new fetch logic (Matt Corallo)
06128da Make GetFetchFlags always request witness objects from witness peers (Matt Corallo)
* Merge #8882: [qa] Fix race conditions in p2p-compactblocks.py and sendheaders.py
b55d941 [qa] Fix race condition in sendheaders.py (Suhas Daftuar)
6976db2 [qa] Another attempt to fix race condition in p2p-compactblocks.py (Suhas Daftuar)
* Merge #8904: [qa] Fix compact block shortids for a test case
4cdece4 [qa] Fix compact block shortids for a test case (Dagur Valberg Johannsson)
* Merge #8637: Compact Block Tweaks (rebase of #8235)
3ac6de0 Align constant names for maximum compact block / blocktxn depth (Pieter Wuille)
b2e93a3 Add cmpctblock to debug help list (instagibbs)
fe998e9 More agressively filter compact block requests (Matt Corallo)
02a337d Dont remove a "preferred" cmpctblock peer if they provide a block (Matt Corallo)
* Merge #8975: Chainparams: Trivial: In AppInit2(), s/Params()/chainparams/
6f2f639 Chainparams: Trivial: In AppInit2(), s/Params()/chainparams/ (Jorge Timón)
* Merge #8968: Don't hold cs_main when calling ProcessNewBlock from a cmpctblock
72ca7d9 Don't hold cs_main when calling ProcessNewBlock from a cmpctblock (Matt Corallo)
* Merge #8995: Add missing cs_main lock to ::GETBLOCKTXN processing
dfe7906 Add missing cs_main lock to ::GETBLOCKTXN processing (Matt Corallo)
* Merge #8515: A few mempool removal optimizations
0334430 Add some missing includes (Pieter Wuille)
4100499 Return shared_ptr<CTransaction> from mempool removes (Pieter Wuille)
51f2783 Make removed and conflicted arguments optional to remove (Pieter Wuille)
f48211b Bypass removeRecursive in removeForReorg (Pieter Wuille)
* Merge #9026: Fix handling of invalid compact blocks
d4833ff Bump the protocol version to distinguish new banning behavior. (Suhas Daftuar)
88c3549 Fix compact block handling to not ban if block is invalid (Suhas Daftuar)
c93beac [qa] Test that invalid compactblocks don't result in ban (Suhas Daftuar)
* Merge #9039: Various serialization simplifcations and optimizations
d59a518 Use fixed preallocation instead of costly GetSerializeSize (Pieter Wuille)
25a211a Add optimized CSizeComputer serializers (Pieter Wuille)
a2929a2 Make CSerAction's ForRead() constexpr (Pieter Wuille)
a603925 Avoid -Wshadow errors (Pieter Wuille)
5284721 Get rid of nType and nVersion (Pieter Wuille)
657e05a Make GetSerializeSize a wrapper on top of CSizeComputer (Pieter Wuille)
fad9b66 Make nType and nVersion private and sometimes const (Pieter Wuille)
c2c5d42 Make streams' read and write return void (Pieter Wuille)
50e8a9c Remove unused ReadVersion and WriteVersion (Pieter Wuille)
* Merge #9058: Fixes for p2p-compactblocks.py test timeouts on travis (#8842)
dac53b5 Modify getblocktxn handler not to drop requests for old blocks (Russell Yanofsky)
55bfddc [qa] Fix stale data bug in test_compactblocks_not_at_tip (Russell Yanofsky)
47e9659 [qa] Fix bug in compactblocks v2 merge (Russell Yanofsky)
* Merge #9160: [trivial] Fix hungarian variable name
ec34648 [trivial] Fix hungarian variable name (Russell Yanofsky)
* Merge #9159: [qa] Wait for specific block announcement in p2p-compactblocks
dfa44d1 [qa] Wait for specific block announcement in p2p-compactblocks (Russell Yanofsky)
* Merge #9125: Make CBlock a vector of shared_ptr of CTransactions
b4e4ba4 Introduce convenience type CTransactionRef (Pieter Wuille)
1662b43 Make CBlock::vtx a vector of shared_ptr<CTransaction> (Pieter Wuille)
da60506 Add deserializing constructors to CTransaction and CMutableTransaction (Pieter Wuille)
0e85204 Add serialization for unique_ptr and shared_ptr (Pieter Wuille)
* Merge #8872: Remove block-request logic from INV message processing
037159c Remove block-request logic from INV message processing (Matt Corallo)
3451203 [qa] Respond to getheaders and do not assume a getdata on inv (Matt Corallo)
d768f15 [qa] Make comptool push blocks instead of relying on inv-fetch (mrbandrews)
* Merge #9199: Always drop the least preferred HB peer when adding a new one.
ca8549d Always drop the least preferred HB peer when adding a new one. (Gregory Maxwell)
* Merge #9233: Fix some typos
15fa95d Fix some typos (fsb4000)
* Merge #9260: Mrs Peacock in The Library with The Candlestick (killed main.{h,cpp})
76faa3c Rename the remaining main.{h,cpp} to validation.{h,cpp} (Matt Corallo)
e736772 Move network-msg-processing code out of main to its own file (Matt Corallo)
87c35f5 Remove orphan state wipe from UnloadBlockIndex. (Matt Corallo)
* Merge #9014: Fix block-connection performance regression
dd0df81 Document ConnectBlock connectTrace postconditions (Matt Corallo)
2d6e561 Switch pblock in ProcessNewBlock to a shared_ptr (Matt Corallo)
2736c44 Make the optional pblock in ActivateBestChain a shared_ptr (Matt Corallo)
ae4db44 Create a shared_ptr for the block we're connecting in ActivateBCS (Matt Corallo)
fd9d890 Keep blocks as shared_ptrs, instead of copying txn in ConnectTip (Matt Corallo)
6fdd43b Add struct to track block-connect-time-generated info for callbacks (Matt Corallo)
* Merge #9240: Remove txConflicted
a874ab5 remove internal tracking of mempool conflicts for reporting to wallet (Alex Morcos)
bf663f8 remove external usage of mempool conflict tracking (Alex Morcos)
* Merge #9344: Do not run functions with necessary side-effects in assert()
da9cdd2 Do not run functions with necessary side-effects in assert() (Gregory Maxwell)
* Merge #9273: Remove unused CDiskBlockPos* argument from ProcessNewBlock
a13fa4c Remove unused CDiskBlockPos* argument from ProcessNewBlock (Matt Corallo)
* Merge #9352: Attempt reconstruction from all compact block announcements
813ede9 [qa] Update compactblocks test for multi-peer reconstruction (Suhas Daftuar)
7017298 Allow compactblock reconstruction when block is in flight (Suhas Daftuar)
* Merge #9252: Release cs_main before calling ProcessNewBlock, or processing headers (cmpctblock handling)
bd02bdd Release cs_main before processing cmpctblock as header (Suhas Daftuar)
680b0c0 Release cs_main before calling ProcessNewBlock (cmpctblock handling) (Suhas Daftuar)
* Merge #9283: A few more CTransactionRef optimizations
91335ba Remove unused MakeTransactionRef overloads (Pieter Wuille)
6713f0f Make FillBlock consume txn_available to avoid shared_ptr copies (Pieter Wuille)
62607d7 Convert COrphanTx to keep a CTransactionRef (Pieter Wuille)
c44e4c4 Make AcceptToMemoryPool take CTransactionRef (Pieter Wuille)
* Merge #9375: Relay compact block messages prior to full block connection
02ee4eb Make most_recent_compact_block a pointer to a const (Matt Corallo)
73666ad Add comment to describe callers to ActivateBestChain (Matt Corallo)
962f7f0 Call ActivateBestChain without cs_main/with most_recent_block (Matt Corallo)
0df777d Use a temp pindex to avoid a const_cast in ProcessNewBlockHeaders (Matt Corallo)
c1ae4fc Avoid holding cs_most_recent_block while calling ReadBlockFromDisk (Matt Corallo)
9eb67f5 Ensure we meet the BIP 152 old-relay-types response requirements (Matt Corallo)
5749a85 Cache most-recently-connected compact block (Matt Corallo)
9eaec08 Cache most-recently-announced block's shared_ptr (Matt Corallo)
c802092 Relay compact block messages prior to full block connection (Matt Corallo)
6987219 Add a CValidationInterface::NewPoWValidBlock callback (Matt Corallo)
180586f Call AcceptBlock with the block's shared_ptr instead of CBlock& (Matt Corallo)
8baaba6 [qa] Avoid race in preciousblock test. (Matt Corallo)
9a0b2f4 [qa] Make compact blocks test construction using fetch methods (Matt Corallo)
8017547 Make CBlockIndex*es in net_processing const (Matt Corallo)
* Merge #9486: Make peer=%d log prints consistent
e6111b2 Make peer id logging consistent ("peer=%d" instead of "peer %d") (Matt Corallo)
* Merge #9400: Set peers as HB peers upon full block validation
d4781ac Set peers as HB peers upon full block validation (Gregory Sanders)
* Merge #9499: Use recent-rejects, orphans, and recently-replaced txn for compact-block-reconstruction
c594580 Add braces around AddToCompactExtraTransactions (Matt Corallo)
1ccfe9b Clarify comment about mempool/extra conflicts (Matt Corallo)
fac4c78 Make PartiallyDownloadedBlock::InitData's second param const (Matt Corallo)
b55b416 Add extra_count lower bound to compact reconstruction debug print (Matt Corallo)
863edb4 Consider all (<100k memusage) txn for compact-block-extra-txn cache (Matt Corallo)
7f8c8ca Consider all orphan txn for compact-block-extra-txn cache (Matt Corallo)
93380c5 Use replaced transactions in compact block reconstruction (Matt Corallo)
1531652 Keep shared_ptrs to recently-replaced txn for compact blocks (Matt Corallo)
edded80 Make ATMP optionally return the CTransactionRefs it replaced (Matt Corallo)
c735540 Move ORPHAN constants from validation.h to net_processing.h (Matt Corallo)
* Merge #9587: Do not shadow local variable named `tx`.
44f2baa Do not shadow local variable named `tx`. (Pavel Janík)
* Merge #9510: [trivial] Fix typos in comments
cc16d99 [trivial] Fix typos in comments (practicalswift)
* Merge #9604: [Trivial] add comment about setting peer as HB peer.
dd5b011 [Trivial] add comment about setting peer as HB peer. (John Newbery)
* Fix using of AcceptToMemoryPool in PrivateSend code
* add `override`
* fSupportsDesiredCmpctVersion
* bring back tx ressurection in DisconnectTip
* Fix delayed headers
* Remove unused CConnman::FindNode overload
* Fix typos and comments
* Fix minor code differences
* Don't use rejection cache for corrupted transactions
Partly based on https://github.com/bitcoin/bitcoin/pull/8525
* Backport missed cs_main locking changes
Missed from https://github.com/bitcoin/bitcoin/commit/58a215ce8c13b900cf982c39f8ee4879290d1a95
* Backport missed comments and mapBlockSource.emplace call
Missed from two commits:
https://github.com/bitcoin/bitcoin/commit/88c35491ab19f9afdf9b3fa9356a072f70ef2f55
https://github.com/bitcoin/bitcoin/commit/7c98ce584ec23bcddcba8cdb33efa6547212f6ef
* Add CheckPeerHeaders() helper and check in (nCount == 0) too
2018-04-11 13:06:01 +02: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!
2014-05-07 16:45:33 +02:00
CBlockIndex * pindexMostWork = NULL ;
2017-07-17 19:49:17 +02:00
CBlockIndex * pindexNewTip = NULL ;
2014-05-06 01:23:13 +02:00
do {
boost : : this_thread : : interruption_point ( ) ;
2016-04-06 10:27:51 +02:00
if ( ShutdownRequested ( ) )
break ;
2014-05-06 01:23:13 +02:00
2014-11-18 22:16:32 +01:00
const CBlockIndex * pindexFork ;
2016-12-05 08:07:22 +01:00
ConnectTrace connectTrace ;
2014-05-07 16:45:33 +02:00
bool fInitialDownload ;
{
LOCK ( cs_main ) ;
2017-01-24 10:07:50 +01:00
{ // TODO: Tempoarily ensure that mempool removals are notified before
// connected transactions. This shouldn't matter, but the abandoned
// state of transactions in our wallet is currently cleared when we
// receive another notification and there is a race condition where
// notification of a connected conflict might cause an outside process
// to abandon a transaction and then have it inadvertantly cleared by
// the notification that the conflicted transaction was evicted.
MemPoolConflictRemovalTracker mrt ( mempool ) ;
2014-11-18 22:16:32 +01:00
CBlockIndex * pindexOldTip = chainActive . Tip ( ) ;
2017-07-10 16:41:14 +02:00
if ( pindexMostWork = = NULL ) {
pindexMostWork = FindMostWorkChain ( ) ;
}
2014-05-06 01:23:13 +02:00
2014-05-07 16:45:33 +02:00
// Whether we have anything to do at all.
if ( pindexMostWork = = NULL | | pindexMostWork = = chainActive . Tip ( ) )
return true ;
2014-05-06 01:23:13 +02:00
2017-07-10 16:41:14 +02:00
bool fInvalidFound = false ;
2016-12-05 08:07:22 +01:00
std : : shared_ptr < const CBlock > nullBlockPtr ;
if ( ! ActivateBestChainStep ( state , chainparams , pindexMostWork , pblock & & pblock - > GetHash ( ) = = pindexMostWork - > GetBlockHash ( ) ? pblock : nullBlockPtr , fInvalidFound , connectTrace ) )
2013-11-16 19:28:24 +01:00
return false ;
2014-05-06 01:23:13 +02:00
2017-07-10 16:41:14 +02:00
if ( fInvalidFound ) {
// Wipe cache, we may need another branch now.
pindexMostWork = NULL ;
}
2014-05-07 16:45:33 +02:00
pindexNewTip = chainActive . Tip ( ) ;
2014-11-18 22:16:32 +01:00
pindexFork = chainActive . FindFork ( pindexOldTip ) ;
2014-05-07 16:45:33 +02:00
fInitialDownload = IsInitialBlockDownload ( ) ;
2017-01-23 07:37:39 +01:00
// throw all transactions though the signal-interface
2017-01-24 10:07:50 +01:00
} // MemPoolConflictRemovalTracker destroyed and conflict evictions are notified
// Transactions in the connnected block are notified
2017-01-23 07:37:39 +01:00
for ( const auto & pair : connectTrace . blocksConnected ) {
assert ( pair . second ) ;
const CBlock & block = * ( pair . second ) ;
for ( unsigned int i = 0 ; i < block . vtx . size ( ) ; i + + )
GetMainSignals ( ) . SyncTransaction ( * block . vtx [ i ] , pair . first , i ) ;
}
2013-11-16 19:28:24 +01:00
}
2014-05-07 16:45:33 +02:00
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
2013-11-16 19:28:24 +01:00
2014-05-07 16:45:33 +02:00
// Notifications/callbacks that can run without cs_main
2017-07-28 16:10:10 +02:00
// Notify external listeners about the new tip.
GetMainSignals ( ) . UpdatedBlockTip ( pindexNewTip , pindexFork , fInitialDownload ) ;
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
2015-11-30 11:32:13 +01:00
// Always notify the UI if a new block tip was connected
if ( pindexFork ! = pindexNewTip ) {
uiInterface . NotifyBlockTip ( fInitialDownload , pindexNewTip ) ;
2013-11-16 19:28:24 +01:00
}
2017-07-17 19:49:17 +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.
2014-11-14 18:19:26 +01:00
if ( ! FlushStateToDisk ( state , FLUSH_STATE_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 ;
2012-11-24 14:26:51 +01:00
}
2010-08-29 18:58:15 +02:00
2014-05-06 01:23:13 +02:00
return true ;
}
2014-03-13 03:48:27 +01:00
2016-10-18 21:35:27 +02:00
bool PreciousBlock ( CValidationState & state , const CChainParams & params , CBlockIndex * pindex )
{
{
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 ( ) ;
}
}
return ActivateBestChain ( state , params ) ;
}
2016-04-21 14:35:51 +02:00
bool 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 ) ;
// Mark the block itself as invalid.
pindex - > nStatus | = BLOCK_FAILED_VALID ;
2014-11-25 12:33:43 +01:00
setDirtyBlockIndex . insert ( pindex ) ;
2014-11-19 09:39:42 +01:00
setBlockIndexCandidates . erase ( pindex ) ;
2018-04-15 08:10:25 +02:00
if ( pindex = = pindexBestHeader ) {
pindexBestInvalid = pindexBestHeader ;
pindexBestHeader = pindexBestHeader - > pprev ;
}
2014-11-19 09:39:42 +01:00
while ( chainActive . Contains ( pindex ) ) {
CBlockIndex * pindexWalk = chainActive . Tip ( ) ;
pindexWalk - > nStatus | = BLOCK_FAILED_CHILD ;
2014-11-25 12:33:43 +01:00
setDirtyBlockIndex . insert ( pindexWalk ) ;
2014-11-19 09:39:42 +01:00
setBlockIndexCandidates . erase ( pindexWalk ) ;
// ActivateBestChain considers blocks already in chainActive
// unconditionally valid already, so force disconnect away from it.
2016-04-21 14:35:51 +02:00
if ( ! DisconnectTip ( state , chainparams ) ) {
2015-11-23 22:06:12 +01:00
mempool . removeForReorg ( pcoinsTip , chainActive . Tip ( ) - > nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS ) ;
2014-11-19 09:39:42 +01:00
return false ;
}
2018-04-15 08:10:25 +02:00
if ( pindexWalk = = pindexBestHeader ) {
pindexBestInvalid = pindexBestHeader ;
pindexBestHeader = pindexBestHeader - > pprev ;
}
2014-11-19 09:39:42 +01:00
}
2015-10-22 20:52:55 +02:00
LimitMempoolSize ( mempool , GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 , GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ) ;
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 ) ;
2015-11-23 22:06:12 +01:00
mempool . removeForReorg ( pcoinsTip , chainActive . Tip ( ) - > nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS ) ;
2018-09-11 16:32:45 +02:00
GetMainSignals ( ) . UpdatedBlockTip ( chainActive . Tip ( ) , NULL , IsInitialBlockDownload ( ) ) ;
2017-04-11 12:53:54 +02:00
uiInterface . NotifyBlockTip ( IsInitialBlockDownload ( ) , pindex - > pprev ) ;
2014-11-19 09:39:42 +01:00
return true ;
}
2016-05-10 12:43:19 +02:00
bool 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.
pindexBestInvalid = NULL ;
}
2013-11-16 19:28:24 +01:00
}
2014-11-19 09:39:42 +01:00
it + + ;
2013-11-16 19:28:24 +01:00
}
2013-08-03 13:08:34 +02:00
2014-11-19 09:39:42 +01:00
// Remove the invalidity flag from all ancestors too.
while ( pindex ! = NULL ) {
2014-11-25 12:33:43 +01:00
if ( pindex - > nStatus & BLOCK_FAILED_MASK ) {
pindex - > nStatus & = ~ BLOCK_FAILED_MASK ;
setDirtyBlockIndex . insert ( pindex ) ;
2014-11-19 09:39:42 +01:00
}
pindex = pindex - > pprev ;
}
2010-08-29 18:58:15 +02:00
return true ;
}
2014-07-12 00:02:35 +02:00
CBlockIndex * AddToBlockIndex ( const CBlockHeader & block )
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-04-06 07:11:16 +02:00
assert ( pindexNew ) ;
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-30 13:13:07 +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-14 00:48:28 +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 ) ;
2014-07-12 00:02:35 +02:00
if ( pindexBestHeader = = NULL | | pindexBestHeader - > nChainWork < pindexNew - > nChainWork )
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). */
2014-03-13 03:48:27 +01:00
bool ReceivedBlockTransactions ( const CBlock & block , CValidationState & state , CBlockIndex * pindexNew , const CDiskBlockPos & pos )
{
2013-06-24 04:00:18 +02: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 ;
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
2014-07-12 00:02:35 +02:00
if ( pindexNew - > pprev = = NULL | | pindexNew - > pprev - > nChainTx ) {
// If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
2017-01-30 13:13:07 +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 + + ;
}
2015-03-13 17:25:34 +01:00
if ( chainActive . Tip ( ) = = NULL | | ! setBlockIndexCandidates . value_comp ( ) ( pindex , chainActive . Tip ( ) ) ) {
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 ) ) ;
}
}
2012-09-03 15:26:57 +02:00
2010-08-29 18:58:15 +02:00
return true ;
}
2013-04-13 07:13:08 +02:00
bool FindBlockPos ( CValidationState & state , 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-22 01:15:20 +01:00
if ( fKnown )
2015-03-07 02:26:09 +01:00
vinfoBlockFile [ nFile ] . nSize = std : : max ( pos . nPos + nAddSize , vinfoBlockFile [ nFile ] . nSize ) ;
2015-03-22 01:15:20 +01:00
else
2015-03-07 02:26:09 +01:00
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 ;
2012-12-04 07:48:57 +01:00
if ( CheckDiskSpace ( nNewChunks * BLOCKFILE_CHUNK_SIZE - pos . nPos ) ) {
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
2012-09-10 04:02:35 +02:00
return state . 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 ;
}
2013-01-27 00:14:11 +01:00
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 ;
2012-12-04 07:48:57 +01:00
if ( CheckDiskSpace ( nNewChunks * UNDOFILE_CHUNK_SIZE - pos . nPos ) ) {
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 ;
}
2016-06-09 01:12:52 +02:00
bool CheckBlockHeader ( const CBlockHeader & block , CValidationState & state , const Consensus : : Params & consensusParams , bool fCheckPOW )
2010-08-29 18:58:15 +02:00
{
2010-09-19 23:20:34 +02:00
// Check proof of work matches claimed amount
2016-06-01 20:51:29 +02:00
if ( fCheckPOW & & ! CheckProofOfWork ( block . GetHash ( ) , block . nBits , consensusParams ) )
2016-02-01 10:21:27 +01:00
return state . DoS ( 50 , false , REJECT_INVALID , " high-hash " , false , " proof of work failed " ) ;
2010-09-19 23:20:34 +02:00
2017-12-20 12:45:01 +01:00
// Check DevNet
2018-02-01 18:05:35 +01:00
if ( ! consensusParams . hashDevnetGenesisBlock . IsNull ( ) & &
block . hashPrevBlock = = consensusParams . hashGenesisBlock & &
block . GetHash ( ) ! = consensusParams . hashDevnetGenesisBlock ) {
2017-12-20 12:45:01 +01:00
return state . DoS ( 100 , error ( " CheckBlockHeader(): wrong devnet genesis " ) ,
REJECT_INVALID , " devnet-genesis " ) ;
}
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 )
2016-02-01 10:21:27 +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 )
2016-02-01 10:21:27 +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.
2017-09-11 16:13:30 +02:00
// Size limits (relaxed)
if ( block . vtx . empty ( ) | | block . vtx . size ( ) > MaxBlockSize ( true ) | | : : GetSerializeSize ( block , SER_NETWORK , PROTOCOL_VERSION ) > MaxBlockSize ( true ) )
2016-02-01 10:21:27 +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-21 10:51:32 +01:00
if ( block . vtx . empty ( ) | | ! block . vtx [ 0 ] - > IsCoinBase ( ) )
2016-02-01 10:21:27 +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-21 10:51:32 +01:00
if ( block . vtx [ i ] - > IsCoinBase ( ) )
2016-02-01 10:21:27 +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
2015-02-03 23:40:00 +01:00
2017-01-29 09:22:14 +01:00
// DASH : CHECK TRANSACTIONS FOR INSTANTSEND
2015-02-03 23:40:00 +01:00
2016-09-01 16:55:25 +02:00
if ( sporkManager . IsSporkActive ( SPORK_3_INSTANTSEND_BLOCK_FILTERING ) ) {
2017-01-29 09:22:14 +01:00
// We should never accept block which conflicts with completed transaction lock,
// that's why this is in CheckBlock unlike coinbase payee/amount.
// Require other nodes to comply, send them some data in case they are missing it.
2018-02-06 12:09:33 +01:00
for ( const auto & tx : block . vtx ) {
2016-10-22 18:52:14 +02:00
// skip coinbase, it has no inputs
2016-11-21 10:51:32 +01:00
if ( tx - > IsCoinBase ( ) ) continue ;
2017-01-29 09:22:14 +01:00
// LOOK FOR TRANSACTION LOCK IN OUR MAP OF OUTPOINTS
2018-02-06 12:09:33 +01:00
for ( const auto & txin : tx - > vin ) {
2017-01-29 09:22:14 +01:00
uint256 hashLocked ;
2016-11-21 10:51:32 +01:00
if ( instantsend . GetLockedOutPointTxHash ( txin . prevout , hashLocked ) & & hashLocked ! = tx - > GetHash ( ) ) {
2017-12-04 07:06:19 +01:00
// The node which relayed this will have to switch later,
2017-09-14 13:41:40 +02:00
// relaying instantsend data won't help it.
2017-01-30 07:01:08 +01:00
LOCK ( cs_main ) ;
2018-02-21 20:26:53 +01:00
mapRejectedBlocks . insert ( std : : make_pair ( block . GetHash ( ) , GetTime ( ) ) ) ;
2016-02-01 10:21:27 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " conflict-tx-lock " , false ,
2016-11-21 10:51:32 +01:00
strprintf ( " transaction %s conflicts with transaction lock %s " , tx - > GetHash ( ) . ToString ( ) , hashLocked . ToString ( ) ) ) ;
2015-02-03 23:40:00 +01:00
}
}
}
2015-02-07 21:05:10 +01:00
} else {
2017-01-29 09:22:14 +01:00
LogPrintf ( " CheckBlock(DASH): spork is off, skipping transaction locking checks \n " ) ;
2014-12-09 02:17:57 +01:00
}
2016-08-17 09:08:25 +02:00
// END DASH
2014-12-09 02:17:57 +01:00
2010-08-29 18:58:15 +02:00
// Check transactions
2016-07-21 11:43:43 +02:00
for ( const auto & tx : block . vtx )
2018-09-19 14:04:35 +02:00
if ( ! CheckTransaction ( * tx , state ) )
2016-02-01 10:21:27 +01:00
return state . Invalid ( false , state . GetRejectCode ( ) , state . GetRejectReason ( ) ,
2016-11-21 10:51:32 +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-21 11:43:43 +02:00
for ( const auto & tx : block . vtx )
2011-10-03 19:05:43 +02:00
{
2016-11-21 10:51:32 +01:00
nSigOps + = GetLegacySigOpCount ( * tx ) ;
2011-10-03 19:05:43 +02:00
}
2017-09-11 16:13:30 +02:00
// sigops limits (relaxed)
if ( nSigOps > MaxBlockSigOps ( true ) )
2016-02-01 10:21:27 +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-03-30 13:48:04 +02:00
static bool CheckIndexAgainstCheckpoint ( const CBlockIndex * pindexPrev , CValidationState & state , const CChainParams & chainparams , const uint256 & hash )
2014-10-20 01:09:50 +02:00
{
2015-03-30 13:48:04 +02:00
if ( * pindexPrev - > phashBlock = = chainparams . GetConsensus ( ) . hashGenesisBlock )
2014-10-20 01:09:50 +02:00
return true ;
int nHeight = pindexPrev - > nHeight + 1 ;
2015-03-30 13:48:04 +02:00
// Don't accept any forks from the main chain prior to last checkpoint
CBlockIndex * pcheckpoint = Checkpoints : : GetLastCheckpoint ( chainparams . Checkpoints ( ) ) ;
if ( pcheckpoint & & nHeight < pcheckpoint - > nHeight )
return state . DoS ( 100 , error ( " %s: forked chain older than last checkpoint (height %d) " , __func__ , nHeight ) ) ;
2010-08-29 18:58:15 +02:00
return true ;
}
2016-06-09 01:12:52 +02:00
bool ContextualCheckBlockHeader ( const CBlockHeader & block , CValidationState & state , const Consensus : : Params & consensusParams , const CBlockIndex * pindexPrev , int64_t nAdjustedTime )
2010-08-29 18:58:15 +02:00
{
2016-08-04 11:55:25 +02:00
const int nHeight = pindexPrev = = NULL ? 0 : pindexPrev - > nHeight + 1 ;
2014-10-20 01:09:50 +02:00
// Check proof of work
2016-02-17 17:29:36 +01:00
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN & & nHeight < = 68589 ) {
// architecture issues with DGW v1 and v2)
unsigned int nBitsNext = GetNextWorkRequired ( pindexPrev , & block , consensusParams ) ;
double n1 = ConvertBitsToDouble ( block . nBits ) ;
double n2 = ConvertBitsToDouble ( nBitsNext ) ;
if ( abs ( n1 - n2 ) > n1 * 0.5 )
return state . DoS ( 100 , error ( " %s : incorrect proof of work (DGW pre-fork) - %f %f %f at %d " , __func__ , abs ( n1 - n2 ) , n1 , n2 , nHeight ) ,
REJECT_INVALID , " bad-diffbits " ) ;
} else {
2016-02-02 16:28:56 +01:00
if ( block . nBits ! = GetNextWorkRequired ( pindexPrev , & block , consensusParams ) )
2016-02-01 10:21:27 +01:00
return state . DoS ( 100 , false , REJECT_INVALID , " bad-diffbits " , false , strprintf ( " incorrect proof of work at %d " , nHeight ) ) ;
2015-05-01 19:17:14 +02:00
}
2012-11-10 14:26:34 +01:00
2014-10-20 01:09:50 +02:00
// Check timestamp against prev
if ( block . GetBlockTime ( ) < = pindexPrev - > GetMedianTimePast ( ) )
2018-09-28 09:55:30 +02:00
return state . Invalid ( false , REJECT_INVALID , " time-too-old " , strprintf ( " block's timestamp is too early %d %d " , block . GetBlockTime ( ) , pindexPrev - > GetMedianTimePast ( ) ) ) ;
2015-01-20 00:37:21 +01:00
2016-06-09 01:12:52 +02:00
// Check timestamp
if ( block . GetBlockTime ( ) > nAdjustedTime + 2 * 60 * 60 )
2018-09-28 09:55:30 +02:00
return state . Invalid ( false , REJECT_INVALID , " time-too-new " , strprintf ( " block timestamp too far in the future %d %d " , block . GetBlockTime ( ) , nAdjustedTime + 2 * 60 * 60 ) ) ;
2016-06-09 01:12:52 +02:00
2016-08-04 11:55:25 +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 ) ) ;
2010-08-29 18:58:15 +02:00
return true ;
}
2016-08-01 01:39:19 +02:00
bool ContextualCheckBlock ( const CBlock & block , CValidationState & state , const Consensus : : Params & consensusParams , const CBlockIndex * pindexPrev )
2012-06-28 01:30:39 +02:00
{
2014-10-20 01:09:50 +02:00
const int nHeight = pindexPrev = = NULL ? 0 : pindexPrev - > nHeight + 1 ;
2012-06-28 01:30:39 +02:00
2016-02-16 17:33:31 +01:00
// Start enforcing BIP113 (Median Time Past) using versionbits logic.
int nLockTimeFlags = 0 ;
if ( VersionBitsState ( pindexPrev , consensusParams , Consensus : : DEPLOYMENT_CSV , versionbitscache ) = = THRESHOLD_ACTIVE ) {
nLockTimeFlags | = LOCKTIME_MEDIAN_TIME_PAST ;
}
int64_t nLockTimeCutoff = ( nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST )
? pindexPrev - > GetMedianTimePast ( )
: block . GetBlockTime ( ) ;
2018-03-08 13:18:24 +01:00
bool fDIP0001Active_context = nHeight > = Params ( ) . GetConsensus ( ) . DIP0001Height ;
2018-04-06 11:00:10 +02:00
bool fDIP0003Active_context = VersionBitsState ( pindexPrev , consensusParams , Consensus : : DEPLOYMENT_DIP0003 , versionbitscache ) = = THRESHOLD_ACTIVE ;
2017-09-11 16:13:30 +02:00
// Size limits
unsigned int nMaxBlockSize = MaxBlockSize ( fDIP0001Active_context ) ;
if ( block . vtx . empty ( ) | | block . vtx . size ( ) > nMaxBlockSize | | : : GetSerializeSize ( block , SER_NETWORK , PROTOCOL_VERSION ) > nMaxBlockSize )
2016-02-01 10:21:27 +01:00
return state . DoS ( 10 , false , REJECT_INVALID , " bad-blk-length " , false , " size limits failed " ) ;
2017-09-11 16:13:30 +02:00
// Check that all transactions are finalized and not over-sized
// Also count sigops
unsigned int nSigOps = 0 ;
2016-07-21 11:43:43 +02:00
for ( const auto & tx : block . vtx ) {
2016-11-21 10:51:32 +01:00
if ( ! IsFinalTx ( * tx , nHeight , nLockTimeCutoff ) ) {
2016-02-01 10:21:27 +01:00
return state . DoS ( 10 , false , REJECT_INVALID , " bad-txns-nonfinal " , false , " non-final transaction " ) ;
2014-10-20 01:09:50 +02:00
}
2018-08-28 13:43:58 +02:00
if ( ! ContextualCheckTransaction ( * tx , state , consensusParams , pindexPrev ) ) {
return false ;
2017-09-11 16:13:30 +02:00
}
2016-11-21 10:51:32 +01:00
nSigOps + = GetLegacySigOpCount ( * tx ) ;
2015-11-03 18:12:36 +01:00
}
2014-10-20 01:09:50 +02:00
2017-09-11 16:13:30 +02:00
// Check sigops
if ( nSigOps > MaxBlockSigOps ( fDIP0001Active_context ) )
2016-02-01 10:21:27 +01:00
return state . DoS ( 10 , false , REJECT_INVALID , " bad-blk-sigops " , false , " out-of-bounds SigOpCount " ) ;
2017-09-11 16:13:30 +02:00
2016-08-04 11:55:25 +02:00
// Enforce rule that the coinbase starts with serialized block height
2018-04-06 11:00:10 +02:00
// After DIP3/DIP4 activation, we don't enforce the height in the input script anymore.
// The CbTx special transaction payload will then contain the height, which is checked in CheckCbTx
if ( nHeight > = consensusParams . BIP34Height & & ! fDIP0003Active_context )
2013-10-10 23:07:44 +02:00
{
2014-10-20 01:09:50 +02:00
CScript expect = CScript ( ) < < nHeight ;
2016-11-21 10:51:32 +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 ( ) ) ) {
2016-02-01 10:21:27 +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
}
2013-10-10 23:07:44 +02:00
}
2018-04-06 11:00:10 +02:00
if ( fDIP0003Active_context ) {
if ( block . vtx [ 0 ] - > nType ! = TRANSACTION_COINBASE ) {
return state . DoS ( 100 , false , REJECT_INVALID , " bad-cb-type " , false , " coinbase is not a CbTx " ) ;
}
}
2014-10-20 01:09:50 +02:00
return true ;
2013-01-07 15:39:53 +01:00
}
2017-08-03 00:19:34 +02:00
static bool AcceptBlockHeader ( const CBlockHeader & block , CValidationState & state , const CChainParams & chainparams , CBlockIndex * * ppindex )
2010-08-29 18:58:15 +02:00
{
2013-12-19 09:09:51 +01: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 ) ;
2014-03-13 03:48:27 +01:00
CBlockIndex * pindex = NULL ;
2015-08-01 10:51:30 +02:00
// TODO : ENABLE BLOCK CACHE IN SPECIFIC CASES
2015-06-17 21:23:53 +02:00
if ( hash ! = chainparams . GetConsensus ( ) . hashGenesisBlock ) {
2010-08-29 18:58:15 +02:00
2015-06-17 21:23:53 +02:00
if ( miSelf ! = mapBlockIndex . end ( ) ) {
// Block header is already known.
pindex = miSelf - > second ;
if ( ppindex )
* ppindex = pindex ;
if ( pindex - > nStatus & BLOCK_FAILED_MASK )
2016-04-28 13:52:31 +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 ;
}
2013-11-29 08:25:30 +01:00
2016-06-09 01:12:52 +02:00
if ( ! CheckBlockHeader ( block , state , chainparams . GetConsensus ( ) ) )
2016-02-01 10:21:27 +01:00
return error ( " %s: Consensus::CheckBlockHeader: %s, %s " , __func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
2014-11-20 08:28:19 +01:00
2015-06-17 21:23:53 +02:00
// Get prev block index
CBlockIndex * pindexPrev = NULL ;
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 ( ) )
2015-01-08 11:44:25 +01:00
return state . DoS ( 10 , error ( " %s: prev block not found " , __func__ ) , 0 , " bad-prevblk " ) ;
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 " ) ;
2015-02-06 00:26:32 +01:00
2015-06-17 21:23:53 +02:00
assert ( pindexPrev ) ;
if ( fCheckpointsEnabled & & ! CheckIndexAgainstCheckpoint ( pindexPrev , state , chainparams , hash ) )
return error ( " %s: CheckIndexAgainstCheckpoint() : % s " , __func__, state.GetRejectReason().c_str()) ;
2010-08-29 18:58:15 +02:00
2016-06-09 01:12:52 +02:00
if ( ! ContextualCheckBlockHeader ( block , state , chainparams . GetConsensus ( ) , pindexPrev , GetAdjustedTime ( ) ) )
2016-02-01 10:21:27 +01:00
return error ( " %s: Consensus::ContextualCheckBlockHeader: %s, %s " , __func__ , hash . ToString ( ) , FormatStateMessage ( state ) ) ;
2015-06-17 21:23:53 +02:00
}
2014-03-13 03:48:27 +01:00
if ( pindex = = NULL )
pindex = AddToBlockIndex ( block ) ;
2010-08-29 18:58:15 +02:00
2014-03-13 03:48:27 +01:00
if ( ppindex )
* ppindex = pindex ;
2017-08-01 17:11:32 +02:00
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
2017-09-03 15:30:08 +02:00
// Notify external listeners about accepted block header
GetMainSignals ( ) . AcceptedBlockHeader ( pindex ) ;
2014-03-13 03:48:27 +01:00
return true ;
}
2011-09-08 18:51:43 +02:00
2017-08-03 00:19:34 +02:00
// Exposed wrapper for AcceptBlockHeader
2016-12-19 08:03:16 +01:00
bool ProcessNewBlockHeaders ( const std : : vector < CBlockHeader > & headers , CValidationState & state , const CChainParams & chainparams , const CBlockIndex * * ppindex )
2017-08-03 00:19:34 +02:00
{
{
LOCK ( cs_main ) ;
for ( const CBlockHeader & header : headers ) {
2017-01-11 23:47:52 +01:00
CBlockIndex * pindex = NULL ; // Use a temp pindex instead of ppindex to avoid a const_cast
if ( ! AcceptBlockHeader ( header , state , chainparams , & pindex ) ) {
2017-08-03 00:19:34 +02:00
return false ;
}
2017-01-11 23:47:52 +01:00
if ( ppindex ) {
* ppindex = pindex ;
}
2017-08-03 00:19:34 +02:00
}
}
NotifyHeaderTip ( ) ;
return true ;
}
2015-04-17 14:40:24 +02:00
/** Store block on disk. If dbp is non-NULL, the file is known to already reside on disk */
2016-12-19 08:24:11 +01:00
static bool 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 ;
2017-07-12 13:13:38 +02:00
if ( fNewBlock ) * fNewBlock = false ;
2014-03-13 03:48:27 +01:00
AssertLockHeld ( cs_main ) ;
2010-08-29 18:58:15 +02:00
2017-07-10 16:41:14 +02:00
CBlockIndex * pindexDummy = NULL ;
CBlockIndex * & pindex = ppindex ? * ppindex : pindexDummy ;
2012-08-21 19:18:53 +02: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 ;
bool fHasMoreWork = ( 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
2017-08-01 17:11:32 +02:00
// TODO: Decouple this function from the block download logic by removing fRequested
// This requires some new chain datastructure to efficiently look up if a
// 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:
if ( pindex - > nTx ! = 0 ) return true ; // This is a previously-processed block that was pruned
if ( ! fHasMoreWork ) return true ; // Don't process less-work chains
2015-06-02 21:17:36 +02:00
if ( fTooFarAhead ) return true ; // Block height is too high
2010-08-29 18:58:15 +02:00
}
2017-07-12 13:13:38 +02:00
if ( fNewBlock ) * fNewBlock = true ;
2010-08-29 18:58:15 +02:00
2017-02-16 10:22:17 +01:00
if ( ! CheckBlock ( block , state , chainparams . GetConsensus ( ) ) | |
2016-08-01 01:39:19 +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 ) ;
2010-08-29 18:58:15 +02:00
}
2016-02-01 10:21:27 +01:00
return error ( " %s: %s " , __func__ , FormatStateMessage ( state ) ) ;
2010-08-29 18:58:15 +02:00
}
2016-12-19 08:26:20 +01:00
// Header is valid/has work, merkle tree is 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 ) ;
2014-03-13 03:48:27 +01:00
int nHeight = pindex - > nHeight ;
2010-08-29 18:58:15 +02:00
// Write block to history file
2013-01-29 01:44:19 +01:00
try {
2013-06-24 04:27:02 +02:00
unsigned int nBlockSize = : : GetSerializeSize ( block , SER_DISK , CLIENT_VERSION ) ;
2013-01-29 01:44:19 +01:00
CDiskBlockPos blockPos ;
if ( dbp ! = NULL )
blockPos = * dbp ;
2014-06-28 23:36:06 +02:00
if ( ! FindBlockPos ( state , blockPos , nBlockSize + 8 , nHeight , block . GetBlockTime ( ) , dbp ! = NULL ) )
2015-01-08 11:44:25 +01:00
return error ( " AcceptBlock() : FindBlockPos failed " ) ;
2013-01-29 01:44:19 +01:00
if ( dbp = = NULL )
2015-04-19 23:48:25 +02:00
if ( ! WriteBlockToDisk ( block , blockPos , chainparams . MessageStart ( ) ) )
2015-01-17 00:57:14 +01:00
AbortNode ( state , " Failed to write block " ) ;
2014-03-13 03:48:27 +01:00
if ( ! ReceivedBlockTransactions ( block , state , pindex , blockPos ) )
2015-01-08 11:44:25 +01:00
return error ( " AcceptBlock() : ReceivedBlockTransactions failed " ) ;
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 ( ) ) ;
2015-01-14 15:28:35 +01:00
}
2014-12-29 01:33:56 +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
if ( fCheckForPruning )
FlushStateToDisk ( state , FLUSH_STATE_NONE ) ; // we just allocated more disk space for block files
2010-08-29 18:58:15 +02:00
return true ;
}
2016-12-14 10:55:20 +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
{
{
2014-07-12 00:02:35 +02:00
CBlockIndex * pindex = NULL ;
2017-08-02 20:35:04 +02:00
if ( fNewBlock ) * fNewBlock = false ;
CValidationState state ;
2017-02-16 10:22:17 +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
ret = AcceptBlock ( pblock , state , chainparams , & pindex , fForceProcessing , NULL , fNewBlock ) ;
}
2015-04-17 14:19:21 +02:00
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
2017-08-02 20:35:04 +02:00
if ( ! ret ) {
GetMainSignals ( ) . BlockChecked ( * pblock , state ) ;
2018-09-28 09:55:30 +02:00
return error ( " %s: AcceptBlock FAILED: %s " , __func__ , FormatStateMessage ( state ) ) ;
2017-08-02 20:35:04 +02:00
}
2012-10-27 21:08:45 +02:00
}
2017-07-10 16:41:14 +02:00
NotifyHeaderTip ( ) ;
2017-08-02 20:35:04 +02:00
CValidationState state ; // Only used to report errors, not invalidity - ignore it
2017-07-28 16:10:10 +02:00
if ( ! ActivateBestChain ( state , chainparams , pblock ) )
2018-09-28 09:55:30 +02:00
return error ( " %s: ActivateBestChain failed: %s " , __func__ , FormatStateMessage ( state ) ) ;
2012-10-27 21:08:45 +02:00
2015-05-01 19:17:14 +02:00
LogPrintf ( " %s : ACCEPTED \n " , __func__ ) ;
2010-08-29 18:58:15 +02:00
return true ;
}
2012-10-27 21:08:45 +02:00
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 ( ) ) ;
if ( fCheckpointsEnabled & & ! CheckIndexAgainstCheckpoint ( pindexPrev , state , chainparams , block . GetHash ( ) ) )
return error ( " %s: CheckIndexAgainstCheckpoint() : % s " , __func__, state.GetRejectReason().c_str()) ;
2012-10-27 21:08:45 +02:00
2014-10-20 04:10:03 +02:00
CCoinsViewCache viewNew ( pcoinsTip ) ;
CBlockIndex indexDummy ( block ) ;
indexDummy . pprev = pindexPrev ;
indexDummy . nHeight = pindexPrev - > nHeight + 1 ;
2012-10-27 21:08:45 +02:00
2018-05-24 14:28:23 +02:00
// begin tx and let it rollback
auto dbTx = evoDb - > BeginTransaction ( ) ;
2014-10-20 04:10:03 +02:00
// NOTE: CheckBlockHeader is called by CheckBlock
2016-06-09 01:12:52 +02:00
if ( ! ContextualCheckBlockHeader ( block , state , chainparams . GetConsensus ( ) , pindexPrev , GetAdjustedTime ( ) ) )
2016-02-01 10:21:27 +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 ) )
2016-02-01 10:21:27 +01:00
return error ( " %s: Consensus::CheckBlock: %s " , __func__ , FormatStateMessage ( state ) ) ;
2016-08-01 01:39:19 +02:00
if ( ! ContextualCheckBlock ( block , state , chainparams . GetConsensus ( ) , pindexPrev ) )
2016-02-01 10:21:27 +01:00
return error ( " %s: Consensus::ContextualCheckBlock: %s " , __func__ , FormatStateMessage ( state ) ) ;
2016-04-21 14:35:51 +02:00
if ( ! ConnectBlock ( block , state , & indexDummy , viewNew , chainparams , true ) )
2014-10-20 04:10:03 +02:00
return false ;
assert ( state . IsValid ( ) ) ;
2012-10-27 21:08:45 +02:00
2014-10-20 04:10:03 +02:00
return true ;
2012-10-27 21:08:45 +02: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
/**
* BLOCK PRUNING CODE
*/
/* Calculate the amount of disk space the block & undo files currently use */
uint64_t CalculateCurrentUsage ( )
{
uint64_t retval = 0 ;
BOOST_FOREACH ( const CBlockFileInfo & file , vinfoBlockFile ) {
retval + = file . nSize + file . nUndoSize ;
}
return retval ;
}
/* Prune a block file (modify associated database entries)*/
void PruneOneBlockFile ( const int fileNumber )
{
for ( BlockMap : : iterator it = mapBlockIndex . begin ( ) ; it ! = mapBlockIndex . end ( ) ; + + it ) {
CBlockIndex * pindex = it - > second ;
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-27 13:25:42 +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-27 13:25:42 +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-22 12:42:55 +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-30 13:13:07 +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 ) ;
boost : : filesystem : : remove ( GetBlockPosFilename ( pos , " blk " ) ) ;
boost : : filesystem : : remove ( GetBlockPosFilename ( pos , " rev " ) ) ;
LogPrintf ( " Prune: %s deleted blk/rev (%05u) \n " , __func__ , * it ) ;
}
}
2017-01-11 14:16:11 +01:00
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
void FindFilesToPruneManual ( std : : set < int > & setFilesToPrune , int nManualPruneHeight )
{
assert ( fPruneMode & & nManualPruneHeight > 0 ) ;
LOCK2 ( cs_main , cs_LastBlockFile ) ;
if ( chainActive . Tip ( ) = = NULL )
return ;
// last block to prune is the lesser of (user-specified height, MIN_BLOCKS_TO_KEEP from the tip)
2017-01-30 13:13:07 +01:00
unsigned int nLastBlockWeCanPrune = std : : min ( ( unsigned ) nManualPruneHeight , chainActive . Tip ( ) - > nHeight - MIN_BLOCKS_TO_KEEP ) ;
2017-01-11 14:16:11 +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 ;
FlushStateToDisk ( state , FLUSH_STATE_NONE , nManualPruneHeight ) ;
}
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
/* Calculate the block/rev files that should be deleted to remain under target*/
2015-04-17 14:40:24 +02:00
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 ) ;
if ( chainActive . Tip ( ) = = NULL | | nPruneTarget = = 0 ) {
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 ;
}
2012-10-27 21:08:45 +02:00
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 ;
2012-10-27 21:08:45 +02: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
if ( nCurrentUsage + nBuffer > = nPruneTarget ) {
for ( int fileNumber = 0 ; fileNumber < nLastBlockFile ; fileNumber + + ) {
nBytesToPrune = vinfoBlockFile [ fileNumber ] . nSize + vinfoBlockFile [ fileNumber ] . nUndoSize ;
2012-10-27 21:08:45 +02: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
if ( vinfoBlockFile [ fileNumber ] . nSize = = 0 )
continue ;
2012-10-27 21:08:45 +02: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
if ( nCurrentUsage + nBuffer < nPruneTarget ) // are we below our target?
break ;
2012-10-27 21:08:45 +02:00
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 ;
2012-10-27 21:08:45 +02: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
PruneOneBlockFile ( fileNumber ) ;
// Queue up the files for removal
setFilesToPrune . insert ( fileNumber ) ;
nCurrentUsage - = nBytesToPrune ;
count + + ;
}
}
2010-08-29 18:58:15 +02:00
2015-04-23 15:40:21 +02:00
LogPrint ( " 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 ) ;
2013-01-27 01:24:06 +01:00
}
2012-10-27 21:08:45 +02:00
2013-04-13 07:13:08 +02:00
bool CheckDiskSpace ( uint64_t nAdditionalBytes )
2010-08-29 18:58:15 +02:00
{
2014-12-19 21:21:29 +01:00
uint64_t nFreeBytesAvailable = boost : : filesystem : : space ( 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 ;
}
2012-08-13 19:11:05 +02:00
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 ( ) )
2010-08-29 18:58:15 +02:00
return NULL ;
2014-09-08 19:29:14 +02:00
boost : : filesystem : : path path = GetBlockPosFilename ( pos , prefix ) ;
2012-08-13 19:11:05 +02:00
boost : : filesystem : : create_directories ( path . parent_path ( ) ) ;
FILE * file = fopen ( path . string ( ) . c_str ( ) , " rb+ " ) ;
if ( ! file & & ! fReadOnly )
file = fopen ( path . string ( ) . c_str ( ) , " 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 ( ) ) ;
2010-08-29 18:58:15 +02:00
return NULL ;
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 ) ;
return NULL ;
}
}
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 ) ;
}
2013-01-18 15:07:05 +01:00
FILE * OpenUndoFile ( const CDiskBlockPos & pos , bool fReadOnly ) {
2012-08-13 19:11:05 +02:00
return OpenDiskFile ( pos , " rev " , fReadOnly ) ;
}
2014-09-08 19:29:14 +02:00
boost : : filesystem : : path GetBlockPosFilename ( const CDiskBlockPos & pos , const char * prefix )
{
2014-09-15 15:56:10 +02:00
return GetDataDir ( ) / " blocks " / strprintf ( " %s%05u.dat " , prefix , pos . nFile ) ;
2014-09-08 19:29:14 +02:00
}
2012-09-03 21:14:03 +02:00
CBlockIndex * InsertBlockIndex ( uint256 hash )
{
2014-12-15 09:11:16 +01:00
if ( hash . IsNull ( ) )
2012-09-03 21:14:03 +02:00
return NULL ;
// 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 ( ) ;
if ( ! pindexNew )
2017-01-30 13:13:07 +01:00
throw std : : runtime_error ( std : : string ( __func__ ) + " : new CBlockIndex failed " ) ;
mi = mapBlockIndex . insert ( std : : make_pair ( hash , pindexNew ) ) . first ;
2012-09-03 21:14:03 +02:00
pindexNew - > phashBlock = & ( ( * mi ) . first ) ;
return pindexNew ;
}
2016-11-02 21:09:24 +01:00
bool static LoadBlockIndexDB ( const CChainParams & chainparams )
2012-09-03 21:14:03 +02:00
{
2016-05-06 10:02:57 +02:00
if ( ! pblocktree - > LoadBlockIndexGuts ( InsertBlockIndex ) )
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-30 13:13:07 +01:00
std : : vector < std : : pair < int , CBlockIndex * > > vSortedByHeight ;
2012-09-03 21:14:03 +02:00
vSortedByHeight . reserve ( mapBlockIndex . size ( ) ) ;
BOOST_FOREACH ( const PAIRTYPE ( uint256 , CBlockIndex * ) & item , mapBlockIndex )
{
CBlockIndex * pindex = item . second ;
2017-01-30 13:13:07 +01:00
vSortedByHeight . push_back ( std : : make_pair ( pindex - > nHeight , pindex ) ) ;
2012-09-03 21:14:03 +02:00
}
sort ( vSortedByHeight . begin ( ) , vSortedByHeight . end ( ) ) ;
BOOST_FOREACH ( const PAIRTYPE ( int , CBlockIndex * ) & item , vSortedByHeight )
{
CBlockIndex * pindex = item . second ;
2014-10-29 17:00:02 +01:00
pindex - > nChainWork = ( pindex - > pprev ? pindex - > pprev - > nChainWork : 0 ) + GetBlockProof ( * pindex ) ;
2017-01-14 00:48:28 +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 ;
}
}
if ( pindex - > IsValid ( BLOCK_VALID_TRANSACTIONS ) & & ( pindex - > nChainTx | | pindex - > pprev = = NULL ) )
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 ( ) ;
2014-07-12 00:02:35 +02:00
if ( pindex - > IsValid ( BLOCK_VALID_TREE ) & & ( pindexBestHeader = = NULL | | CBlockIndexWorkComparator ( ) ( pindexBestHeader , pindex ) ) )
pindexBestHeader = pindex ;
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-30 13:13:07 +01:00
std : : set < int > setBlkDataFiles ;
2014-05-11 14:05:04 +02:00
BOOST_FOREACH ( const PAIRTYPE ( uint256 , CBlockIndex * ) & item , mapBlockIndex )
{
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 ;
}
}
2012-10-05 19:22:21 +02: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
// 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 ) ;
fReindex | = fReindexing ;
2013-01-11 01:47:57 +01:00
// Check whether we have a transaction index
pblocktree - > ReadFlag ( " txindex " , fTxIndex ) ;
2015-02-25 18:40:32 +01:00
LogPrintf ( " %s: transaction index %s \n " , __func__ , fTxIndex ? " enabled " : " disabled " ) ;
2013-01-11 01:47:57 +01:00
2016-03-05 22:31:10 +01:00
// Check whether we have an address index
pblocktree - > ReadFlag ( " addressindex " , fAddressIndex ) ;
LogPrintf ( " %s: address index %s \n " , __func__ , fAddressIndex ? " enabled " : " disabled " ) ;
2016-03-22 23:11:04 +01:00
// Check whether we have a timestamp index
pblocktree - > ReadFlag ( " timestampindex " , fTimestampIndex ) ;
LogPrintf ( " %s: timestamp index %s \n " , __func__ , fTimestampIndex ? " enabled " : " disabled " ) ;
2016-04-05 21:53:38 +02:00
// Check whether we have a spent index
pblocktree - > ReadFlag ( " spentindex " , fSpentIndex ) ;
LogPrintf ( " %s: spent index %s \n " , __func__ , fSpentIndex ? " enabled " : " disabled " ) ;
2013-10-13 22:15:48 +02:00
// Load pointer to end of best chain
2014-09-04 02:02:44 +02:00
BlockMap : : iterator it = mapBlockIndex . find ( pcoinsTip - > GetBestBlock ( ) ) ;
2013-11-05 02:27:39 +01:00
if ( it = = mapBlockIndex . end ( ) )
2012-12-02 21:59:22 +01:00
return true ;
2013-11-05 02:27:39 +01:00
chainActive . SetTip ( it - > second ) ;
2014-11-01 22:42:12 +01:00
PruneBlockIndexCandidates ( ) ;
2015-02-25 18:40:32 +01:00
LogPrintf ( " %s: hashBestChain=%s height=%d date=%s progress=%f \n " , __func__ ,
2014-01-16 16:15:27 +01:00
chainActive . Tip ( ) - > GetBlockHash ( ) . ToString ( ) , chainActive . Height ( ) ,
2014-02-18 20:04:06 +01:00
DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , chainActive . Tip ( ) - > GetBlockTime ( ) ) ,
2017-01-12 12:12:56 +01:00
GuessVerificationProgress ( chainparams . TxData ( ) , chainActive . Tip ( ) ) ) ;
2012-09-03 21:14:03 +02:00
2013-01-03 15:29:07 +01:00
return true ;
}
2014-05-23 18:04:09 +02:00
CVerifyDB : : CVerifyDB ( )
{
uiInterface . ShowProgress ( _ ( " Verifying blocks... " ) , 0 ) ;
}
CVerifyDB : : ~ CVerifyDB ( )
{
uiInterface . ShowProgress ( " " , 100 ) ;
}
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 ) ;
2013-10-10 23:07:44 +02:00
if ( chainActive . Tip ( ) = = NULL | | chainActive . Tip ( ) - > pprev = = NULL )
2013-01-03 15:29:07 +01:00
return true ;
2018-05-24 14:28:23 +02:00
// begin tx and let it rollback
auto dbTx = evoDb - > BeginTransaction ( ) ;
2012-09-03 21:14:03 +02:00
// Verify blocks in the best chain
2013-06-19 17:53:02 +02:00
if ( nCheckDepth < = 0 )
2012-09-03 21:14:03 +02:00
nCheckDepth = 1000000000 ; // suffices until the year 19000
2013-10-10 23:07:44 +02:00
if ( nCheckDepth > chainActive . Height ( ) )
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 ) ;
2013-10-10 23:07:44 +02:00
CBlockIndex * pindexState = chainActive . Tip ( ) ;
2013-01-03 15:29:07 +01:00
CBlockIndex * pindexFailure = NULL ;
int nGoodTransactions = 0 ;
2013-01-27 00:14:11 +01:00
CValidationState state ;
2016-06-07 15:17:58 +02:00
int reportDone = 0 ;
2016-07-29 12:32:38 +02:00
LogPrintf ( " [0%%]... " ) ;
2013-10-10 23:07:44 +02:00
for ( CBlockIndex * pindex = chainActive . Tip ( ) ; pindex & & pindex - > pprev ; pindex = pindex - > pprev )
2012-09-03 21:14:03 +02:00
{
2013-03-09 18:02:57 +01:00
boost : : this_thread : : interruption_point ( ) ;
2016-06-07 15:17:58 +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
LogPrintf ( " [%d%%]... " , percentageDone ) ;
reportDone = percentageDone / 10 ;
}
uiInterface . ShowProgress ( _ ( " Verifying blocks... " ) , percentageDone ) ;
2013-10-10 23:07:44 +02:00
if ( pindex - > nHeight < chainActive . Height ( ) - nCheckDepth )
2012-09-03 21:14:03 +02:00
break ;
2016-05-25 16:28:12 +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 ( ) ) )
2017-01-24 10:07:50 +01:00
return error ( " %s: *** found bad block at %d, hash=%s (%s) \n " , __func__ ,
2016-02-01 10:21:27 +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 ;
CDiskBlockPos pos = pindex - > GetUndoPos ( ) ;
if ( ! pos . IsNull ( ) ) {
2014-10-27 14:35:52 +01:00
if ( ! UndoReadFromDisk ( undo , pos , pindex - > pprev - > GetBlockHash ( ) ) )
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()) ;
2013-01-03 15:29:07 +01:00
}
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
2015-05-04 01:38:08 +02:00
if ( nCheckLevel > = 3 & & pindex = = pindexState & & ( coins . DynamicMemoryUsage ( ) + pcoinsTip - > DynamicMemoryUsage ( ) ) < = nCoinCacheUsage ) {
2017-05-03 05:35:05 +02:00
DisconnectResult res = DisconnectBlock ( block , state , pindex , coins ) ;
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-05-03 05:35:05 +02:00
}
2013-01-03 15:29:07 +01:00
pindexState = pindex - > pprev ;
2017-05-03 05:35:05 +02:00
if ( res = = DISCONNECT_UNCLEAN ) {
2013-01-03 15:29:07 +01:00
nGoodTransactions = 0 ;
pindexFailure = pindex ;
2017-05-03 05:35:05 +02:00
} else {
2013-01-03 15:29:07 +01:00
nGoodTransactions + = block . vtx . size ( ) ;
2017-05-03 05:35:05 +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
// check level 4: try reconnecting blocks
if ( nCheckLevel > = 4 ) {
CBlockIndex * pindex = pindexState ;
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 ( ) ;
2014-05-23 18:04:09 +02:00
uiInterface . ShowProgress ( _ ( " Verifying blocks... " ) , std : : max ( 1 , std : : min ( 99 , 100 - ( int ) ( ( ( double ) ( chainActive . Height ( ) - pindex - > nHeight ) ) / ( double ) nCheckDepth * 50 ) ) ) ) ;
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()) ;
2016-04-21 14:35:51 +02:00
if ( ! ConnectBlock ( block , state , pindex , coins , chainparams ) )
2015-01-08 11:44:25 +01:00
return error ( " VerifyDB() : * * * found unconnectable block at % d , hash = % s " , pindex->nHeight, pindex->GetBlockHash().ToString()) ;
2013-01-03 15:29:07 +01:00
}
2012-09-03 21:14:03 +02:00
}
2016-06-07 15:17:58 +02:00
LogPrintf ( " [DONE]. \n " ) ;
2013-10-10 23:07:44 +02:00
LogPrintf ( " No coin database inconsistencies in last %i blocks (%i transactions) \n " , chainActive . Height ( ) - pindexState - > nHeight , nGoodTransactions ) ;
2013-01-03 15:29:07 +01:00
2012-09-03 21:14:03 +02:00
return true ;
}
2017-08-01 17:11:32 +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 ) ;
2014-10-06 08:31:33 +02:00
setBlockIndexCandidates . clear ( ) ;
2013-10-10 23:07:44 +02:00
chainActive . SetTip ( NULL ) ;
2013-10-13 22:15:48 +02:00
pindexBestInvalid = NULL ;
2015-03-03 16:49:12 +01:00
pindexBestHeader = NULL ;
mempool . clear ( ) ;
mapBlocksUnlinked . clear ( ) ;
vinfoBlockFile . clear ( ) ;
nLastBlockFile = 0 ;
nBlockSequenceId = 1 ;
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
BOOST_FOREACH ( BlockMap : : value_type & entry , mapBlockIndex ) {
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 ;
2013-02-16 17:58:45 +01:00
}
2016-11-02 21:09:24 +01: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
2016-11-02 21:09:24 +01:00
if ( ! fReindex & & ! LoadBlockIndexDB ( chainparams ) )
2010-08-29 18:58:15 +02:00
return false ;
2013-01-30 21:43:36 +01:00
return true ;
}
2013-01-11 01:47:57 +01:00
2017-12-20 12:45:01 +01:00
static bool AddGenesisBlock ( const CChainParams & chainparams , const CBlock & block , CValidationState & state )
{
// Start new block file
unsigned int nBlockSize = : : GetSerializeSize ( block , SER_DISK , CLIENT_VERSION ) ;
CDiskBlockPos blockPos ;
if ( ! FindBlockPos ( state , blockPos , nBlockSize + 8 , 0 , block . GetBlockTime ( ) ) )
return error ( " %s: FindBlockPos failed " , __func__ ) ;
if ( ! WriteBlockToDisk ( block , blockPos , chainparams . MessageStart ( ) ) )
return error ( " %s: writing genesis block to disk failed " , __func__ ) ;
CBlockIndex * pindex = AddToBlockIndex ( block ) ;
if ( ! ReceivedBlockTransactions ( block , state , pindex , blockPos ) )
return error ( " %s: genesis block not accepted " , __func__ ) ;
return true ;
}
2017-01-24 10:07:50 +01:00
bool InitBlockIndex ( 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
2013-01-30 21:43:36 +01:00
// Check whether we're already initialized
2013-10-10 23:07:44 +02:00
if ( chainActive . Genesis ( ) ! = NULL )
2013-01-30 21:43:36 +01:00
return true ;
// Use the provided setting for -txindex in the new database
2015-06-27 21:21:41 +02:00
fTxIndex = GetBoolArg ( " -txindex " , DEFAULT_TXINDEX ) ;
2013-01-30 21:43:36 +01:00
pblocktree - > WriteFlag ( " txindex " , fTxIndex ) ;
2016-03-05 22:31:10 +01:00
// Use the provided setting for -addressindex in the new database
fAddressIndex = GetBoolArg ( " -addressindex " , DEFAULT_ADDRESSINDEX ) ;
pblocktree - > WriteFlag ( " addressindex " , fAddressIndex ) ;
2016-03-22 23:11:04 +01:00
// Use the provided setting for -timestampindex in the new database
fTimestampIndex = GetBoolArg ( " -timestampindex " , DEFAULT_TIMESTAMPINDEX ) ;
pblocktree - > WriteFlag ( " timestampindex " , fTimestampIndex ) ;
2016-04-05 21:53:38 +02:00
fSpentIndex = GetBoolArg ( " -spentindex " , DEFAULT_SPENTINDEX ) ;
pblocktree - > WriteFlag ( " spentindex " , fSpentIndex ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " Initializing databases... \n " ) ;
2013-01-30 21:43:36 +01:00
// Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
if ( ! fReindex ) {
try {
CValidationState state ;
2017-12-20 12:45:01 +01:00
if ( ! AddGenesisBlock ( chainparams , chainparams . GenesisBlock ( ) , state ) )
return false ;
if ( chainparams . NetworkIDString ( ) = = CBaseChainParams : : DEVNET ) {
2018-05-13 22:56:51 +02:00
// We can't continue if devnet genesis block is invalid
std : : shared_ptr < const CBlock > shared_pblock = std : : make_shared < const CBlock > ( chainparams . DevNetGenesisBlock ( ) ) ;
bool fProcessDevnetGenesisBlock = ProcessNewBlock ( chainparams , shared_pblock , true , NULL ) ;
assert ( fProcessDevnetGenesisBlock ) ;
2017-12-20 12:45:01 +01:00
}
2014-11-25 18:54:36 +01:00
// Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
2014-11-14 18:19:26 +01:00
return FlushStateToDisk ( state , FLUSH_STATE_ALWAYS ) ;
2014-12-07 13:29:06 +01:00
} catch ( const std : : runtime_error & e ) {
2017-06-06 01:47:23 +02:00
return error ( " %s: failed to initialize block database: %s " , __func__ , e . what ( ) ) ;
2013-01-30 21:43:36 +01:00
}
2010-08-29 18:58:15 +02:00
}
return true ;
}
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 {
2017-09-11 16:13:30 +02:00
unsigned int nMaxBlockSize = MaxBlockSize ( true ) ;
2014-09-25 08:53:43 +02:00
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
2017-09-11 16:13:30 +02:00
CBufferedFile blkdat ( fileIn , 2 * nMaxBlockSize , nMaxBlockSize + 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-15 10:27:42 +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 ;
blkdat > > FLATDATA ( buf ) ;
2016-10-15 10:27:42 +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 ;
2017-09-11 16:13:30 +02:00
if ( nSize < 80 | | nSize > nMaxBlockSize )
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 ;
2012-10-27 22:01:38 +02:00
blkdat > > block ;
nRewind = blkdat . GetPos ( ) ;
2012-10-21 21:23:13 +02:00
2014-10-07 21:15:32 +02:00
// detect out of order blocks, and store them for later
uint256 hash = block . GetHash ( ) ;
2015-04-09 15:58:34 +02:00
if ( hash ! = chainparams . GetConsensus ( ) . hashGenesisBlock & & mapBlockIndex . find ( block . hashPrevBlock ) = = mapBlockIndex . end ( ) ) {
2014-10-07 18:06:30 +02:00
LogPrint ( " reindex " , " %s: Out of order block %s, parent %s not known \n " , __func__ , hash . ToString ( ) ,
2014-10-07 21:15:32 +02:00
block . hashPrevBlock . ToString ( ) ) ;
2012-10-21 21:23:13 +02:00
if ( dbp )
2014-10-07 21:15:32 +02:00
mapBlocksUnknownParent . insert ( std : : make_pair ( block . hashPrevBlock , * dbp ) ) ;
2014-10-07 18:06:30 +02:00
continue ;
}
2014-10-07 21:15:32 +02:00
// process in case the block isn't known yet
2014-10-30 01:01:18 +01:00
if ( mapBlockIndex . count ( hash ) = = 0 | | ( mapBlockIndex [ hash ] - > nStatus & BLOCK_HAVE_DATA ) = = 0 ) {
2017-07-10 16:41:14 +02:00
LOCK ( cs_main ) ;
2013-01-27 00:14:11 +01:00
CValidationState state ;
2016-12-19 08:24:11 +01:00
if ( AcceptBlock ( pblock , state , chainparams , NULL , true , dbp , NULL ) )
2012-02-20 20:50:26 +01:00
nLoaded + + ;
2013-01-27 00:14:11 +01:00
if ( state . IsError ( ) )
break ;
2015-04-09 15:58:34 +02:00
} else if ( hash ! = chainparams . GetConsensus ( ) . hashGenesisBlock & & mapBlockIndex [ hash ] - > nHeight % 1000 = = 0 ) {
2017-07-10 16:41:14 +02:00
LogPrint ( " reindex " , " Block Import: already had block %s at height %d \n " , hash . ToString ( ) , mapBlockIndex [ hash ] - > nHeight ) ;
}
// 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
2017-07-10 16:41:14 +02:00
NotifyHeaderTip ( ) ;
2014-10-07 18:06:30 +02:00
// Recursively process earlier encountered successors of this block
2017-01-30 13:13:07 +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-19 08:24:11 +01:00
LogPrint ( " 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 ( ) ) ;
2017-07-10 16:41:14 +02:00
LOCK ( cs_main ) ;
2014-10-07 18:06:30 +02:00
CValidationState dummy ;
2016-12-19 08:24:11 +01:00
if ( AcceptBlock ( pblockrecursive , dummy , chainparams , NULL , true , & it - > second , NULL ) )
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 ) ;
2017-07-10 16:41:14 +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
2015-04-17 14:19:21 +02:00
void static 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 ;
for ( BlockMap : : iterator it = mapBlockIndex . begin ( ) ; it ! = mapBlockIndex . end ( ) ; it + + ) {
forward . insert ( std : : make_pair ( it - > second - > pprev , it - > second ) ) ;
}
assert ( forward . size ( ) = = mapBlockIndex . size ( ) ) ;
std : : pair < std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator , std : : multimap < CBlockIndex * , CBlockIndex * > : : iterator > rangeGenesis = forward . equal_range ( NULL ) ;
CBlockIndex * pindex = rangeGenesis . first - > second ;
rangeGenesis . first + + ;
assert ( rangeGenesis . first = = rangeGenesis . second ) ; // There is only one index entry with parent NULL.
// 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 ;
CBlockIndex * pindexFirstInvalid = NULL ; // Oldest ancestor of pindex which is invalid.
CBlockIndex * pindexFirstMissing = NULL ; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA.
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
CBlockIndex * pindexFirstNeverProcessed = NULL ; // Oldest ancestor of pindex for which nTx == 0.
2015-03-13 17:25:34 +01:00
CBlockIndex * pindexFirstNotTreeValid = NULL ; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not).
2015-04-01 19:12:50 +02:00
CBlockIndex * pindexFirstNotTransactionsValid = NULL ; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not).
2015-03-13 17:25:34 +01:00
CBlockIndex * pindexFirstNotChainValid = NULL ; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not).
CBlockIndex * pindexFirstNotScriptsValid = NULL ; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not).
while ( pindex ! = NULL ) {
nNodes + + ;
if ( pindexFirstInvalid = = NULL & & pindex - > nStatus & BLOCK_FAILED_VALID ) pindexFirstInvalid = pindex ;
if ( pindexFirstMissing = = NULL & & ! ( pindex - > nStatus & BLOCK_HAVE_DATA ) ) pindexFirstMissing = pindex ;
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 ( pindexFirstNeverProcessed = = NULL & & pindex - > nTx = = 0 ) pindexFirstNeverProcessed = pindex ;
2015-03-13 17:25:34 +01:00
if ( pindex - > pprev ! = NULL & & pindexFirstNotTreeValid = = NULL & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_TREE ) pindexFirstNotTreeValid = pindex ;
2015-04-01 19:12:50 +02:00
if ( pindex - > pprev ! = NULL & & pindexFirstNotTransactionsValid = = NULL & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_TRANSACTIONS ) pindexFirstNotTransactionsValid = pindex ;
2015-03-13 17:25:34 +01:00
if ( pindex - > pprev ! = NULL & & pindexFirstNotChainValid = = NULL & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_CHAIN ) pindexFirstNotChainValid = pindex ;
if ( pindex - > pprev ! = NULL & & pindexFirstNotScriptsValid = = NULL & & ( pindex - > nStatus & BLOCK_VALID_MASK ) < BLOCK_VALID_SCRIPTS ) pindexFirstNotScriptsValid = pindex ;
// Begin: actual consistency checks.
if ( pindex - > pprev = = NULL ) {
// 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-10-18 21:35:27 +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.
assert ( ( pindexFirstNeverProcessed ! = NULL ) = = ( pindex - > nChainTx = = 0 ) ) ; // nChainTx != 0 is used to signal that all parent blocks have been processed (but may have been pruned).
2015-04-01 19:12:50 +02:00
assert ( ( pindexFirstNotTransactionsValid ! = NULL ) = = ( pindex - > nChainTx = = 0 ) ) ;
2015-03-13 17:25:34 +01:00
assert ( pindex - > nHeight = = nHeight ) ; // nHeight must be consistent.
assert ( pindex - > pprev = = NULL | | pindex - > nChainWork > = pindex - > pprev - > nChainWork ) ; // For every block except the genesis block, the chainwork must be larger than the parent's.
assert ( nHeight < 2 | | ( pindex - > pskip & & ( pindex - > pskip - > nHeight < nHeight ) ) ) ; // The pskip pointer must point back for all but the first 2 blocks.
assert ( pindexFirstNotTreeValid = = NULL ) ; // All mapBlockIndex entries must at least be TREE valid
if ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_TREE ) assert ( pindexFirstNotTreeValid = = NULL ) ; // TREE valid implies all parents are TREE valid
if ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_CHAIN ) assert ( pindexFirstNotChainValid = = NULL ) ; // CHAIN valid implies all parents are CHAIN valid
if ( ( pindex - > nStatus & BLOCK_VALID_MASK ) > = BLOCK_VALID_SCRIPTS ) assert ( pindexFirstNotScriptsValid = = NULL ) ; // SCRIPTS valid implies all parents are SCRIPTS valid
if ( pindexFirstInvalid = = NULL ) {
// Checks for not-invalid blocks.
assert ( ( pindex - > nStatus & BLOCK_FAILED_MASK ) = = 0 ) ; // The failed mask cannot be set for blocks without invalid parents.
}
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 ( ! CBlockIndexWorkComparator ( ) ( pindex , chainActive . Tip ( ) ) & & pindexFirstNeverProcessed = = NULL ) {
if ( pindexFirstInvalid = = NULL ) {
// 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.
if ( pindexFirstMissing = = NULL | | pindex = = chainActive . Tip ( ) ) {
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 + + ;
}
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 - > pprev & & ( pindex - > nStatus & BLOCK_HAVE_DATA ) & & pindexFirstNeverProcessed ! = NULL & & pindexFirstInvalid = = NULL ) {
// 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
if ( pindexFirstMissing = = NULL ) assert ( ! foundInUnlinked ) ; // We aren't missing data for any parent -- cannot be in mapBlocksUnlinked.
if ( pindex - > pprev & & ( pindex - > nStatus & BLOCK_HAVE_DATA ) & & pindexFirstNeverProcessed = = NULL & & pindexFirstMissing ! = NULL ) {
// 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 ) {
if ( pindexFirstInvalid = = NULL ) {
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.
if ( pindex = = pindexFirstInvalid ) pindexFirstInvalid = NULL ;
if ( pindex = = pindexFirstMissing ) pindexFirstMissing = NULL ;
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 = = pindexFirstNeverProcessed ) pindexFirstNeverProcessed = NULL ;
2015-03-13 17:25:34 +01:00
if ( pindex = = pindexFirstNotTreeValid ) pindexFirstNotTreeValid = NULL ;
2015-04-01 19:12:50 +02:00
if ( pindex = = pindexFirstNotTransactionsValid ) pindexFirstNotTransactionsValid = NULL ;
2015-03-13 17:25:34 +01:00
if ( pindex = = pindexFirstNotChainValid ) pindexFirstNotChainValid = NULL ;
if ( pindex = = pindexFirstNotScriptsValid ) pindexFirstNotScriptsValid = NULL ;
// 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-12-19 12:38:35 +01:00
std : : string CBlockFileInfo : : ToString ( ) const {
return strprintf ( " CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s) " , nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat( " % Y - % m - % d " , nTimeFirst), DateTimeStrFormat( " % Y - % m - % d " , nTimeLast)) ;
2010-08-29 18:58:15 +02:00
}
2016-06-01 18:28:07 +02:00
2017-02-22 12:42:55 +01:00
CBlockFileInfo * GetBlockFileInfo ( size_t n )
{
return & vinfoBlockFile . at ( n ) ;
}
2017-08-09 02:19:06 +02:00
ThresholdState VersionBitsTipState ( const Consensus : : Params & params , Consensus : : DeploymentPos pos )
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
{
2017-09-15 20:05:03 +02:00
AssertLockHeld ( cs_main ) ;
2017-08-09 02:19:06 +02:00
return VersionBitsState ( chainActive . Tip ( ) , params , pos , versionbitscache ) ;
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
}
2016-10-19 16:36:21 +02:00
int VersionBitsTipStateSinceHeight ( const Consensus : : Params & params , Consensus : : DeploymentPos pos )
{
LOCK ( cs_main ) ;
return VersionBitsStateSinceHeight ( chainActive . Tip ( ) , params , pos , versionbitscache ) ;
}
2016-11-02 11:12:48 +01:00
static const uint64_t MEMPOOL_DUMP_VERSION = 1 ;
bool LoadMempool ( void )
{
int64_t nExpiryTimeout = GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ;
2017-02-21 09:50:37 +01:00
FILE * filestr = fopen ( ( GetDataDir ( ) / " mempool.dat " ) . string ( ) . c_str ( ) , " rb " ) ;
2016-11-02 11:12:48 +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 ;
int64_t skipped = 0 ;
int64_t failed = 0 ;
int64_t nNow = GetTime ( ) ;
try {
uint64_t version ;
file > > version ;
if ( version ! = MEMPOOL_DUMP_VERSION ) {
return false ;
}
uint64_t num ;
file > > num ;
double prioritydummy = 0 ;
while ( num - - ) {
2017-01-04 12:22:49 +01:00
CTransactionRef tx ;
2016-11-02 11:12:48 +01:00
int64_t nTime ;
int64_t nFeeDelta ;
2017-01-04 12:22:49 +01:00
file > > tx ;
2016-11-02 11:12:48 +01:00
file > > nTime ;
file > > nFeeDelta ;
CAmount amountdelta = nFeeDelta ;
if ( amountdelta ) {
2017-01-04 12:22:49 +01:00
mempool . PrioritiseTransaction ( tx - > GetHash ( ) , tx - > GetHash ( ) . ToString ( ) , prioritydummy , amountdelta ) ;
2016-11-02 11:12:48 +01:00
}
CValidationState state ;
if ( nTime + nExpiryTimeout > nNow ) {
LOCK ( cs_main ) ;
AcceptToMemoryPoolWithTime ( mempool , state , tx , true , NULL , nTime ) ;
if ( state . IsValid ( ) ) {
+ + count ;
} else {
+ + failed ;
}
} else {
+ + skipped ;
}
2017-01-06 18:28:46 +01:00
if ( ShutdownRequested ( ) )
return false ;
2016-11-02 11:12:48 +01:00
}
std : : map < uint256 , CAmount > mapDeltas ;
file > > mapDeltas ;
for ( const auto & i : mapDeltas ) {
mempool . PrioritiseTransaction ( i . first , i . first . ToString ( ) , prioritydummy , i . second ) ;
}
} catch ( const std : : exception & e ) {
LogPrintf ( " Failed to deserialize mempool data on disk: %s. Continuing anyway. \n " , e . what ( ) ) ;
return false ;
}
LogPrintf ( " Imported mempool transactions from disk: %i successes, %i failed, %i expired \n " , count , failed , skipped ) ;
return true ;
}
void DumpMempool ( void )
{
int64_t start = GetTimeMicros ( ) ;
std : : map < uint256 , CAmount > mapDeltas ;
std : : vector < TxMempoolInfo > vinfo ;
{
LOCK ( mempool . cs ) ;
for ( const auto & i : mempool . mapDeltas ) {
2017-01-23 19:31:28 +01:00
mapDeltas [ i . first ] = i . second . second ;
2016-11-02 11:12:48 +01:00
}
vinfo = mempool . infoAll ( ) ;
}
int64_t mid = GetTimeMicros ( ) ;
try {
2017-02-21 09:50:37 +01:00
FILE * filestr = fopen ( ( GetDataDir ( ) / " mempool.dat.new " ) . string ( ) . c_str ( ) , " wb " ) ;
2016-11-02 11:12:48 +01:00
if ( ! filestr ) {
return ;
}
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 ;
FileCommit ( file . Get ( ) ) ;
file . fclose ( ) ;
RenameOver ( GetDataDir ( ) / " mempool.dat.new " , GetDataDir ( ) / " mempool.dat " ) ;
int64_t last = GetTimeMicros ( ) ;
LogPrintf ( " Dumped mempool: %gs to copy, %gs to dump \n " , ( mid - start ) * 0.000001 , ( last - mid ) * 0.000001 ) ;
} catch ( const std : : exception & e ) {
LogPrintf ( " Failed to dump mempool: %s. Continuing anyway. \n " , e . what ( ) ) ;
}
}
2017-01-12 12:12:56 +01:00
//! Guess how far we are in the verification process at the given block index
double GuessVerificationProgress ( const ChainTxData & data , CBlockIndex * pindex ) {
if ( pindex = = NULL )
return 0.0 ;
int64_t nNow = time ( NULL ) ;
double fTxTotal ;
if ( pindex - > nChainTx < = data . nTxCount ) {
fTxTotal = data . nTxCount + ( nNow - data . nTime ) * data . dTxRate ;
} else {
fTxTotal = pindex - > nChainTx + ( nNow - pindex - > GetBlockTime ( ) ) * data . dTxRate ;
}
return pindex - > nChainTx / fTxTotal ;
}
2017-08-09 02:19:06 +02:00
class CMainCleanup
2013-03-29 02:17:10 +01:00
{
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 ;