aboutsummaryrefslogtreecommitdiff
path: root/src/main.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.h')
-rw-r--r--src/main.h299
1 files changed, 98 insertions, 201 deletions
diff --git a/src/main.h b/src/main.h
index 1bb0919817..8f0378647d 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MAIN_H
@@ -14,8 +14,8 @@
#include "chain.h"
#include "chainparams.h"
#include "coins.h"
-#include "core/block.h"
-#include "core/transaction.h"
+#include "primitives/block.h"
+#include "primitives/transaction.h"
#include "net.h"
#include "pow.h"
#include "script/script.h"
@@ -49,8 +49,6 @@ class CValidationState;
struct CBlockTemplate;
struct CNodeStateStats;
-/** The maximum allowed size for a serialized block, in bytes (network rule) */
-static const unsigned int MAX_BLOCK_SIZE = 1000000;
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
@@ -60,7 +58,7 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
/** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
-/** Maxiumum number of signature check operations in an IsStandard() P2SH script */
+/** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
@@ -94,8 +92,12 @@ static const unsigned int MAX_HEADERS_RESULTS = 2000;
* 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 blockchain state to disk. */
+static const unsigned int DATABASE_WRITE_INTERVAL = 3600;
+/** Maximum length of reject messages. */
+static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
-/** "reject" message codes **/
+/** "reject" message codes */
static const unsigned char REJECT_MALFORMED = 0x01;
static const unsigned char REJECT_INVALID = 0x10;
static const unsigned char REJECT_OBSOLETE = 0x11;
@@ -129,10 +131,10 @@ extern bool fIsBareMultisigStd;
extern unsigned int nCoinCacheSize;
extern CFeeRate minRelayTxFee;
-// Best header we've seen so far (used for getheaders queries' starting points).
+/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex *pindexBestHeader;
-// Minimum disk space required - used in CheckDiskSpace()
+/** Minimum disk space required - used in CheckDiskSpace() */
static const uint64_t nMinDiskSpace = 52428800;
/** Register a wallet to receive updates from core */
@@ -149,15 +151,17 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
/** Unregister a network node */
void UnregisterNodeSignals(CNodeSignals& nodeSignals);
-/** 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!
- @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state iff pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation.
- @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
- @param[in] pblock The block we want to process.
- @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
- @return True if state.IsValid()
-*/
+/**
+ * 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!
+ *
+ * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation.
+ * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
+ * @param[in] pblock The block we want to process.
+ * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
+ * @return True if state.IsValid()
+ */
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
@@ -175,8 +179,6 @@ bool InitBlockIndex();
bool LoadBlockIndex();
/** Unload database information */
void UnloadBlockIndex();
-/** Print the loaded block tree */
-void PrintBlockTree();
/** Process protocol messages received from a given node */
bool ProcessMessages(CNode* pfrom);
/** Send queued protocol messages to be sent to a give node */
@@ -201,6 +203,8 @@ bool AbortNode(const std::string &msg, const std::string &userMessage="");
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
/** Increase a node's misbehavior score. */
void Misbehaving(NodeId nodeid, int howmuch);
+/** Flush all state, indexes and buffers to disk. */
+void FlushStateToDisk();
/** (try to) add transaction to memory pool **/
@@ -243,54 +247,59 @@ struct CDiskTxPos : public CDiskBlockPos
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
-//
-// 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 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 for standard transaction types
- @param[in] mapInputs Map of previous transactions that have outputs we're spending
- @return True if all inputs (scriptSigs) use only standard transaction forms
-*/
+/**
+ * Check for standard transaction types
+ * @param[in] mapInputs Map of previous transactions that have outputs we're spending
+ * @return True if all inputs (scriptSigs) use only standard transaction forms
+ */
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
-/** Count ECDSA signature operations the old-fashioned (pre-0.6) way
- @return number of sigops this transaction's outputs will produce when spent
- @see CTransaction::FetchInputs
-*/
+/**
+ * Count ECDSA signature operations the old-fashioned (pre-0.6) way
+ * @return number of sigops this transaction's outputs will produce when spent
+ * @see CTransaction::FetchInputs
+ */
unsigned int GetLegacySigOpCount(const CTransaction& tx);
-/** Count ECDSA signature operations in pay-to-script-hash inputs.
-
- @param[in] mapInputs Map of previous transactions that have outputs we're spending
- @return maximum number of sigops required to validate this transaction's inputs
- @see CTransaction::FetchInputs
+/**
+ * Count ECDSA signature operations in pay-to-script-hash inputs.
+ *
+ * @param[in] mapInputs Map of previous transactions that have outputs we're spending
+ * @return maximum number of sigops required to validate this transaction's inputs
+ * @see CTransaction::FetchInputs
*/
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
-// 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.
+/**
+ * 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, std::vector<CScriptCheck> *pvChecks = NULL);
-// Apply the effects of this transaction on the UTXO set represented by view
+/** Apply the effects of this transaction on the UTXO set represented by view */
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight);
-// Context-independent validity checks
+/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
/** Check for standard transaction types
- @return True if all outputs (scriptPubKeys) use only standard transaction forms
-*/
+ * @return True if all outputs (scriptPubKeys) use only standard transaction forms
+ */
bool IsStandardTx(const CTransaction& tx, std::string& reason);
bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0);
@@ -313,8 +322,10 @@ public:
};
-/** Closure representing one script verification
- * Note that this stores references to the spending transaction */
+/**
+ * Closure representing one script verification
+ * Note that this stores references to the spending transaction
+ */
class CScriptCheck
{
private:
@@ -323,14 +334,15 @@ private:
unsigned int nIn;
unsigned int nFlags;
bool cacheStore;
+ ScriptError error;
public:
- CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false) {}
+ CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
- ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn) { }
+ ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
- bool operator()() const;
+ bool operator()();
void swap(CScriptCheck &check) {
scriptPubKey.swap(check.scriptPubKey);
@@ -338,110 +350,13 @@ public:
std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore);
+ std::swap(error, check.error);
}
-};
-
-/** Data structure that represents a partial merkle tree.
- *
- * It respresents a subset of the txid's of a known block, in a way that
- * allows recovery of the list of txid's and the merkle root, in an
- * authenticated way.
- *
- * The encoding works as follows: we traverse the tree in depth-first order,
- * storing a bit for each traversed node, signifying whether the node is the
- * parent of at least one matched leaf txid (or a matched txid itself). In
- * case we are at the leaf level, or this bit is 0, its merkle node hash is
- * stored, and its children are not explorer further. Otherwise, no hash is
- * stored, but we recurse into both (or the only) child branch. During
- * decoding, the same depth-first traversal is performed, consuming bits and
- * hashes as they written during encoding.
- *
- * The serialization is fixed and provides a hard guarantee about the
- * encoded size:
- *
- * SIZE <= 10 + ceil(32.25*N)
- *
- * Where N represents the number of leaf nodes of the partial tree. N itself
- * is bounded by:
- *
- * N <= total_transactions
- * N <= 1 + matched_transactions*tree_height
- *
- * The serialization format:
- * - uint32 total_transactions (4 bytes)
- * - varint number of hashes (1-3 bytes)
- * - uint256[] hashes in depth-first order (<= 32*N bytes)
- * - varint number of bytes of flag bits (1-3 bytes)
- * - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits)
- * The size constraints follow from this.
- */
-class CPartialMerkleTree
-{
-protected:
- // the total number of transactions in the block
- unsigned int nTransactions;
- // node-is-parent-of-matched-txid bits
- std::vector<bool> vBits;
-
- // txids and internal hashes
- std::vector<uint256> vHash;
-
- // flag set when encountering invalid data
- bool fBad;
-
- // helper function to efficiently calculate the number of nodes at given height in the merkle tree
- unsigned int CalcTreeWidth(int height) {
- return (nTransactions+(1 << height)-1) >> height;
- }
-
- // calculate the hash of a node in the merkle tree (at leaf level: the txid's themself)
- uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid);
-
- // recursive function that traverses tree nodes, storing the data as bits and hashes
- void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
-
- // recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
- // it returns the hash of the respective node.
- uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
-
-public:
-
- // serialization implementation
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(nTransactions);
- READWRITE(vHash);
- std::vector<unsigned char> vBytes;
- if (ser_action.ForRead()) {
- READWRITE(vBytes);
- CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
- us.vBits.resize(vBytes.size() * 8);
- for (unsigned int p = 0; p < us.vBits.size(); p++)
- us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
- us.fBad = false;
- } else {
- vBytes.resize((vBits.size()+7)/8);
- for (unsigned int p = 0; p < vBits.size(); p++)
- vBytes[p / 8] |= vBits[p] << (p % 8);
- READWRITE(vBytes);
- }
- }
-
- // Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them
- CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
-
- CPartialMerkleTree();
-
- // extract the matching txid's represented by this partial merkle tree.
- // returns the merkle root, or 0 in case of failure
- uint256 ExtractMatches(std::vector<uint256> &vMatch);
+ ScriptError GetScriptError() const { return error; }
};
-
/** Functions for disk access for blocks */
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
@@ -456,15 +371,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
* of problems. Note that in any case, coins may be modified. */
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL);
-// Apply the effects of this block (with given index) on the UTXO set represented by coins
-bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
+/** Apply the effects of this block (with given index) on the UTXO set represented by coins */
+bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
-// Context-independent validity checks
+/** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
-// Store block on disk
-// if dbp is provided, the file is known to already reside on disk
+/** 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);
+
+/** Store block on disk. If dbp is provided, the file is known to already reside on disk */
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);
@@ -473,13 +394,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
class CBlockFileInfo
{
public:
- unsigned int nBlocks; // number of blocks stored in file
- unsigned int nSize; // number of used bytes of block file
- unsigned int nUndoSize; // number of used bytes in the undo file
- unsigned int nHeightFirst; // lowest height of block in file
- unsigned int nHeightLast; // highest height of block in file
- uint64_t nTimeFirst; // earliest time of block in file
- uint64_t nTimeLast; // latest time of block in file
+ unsigned int nBlocks; //! number of blocks stored in file
+ unsigned int nSize; //! number of used bytes of block file
+ unsigned int nUndoSize; //! number of used bytes in the undo file
+ unsigned int nHeightFirst; //! lowest height of block in file
+ unsigned int nHeightLast; //! highest height of block in file
+ uint64_t nTimeFirst; //! earliest time of block in file
+ uint64_t nTimeLast; //! latest time of block in file
ADD_SERIALIZE_METHODS;
@@ -510,7 +431,7 @@ public:
std::string ToString() const;
- // update statistics (does not update nSize)
+ /** update statistics (does not update nSize) */
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
if (nBlocks==0 || nHeightFirst > nHeightIn)
nHeightFirst = nHeightIn;
@@ -528,9 +449,9 @@ public:
class CValidationState {
private:
enum mode_state {
- MODE_VALID, // everything ok
- MODE_INVALID, // network rule violation (DoS value may be set)
- MODE_ERROR, // run-time error
+ MODE_VALID, //! everything ok
+ MODE_INVALID, //! network rule violation (DoS value may be set)
+ MODE_ERROR, //! run-time error
} mode;
int nDoS;
std::string strRejectReason;
@@ -598,6 +519,12 @@ public:
/** 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, CBlockIndex *pindex);
+
+/** Remove invalidity status from a block and its descendants. */
+bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex);
+
/** The currently-connected chain of blocks. */
extern CChain chainActive;
@@ -619,36 +546,6 @@ struct CBlockTemplate
-/** Used to relay blocks as header + vector<merkle branch>
- * to filtered nodes.
- */
-class CMerkleBlock
-{
-public:
- // Public only for unit testing
- CBlockHeader header;
- CPartialMerkleTree txn;
-
-public:
- // Public only for unit testing and relay testing
- // (not relayed)
- std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
-
- // Create from a CBlock, filtering transactions according to filter
- // Note that this will call IsRelevantAndUpdate on the filter for each transaction,
- // thus the filter will likely be modified.
- CMerkleBlock(const CBlock& block, CBloomFilter& filter);
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(header);
- READWRITE(txn);
- }
-};
-
-
class CValidationInterface {
protected:
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {};