<NME> block.h
<BEF> // 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_PRIMITIVES_BLOCK_H
#define BITCOIN_PRIMITIVES_BLOCK_H

#include <deque>
#include <type_traits>
#include <boost/foreach.hpp>
#include "uint256.h"
#include "definition.h"

#define SWITCH_TO_MTP_BLOCK_HEADER 1528995835


unsigned char GetNfactor(int64_t nTimestamp);
#include "crypto/progpow.h"

// Can't include sigma.h
namespace sigma {
class CSigmaTxInfo;

} // namespace sigma.

namespace lelantus {
class CLelantusTxInfo;

} // namespace lelantus

unsigned char GetNfactor(int64_t nTimestamp);

/** 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
 * to everyone and the block is added to the block chain.  The first transaction
 * in the block is a special one that creates a new coin owned by the creator
 * of the block.
 */

inline int GetZerocoinChainID()
{
    return 0x0001; // We are the first :)
}

// Firo - MTP
class CMTPHashData {
public:
    uint8_t hashRootMTP[16]; // 16 is 128 bit of blake2b
    uint64_t nBlockMTP[mtp::MTP_L*2][128]; // 128 is ARGON2_QWORDS_IN_BLOCK
    std::deque<std::vector<uint8_t>> nProofMTP[mtp::MTP_L*3];

    CMTPHashData() {
        memset(hashRootMTP, 0, sizeof(hashRootMTP));
        memset(nBlockMTP, 0, sizeof(nBlockMTP));
    }

    bool IsMTPDataStripped() const {
        // if MTP data is stripped for this block hashRootMTP is all zeroes
        return std::all_of(hashRootMTP, hashRootMTP+16, [](uint8_t b) {return b==0;});
    }

    void StripMTPData() {
        memset(hashRootMTP, 0, sizeof(hashRootMTP));
    }

    ADD_SERIALIZE_METHODS;
        READWRITE(nBits);
        READWRITE(nNonce);
        // Zcoin - MTP
        if(nTime >= 1528995835){
        	READWRITE(nVersionMTP);
        	int i, j;
        	for(i = 0; i < 16; i++){
    inline void SerializationOp(Stream &s, Operation ser_action) {
        READWRITE(hashRootMTP);
        if (IsMTPDataStripped())
            return;

        READWRITE(nBlockMTP);
        for (int i = 0; i < mtp::MTP_L*3; i++) {
            assert(nProofMTP[i].size() < 256);
            uint8_t numberOfProofBlocks = (uint8_t)nProofMTP[i].size();
            READWRITE(numberOfProofBlocks);
            for (const std::vector<uint8_t> &mtpData: nProofMTP[i]) {
                // data size should be 16 for each block
                assert(mtpData.size() == 16);
                s.write((const char *)mtpData.data(), 16);
            }
        }
    }

    // Function for reading
    template <typename Stream>
    inline void SerializationOp(Stream &s, CSerActionUnserialize ser_action) {
        READWRITE(hashRootMTP);

        if (IsMTPDataStripped())
            return;

        READWRITE(nBlockMTP);
        for (int i = 0; i < mtp::MTP_L*3; i++) {
            uint8_t numberOfProofBlocks;
            READWRITE(numberOfProofBlocks);
            for (uint8_t j=0; j<numberOfProofBlocks; j++) {
                std::vector<uint8_t> mtpData(16, 0);
                s.read((char *)mtpData.data(), 16);
                nProofMTP[i].emplace_back(std::move(mtpData));
            }
        }
    }
};

class CBlockHeader
{
public:
    // header
    int32_t nVersion;
    uint256 hashPrevBlock;
    uint256 hashMerkleRoot;
    uint32_t nTime;
    uint32_t nBits;
    uint32_t nNonce;   //! std satoshi

    // Firo - ProgPow 
    uint32_t nHeight;
    uint64_t nNonce64;
    uint256 mix_hash;

    // Firo - MTP
    int32_t nVersionMTP = 0x1000;
    uint256 mtpHashValue;

    // Reserved fields
    uint256 reserved[2];

    // Store this only when absolutely needed for verification
    std::shared_ptr<CMTPHashData> mtpHashData;

    static const int CURRENT_VERSION = 2;

    mutable uint256 cachedPoWHash;

    CBlockHeader()
    {
        SetNull();
    }

    ADD_SERIALIZE_METHODS;

    class CSerializeBlockHeader {};
    class CReadBlockHeader : public CSerActionUnserialize, public CSerializeBlockHeader {};
    class CWriteBlockHeader : public CSerActionSerialize, public CSerializeBlockHeader {};

    template <typename Stream, typename Operation, typename = typename std::enable_if<!std::is_base_of<CSerializeBlockHeader,Operation>::value>::type>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        READWRITE(this->nVersion);
        READWRITE(hashPrevBlock);
        READWRITE(hashMerkleRoot);
        READWRITE(nTime);
        READWRITE(nBits);

        // Firo - ProgPoW
        // Return std 4byte, if ProgPoW return 8byte
        if (IsProgPow()) {

            READWRITE(nHeight);
            READWRITE(nNonce64);
            READWRITE(mix_hash);

        } else {

            READWRITE(nNonce);

            // Firo - MTP
            // On read: allocate and read. On write: write only if already allocated
            if (IsMTP()) {
                READWRITE(nVersionMTP);
                READWRITE(mtpHashValue);
                READWRITE(reserved[0]);
                READWRITE(reserved[1]);
                if (ser_action.ForRead()) {
                    mtpHashData = std::make_shared<CMTPHashData>();
                    READWRITE(*mtpHashData);
                }
                else {
                    if (mtpHashData && !(s.GetType() & SER_GETHASH))
                        READWRITE(*mtpHashData);
                }
            }
        }

    }

    template <typename Stream>
    inline void SerializationOp(Stream &s, CReadBlockHeader ser_action) {
        READWRITE(this->nVersion);
        READWRITE(hashPrevBlock);
        READWRITE(hashMerkleRoot);
        READWRITE(nTime);
        READWRITE(nBits);
        if (IsProgPow()) {
            READWRITE(nHeight);
            READWRITE(nNonce64);
            READWRITE(mix_hash);
        } else {
            READWRITE(nNonce);
            if (IsMTP()) {
                READWRITE(nVersionMTP);
                READWRITE(mtpHashValue);
                READWRITE(reserved[0]);
                READWRITE(reserved[1]);
            }
        };
    
    }

    void SetNull()
    {
        nVersion = CBlockHeader::CURRENT_VERSION | (GetZerocoinChainID() * BLOCK_VERSION_CHAIN_START);
        hashPrevBlock.SetNull();
        hashMerkleRoot.SetNull();
        nTime = 0;
        nBits = 0;
        nNonce = 0;

        // Firo - ProgPow
        nNonce64 = 0;
        nHeight  = 0;
        mix_hash.SetNull();

        cachedPoWHash.SetNull();

        // Firo - MTP
        mtpHashData.reset();
        mtpHashValue.SetNull();
        reserved[0].SetNull();
        reserved[1].SetNull();
    }

    int GetChainID() const
    {
        return nVersion / BLOCK_VERSION_CHAIN_START;
    }

    bool IsNull() const
    {
        return (nBits == 0);
    }

    uint256 GetPoWHash(int nHeight) const;

    uint256 GetHash() const;
    uint256 GetHashFull(uint256& mix_hash) const;
    
    int64_t GetBlockTime() const
    {
        return (int64_t)nTime;
    }
    void InvalidateCachedPoWHash(int nHeight) const;

    bool IsMTP() const;
    bool IsProgPow() const;
    bool IsShorterBlocksSpacing() const;

    int GetTargetBlocksSpacing() const;

    CProgPowHeader GetProgPowHeader() const;
    uint256 GetProgPowHeaderHash() const;
    uint256 GetProgPowHashFull(uint256& mix_hash) const;
    uint256 GetProgPowHashLight() const;

};

class CBlock : public CBlockHeader
{
public:
    // network and disk
    std::vector<CTransactionRef> vtx;

