aboutsummaryrefslogtreecommitdiff
path: root/src/main.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.h')
-rw-r--r--src/main.h217
1 files changed, 126 insertions, 91 deletions
diff --git a/src/main.h b/src/main.h
index 1bb0919817..f3d30fafb3 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"
@@ -60,7 +60,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 +94,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 +133,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 +153,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 +181,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 +205,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 +249,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 +324,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 +336,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,12 +352,15 @@ public:
std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore);
+ std::swap(error, check.error);
}
+
+ ScriptError GetScriptError() const { return 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
+ * It represents 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.
*
@@ -378,36 +395,38 @@ public:
class CPartialMerkleTree
{
protected:
- // the total number of transactions in the block
+ /** the total number of transactions in the block */
unsigned int nTransactions;
- // node-is-parent-of-matched-txid bits
+ /** node-is-parent-of-matched-txid bits */
std::vector<bool> vBits;
- // txids and internal hashes
+ /** txids and internal hashes */
std::vector<uint256> vHash;
- // flag set when encountering invalid data
+ /** flag set when encountering invalid data */
bool fBad;
- // helper function to efficiently calculate the number of nodes at given height in the merkle tree
+ /** 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)
+ /** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */
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
+ /** 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.
+ /**
+ * 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
+ /** serialization implementation */
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
@@ -430,13 +449,15 @@ public:
}
}
- // Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them
+ /** 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
+ /**
+ * 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);
};
@@ -456,15 +477,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 +500,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 +537,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 +555,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 +625,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,24 +652,26 @@ struct CBlockTemplate
-/** Used to relay blocks as header + vector<merkle branch>
+/**
+ * Used to relay blocks as header + vector<merkle branch>
* to filtered nodes.
*/
class CMerkleBlock
{
public:
- // Public only for unit testing
+ /** Public only for unit testing */
CBlockHeader header;
CPartialMerkleTree txn;
public:
- // Public only for unit testing and relay testing
- // (not relayed)
+ /** 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.
+ /**
+ * 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;