aboutsummaryrefslogtreecommitdiff
path: root/src/main.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.h')
-rw-r--r--src/main.h209
1 files changed, 197 insertions, 12 deletions
diff --git a/src/main.h b/src/main.h
index 44fa5c1de3..db41584b56 100644
--- a/src/main.h
+++ b/src/main.h
@@ -53,6 +53,8 @@ inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONE
static const int COINBASE_MATURITY = 100;
/** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
+/** Maximum number of script-checking threads allowed */
+static const int MAX_SCRIPTCHECK_THREADS = 16;
#ifdef USE_UPNP
static const int fHaveUPnP = true;
#else
@@ -90,6 +92,8 @@ extern unsigned char pchMessageStart[4];
extern bool fImporting;
extern bool fReindex;
extern bool fBenchmark;
+extern int nScriptCheckThreads;
+extern bool fTxIndex;
extern unsigned int nCoinCacheSize;
// Settings
@@ -107,6 +111,7 @@ class CCoins;
class CTxUndo;
class CCoinsView;
class CCoinsViewCache;
+class CScriptCheck;
struct CBlockTemplate;
@@ -140,6 +145,10 @@ bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
/** Run the importer thread, which deals with reindexing, loading bootstrap.dat, and whatever is passed to -loadblock */
void ThreadImport(void *parg);
+/** Run an instance of the script checking thread */
+void ThreadScriptCheck(void* parg);
+/** Stop the script checking threads */
+void ThreadScriptCheckQuit();
/** Run the miner threads */
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
/** Generate a new block, without valid proof-of-work */
@@ -168,6 +177,8 @@ bool SetBestChain(CBlockIndex* pindexNew);
bool ConnectBestBlock();
/** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex(uint256 hash);
+/** Verify a signature */
+bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
@@ -186,9 +197,8 @@ static inline std::string BlockHashStr(const uint256& hash)
bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
-class CDiskBlockPos
+struct CDiskBlockPos
{
-public:
int nFile;
unsigned int nPos;
@@ -218,7 +228,27 @@ public:
bool IsNull() const { return (nFile == -1); }
};
+struct CDiskTxPos : public CDiskBlockPos
+{
+ unsigned int nTxOffset; // after header
+
+ IMPLEMENT_SERIALIZE(
+ READWRITE(*(CDiskBlockPos*)this);
+ READWRITE(VARINT(nTxOffset));
+ )
+ CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
+ }
+
+ CDiskTxPos() {
+ SetNull();
+ }
+
+ void SetNull() {
+ CDiskBlockPos::SetNull();
+ nTxOffset = 0;
+ }
+};
/** An inpoint - a combination of a transaction and an index n into its vin */
@@ -432,14 +462,6 @@ enum GetMinFee_mode
GMF_SEND,
};
-// Modes for script/signature checking
-enum CheckSig_mode
-{
- CS_NEVER, // never validate scripts
- CS_AFTER_CHECKPOINT, // validate scripts after the last checkpoint
- CS_ALWAYS // always validate scripts
-};
-
/** The basic transaction that is broadcasted on the network and contained in
* blocks. A transaction can contain multiple inputs and outputs.
*/
@@ -639,8 +661,11 @@ public:
bool HaveInputs(CCoinsViewCache &view) const;
// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
- // This does not modify the UTXO set
- bool CheckInputs(CCoinsViewCache &view, enum CheckSig_mode csmode, unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC) const;
+ // 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(CCoinsViewCache &view, bool fScriptChecks = true,
+ unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC,
+ std::vector<CScriptCheck> *pvChecks = NULL) const;
// Apply the effects of this transaction on the UTXO set represented by view
bool UpdateCoins(CCoinsViewCache &view, CTxUndo &txundo, int nHeight, const uint256 &txhash) const;
@@ -1056,7 +1081,33 @@ public:
}
};
+/** Closure representing one script verification
+ * Note that this stores references to the spending transaction */
+class CScriptCheck
+{
+private:
+ CScript scriptPubKey;
+ const CTransaction *ptxTo;
+ unsigned int nIn;
+ unsigned int nFlags;
+ int nHashType;
+
+public:
+ CScriptCheck() {}
+ CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, int nHashTypeIn) :
+ scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
+ ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), nHashType(nHashTypeIn) { }
+ bool operator()() const;
+
+ void swap(CScriptCheck &check) {
+ scriptPubKey.swap(check.scriptPubKey);
+ std::swap(ptxTo, check.ptxTo);
+ std::swap(nIn, check.nIn);
+ std::swap(nFlags, check.nFlags);
+ std::swap(nHashType, check.nHashType);
+ }
+};
/** A transaction with a merkle branch linking it to the block chain. */
class CMerkleTx : public CTransaction
@@ -1110,11 +1161,101 @@ public:
+/** 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
+ IMPLEMENT_SERIALIZE(
+ READWRITE(nTransactions);
+ READWRITE(vHash);
+ std::vector<unsigned char> vBytes;
+ if (fRead) {
+ 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);
+};
/** Nodes collect new transactions into a block, hash them into a hash tree,
@@ -1218,6 +1359,18 @@ public:
nDoS = 0;
}
+ CBlockHeader GetBlockHeader() const
+ {
+ CBlockHeader block;
+ block.nVersion = nVersion;
+ block.hashPrevBlock = hashPrevBlock;
+ block.hashMerkleRoot = hashMerkleRoot;
+ block.nTime = nTime;
+ block.nBits = nBits;
+ block.nNonce = nNonce;
+ return block;
+ }
+
uint256 BuildMerkleTree() const
{
vMerkleTree.clear();
@@ -2027,4 +2180,36 @@ struct CBlockTemplate
std::vector<int64_t> vTxSigOps;
};
+
+
+
+
+
+/** 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);
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(header);
+ READWRITE(txn);
+ )
+};
+
#endif