    // memory only
    mutable CTxOut txoutZnode; // znode payment
    mutable std::vector<CTxOut> voutSuperblock; // superblock payment
    mutable bool fChecked;

    // memory only, zerocoin tx info after V3-sigma.
    mutable std::shared_ptr<sigma::CSigmaTxInfo> sigmaTxInfo;

    mutable std::shared_ptr<lelantus::CLelantusTxInfo> lelantusTxInfo;

    CBlock()
    {
        SetNull();
    }

    CBlock(const CBlockHeader &header)
    {
        SetNull();
        *((CBlockHeader*)this) = header;
    }

    ~CBlock() {
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        READWRITE(*(CBlockHeader*)this);
        READWRITE(vtx);
    }

    template <typename Stream>
    inline void SerializationOp(Stream &s, CReadBlockHeader ser_action) {
        CBlockHeader::SerializationOp(s, ser_action);
    }

    void SetNull()
    {
        CBlockHeader::SetNull();
        vtx.clear();
        txoutZnode = CTxOut();
        voutSuperblock.clear();
        fChecked = false;
    }

    CBlockHeader GetBlockHeader() const
    {
        CBlockHeader block;
        block.nVersion       = nVersion;
        block.hashPrevBlock  = hashPrevBlock;
        block.hashMerkleRoot = hashMerkleRoot;
        block.nTime          = nTime;
        block.nBits          = nBits;

        if (IsProgPow()) {
            block.nHeight    = nHeight;
            block.nNonce64   = nNonce64;
            block.mix_hash   = mix_hash;
        } else {
            block.nNonce     = nNonce;
            if (block.IsMTP()) {
                block.nVersionMTP = nVersionMTP;
                block.mtpHashData = mtpHashData;
                block.reserved[0] = reserved[0];
                block.reserved[1] = reserved[1];
            }
        }

        return block;
    }

    std::string ToString() const;

};

/** Describes a place in the block chain to another node such that if the
 * other node doesn't have the same branch, it can find a recent common trunk.
 * The further back it is, the further before the fork it may be.
 */
struct CBlockLocator
{
    std::vector<uint256> vHave;

    CBlockLocator() {}

    CBlockLocator(const std::vector<uint256>& vHaveIn)
    {
        vHave = vHaveIn;
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        int nVersion = s.GetVersion();
        if (!(s.GetType() & SER_GETHASH))
            READWRITE(nVersion);
        READWRITE(vHave);
    }

    void SetNull()
    {
        vHave.clear();
    }

