diff options
Diffstat (limited to 'src/primitives')
| -rw-r--r-- | src/primitives/block.cpp | 20 | ||||
| -rw-r--r-- | src/primitives/block.h | 67 | ||||
| -rw-r--r-- | src/primitives/pureheader.cpp | 30 | ||||
| -rw-r--r-- | src/primitives/pureheader.h | 156 |
4 files changed, 230 insertions, 43 deletions
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 4cfc576f0..1df912d35 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -6,21 +6,21 @@ #include "primitives/block.h" #include "hash.h" -#include "crypto/scrypt.h" #include "tinyformat.h" #include "utilstrencodings.h" #include "crypto/common.h" -uint256 CBlockHeader::GetHash() const +void CBlockHeader::SetAuxpow (CAuxPow* apow) { - return SerializeHash(*this); -} - -uint256 CBlockHeader::GetPoWHash() const -{ - uint256 thash; - scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash)); - return thash; + if (apow) + { + auxpow.reset(apow); + SetAuxpowFlag(true); + } else + { + auxpow.reset(); + SetAuxpowFlag(false); + } } std::string CBlock::ToString() const diff --git a/src/primitives/block.h b/src/primitives/block.h index 8b2f1de89..dcde500ab 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -6,10 +6,14 @@ #ifndef BITCOIN_PRIMITIVES_BLOCK_H #define BITCOIN_PRIMITIVES_BLOCK_H +#include "auxpow.h" #include "primitives/transaction.h" +#include "primitives/pureheader.h" #include "serialize.h" #include "uint256.h" +#include <boost/shared_ptr.hpp> + /** Nodes collect new transactions into a block, hash them into a hash tree, * and scan through nonce values to make the block's hash satisfy proof-of-work * requirements. When they solve the proof-of-work, they broadcast the block @@ -17,16 +21,11 @@ * in the block is a special one that creates a new coin owned by the creator * of the block. */ -class CBlockHeader +class CBlockHeader : public CPureBlockHeader { public: - // header - int32_t nVersion; - uint256 hashPrevBlock; - uint256 hashMerkleRoot; - uint32_t nTime; - uint32_t nBits; - uint32_t nNonce; + // auxpow (if this is a merge-minded block) + boost::shared_ptr<CAuxPow> auxpow; CBlockHeader() { @@ -37,37 +36,30 @@ public: template <typename Stream, typename Operation> inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(this->nVersion); - READWRITE(hashPrevBlock); - READWRITE(hashMerkleRoot); - READWRITE(nTime); - READWRITE(nBits); - READWRITE(nNonce); + READWRITE(*(CPureBlockHeader*)this); + + if (this->IsAuxpow()) + { + if (ser_action.ForRead()) + auxpow.reset(new CAuxPow()); + assert(auxpow); + READWRITE(*auxpow); + } else if (ser_action.ForRead()) + auxpow.reset(); } void SetNull() { - nVersion = 0; - hashPrevBlock.SetNull(); - hashMerkleRoot.SetNull(); - nTime = 0; - nBits = 0; - nNonce = 0; - } - - bool IsNull() const - { - return (nBits == 0); + CPureBlockHeader::SetNull(); + auxpow.reset(); } - uint256 GetHash() const; - - uint256 GetPoWHash() const; - - int64_t GetBlockTime() const - { - return (int64_t)nTime; - } + /** + * Set the block's auxpow (or unset it). This takes care of updating + * the version accordingly. + * @param apow Pointer to the auxpow to use or NULL. + */ + void SetAuxpow(CAuxPow* apow); }; @@ -115,9 +107,18 @@ public: block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; + block.auxpow = auxpow; return block; } + // Build the in-memory merkle tree for this block and return the merkle root. + // If non-NULL, *mutated is set to whether mutation was detected in the merkle + // tree (a duplication of transactions in the block leading to an identical + // merkle root). + uint256 BuildMerkleTree(bool* mutated = NULL) const; + + std::vector<uint256> GetMerkleBranch(int nIndex) const; + static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex); std::string ToString() const; }; diff --git a/src/primitives/pureheader.cpp b/src/primitives/pureheader.cpp new file mode 100644 index 000000000..9a339bf1f --- /dev/null +++ b/src/primitives/pureheader.cpp @@ -0,0 +1,30 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "primitives/pureheader.h" + +#include "chainparams.h" +#include "crypto/scrypt.h" +#include "hash.h" +#include "utilstrencodings.h" + +void CPureBlockHeader::SetBaseVersion(int32_t nBaseVersion, int32_t nChainId) +{ + assert(nBaseVersion >= 1 && nBaseVersion < VERSION_AUXPOW); + assert(!IsAuxpow()); + nVersion = nBaseVersion | (nChainId * VERSION_CHAIN_START); +} + +uint256 CPureBlockHeader::GetHash() const +{ + return SerializeHash(*this); +} + +uint256 CPureBlockHeader::GetPoWHash() const +{ + uint256 thash; + scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash)); + return thash; +} diff --git a/src/primitives/pureheader.h b/src/primitives/pureheader.h new file mode 100644 index 000000000..0443a530d --- /dev/null +++ b/src/primitives/pureheader.h @@ -0,0 +1,156 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_PRIMITIVES_PUREHEADER_H +#define BITCOIN_PRIMITIVES_PUREHEADER_H + +#include "serialize.h" +#include "uint256.h" + +/** + * A block header without auxpow information. This "intermediate step" + * in constructing the full header is useful, because it breaks the cyclic + * dependency between auxpow (referencing a parent block header) and + * the block header (referencing an auxpow). The parent block header + * does not have auxpow itself, so it is a pure header. + */ +class CPureBlockHeader +{ +public: + /* Modifiers to the version. */ + static const int32_t VERSION_AUXPOW = (1 << 8); + + /** Bits above are reserved for the auxpow chain ID. */ + static const int32_t VERSION_CHAIN_START = (1 << 16); + + // header + int32_t nVersion; + uint256 hashPrevBlock; + uint256 hashMerkleRoot; + uint32_t nTime; + uint32_t nBits; + uint32_t nNonce; + + CPureBlockHeader() + { + SetNull(); + } + + ADD_SERIALIZE_METHODS; + + template <typename Stream, typename Operation> + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(this->nVersion); + READWRITE(hashPrevBlock); + READWRITE(hashMerkleRoot); + READWRITE(nTime); + READWRITE(nBits); + READWRITE(nNonce); + } + + void SetNull() + { + nVersion = 0; + hashPrevBlock.SetNull(); + hashMerkleRoot.SetNull(); + nTime = 0; + nBits = 0; + nNonce = 0; + } + + bool IsNull() const + { + return (nBits == 0); + } + + uint256 GetHash() const; + + uint256 GetPoWHash() const; + + int64_t GetBlockTime() const + { + return (int64_t)nTime; + } + + /* Below are methods to interpret the version with respect to + auxpow data and chain ID. This used to be in the CBlockVersion + class, but was moved here when we switched back to nVersion being + a pure int member as preparation to undoing the "abuse" and + allowing BIP9 to work. */ + + /** + * Extract the base version (without modifiers and chain ID). + * @return The base version./ + */ + inline int32_t GetBaseVersion() const + { + return GetBaseVersion(nVersion); + } + static inline int32_t GetBaseVersion(int32_t ver) + { + return ver % VERSION_AUXPOW; + } + + /** + * Set the base version (apart from chain ID and auxpow flag) to + * the one given. This should only be called when auxpow is not yet + * set, to initialise a block! + * @param nBaseVersion The base version. + * @param nChainId The auxpow chain ID. + */ + void SetBaseVersion(int32_t nBaseVersion, int32_t nChainId); + + /** + * Extract the chain ID. + * @return The chain ID encoded in the version. + */ + inline int32_t GetChainId() const + { + return nVersion >> 16; + } + + /** + * Set the chain ID. This is used for the test suite. + * @param ch The chain ID to set. + */ + inline void SetChainId(int32_t chainId) + { + nVersion %= VERSION_CHAIN_START; + nVersion |= chainId * VERSION_CHAIN_START; + } + + /** + * Check if the auxpow flag is set in the version. + * @return True if this block version is marked as auxpow. + */ + inline bool IsAuxpow() const + { + return nVersion & VERSION_AUXPOW; + } + + /** + * Set the auxpow flag. This is used for testing. + * @param auxpow Whether to mark auxpow as true. + */ + inline void SetAuxpowFlag(bool auxpow) + { + if (auxpow) + nVersion |= VERSION_AUXPOW; + else + nVersion &= ~VERSION_AUXPOW; + } + + /** + * Check whether this is a "legacy" block without chain ID. + * @return True if it is. + */ + inline bool IsLegacy() const + { + return nVersion == 1; + } +}; + +#endif // BITCOIN_PRIMITIVES_PUREHEADER_H |