static const unsigned int MAX_BLOCK_SIZE = 1000000;
/** The maximum size for mined blocks */
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
+/** The maximum size for transactions we're willing to relay/mine */
+static const unsigned int MAX_STANDARD_TX_SIZE = MAX_BLOCK_SIZE_GEN/5;
/** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** The maximum number of orphan transactions kept in memory */
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
extern bool fImporting;
extern bool fReindex;
extern bool fBenchmark;
+extern int nScriptCheckThreads;
+extern bool fTxIndex;
extern unsigned int nCoinCacheSize;
// Settings
class CReserveKey;
class CCoinsDB;
class CBlockTreeDB;
-class CDiskBlockPos;
+struct CDiskBlockPos;
class CCoins;
class CTxUndo;
class CCoinsView;
class CCoinsViewCache;
+class CScriptCheck;
+class CValidationState;
+
+struct CBlockTemplate;
/** Register a wallet to receive updates from core */
void RegisterWallet(CWallet* pwalletIn);
/** Push an updated transaction to all registered wallets */
void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false);
/** Process an incoming block */
-bool ProcessBlock(CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
+bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
/** Check whether enough disk space is available for an incoming block */
-bool CheckDiskSpace(uint64 nAdditionalBytes=0);
+bool CheckDiskSpace(uint64 nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
/** Open an undo file (rev?????.dat) */
FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
/** Import blocks from an external file */
bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL);
+/** Initialize a new block tree database + block data on disk */
+bool InitBlockIndex();
/** Load the block tree and coins database from disk */
bool LoadBlockIndex();
+/** Unload database information */
+void UnloadBlockIndex();
+/** Verify consistency of the block and coin databases */
+bool VerifyDB();
/** Print the loaded block tree */
void PrintBlockTree();
/** Find a block by height in the currently-connected chain */
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 */
-CBlock* CreateNewBlock(CReserveKey& reservekey);
+CBlockTemplate* CreateNewBlock(CReserveKey& reservekey);
/** Modify the extranonce in a block */
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
/** Do mining precalculation */
unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
/** Get the number of active peers */
int GetNumBlocksOfPeers();
-/** Check whether we are doin an inital block download (synchronizing from disk or network) */
+/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool IsInitialBlockDownload();
/** Format a string that describes several potential problems detected by the core */
std::string GetWarnings(std::string strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false);
/** Connect/disconnect blocks until pindexNew is the new tip of the active block chain */
-bool SetBestChain(CBlockIndex* pindexNew);
+bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew);
/** Find the best known block, and make it the tip of the block chain */
-bool ConnectBestBlock();
+bool ConnectBestBlock(CValidationState &state);
/** 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);
+/** Abort with a message */
+bool AbortNode(const std::string &msg);
bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
-class CDiskBlockPos
+struct CDiskBlockPos
{
-public:
int nFile;
unsigned int nPos;
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 */
-
enum GetMinFee_mode
{
GMF_BLOCK,
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.
+ * blocks. A transaction can contain multiple inputs and outputs.
*/
class CTransaction
{
std::vector<CTxOut> vout;
unsigned int nLockTime;
- // Denial-of-service detection:
- mutable int nDoS;
- bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
-
CTransaction()
{
SetNull();
vin.clear();
vout.clear();
nLockTime = 0;
- nDoS = 0; // Denial-of-service prevention
}
bool IsNull() const
/** 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
- @see CTransaction::FetchInputs
*/
bool AreInputsStandard(CCoinsViewCache& mapInputs) const;
/** 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;
@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(CCoinsViewCache& mapInputs) const;
@param[in] mapInputs Map of previous transactions that have outputs we're spending
@return Sum of value of all inputs (scriptSigs)
- @see CTransaction::FetchInputs
*/
int64 GetValueIn(CCoinsViewCache& mapInputs) const;
}
- // Do all possible client-mode checks
- bool ClientCheckInputs() const;
-
// Check whether all prevouts of this transaction are present in the UTXO set represented by view
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(CValidationState &state, 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;
+ bool UpdateCoins(CValidationState &state, CCoinsViewCache &view, CTxUndo &txundo, int nHeight, const uint256 &txhash) const;
// Context-independent validity checks
- bool CheckTransaction() const;
+ bool CheckTransaction(CValidationState &state) const;
// Try to accept this transaction into the memory pool
- bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
+ bool AcceptToMemoryPool(CValidationState &state, bool fCheckInputs=true, bool fLimitFree = true, bool* pfMissingInputs=NULL);
protected:
static const CTxOut &GetOutputFor(const CTxIn& input, CCoinsViewCache& mapInputs);
READWRITE(vtxundo);
)
- bool WriteToDisk(CDiskBlockPos &pos)
+ bool WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock)
{
// Open history file to append
CAutoFile fileout = CAutoFile(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
pos.nPos = (unsigned int)fileOutPos;
fileout << *this;
+ // calculate & write checksum
+ CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
+ hasher << hashBlock;
+ hasher << *this;
+ fileout << hasher.GetHash();
+
// Flush stdio buffers and commit to disk before returning
fflush(fileout);
if (!IsInitialBlockDownload())
return true;
}
+
+ bool ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock)
+ {
+ // Open history file to read
+ CAutoFile filein = CAutoFile(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
+ if (!filein)
+ return error("CBlockUndo::ReadFromDisk() : OpenBlockFile failed");
+
+ // Read block
+ uint256 hashChecksum;
+ try {
+ filein >> *this;
+ filein >> hashChecksum;
+ }
+ catch (std::exception &e) {
+ return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
+ }
+
+ // Verify checksum
+ CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
+ hasher << hashBlock;
+ hasher << *this;
+ if (hashChecksum != hasher.GetHash())
+ return error("CBlockUndo::ReadFromDisk() : checksum mismatch");
+
+ return true;
+ }
};
/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
void Cleanup() {
while (vout.size() > 0 && vout.back().IsNull())
vout.pop_back();
+ if (vout.empty())
+ std::vector<CTxOut>().swap(vout);
+ }
+
+ void swap(CCoins &to) {
+ std::swap(to.fCoinBase, fCoinBase);
+ to.vout.swap(vout);
+ std::swap(to.nHeight, nHeight);
+ std::swap(to.nVersion, nVersion);
}
// equality test
}
};
+/** 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
int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const;
- bool AcceptToMemoryPool(bool fCheckInputs=true);
+ bool AcceptToMemoryPool(bool fCheckInputs=true, bool fLimitFree=true);
};
+/** 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,
// memory only
mutable std::vector<uint256> vMerkleTree;
- // Denial-of-service detection:
- mutable int nDoS;
- bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
-
CBlock()
{
SetNull();
CBlockHeader::SetNull();
vtx.clear();
vMerkleTree.clear();
- 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
return hash;
}
-
bool WriteToDisk(CDiskBlockPos &pos)
{
// Open history file to append
}
- // Undo the effects of this block (with given index) on the UTXO set represented by coins
- bool DisconnectBlock(CBlockIndex *pindex, CCoinsViewCache &coins);
+ /** Undo the effects of this block (with given index) on the UTXO set represented by coins.
+ * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
+ * will be true if no problems were found. Otherwise, the return value will be false in case
+ * of problems. Note that in any case, coins may be modified. */
+ bool DisconnectBlock(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(CBlockIndex *pindex, CCoinsViewCache &coins, bool fJustCheck=false);
+ bool ConnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &coins, bool fJustCheck=false);
// Read a block from disk
bool ReadFromDisk(const CBlockIndex* pindex);
// Add this block to the block index, and if necessary, switch the active block chain to this
- bool AddToBlockIndex(const CDiskBlockPos &pos);
+ bool AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos);
// Context-independent validity checks
- bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true) const;
+ bool CheckBlock(CValidationState &state, bool fCheckPOW=true, bool fCheckMerkleRoot=true) const;
// Store block on disk
// if dbp is provided, the file is known to already reside on disk
- bool AcceptBlock(CDiskBlockPos *dbp = NULL);
+ bool AcceptBlock(CValidationState &state, CDiskBlockPos *dbp = NULL);
};
}
std::string ToString() const {
- return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u..%u, time=%s..%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst).c_str(), DateTimeStrFormat("%Y-%m-%d", nTimeLast).c_str());
+ return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst).c_str(), DateTimeStrFormat("%Y-%m-%d", nTimeLast).c_str());
}
// update statistics (does not update nSize)
}
};
+/** Capture information about block/transaction validation */
+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;
+ int nDoS;
+public:
+ CValidationState() : mode(MODE_VALID), nDoS(0) {}
+ bool DoS(int level, bool ret = false) {
+ if (mode == MODE_ERROR)
+ return ret;
+ nDoS += level;
+ mode = MODE_INVALID;
+ return ret;
+ }
+ bool Invalid(bool ret = false) {
+ return DoS(0, ret);
+ }
+ bool Error() {
+ mode = MODE_ERROR;
+ return false;
+ }
+ bool Abort(const std::string &msg) {
+ AbortNode(msg);
+ return Error();
+ }
+ bool IsValid() {
+ return mode == MODE_VALID;
+ }
+ bool IsInvalid() {
+ return mode == MODE_INVALID;
+ }
+ bool IsError() {
+ return mode == MODE_ERROR;
+ }
+ bool IsInvalid(int &nDoSOut) {
+ if (IsInvalid()) {
+ nDoSOut = nDoS;
+ return true;
+ }
+ return false;
+ }
+};
std::map<uint256, CTransaction> mapTx;
std::map<COutPoint, CInPoint> mapNextTx;
- bool accept(CTransaction &tx, bool fCheckInputs, bool* pfMissingInputs);
+ bool accept(CValidationState &state, CTransaction &tx, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs);
bool addUnchecked(const uint256& hash, CTransaction &tx);
bool remove(const CTransaction &tx, bool fRecursive = false);
bool removeConflicts(const CTransaction &tx);
{
public:
// Retrieve the CCoins (unspent transaction outputs) for a given txid
- virtual bool GetCoins(uint256 txid, CCoins &coins);
+ virtual bool GetCoins(const uint256 &txid, CCoins &coins);
// Modify the CCoins for a given txid
- virtual bool SetCoins(uint256 txid, const CCoins &coins);
+ virtual bool SetCoins(const uint256 &txid, const CCoins &coins);
// Just check whether we have data for a given txid.
// This may (but cannot always) return true for fully spent transactions
- virtual bool HaveCoins(uint256 txid);
+ virtual bool HaveCoins(const uint256 &txid);
// Retrieve the block index whose state this CCoinsView currently represents
virtual CBlockIndex *GetBestBlock();
public:
CCoinsViewBacked(CCoinsView &viewIn);
- bool GetCoins(uint256 txid, CCoins &coins);
- bool SetCoins(uint256 txid, const CCoins &coins);
- bool HaveCoins(uint256 txid);
+ bool GetCoins(const uint256 &txid, CCoins &coins);
+ bool SetCoins(const uint256 &txid, const CCoins &coins);
+ bool HaveCoins(const uint256 &txid);
CBlockIndex *GetBestBlock();
bool SetBestBlock(CBlockIndex *pindex);
void SetBackend(CCoinsView &viewIn);
CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false);
// Standard CCoinsView methods
- bool GetCoins(uint256 txid, CCoins &coins);
- bool SetCoins(uint256 txid, const CCoins &coins);
- bool HaveCoins(uint256 txid);
+ bool GetCoins(const uint256 &txid, CCoins &coins);
+ bool SetCoins(const uint256 &txid, const CCoins &coins);
+ bool HaveCoins(const uint256 &txid);
CBlockIndex *GetBestBlock();
bool SetBestBlock(CBlockIndex *pindex);
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
// Return a modifiable reference to a CCoins. Check HaveCoins first.
// Many methods explicitly require a CCoinsViewCache because of this method, to reduce
// copying.
- CCoins &GetCoins(uint256 txid);
+ CCoins &GetCoins(const uint256 &txid);
// Push the modifications applied to this cache to its base.
// Failure to call this method before destruction will cause the changes to be forgotten.
unsigned int GetCacheSize();
private:
- std::map<uint256,CCoins>::iterator FetchCoins(uint256 txid);
+ std::map<uint256,CCoins>::iterator FetchCoins(const uint256 &txid);
};
/** CCoinsView that brings transactions from a memorypool into view.
public:
CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn);
- bool GetCoins(uint256 txid, CCoins &coins);
- bool HaveCoins(uint256 txid);
+ bool GetCoins(const uint256 &txid, CCoins &coins);
+ bool HaveCoins(const uint256 &txid);
};
/** Global variable that points to the active CCoinsView (protected by cs_main) */
/** Global variable that points to the active block tree (protected by cs_main) */
extern CBlockTreeDB *pblocktree;
+struct CBlockTemplate
+{
+ CBlock block;
+ std::vector<int64_t> vTxFees;
+ 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