    bool IsNull() const
    {
        return vHave.empty();
    }
};

/** Compute the consensus-critical block weight (see BIP 141). */
int64_t GetBlockWeight(const CBlock& tx);

#endif // BITCOIN_PRIMITIVES_BLOCK_H

<MSG> changed timestamp to 1529062072
<DFF> @@ -12,7 +12,7 @@
 #include "uint256.h"
 #include "definition.h"
 
-#define SWITCH_TO_MTP_BLOCK_HEADER 1528995835
+#define SWITCH_TO_MTP_BLOCK_HEADER 1529062072
 
 
 unsigned char GetNfactor(int64_t nTimestamp);
@@ -69,7 +69,7 @@ public:
         READWRITE(nBits);
         READWRITE(nNonce);
         // Zcoin - MTP
-        if(nTime >= 1528995835){
+        if(nTime >= SWITCH_TO_MTP_BLOCK_HEADER){
         	READWRITE(nVersionMTP);
         	int i, j;
         	for(i = 0; i < 16; i++){

{'commit': 'diff --git a/src/main.h b/src/main.h\nindex 6c5d48cc8..fb5d072c7 100644\n--- a/src/main.h\n+++ b/src/main.h\n@@ -173,7 +173,7 @@ static const bool DEFAULT_PEERBLOOMFILTERS = true;\n // Add more spend txs per block at block height\n #define SWITCH_TO_MORE_SPEND_TXS 60000\n \n-#define SWITCH_TO_MTP_BLOCK_HEADER 1528995835\n+#define SWITCH_TO_MTP_BLOCK_HEADER 1529062072\n \n \n struct BlockHasher\ndiff --git a/src/primitives/block.h b/src/primitives/block.h\nindex 71eee34c2..93b9f55ee 100644\n--- a/src/primitives/block.h\n+++ b/src/primitives/block.h\n@@ -12,7 +12,7 @@\n #include "uint256.h"\n #include "definition.h"\n \n-#define SWITCH_TO_MTP_BLOCK_HEADER 1528995835\n+#define SWITCH_TO_MTP_BLOCK_HEADER 1529062072\n \n \n unsigned char GetNfactor(int64_t nTimestamp);\n@@ -69,7 +69,7 @@ public:\n         READWRITE(nBits);\n         READWRITE(nNonce);\n         // Zcoin - MTP\n-        if(nTime >= 1528995835){\n+        if(nTime >= SWITCH_TO_MTP_BLOCK_HEADER){\n         \tREADWRITE(nVersionMTP);\n         \tint i, j;\n         \tfor(i = 0; i < 16; i++){\n', 'commit_subject': 'changed timestamp to 1529062072', 'repo_name': 'zcoinofficial/zcoin', 'committer': {'name': 'Poramin Insom', 'email': 'b6cc8e425c4132225256d52e99da46e1d90af021@zcoin.io', 'time_sec': '1529060145', 'tz_offset': '420', 'date': {'seconds': '1529060145'}}, 'commit_tree': 'cd0c5f97b46a06f4e12ad1c6d7fd3d9607eac210', 'commit_message': 'changed timestamp to 1529062072', 'language_name': 'C++', 'license': 'mit', 'hunks': '@@ -12,7 +12,7 @@\n #include "uint256.h"\n #include "definition.h"\n \n-#define SWITCH_TO_MTP_BLOCK_HEADER 1528995835\n+#define SWITCH_TO_MTP_BLOCK_HEADER 1529062072\n \n \n unsigned char GetNfactor(int64_t nTimestamp);\n@@ -69,7 +69,7 @@ public:\n         READWRITE(nBits);\n         READWRITE(nNonce);\n         // Zcoin - MTP\n-        if(nTime >= 1528995835){\n+        if(nTime >= SWITCH_TO_MTP_BLOCK_HEADER){\n         \tREADWRITE(nVersionMTP);\n         \tint i, j;\n         \tfor(i = 0; i < 16; i++){\n', 'addition_count': 2, 'deletion_count': 2, 'src_file': 'a/src/primitives/block.h', 'tgt_file': 'b/src/primitives/block.h', 'file_extension': '.h', 'before_file': '// Copyright (c) 2009-2010 Satoshi Nakamoto\n// Copyright (c) 2009-2016 The Bitcoin Core developers\n// Distributed under the MIT software license, see the accompanying\n// file COPYING or http://www.opensource.org/licenses/mit-license.php.\n\n#ifndef BITCOIN_PRIMITIVES_BLOCK_H\n#define BITCOIN_PRIMITIVES_BLOCK_H\n\n#include <deque>\n#include <type_traits>\n#include <boost/foreach.hpp>\n#include "uint256.h"\n#include "definition.h"\n\n#define SWITCH_TO_MTP_BLOCK_HEADER 1528995835\n\n\nunsigned char GetNfactor(int64_t nTimestamp);\n#include "crypto/progpow.h"\n\n// Can\'t include sigma.h\nnamespace sigma {\nclass CSigmaTxInfo;\n\n} // namespace sigma.\n\nnamespace lelantus {\nclass CLelantusTxInfo;\n\n} // namespace lelantus\n\nunsigned char GetNfactor(int64_t nTimestamp);\n\n/** Nodes collect new transactions into a block, hash them into a hash tree,\n * and scan through nonce values to make the block\'s hash satisfy proof-of-work\n * requirements.  When they solve the proof-of-work, they broadcast the block\n * to everyone and the block is added to the block chain.  The first transaction\n * in the block is a special one that creates a new coin owned by the creator\n * of the block.\n */\n\ninline int GetZerocoinChainID()\n{\n    return 0x0001; // We are the first :)\n}\n\n// Firo - MTP\nclass CMTPHashData {\npublic:\n    uint8_t hashRootMTP[16]; // 16 is 128 bit of blake2b\n    uint64_t nBlockMTP[mtp::MTP_L*2][128]; // 128 is ARGON2_QWORDS_IN_BLOCK\n    std::deque<std::vector<uint8_t>> nProofMTP[mtp::MTP_L*3];\n\n    CMTPHashData() {\n        memset(hashRootMTP, 0, sizeof(hashRootMTP));\n        memset(nBlockMTP, 0, sizeof(nBlockMTP));\n    }\n\n    bool IsMTPDataStripped() const {\n        // if MTP data is stripped for this block hashRootMTP is all zeroes\n        return std::all_of(hashRootMTP, hashRootMTP+16, [](uint8_t b) {return b==0;});\n    }\n\n    void StripMTPData() {\n        memset(hashRootMTP, 0, sizeof(hashRootMTP));\n    }\n\n    ADD_SERIALIZE_METHODS;\n        READWRITE(nBits);\n        READWRITE(nNonce);\n        // Zcoin - MTP\n        if(nTime >= 1528995835){\n        \tREADWRITE(nVersionMTP);\n        \tint i, j;\n        \tfor(i = 0; i < 16; i++){\n    inline void SerializationOp(Stream &s, Operation ser_action) {\n        READWRITE(hashRootMTP);\n        if (IsMTPDataStripped())\n            return;\n\n        READWRITE(nBlockMTP);\n        for (int i = 0; i < mtp::MTP_L*3; i++) {\n            assert(nProofMTP[i].size() < 256);\n            uint8_t numberOfProofBlocks = (uint8_t)nProofMTP[i].size();\n            READWRITE(numberOfProofBlocks);\n            for (const std::vector<uint8_t> &mtpData: nProofMTP[i]) {\n                // data size should be 16 for each block\n                assert(mtpData.size() == 16);\n                s.write((const char *)mtpData.data(), 16);\n            }\n        }\n    }\n\n    // Function for reading\n    template <typename Stream>\n    inline void SerializationOp(Stream &s, CSerActionUnserialize ser_action) {\n        READWRITE(hashRootMTP);\n\n        if (IsMTPDataStripped())\n            return;\n\n        READWRITE(nBlockMTP);\n        for (int i = 0; i < mtp::MTP_L*3; i++) {\n            uint8_t numberOfProofBlocks;\n            READWRITE(numberOfProofBlocks);\n            for (uint8_t j=0; j<numberOfProofBlocks; j++) {\n                std::vector<uint8_t> mtpData(16, 0);\n                s.read((char *)mtpData.data(), 16);\n                nProofMTP[i].emplace_back(std::move(mtpData));\n            }\n        }\n    }\n};\n\nclass CBlockHeader\n{\npublic:\n    // header\n    int32_t nVersion;\n    uint256 hashPrevBlock;\n    uint256 hashMerkleRoot;\n    uint32_t nTime;\n    uint32_t nBits;\n    uint32_t nNonce;   //! std satoshi\n\n    // Firo - ProgPow \n    uint32_t nHeight;\n    uint64_t nNonce64;\n    uint256 mix_hash;\n\n    // Firo - MTP\n    int32_t nVersionMTP = 0x1000;\n    uint256 mtpHashValue;\n\n    // Reserved fields\n    uint256 reserved[2];\n\n    // Store this only when absolutely needed for verification\n    std::shared_ptr<CMTPHashData> mtpHashData;\n\n    static const int CURRENT_VERSION = 2;\n\n    mutable uint256 cachedPoWHash;\n\n    CBlockHeader()\n    {\n        SetNull();\n    }\n\n    ADD_SERIALIZE_METHODS;\n\n    class CSerializeBlockHeader {};\n    class CReadBlockHeader : public CSerActionUnserialize, public CSerializeBlockHeader {};\n    class CWriteBlockHeader : public CSerActionSerialize, public CSerializeBlockHeader {};\n\n    template <typename Stream, typename Operation, typename = typename std::enable_if<!std::is_base_of<CSerializeBlockHeader,Operation>::value>::type>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        READWRITE(this->nVersion);\n        READWRITE(hashPrevBlock);\n        READWRITE(hashMerkleRoot);\n        READWRITE(nTime);\n        READWRITE(nBits);\n\n        // Firo - ProgPoW\n        // Return std 4byte, if ProgPoW return 8byte\n        if (IsProgPow()) {\n\n            READWRITE(nHeight);\n            READWRITE(nNonce64);\n            READWRITE(mix_hash);\n\n        } else {\n\n            READWRITE(nNonce);\n\n            // Firo - MTP\n            // On read: allocate and read. On write: write only if already allocated\n            if (IsMTP()) {\n                READWRITE(nVersionMTP);\n                READWRITE(mtpHashValue);\n                READWRITE(reserved[0]);\n                READWRITE(reserved[1]);\n                if (ser_action.ForRead()) {\n                    mtpHashData = std::make_shared<CMTPHashData>();\n                    READWRITE(*mtpHashData);\n                }\n                else {\n                    if (mtpHashData && !(s.GetType() & SER_GETHASH))\n                        READWRITE(*mtpHashData);\n                }\n            }\n        }\n\n    }\n\n    template <typename Stream>\n    inline void SerializationOp(Stream &s, CReadBlockHeader ser_action) {\n        READWRITE(this->nVersion);\n        READWRITE(hashPrevBlock);\n        READWRITE(hashMerkleRoot);\n        READWRITE(nTime);\n        READWRITE(nBits);\n        if (IsProgPow()) {\n            READWRITE(nHeight);\n            READWRITE(nNonce64);\n            READWRITE(mix_hash);\n        } else {\n            READWRITE(nNonce);\n            if (IsMTP()) {\n                READWRITE(nVersionMTP);\n                READWRITE(mtpHashValue);\n                READWRITE(reserved[0]);\n                READWRITE(reserved[1]);\n            }\n        };\n    \n    }\n\n    void SetNull()\n    {\n        nVersion = CBlockHeader::CURRENT_VERSION | (GetZerocoinChainID() * BLOCK_VERSION_CHAIN_START);\n        hashPrevBlock.SetNull();\n        hashMerkleRoot.SetNull();\n        nTime = 0;\n        nBits = 0;\n        nNonce = 0;\n\n        // Firo - ProgPow\n        nNonce64 = 0;\n        nHeight  = 0;\n        mix_hash.SetNull();\n\n        cachedPoWHash.SetNull();\n\n        // Firo - MTP\n        mtpHashData.reset();\n        mtpHashValue.SetNull();\n        reserved[0].SetNull();\n        reserved[1].SetNull();\n    }\n\n    int GetChainID() const\n    {\n        return nVersion / BLOCK_VERSION_CHAIN_START;\n    }\n\n    bool IsNull() const\n    {\n        return (nBits == 0);\n    }\n\n    uint256 GetPoWHash(int nHeight) const;\n\n    uint256 GetHash() const;\n    uint256 GetHashFull(uint256& mix_hash) const;\n    \n    int64_t GetBlockTime() const\n    {\n        return (int64_t)nTime;\n    }\n    void InvalidateCachedPoWHash(int nHeight) const;\n\n    bool IsMTP() const;\n    bool IsProgPow() const;\n    bool IsShorterBlocksSpacing() const;\n\n    int GetTargetBlocksSpacing() const;\n\n    CProgPowHeader GetProgPowHeader() const;\n    uint256 GetProgPowHeaderHash() const;\n    uint256 GetProgPowHashFull(uint256& mix_hash) const;\n    uint256 GetProgPowHashLight() const;\n\n};\n\nclass CBlock : public CBlockHeader\n{\npublic:\n    // network and disk\n    std::vector<CTransactionRef> vtx;\n\n    // memory only\n    mutable CTxOut txoutZnode; // znode payment\n    mutable std::vector<CTxOut> voutSuperblock; // superblock payment\n    mutable bool fChecked;\n\n    // memory only, zerocoin tx info after V3-sigma.\n    mutable std::shared_ptr<sigma::CSigmaTxInfo> sigmaTxInfo;\n\n    mutable std::shared_ptr<lelantus::CLelantusTxInfo> lelantusTxInfo;\n\n    CBlock()\n    {\n        SetNull();\n    }\n\n    CBlock(const CBlockHeader &header)\n    {\n        SetNull();\n        *((CBlockHeader*)this) = header;\n    }\n\n    ~CBlock() {\n    }\n\n    ADD_SERIALIZE_METHODS;\n\n    template <typename Stream, typename Operation>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        READWRITE(*(CBlockHeader*)this);\n        READWRITE(vtx);\n    }\n\n    template <typename Stream>\n    inline void SerializationOp(Stream &s, CReadBlockHeader ser_action) {\n        CBlockHeader::SerializationOp(s, ser_action);\n    }\n\n    void SetNull()\n    {\n        CBlockHeader::SetNull();\n        vtx.clear();\n        txoutZnode = CTxOut();\n        voutSuperblock.clear();\n        fChecked = false;\n    }\n\n    CBlockHeader GetBlockHeader() const\n    {\n        CBlockHeader block;\n        block.nVersion       = nVersion;\n        block.hashPrevBlock  = hashPrevBlock;\n        block.hashMerkleRoot = hashMerkleRoot;\n        block.nTime          = nTime;\n        block.nBits          = nBits;\n\n        if (IsProgPow()) {\n            block.nHeight    = nHeight;\n            block.nNonce64   = nNonce64;\n            block.mix_hash   = mix_hash;\n        } else {\n            block.nNonce     = nNonce;\n            if (block.IsMTP()) {\n                block.nVersionMTP = nVersionMTP;\n                block.mtpHashData = mtpHashData;\n                block.reserved[0] = reserved[0];\n                block.reserved[1] = reserved[1];\n            }\n        }\n\n        return block;\n    }\n\n    std::string ToString() const;\n\n};\n\n/** Describes a place in the block chain to another node such that if the\n * other node doesn\'t have the same branch, it can find a recent common trunk.\n * The further back it is, the further before the fork it may be.\n */\nstruct CBlockLocator\n{\n    std::vector<uint256> vHave;\n\n    CBlockLocator() {}\n\n    CBlockLocator(const std::vector<uint256>& vHaveIn)\n    {\n        vHave = vHaveIn;\n    }\n\n    ADD_SERIALIZE_METHODS;\n\n    template <typename Stream, typename Operation>\n    inline void SerializationOp(Stream& s, Operation ser_action) {\n        int nVersion = s.GetVersion();\n        if (!(s.GetType() & SER_GETHASH))\n            READWRITE(nVersion);\n        READWRITE(vHave);\n    }\n\n    void SetNull()\n    {\n        vHave.clear();\n    }\n\n    bool IsNull() const\n    {\n        return vHave.empty();\n    }\n};\n\n/** Compute the consensus-critical block weight (see BIP 141). */\nint64_t GetBlockWeight(const CBlock& tx);\n\n#endif // BITCOIN_PRIMITIVES_BLOCK_H\n', 'message': 'changed timestamp to 1529062072', 'author_name': 'Poramin Insom', 'lang': 'h'}