forked from dashpay/dash
/
validation.h
409 lines (346 loc) · 17 KB
/
validation.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2011-2013 The PPCoin developers
// Copyright (c) 2013-2014 The NovaCoin Developers
// Copyright (c) 2014-2018 The BlackCoin Developers
// Copyright (c) 2015-2020 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MAIN_H
#define BITCOIN_MAIN_H
#if defined(HAVE_CONFIG_H)
#include "config/pivx-config.h"
#endif
#include "amount.h"
#include "chain.h"
#include "coins.h"
#include "consensus/validation.h"
#include "fs.h"
#include "moneysupply.h"
#include "policy/feerate.h"
#include "script/script_error.h"
#include "sync.h"
#include "txmempool.h"
#include <algorithm>
#include <atomic>
#include <exception>
#include <map>
#include <memory>
#include <set>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
class CBlockIndex;
class CBlockTreeDB;
class CBudgetManager;
class CZerocoinDB;
class CSporkDB;
class CBloomFilter;
class CInv;
class CConnman;
class CNode;
class CScriptCheck;
struct PrecomputedTransactionData;
/** Default for -limitancestorcount, max number of in-mempool ancestors */
static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25;
/** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */
static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 101;
/** Default for -banscore */
static const int DEFAULT_BANSCORE_THRESHOLD = 100;
/** Default for -persistmempool */
static const bool DEFAULT_PERSIST_MEMPOOL = true;
/** Default for -limitdescendantcount, max number of in-mempool descendants */
static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25;
/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */
static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101;
/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 72;
/** Default for -txindex */
static const bool DEFAULT_TXINDEX = true;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
/** The maximum size for transactions we're willing to relay/mine */
static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
static const unsigned int MAX_ZEROCOIN_TX_SIZE = 150000;
/** Maximum kilobytes for transactions to store for processing during reorg */
static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE = 20000;
/** Default for -checkblocks */
static const signed int DEFAULT_CHECKBLOCKS = 6;
static const unsigned int DEFAULT_CHECKLEVEL = 3;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
/** Maximum number of script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 16;
/** -par default (number of script-checking threads, 0 = auto) */
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
/** Number of blocks that can be requested at any given time from a single peer. */
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
/** Timeout in seconds during which a peer must stall block download progress before being disconnected. */
static const unsigned int BLOCK_STALLING_TIMEOUT = 2;
/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
* less than this number, we reached their tip. Changing this value is a protocol upgrade. */
static const unsigned int MAX_HEADERS_RESULTS = 2000;
/** Size of the "block download window": how far ahead of our current height do we fetch?
* Larger windows tolerate larger download speed differences between peer, but increase the potential
* degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning
* harder). We'll probably want to make this a per-peer adaptive value at some point. */
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Time to wait (in seconds) between writing blocks/block index to disk. */
static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60;
/** Time to wait (in seconds) between flushing chainstate to disk. */
static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60;
/** Average delay between local address broadcasts in seconds. */
static const unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 24 * 60;
/** Average delay between peer address broadcasts in seconds. */
static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30;
/** Default multiplier used in the computation for shielded txes min fee */
static const unsigned int DEFAULT_SHIELDEDTXFEE_K = 100;
/** Enable bloom filter */
static const bool DEFAULT_PEERBLOOMFILTERS = true;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
/** Maximum age of our tip in seconds for us to be considered current for fee estimation */
static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
struct BlockHasher {
size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); }
};
extern CScript COINBASE_FLAGS;
extern RecursiveMutex cs_main;
extern CTxMemPool mempool;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap mapBlockIndex;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
extern int64_t nTimeBestReceived;
// Best block section
extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
extern uint256 g_best_block;
extern int64_t g_best_block_time;
extern std::atomic<bool> fImporting;
extern std::atomic<bool> fReindex;
extern int nScriptCheckThreads;
extern bool fTxIndex;
extern bool fRequireStandard;
extern bool fCheckBlockIndex;
extern size_t nCoinCacheUsage;
extern CFeeRate minRelayTxFee;
extern int64_t nMaxTipAge;
extern bool fLargeWorkForkFound;
extern bool fLargeWorkInvalidChainFound;
extern std::map<uint256, int64_t> mapRejectedBlocks;
extern CMoneySupply MoneySupply;
/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex* pindexBestHeader;
/**
* Process an incoming block. This only returns after the best known valid
* block is made active. Note that it does not, however, guarantee that the
* specific block passed to it has been checked for validity!
*
* If you want to *possibly* get feedback on whether pblock is valid, you must
* install a CValidationInterface (see validationinterface.h) - this will have
* its BlockChecked method called whenever *any* block completes validation.
*
* Note that we guarantee that either the proof-of-work is valid on pblock, or
* (and possibly also) BlockChecked will have been called.
*
* @param[in] pblock The block we want to process.
* @param[out] dbp The already known disk position of pblock, or nullptr if not yet stored.
* @return True if state.IsValid()
*/
bool ProcessNewBlock(const std::shared_ptr<const CBlock>& pblock, const FlatFilePos* dbp);
/** Open a block file (blk?????.dat) */
FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly = false);
/** Open an undo file (rev?????.dat) */
FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false);
/** Translation to a filesystem path */
fs::path GetBlockPosFilename(const FlatFilePos &pos);
/** Import blocks from an external file */
bool LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = NULL);
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
bool LoadGenesisBlock();
/** Load the block tree and coins database from disk,
* initializing state if we're running with -reindex. */
bool LoadBlockIndex(std::string& strError);
/** Update the chain tip based on database information. */
bool LoadChainTip(const CChainParams& chainparams);
/** Unload database information */
void UnloadBlockIndex();
/** See whether the protocol update is enforced for connected nodes */
int ActiveProtocol();
/** Run an instance of the script checking thread */
void ThreadScriptCheck();
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool IsInitialBlockDownload();
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256& hash, CTransactionRef& tx, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr);
/** Retrieve an output (from memory pool, or from disk, if possible) */
bool GetOutput(const uint256& hash, unsigned int index, CValidationState& state, CTxOut& out);
double ConvertBitsToDouble(unsigned int nBits);
int64_t GetMasternodePayment();
/** Find the best known block, and make it the tip of the block chain */
bool ActivateBestChain(CValidationState& state, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>());
CAmount GetBlockValue(int nHeight);
/** Create a new block index entry for a given block hash */
CBlockIndex* InsertBlockIndex(uint256 hash);
/** Flush all state, indexes and buffers to disk. */
void FlushStateToDisk();
/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransactionRef& tx, bool fLimitFree, bool* pfMissingInputs, bool fOverrideMempoolLimit = false, bool fRejectInsaneFee = false, bool ignoreFees = false);
/** (try to) add transaction to memory pool with a specified acceptance time **/
bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit = false,
bool fRejectInsaneFee = false, bool ignoreFees = false);
/** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state);
CAmount GetMinRelayFee(const CTransaction& tx, const CTxMemPool& pool, unsigned int nBytes);
CAmount GetMinRelayFee(unsigned int nBytes);
/**
* Return the minimum fee for a shielded tx.
*/
CAmount GetShieldedTxMinFee(const CTransaction& tx);
/**
* Check transaction inputs, and make sure any
* pay-to-script-hash transactions are evaluating IsStandard scripts
*
* Why bother? To avoid denial-of-service attacks; an attacker
* can submit a standard HASH... OP_EQUAL transaction,
* which will get accepted into blocks. The redemption
* script can be anything; an attacker could use a very
* expensive-to-check-upon-redemption script like:
* DUP CHECKSIG DROP ... repeated 100 times... OP_1
*/
/**
* Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
* This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
* instead of being performed inline.
*/
bool CheckInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& view, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& precomTxData, std::vector<CScriptCheck>* pvChecks = NULL);
/** Apply the effects of this transaction on the UTXO set represented by view */
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight, bool fSkipInvalid = false);
bool IsTransactionInChain(const uint256& txId, int& nHeightTx, CTransactionRef& tx);
bool IsTransactionInChain(const uint256& txId, int& nHeightTx);
bool IsBlockHashInChain(const uint256& hashBlock);
/**
* Check if transaction will be final in the next block to be created.
*
* Calls IsFinalTx() with current block height and appropriate block time.
*
* See consensus/consensus.h for flag definitions.
*/
bool CheckFinalTx(const CTransactionRef& tx, int flags = -1);
/*
* Retrieve an unspent coin in pcoinsTip. Lock cs_main.
*/
bool GetUTXOCoin(const COutPoint& outpoint, Coin& coin);
Optional<int> GetUTXOHeight(const COutPoint& outpoint);
/**
* Closure representing one script verification
* Note that this stores references to the spending transaction
*/
class CScriptCheck
{
private:
CTxOut m_tx_out;
const CTransaction* ptxTo;
unsigned int nIn;
unsigned int nFlags;
bool cacheStore;
ScriptError error;
PrecomputedTransactionData *precomTxData;
public:
CScriptCheck() : ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR), precomTxData(nullptr) {}
CScriptCheck(const CTxOut& outIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* cachedHashesIn) :
m_tx_out(outIn),
ptxTo(&txToIn),
nIn(nInIn),
nFlags(nFlagsIn),
cacheStore(cacheIn),
error(SCRIPT_ERR_UNKNOWN_ERROR),
precomTxData(cachedHashesIn) {}
bool operator()();
void swap(CScriptCheck& check)
{
std::swap(ptxTo, check.ptxTo);
std::swap(m_tx_out, check.m_tx_out);
std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore);
std::swap(error, check.error);
std::swap(precomTxData, check.precomTxData);
}
ScriptError GetScriptError() const { return error; }
};
/** Functions for disk access for blocks */
bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos);
bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos);
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
/** Functions for validating blocks and updating the block tree */
/** Context-independent validity checks */
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true, bool fCheckSig = true);
bool CheckWork(const CBlock& block, const CBlockIndex* const pindexPrev);
/** Context-dependent validity checks */
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex* pindexPrev);
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindexPrev);
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true, bool fCheckBlockSig = true);
bool AcceptBlockHeader(const CBlock& block, CValidationState& state, CBlockIndex** ppindex = nullptr, CBlockIndex* pindexPrev = nullptr);
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */
class CVerifyDB
{
public:
CVerifyDB();
~CVerifyDB();
bool VerifyDB(CCoinsView* coinsview, int nCheckLevel, int nCheckDepth);
};
/** Replay blocks that aren't fully applied to the database. */
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
/** Find the last common block between the parameter chain and a locator. */
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
/** Mark a block as invalid. */
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex);
/** Remove invalidity status from a block and its descendants. */
bool ReconsiderBlock(CValidationState& state, CBlockIndex* pindex);
/** The currently-connected chain of blocks (protected by cs_main). */
extern CChain chainActive;
/** Global variable that points to the active CCoinsView (protected by cs_main) */
extern CCoinsViewCache* pcoinsTip;
/** Global variable that points to the active block tree (protected by cs_main) */
extern CBlockTreeDB* pblocktree;
/** Global variable that points to the zerocoin database (protected by cs_main) */
extern CZerocoinDB* zerocoinDB;
/** Global variable that points to the spork database (protected by cs_main) */
extern CSporkDB* pSporkDB;
/**
* Return a reliable pointer (in mapBlockIndex) to the chain's tip index
*/
CBlockIndex* GetChainTip();
/**
* Return the spend height, which is one more than the inputs.GetBestBlock().
* While checking, GetBestBlock() refers to the parent block. (protected by cs_main)
* This is also true for mempool checks.
*/
int GetSpendHeight(const CCoinsViewCache& inputs);
/** Reject codes greater or equal to this can be returned by AcceptToMemPool
* for transactions, to signal internal conditions. They cannot and should not
* be sent over the P2P network.
*/
static const unsigned int REJECT_INTERNAL = 0x100;
/** Too high fee. Can not be triggered by P2P transactions */
static const unsigned int REJECT_HIGHFEE = 0x100;
/** Transaction is already known (either in mempool or blockchain) */
static const unsigned int REJECT_ALREADY_KNOWN = 0x101;
/** Transaction conflicts with a transaction already known */
static const unsigned int REJECT_CONFLICT = 0x102;
/** Get block file info entry for one block file */
CBlockFileInfo* GetBlockFileInfo(size_t n);
/** Dump the mempool to disk. */
bool DumpMempool(const CTxMemPool& pool);
/** Load the mempool from disk. */
bool LoadMempool(CTxMemPool& pool);
#endif // BITCOIN_MAIN_H