diff --git a/src/arith_uint256.h b/src/arith_uint256.h index e4624ea10..df5db1bc2 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -1,304 +1,304 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_ARITH_UINT256_H #define BITCOIN_ARITH_UINT256_H #include #include #include #include #include #include class uint256; class uint_error : public std::runtime_error { public: explicit uint_error(const std::string &str) : std::runtime_error(str) {} }; /** Template base class for unsigned big integers. */ template class base_uint { protected: - enum { WIDTH = BITS / 32 }; + static constexpr int WIDTH = BITS / 32; uint32_t pn[WIDTH]; public: base_uint() { for (int i = 0; i < WIDTH; i++) pn[i] = 0; } base_uint(const base_uint &b) { for (int i = 0; i < WIDTH; i++) pn[i] = b.pn[i]; } base_uint &operator=(const base_uint &b) { for (int i = 0; i < WIDTH; i++) pn[i] = b.pn[i]; return *this; } base_uint(uint64_t b) { pn[0] = (unsigned int)b; pn[1] = (unsigned int)(b >> 32); for (int i = 2; i < WIDTH; i++) pn[i] = 0; } explicit base_uint(const std::string &str); bool operator!() const { for (int i = 0; i < WIDTH; i++) if (pn[i] != 0) return false; return true; } const base_uint operator~() const { base_uint ret; for (int i = 0; i < WIDTH; i++) ret.pn[i] = ~pn[i]; return ret; } const base_uint operator-() const { base_uint ret; for (int i = 0; i < WIDTH; i++) ret.pn[i] = ~pn[i]; ret++; return ret; } double getdouble() const; base_uint &operator=(uint64_t b) { pn[0] = (unsigned int)b; pn[1] = (unsigned int)(b >> 32); for (int i = 2; i < WIDTH; i++) pn[i] = 0; return *this; } base_uint &operator^=(const base_uint &b) { for (int i = 0; i < WIDTH; i++) pn[i] ^= b.pn[i]; return *this; } base_uint &operator&=(const base_uint &b) { for (int i = 0; i < WIDTH; i++) pn[i] &= b.pn[i]; return *this; } base_uint &operator|=(const base_uint &b) { for (int i = 0; i < WIDTH; i++) pn[i] |= b.pn[i]; return *this; } base_uint &operator^=(uint64_t b) { pn[0] ^= (unsigned int)b; pn[1] ^= (unsigned int)(b >> 32); return *this; } base_uint &operator|=(uint64_t b) { pn[0] |= (unsigned int)b; pn[1] |= (unsigned int)(b >> 32); return *this; } base_uint &operator<<=(unsigned int shift); base_uint &operator>>=(unsigned int shift); base_uint &operator+=(const base_uint &b) { uint64_t carry = 0; for (int i = 0; i < WIDTH; i++) { uint64_t n = carry + pn[i] + b.pn[i]; pn[i] = n & 0xffffffff; carry = n >> 32; } return *this; } base_uint &operator-=(const base_uint &b) { *this += -b; return *this; } base_uint &operator+=(uint64_t b64) { base_uint b; b = b64; *this += b; return *this; } base_uint &operator-=(uint64_t b64) { base_uint b; b = b64; *this += -b; return *this; } base_uint &operator*=(uint32_t b32); base_uint &operator*=(const base_uint &b); base_uint &operator/=(const base_uint &b); base_uint &operator++() { // prefix operator int i = 0; while (++pn[i] == 0 && i < WIDTH - 1) i++; return *this; } const base_uint operator++(int) { // postfix operator const base_uint ret = *this; ++(*this); return ret; } base_uint &operator--() { // prefix operator int i = 0; while (--pn[i] == (uint32_t)-1 && i < WIDTH - 1) i++; return *this; } const base_uint operator--(int) { // postfix operator const base_uint ret = *this; --(*this); return ret; } int CompareTo(const base_uint &b) const; bool EqualTo(uint64_t b) const; friend inline const base_uint operator+(const base_uint &a, const base_uint &b) { return base_uint(a) += b; } friend inline const base_uint operator-(const base_uint &a, const base_uint &b) { return base_uint(a) -= b; } friend inline const base_uint operator*(const base_uint &a, const base_uint &b) { return base_uint(a) *= b; } friend inline const base_uint operator/(const base_uint &a, const base_uint &b) { return base_uint(a) /= b; } friend inline const base_uint operator|(const base_uint &a, const base_uint &b) { return base_uint(a) |= b; } friend inline const base_uint operator&(const base_uint &a, const base_uint &b) { return base_uint(a) &= b; } friend inline const base_uint operator^(const base_uint &a, const base_uint &b) { return base_uint(a) ^= b; } friend inline const base_uint operator>>(const base_uint &a, int shift) { return base_uint(a) >>= shift; } friend inline const base_uint operator<<(const base_uint &a, int shift) { return base_uint(a) <<= shift; } friend inline const base_uint operator*(const base_uint &a, uint32_t b) { return base_uint(a) *= b; } friend inline bool operator==(const base_uint &a, const base_uint &b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) == 0; } friend inline bool operator!=(const base_uint &a, const base_uint &b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) != 0; } friend inline bool operator>(const base_uint &a, const base_uint &b) { return a.CompareTo(b) > 0; } friend inline bool operator<(const base_uint &a, const base_uint &b) { return a.CompareTo(b) < 0; } friend inline bool operator>=(const base_uint &a, const base_uint &b) { return a.CompareTo(b) >= 0; } friend inline bool operator<=(const base_uint &a, const base_uint &b) { return a.CompareTo(b) <= 0; } friend inline bool operator==(const base_uint &a, uint64_t b) { return a.EqualTo(b); } friend inline bool operator!=(const base_uint &a, uint64_t b) { return !a.EqualTo(b); } std::string GetHex() const; void SetHex(const char *psz); void SetHex(const std::string &str); std::string ToString() const; unsigned int size() const { return sizeof(pn); } /** * Returns the position of the highest bit set plus one, or zero if the * value is zero. */ unsigned int bits() const; uint64_t GetLow64() const { static_assert(WIDTH >= 2, "Assertion WIDTH >= 2 failed (WIDTH = BITS / " "32). BITS is a template parameter."); return pn[0] | (uint64_t)pn[1] << 32; } }; /** 256-bit unsigned big integer. */ class arith_uint256 : public base_uint<256> { public: arith_uint256() {} arith_uint256(const base_uint<256> &b) : base_uint<256>(b) {} arith_uint256(uint64_t b) : base_uint<256>(b) {} explicit arith_uint256(const std::string &str) : base_uint<256>(str) {} /** * The "compact" format is a representation of a whole number N using an * unsigned 32bit number similar to a floating point format. * The most significant 8 bits are the unsigned exponent of base 256. * This exponent can be thought of as "number of bytes of N". * The lower 23 bits are the mantissa. * Bit number 24 (0x800000) represents the sign of N. * N = (-1^sign) * mantissa * 256^(exponent-3) * * Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). * MPI uses the most significant bit of the first byte as sign. * Thus 0x1234560000 is compact (0x05123456) * and 0xc0de000000 is compact (0x0600c0de) * * Bitcoin only uses this "compact" format for encoding difficulty targets, * which are unsigned 256bit quantities. Thus, all the complexities of the * sign bit and using base 256 are probably an implementation accident. */ arith_uint256 &SetCompact(uint32_t nCompact, bool *pfNegative = nullptr, bool *pfOverflow = nullptr); uint32_t GetCompact(bool fNegative = false) const; friend uint256 ArithToUint256(const arith_uint256 &); friend arith_uint256 UintToArith256(const uint256 &); }; uint256 ArithToUint256(const arith_uint256 &); arith_uint256 UintToArith256(const uint256 &); #endif // BITCOIN_ARITH_UINT256_H diff --git a/src/chain.h b/src/chain.h index 91f6c407e..2cc6dca38 100644 --- a/src/chain.h +++ b/src/chain.h @@ -1,411 +1,411 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CHAIN_H #define BITCOIN_CHAIN_H #include "arith_uint256.h" #include "blockstatus.h" #include "blockvalidity.h" #include "consensus/params.h" #include "diskblockpos.h" #include "pow.h" #include "primitives/block.h" #include "tinyformat.h" #include "uint256.h" #include #include /** * Maximum amount of time that a block timestamp is allowed to exceed the * current network-adjusted time before the block will be accepted. */ static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60; /** * Timestamp window used as a grace period by code that compares external * timestamps (such as timestamps passed to RPCs, or wallet key creation times) * to block timestamps. This should be set at least as high as * MAX_FUTURE_BLOCK_TIME. */ static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME; /** * The block chain is a tree shaped structure starting with the genesis block at * the root, with each block potentially having multiple candidates to be the * next block. A blockindex may have multiple pprev pointing to it, but at most * one of them can be part of the currently active branch. */ class CBlockIndex { public: //! pointer to the hash of the block, if any. Memory is owned by this //! CBlockIndex const uint256 *phashBlock; //! pointer to the index of the predecessor of this block CBlockIndex *pprev; //! pointer to the index of some further predecessor of this block CBlockIndex *pskip; //! height of the entry in the chain. The genesis block has height 0 int nHeight; //! Which # file this block is stored in (blk?????.dat) int nFile; //! Byte offset within blk?????.dat where this block's data is stored unsigned int nDataPos; //! Byte offset within rev?????.dat where this block's undo data is stored unsigned int nUndoPos; //! (memory only) Total amount of work (expected number of hashes) in the //! chain up to and including this block arith_uint256 nChainWork; //! Number of transactions in this block. //! Note: in a potential headers-first mode, this number cannot be relied //! upon unsigned int nTx; //! (memory only) Number of transactions in the chain up to and including //! this block. //! This value will be non-zero only if and only if transactions for this //! block and all its parents are available. Change to 64-bit type when //! necessary; won't happen before 2030 unsigned int nChainTx; //! Verification status of this block. See enum BlockStatus BlockStatus nStatus; //! block header int32_t nVersion; uint256 hashMerkleRoot; uint32_t nTime; uint32_t nBits; uint32_t nNonce; //! (memory only) Sequential id assigned to distinguish order in which //! blocks are received. int32_t nSequenceId; //! (memory only) block header metadata uint64_t nTimeReceived; //! (memory only) Maximum nTime in the chain upto and including this block. unsigned int nTimeMax; void SetNull() { phashBlock = nullptr; pprev = nullptr; pskip = nullptr; nHeight = 0; nFile = 0; nDataPos = 0; nUndoPos = 0; nChainWork = arith_uint256(); nTx = 0; nChainTx = 0; nStatus = BlockStatus(); nSequenceId = 0; nTimeMax = 0; nVersion = 0; hashMerkleRoot = uint256(); nTime = 0; nTimeReceived = 0; nBits = 0; nNonce = 0; } CBlockIndex() { SetNull(); } explicit CBlockIndex(const CBlockHeader &block) { SetNull(); nVersion = block.nVersion; hashMerkleRoot = block.hashMerkleRoot; nTime = block.nTime; nTimeReceived = 0; nBits = block.nBits; nNonce = block.nNonce; } CDiskBlockPos GetBlockPos() const { CDiskBlockPos ret; if (nStatus.hasData()) { ret.nFile = nFile; ret.nPos = nDataPos; } return ret; } CDiskBlockPos GetUndoPos() const { CDiskBlockPos ret; if (nStatus.hasUndo()) { ret.nFile = nFile; ret.nPos = nUndoPos; } return ret; } CBlockHeader GetBlockHeader() const { CBlockHeader block; block.nVersion = nVersion; if (pprev) { block.hashPrevBlock = pprev->GetBlockHash(); } block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; return block; } uint256 GetBlockHash() const { return *phashBlock; } int64_t GetBlockTime() const { return int64_t(nTime); } int64_t GetBlockTimeMax() const { return int64_t(nTimeMax); } int64_t GetHeaderReceivedTime() const { return nTimeReceived; } int64_t GetReceivedTimeDiff() const { return GetHeaderReceivedTime() - GetBlockTime(); } - enum { nMedianTimeSpan = 11 }; + static constexpr int nMedianTimeSpan = 11; int64_t GetMedianTimePast() const { int64_t pmedian[nMedianTimeSpan]; int64_t *pbegin = &pmedian[nMedianTimeSpan]; int64_t *pend = &pmedian[nMedianTimeSpan]; const CBlockIndex *pindex = this; for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev) { *(--pbegin) = pindex->GetBlockTime(); } std::sort(pbegin, pend); return pbegin[(pend - pbegin) / 2]; } std::string ToString() const { return strprintf( "CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", pprev, nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString()); } //! Check whether this block index entry is valid up to the passed validity //! level. bool IsValid(enum BlockValidity nUpTo = BlockValidity::TRANSACTIONS) const { return nStatus.isValid(nUpTo); } //! Raise the validity level of this block index entry. //! Returns true if the validity was changed. bool RaiseValidity(enum BlockValidity nUpTo) { // Only validity flags allowed. if (nStatus.isInvalid()) { return false; } if (nStatus.getValidity() >= nUpTo) { return false; } nStatus = nStatus.withValidity(nUpTo); return true; } //! Build the skiplist pointer for this entry. void BuildSkip(); //! Efficiently find an ancestor of this block. CBlockIndex *GetAncestor(int height); const CBlockIndex *GetAncestor(int height) const; }; /** * Maintain a map of CBlockIndex for all known headers. */ struct BlockHasher { size_t operator()(const uint256 &hash) const { return hash.GetCheapHash(); } }; typedef std::unordered_map BlockMap; extern BlockMap mapBlockIndex; arith_uint256 GetBlockProof(const CBlockIndex &block); /** * Return the time it would take to redo the work difference between from and * to, assuming the current hashrate corresponds to the difficulty at tip, in * seconds. */ int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params &); /** * Find the forking point between two chain tips. */ const CBlockIndex *LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb); /** * Check if two block index are on the same fork. */ bool AreOnTheSameFork(const CBlockIndex *pa, const CBlockIndex *pb); /** Used to marshal pointers into hashes for db storage. */ class CDiskBlockIndex : public CBlockIndex { public: uint256 hashPrev; CDiskBlockIndex() { hashPrev = uint256(); } explicit CDiskBlockIndex(const CBlockIndex *pindex) : CBlockIndex(*pindex) { hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); } ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream &s, Operation ser_action) { int _nVersion = s.GetVersion(); if (!(s.GetType() & SER_GETHASH)) { READWRITE(VARINT(_nVersion)); } READWRITE(VARINT(nHeight)); READWRITE(nStatus); READWRITE(VARINT(nTx)); if (nStatus.hasData() || nStatus.hasUndo()) { READWRITE(VARINT(nFile)); } if (nStatus.hasData()) { READWRITE(VARINT(nDataPos)); } if (nStatus.hasUndo()) { READWRITE(VARINT(nUndoPos)); } // block header READWRITE(this->nVersion); READWRITE(hashPrev); READWRITE(hashMerkleRoot); READWRITE(nTime); READWRITE(nBits); READWRITE(nNonce); } uint256 GetBlockHash() const { CBlockHeader block; block.nVersion = nVersion; block.hashPrevBlock = hashPrev; block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; return block.GetHash(); } std::string ToString() const { std::string str = "CDiskBlockIndex("; str += CBlockIndex::ToString(); str += strprintf("\n hashBlock=%s, hashPrev=%s)", GetBlockHash().ToString(), hashPrev.ToString()); return str; } }; /** * An in-memory indexed chain of blocks. */ class CChain { private: std::vector vChain; public: /** * Returns the index entry for the genesis block of this chain, or nullptr * if none. */ CBlockIndex *Genesis() const { return vChain.size() > 0 ? vChain[0] : nullptr; } /** * Returns the index entry for the tip of this chain, or nullptr if none. */ CBlockIndex *Tip() const { return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr; } /** * Returns the index entry at a particular height in this chain, or nullptr * if no such height exists. */ CBlockIndex *operator[](int nHeight) const { if (nHeight < 0 || nHeight >= (int)vChain.size()) { return nullptr; } return vChain[nHeight]; } /** Compare two chains efficiently. */ friend bool operator==(const CChain &a, const CChain &b) { return a.vChain.size() == b.vChain.size() && a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1]; } /** Efficiently check whether a block is present in this chain. */ bool Contains(const CBlockIndex *pindex) const { return (*this)[pindex->nHeight] == pindex; } /** * Find the successor of a block in this chain, or nullptr if the given * index is not found or is the tip. */ CBlockIndex *Next(const CBlockIndex *pindex) const { if (!Contains(pindex)) { return nullptr; } return (*this)[pindex->nHeight + 1]; } /** * Return the maximal height in the chain. Is equal to chain.Tip() ? * chain.Tip()->nHeight : -1. */ int Height() const { return vChain.size() - 1; } /** Set/initialize a chain with a given tip. */ void SetTip(CBlockIndex *pindex); /** * Return a CBlockLocator that refers to a block in this chain (by default * the tip). */ CBlockLocator GetLocator(const CBlockIndex *pindex = nullptr) const; /** * Find the last common block between this chain and a block index entry. */ const CBlockIndex *FindFork(const CBlockIndex *pindex) const; /** * Find the earliest block with timestamp equal or greater than the given. */ CBlockIndex *FindEarliestAtLeast(int64_t nTime) const; }; #endif // BITCOIN_CHAIN_H diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 8667105a1..48c4f8d90 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -1,58 +1,55 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CONSENSUS_CONSENSUS_H #define BITCOIN_CONSENSUS_CONSENSUS_H #include /** 1MB */ static const uint64_t ONE_MEGABYTE = 1000000; /** The maximum allowed size for a transaction, in bytes */ static const uint64_t MAX_TX_SIZE = ONE_MEGABYTE; /** The minimum allowed size for a transaction, in bytes */ static const uint64_t MIN_TX_SIZE = 100; /** The maximum allowed size for a block, before the UAHF */ static const uint64_t LEGACY_MAX_BLOCK_SIZE = ONE_MEGABYTE; /** Default setting for maximum allowed size for a block, in bytes */ static const uint64_t DEFAULT_MAX_BLOCK_SIZE = 32 * ONE_MEGABYTE; /** * The maximum allowed number of signature check operations per MB in a block * (network rule). */ static const int64_t MAX_BLOCK_SIGOPS_PER_MB = 20000; /** allowed number of signature check operations per transaction. */ static const uint64_t MAX_TX_SIGOPS_COUNT = 20000; /** * Coinbase transaction outputs can only be spent after this number of new * blocks (network rule). */ static const int COINBASE_MATURITY = 100; /** Coinbase scripts have their own script size limit. */ static const int MAX_COINBASE_SCRIPTSIG_SIZE = 100; /** Activation time for P2SH (April 1st 2012) */ static const int64_t P2SH_ACTIVATION_TIME = 1333234914; /** Flags for nSequence and nLockTime locks */ -enum { - /* Interpret sequence numbers as relative lock-time constraints. */ - LOCKTIME_VERIFY_SEQUENCE = (1 << 0), - - /* Use GetMedianTimePast() instead of nTime for end point timestamp. */ - LOCKTIME_MEDIAN_TIME_PAST = (1 << 1), -}; +/** Interpret sequence numbers as relative lock-time constraints. */ +static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE = (1 << 0); +/** Use GetMedianTimePast() instead of nTime for end point timestamp. */ +static constexpr unsigned int LOCKTIME_MEDIAN_TIME_PAST = (1 << 1); /** * Compute the maximum number of sigops operation that can contained in a block * given the block size as parameter. It is computed by multiplying * MAX_BLOCK_SIGOPS_PER_MB by the size of the block in MB rounded up to the * closest integer. */ inline uint64_t GetMaxBlockSigOpsCount(uint64_t blockSize) { auto nMbRoundedUp = 1 + ((blockSize - 1) / ONE_MEGABYTE); return nMbRoundedUp * MAX_BLOCK_SIGOPS_PER_MB; } #endif // BITCOIN_CONSENSUS_CONSENSUS_H diff --git a/src/protocol.h b/src/protocol.h index 642acc6f0..d86bdfa8f 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,470 +1,469 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef __cplusplus #error This header can only be compiled as C++. #endif #ifndef BITCOIN_PROTOCOL_H #define BITCOIN_PROTOCOL_H #include "netaddress.h" #include "serialize.h" #include "uint256.h" #include "version.h" #include #include #include class Config; /** * Maximum length of incoming protocol messages (Currently 2MB). * NB: Messages propagating block content are not subject to this limit. */ static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024; /** * Message header. * (4) message start. * (12) command. * (4) size. * (4) checksum. */ class CMessageHeader { public: - enum { - MESSAGE_START_SIZE = 4, - COMMAND_SIZE = 12, - MESSAGE_SIZE_SIZE = 4, - CHECKSUM_SIZE = 4, - - MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE, - CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE, - HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + - CHECKSUM_SIZE - }; + static constexpr size_t MESSAGE_START_SIZE = 4; + static constexpr size_t COMMAND_SIZE = 12; + static constexpr size_t MESSAGE_SIZE_SIZE = 4; + static constexpr size_t CHECKSUM_SIZE = 4; + static constexpr size_t MESSAGE_SIZE_OFFSET = + MESSAGE_START_SIZE + COMMAND_SIZE; + static constexpr size_t CHECKSUM_OFFSET = + MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE; + static constexpr size_t HEADER_SIZE = + MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE; typedef std::array MessageMagic; explicit CMessageHeader(const MessageMagic &pchMessageStartIn); CMessageHeader(const MessageMagic &pchMessageStartIn, const char *pszCommand, unsigned int nMessageSizeIn); std::string GetCommand() const; bool IsValid(const Config &config) const; bool IsValidWithoutConfig(const MessageMagic &magic) const; bool IsOversized(const Config &config) const; ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream &s, Operation ser_action) { READWRITE(FLATDATA(pchMessageStart)); READWRITE(FLATDATA(pchCommand)); READWRITE(nMessageSize); READWRITE(FLATDATA(pchChecksum)); } MessageMagic pchMessageStart; std::array pchCommand; uint32_t nMessageSize; uint8_t pchChecksum[CHECKSUM_SIZE]; }; /** * Bitcoin protocol message types. When adding new message types, don't forget * to update allNetMessageTypes in protocol.cpp. */ namespace NetMsgType { /** * The version message provides information about the transmitting node to the * receiving node at the beginning of a connection. * @see https://bitcoin.org/en/developer-reference#version */ extern const char *VERSION; /** * The verack message acknowledges a previously-received version message, * informing the connecting node that it can begin to send other messages. * @see https://bitcoin.org/en/developer-reference#verack */ extern const char *VERACK; /** * The addr (IP address) message relays connection information for peers on the * network. * @see https://bitcoin.org/en/developer-reference#addr */ extern const char *ADDR; /** * The inv message (inventory message) transmits one or more inventories of * objects known to the transmitting peer. * @see https://bitcoin.org/en/developer-reference#inv */ extern const char *INV; /** * The getdata message requests one or more data objects from another node. * @see https://bitcoin.org/en/developer-reference#getdata */ extern const char *GETDATA; /** * The merkleblock message is a reply to a getdata message which requested a * block using the inventory type MSG_MERKLEBLOCK. * @since protocol version 70001 as described by BIP37. * @see https://bitcoin.org/en/developer-reference#merkleblock */ extern const char *MERKLEBLOCK; /** * The getblocks message requests an inv message that provides block header * hashes starting from a particular point in the block chain. * @see https://bitcoin.org/en/developer-reference#getblocks */ extern const char *GETBLOCKS; /** * The getheaders message requests a headers message that provides block * headers starting from a particular point in the block chain. * @since protocol version 31800. * @see https://bitcoin.org/en/developer-reference#getheaders */ extern const char *GETHEADERS; /** * The tx message transmits a single transaction. * @see https://bitcoin.org/en/developer-reference#tx */ extern const char *TX; /** * The headers message sends one or more block headers to a node which * previously requested certain headers with a getheaders message. * @since protocol version 31800. * @see https://bitcoin.org/en/developer-reference#headers */ extern const char *HEADERS; /** * The block message transmits a single serialized block. * @see https://bitcoin.org/en/developer-reference#block */ extern const char *BLOCK; /** * The getaddr message requests an addr message from the receiving node, * preferably one with lots of IP addresses of other receiving nodes. * @see https://bitcoin.org/en/developer-reference#getaddr */ extern const char *GETADDR; /** * The mempool message requests the TXIDs of transactions that the receiving * node has verified as valid but which have not yet appeared in a block. * @since protocol version 60002. * @see https://bitcoin.org/en/developer-reference#mempool */ extern const char *MEMPOOL; /** * The ping message is sent periodically to help confirm that the receiving * peer is still connected. * @see https://bitcoin.org/en/developer-reference#ping */ extern const char *PING; /** * The pong message replies to a ping message, proving to the pinging node that * the ponging node is still alive. * @since protocol version 60001 as described by BIP31. * @see https://bitcoin.org/en/developer-reference#pong */ extern const char *PONG; /** * The notfound message is a reply to a getdata message which requested an * object the receiving node does not have available for relay. * @ince protocol version 70001. * @see https://bitcoin.org/en/developer-reference#notfound */ extern const char *NOTFOUND; /** * The filterload message tells the receiving peer to filter all relayed * transactions and requested merkle blocks through the provided filter. * @since protocol version 70001 as described by BIP37. * Only available with service bit NODE_BLOOM since protocol version * 70011 as described by BIP111. * @see https://bitcoin.org/en/developer-reference#filterload */ extern const char *FILTERLOAD; /** * The filteradd message tells the receiving peer to add a single element to a * previously-set bloom filter, such as a new public key. * @since protocol version 70001 as described by BIP37. * Only available with service bit NODE_BLOOM since protocol version * 70011 as described by BIP111. * @see https://bitcoin.org/en/developer-reference#filteradd */ extern const char *FILTERADD; /** * The filterclear message tells the receiving peer to remove a previously-set * bloom filter. * @since protocol version 70001 as described by BIP37. * Only available with service bit NODE_BLOOM since protocol version * 70011 as described by BIP111. * @see https://bitcoin.org/en/developer-reference#filterclear */ extern const char *FILTERCLEAR; /** * The reject message informs the receiving node that one of its previous * messages has been rejected. * @since protocol version 70002 as described by BIP61. * @see https://bitcoin.org/en/developer-reference#reject */ extern const char *REJECT; /** * Indicates that a node prefers to receive new block announcements via a * "headers" message rather than an "inv". * @since protocol version 70012 as described by BIP130. * @see https://bitcoin.org/en/developer-reference#sendheaders */ extern const char *SENDHEADERS; /** * The feefilter message tells the receiving peer not to inv us any txs * which do not meet the specified min fee rate. * @since protocol version 70013 as described by BIP133 */ extern const char *FEEFILTER; /** * Contains a 1-byte bool and 8-byte LE version number. * Indicates that a node is willing to provide blocks via "cmpctblock" messages. * May indicate that a node prefers to receive new block announcements via a * "cmpctblock" message rather than an "inv", depending on message contents. * @since protocol version 70014 as described by BIP 152 */ extern const char *SENDCMPCT; /** * Contains a CBlockHeaderAndShortTxIDs object - providing a header and * list of "short txids". * @since protocol version 70014 as described by BIP 152 */ extern const char *CMPCTBLOCK; /** * Contains a BlockTransactionsRequest * Peer should respond with "blocktxn" message. * @since protocol version 70014 as described by BIP 152 */ extern const char *GETBLOCKTXN; /** * Contains a BlockTransactions. * Sent in response to a "getblocktxn" message. * @since protocol version 70014 as described by BIP 152 */ extern const char *BLOCKTXN; /** * Contains an AvalanchePoll. * Peer should respond with "avaresponse" message. */ extern const char *AVAPOLL; /** * Contains an AvalancheResponse. * Sent in response to a "avapoll" message. */ extern const char *AVARESPONSE; /** * Indicate if the message is used to transmit the content of a block. * These messages can be significantly larger than usual messages and therefore * may need to be processed differently. */ bool IsBlockLike(const std::string &strCommand); }; // namespace NetMsgType /* Get a vector of all valid message types (see above) */ const std::vector &getAllNetMessageTypes(); /** * nServices flags. */ enum ServiceFlags : uint64_t { // Nothing NODE_NONE = 0, // NODE_NETWORK means that the node is capable of serving the complete block // chain. It is currently set by all Bitcoin ABC non pruned nodes, and is // unset by SPV clients or other light clients. NODE_NETWORK = (1 << 0), // NODE_GETUTXO means the node is capable of responding to the getutxo // protocol request. Bitcoin ABC does not support this but a patch set // called Bitcoin XT does. See BIP 64 for details on how this is // implemented. NODE_GETUTXO = (1 << 1), // NODE_BLOOM means the node is capable and willing to handle bloom-filtered // connections. Bitcoin ABC nodes used to support this by default, without // advertising this bit, but no longer do as of protocol version 70011 (= // NO_BLOOM_VERSION) NODE_BLOOM = (1 << 2), // NODE_XTHIN means the node supports Xtreme Thinblocks. If this is turned // off then the node will not service nor make xthin requests. NODE_XTHIN = (1 << 4), // NODE_BITCOIN_CASH means the node supports Bitcoin Cash and the // associated consensus rule changes. // This service bit is intended to be used prior until some time after the // UAHF activation when the Bitcoin Cash network has adequately separated. // TODO: remove (free up) the NODE_BITCOIN_CASH service bit once no longer // needed. NODE_BITCOIN_CASH = (1 << 5), // NODE_NETWORK_LIMITED means the same as NODE_NETWORK with the limitation // of only serving the last 288 (2 day) blocks // See BIP159 for details on how this is implemented. NODE_NETWORK_LIMITED = (1 << 10), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the // bitcoin-development mailing list. Remember that service bits are just // unauthenticated advertisements, so your code must be robust against // collisions and other cases where nodes may be advertising a service they // do not actually support. Other service bits should be allocated via the // BIP process. // NODE_AVALANCHE means the node supports Bitcoin Cash's avalanche // preconsensus mechanism. NODE_AVALANCHE = (1 << 24), }; /** * Gets the set of service flags which are "desirable" for a given peer. * * These are the flags which are required for a peer to support for them * to be "interesting" to us, ie for us to wish to use one of our few * outbound connection slots for or for us to wish to prioritize keeping * their connection around. * * Relevant service flags may be peer- and state-specific in that the * version of the peer may determine which flags are required (eg in the * case of NODE_NETWORK_LIMITED where we seek out NODE_NETWORK peers * unless they set NODE_NETWORK_LIMITED and we are out of IBD, in which * case NODE_NETWORK_LIMITED suffices). * * Thus, generally, avoid calling with peerServices == NODE_NONE, unless * state-specific flags must absolutely be avoided. When called with * peerServices == NODE_NONE, the returned desirable service flags are * guaranteed to not change dependant on state - ie they are suitable for * use when describing peers which we know to be desirable, but for which * we do not have a confirmed set of service flags. * * If the NODE_NONE return value is changed, contrib/seeds/makeseeds.py * should be updated appropriately to filter for the same nodes. */ ServiceFlags GetDesirableServiceFlags(ServiceFlags services); /** * Set the current IBD status in order to figure out the desirable service * flags */ void SetServiceFlagsIBDCache(bool status); /** * A shortcut for (services & GetDesirableServiceFlags(services)) * == GetDesirableServiceFlags(services), ie determines whether the given * set of service flags are sufficient for a peer to be "relevant". */ static inline bool HasAllDesirableServiceFlags(ServiceFlags services) { return !(GetDesirableServiceFlags(services) & (~services)); } /** * Checks if a peer with the given service flags may be capable of having a * robust address-storage DB. */ static inline bool MayHaveUsefulAddressDB(ServiceFlags services) { return (services & NODE_NETWORK) || (services & NODE_NETWORK_LIMITED); } /** * A CService with information about it as peer. */ class CAddress : public CService { public: CAddress(); explicit CAddress(CService ipIn, ServiceFlags nServicesIn); void Init(); ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream &s, Operation ser_action) { if (ser_action.ForRead()) Init(); int nVersion = s.GetVersion(); if (s.GetType() & SER_DISK) READWRITE(nVersion); if ((s.GetType() & SER_DISK) || (nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH))) READWRITE(nTime); uint64_t nServicesInt = nServices; READWRITE(nServicesInt); nServices = (ServiceFlags)nServicesInt; READWRITE(*(CService *)this); } // TODO: make private (improves encapsulation) public: ServiceFlags nServices; // disk and network only unsigned int nTime; }; /** getdata message type flags */ const uint32_t MSG_TYPE_MASK = 0xffffffff >> 3; /** getdata / inv message types. * These numbers are defined by the protocol. When adding a new value, be sure * to mention it in the respective BIP. */ enum GetDataMsg { UNDEFINED = 0, MSG_TX = 1, MSG_BLOCK = 2, // The following can only occur in getdata. Invs always use TX or BLOCK. //!< Defined in BIP37 MSG_FILTERED_BLOCK = 3, //!< Defined in BIP152 MSG_CMPCT_BLOCK = 4, }; /** * Inv(ventory) message data. * Intended as non-ambiguous identifier of objects (eg. transactions, blocks) * held by peers. */ class CInv { public: // TODO: make private (improves encapsulation) uint32_t type; uint256 hash; public: CInv() : type(0), hash() {} CInv(uint32_t typeIn, const uint256 &hashIn) : type(typeIn), hash(hashIn) {} ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream &s, Operation ser_action) { READWRITE(type); READWRITE(hash); } friend bool operator<(const CInv &a, const CInv &b) { return a.type < b.type || (a.type == b.type && a.hash < b.hash); } std::string GetCommand() const; std::string ToString() const; uint32_t GetKind() const { return type & MSG_TYPE_MASK; } bool IsTx() const { auto k = GetKind(); return k == MSG_TX; } bool IsSomeBlock() const { auto k = GetKind(); return k == MSG_BLOCK || k == MSG_FILTERED_BLOCK || k == MSG_CMPCT_BLOCK; } }; #endif // BITCOIN_PROTOCOL_H diff --git a/src/uint256.h b/src/uint256.h index a1e74de82..d5e719c5c 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,173 +1,173 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_UINT256_H #define BITCOIN_UINT256_H #include "crypto/common.h" #include #include #include #include #include #include /** Template base class for fixed-sized opaque blobs. */ template class base_blob { protected: - enum { WIDTH = BITS / 8 }; + static constexpr int WIDTH = BITS / 8; uint8_t data[WIDTH]; public: base_blob() { memset(data, 0, sizeof(data)); } explicit base_blob(const std::vector &vch); bool IsNull() const { for (int i = 0; i < WIDTH; i++) { if (data[i] != 0) { return false; } } return true; } void SetNull() { memset(data, 0, sizeof(data)); } inline int Compare(const base_blob &other) const { for (size_t i = 0; i < sizeof(data); i++) { uint8_t a = data[sizeof(data) - 1 - i]; uint8_t b = other.data[sizeof(data) - 1 - i]; if (a > b) { return 1; } if (a < b) { return -1; } } return 0; } friend inline bool operator==(const base_blob &a, const base_blob &b) { return a.Compare(b) == 0; } friend inline bool operator!=(const base_blob &a, const base_blob &b) { return a.Compare(b) != 0; } friend inline bool operator<(const base_blob &a, const base_blob &b) { return a.Compare(b) < 0; } friend inline bool operator<=(const base_blob &a, const base_blob &b) { return a.Compare(b) <= 0; } friend inline bool operator>(const base_blob &a, const base_blob &b) { return a.Compare(b) > 0; } friend inline bool operator>=(const base_blob &a, const base_blob &b) { return a.Compare(b) >= 0; } std::string GetHex() const; void SetHex(const char *psz); void SetHex(const std::string &str); std::string ToString() const { return GetHex(); } uint8_t *begin() { return &data[0]; } uint8_t *end() { return &data[WIDTH]; } const uint8_t *begin() const { return &data[0]; } const uint8_t *end() const { return &data[WIDTH]; } unsigned int size() const { return sizeof(data); } uint64_t GetUint64(int pos) const { const uint8_t *ptr = data + pos * 8; return uint64_t(ptr[0]) | (uint64_t(ptr[1]) << 8) | (uint64_t(ptr[2]) << 16) | (uint64_t(ptr[3]) << 24) | (uint64_t(ptr[4]) << 32) | (uint64_t(ptr[5]) << 40) | (uint64_t(ptr[6]) << 48) | (uint64_t(ptr[7]) << 56); } template void Serialize(Stream &s) const { s.write((char *)data, sizeof(data)); } template void Unserialize(Stream &s) { s.read((char *)data, sizeof(data)); } }; /** * 160-bit opaque blob. * @note This type is called uint160 for historical reasons only. It is an * opaque blob of 160 bits and has no integer operations. */ class uint160 : public base_blob<160> { public: uint160() {} explicit uint160(const base_blob<160> &b) : base_blob<160>(b) {} explicit uint160(const std::vector &vch) : base_blob<160>(vch) {} }; /** * 256-bit opaque blob. * @note This type is called uint256 for historical reasons only. It is an * opaque blob of 256 bits and has no integer operations. Use arith_uint256 if * those are required. */ class uint256 : public base_blob<256> { public: uint256() {} explicit uint256(const base_blob<256> &b) : base_blob<256>(b) {} explicit uint256(const std::vector &vch) : base_blob<256>(vch) {} /** * A cheap hash function that just returns 64 bits from the result, it can * be used when the contents are considered uniformly random. It is not * appropriate when the value can easily be influenced from outside as e.g. * a network adversary could provide values to trigger worst-case behavior. */ uint64_t GetCheapHash() const { return ReadLE64(data); } }; /** * uint256 from const char *. * This is a separate function because the constructor uint256(const char*) can * result in dangerously catching uint256(0). */ inline uint256 uint256S(const char *str) { uint256 rv; rv.SetHex(str); return rv; } /** * uint256 from std::string. * This is a separate function because the constructor uint256(const std::string * &str) can result in dangerously catching uint256(0) via std::string(const * char*). */ inline uint256 uint256S(const std::string &str) { uint256 rv; rv.SetHex(str); return rv; } inline uint160 uint160S(const char *str) { uint160 rv; rv.SetHex(str); return rv; } inline uint160 uint160S(const std::string &str) { uint160 rv; rv.SetHex(str); return rv; } #endif // BITCOIN_UINT256_H