// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#ifndef BITCOIN_PRIMITIVES_BLOCK_H
#define BITCOIN_PRIMITIVES_BLOCK_H
-#include "primitives/transaction.h"
#include "primitives/nonce.h"
+#include "primitives/transaction.h"
#include "serialize.h"
#include "uint256.h"
#include "arith_uint256.h"
+#include "primitives/solutiondata.h"
+
+// does not check for height / sapling upgrade, etc. this should not be used to get block proofs
+// on a pre-VerusPoP chain
+arith_uint256 GetCompactPower(const uint256 &nNonce, uint32_t nBits, int32_t version=CPOSNonce::VERUS_V2);
+class CMMRPowerNode;
+class CMerkleBranch;
+class CBlockHeader;
/** 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
{
public:
// header
- static const size_t HEADER_SIZE=4+32+32+32+4+4+32; // excluding Equihash solution
- static const int32_t CURRENT_VERSION=4;
+ static const size_t HEADER_SIZE = 4+32+32+32+4+4+32; // excluding Equihash solution
+ static const int32_t CURRENT_VERSION = CPOSNonce::VERUS_V1;
+ static const int32_t CURRENT_VERSION_MASK = 0x0000ffff; // for compatibility
+ static const int32_t VERUS_V2 = CPOSNonce::VERUS_V2;
+
static uint256 (CBlockHeader::*hashFunction)() const;
- static void SetHashAlgo();
int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
- uint256 hashReserved;
+ uint256 hashFinalSaplingRoot;
uint32_t nTime;
uint32_t nBits;
CPOSNonce nNonce;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
- nVersion = this->nVersion;
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
- READWRITE(hashReserved);
+ READWRITE(hashFinalSaplingRoot);
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
nVersion = CBlockHeader::CURRENT_VERSION;
hashPrevBlock.SetNull();
hashMerkleRoot.SetNull();
- hashReserved.SetNull();
+ hashFinalSaplingRoot.SetNull();
nTime = 0;
nBits = 0;
nNonce = uint256();
return (nBits == 0);
}
+ // returns 0 if not PBaaS, 1 if PBaaS PoW, -1 if PBaaS PoS
+ int32_t IsPBaaS()
+ {
+ if (nVersion == VERUS_V2)
+ {
+ return CVerusSolutionVector(nSolution).IsPBaaS();
+ }
+ return 0;
+ }
+
+ // return a vector of bytes that contains the internal data for this solution vector
+ void GetExtraData(std::vector<unsigned char> &dataVec)
+ {
+ CVerusSolutionVector(nSolution).GetExtraData(dataVec);
+ }
+
+ // set the extra data with a pointer to bytes and length
+ bool SetExtraData(const unsigned char *pbegin, uint32_t len)
+ {
+ return CVerusSolutionVector(nSolution).SetExtraData(pbegin, len);
+ }
+
+ void ResizeExtraData(uint32_t newSize)
+ {
+ CVerusSolutionVector(nSolution).ResizeExtraData(newSize);
+ }
+
+ uint32_t ExtraDataLen()
+ {
+ return CVerusSolutionVector(nSolution).ExtraDataLen();
+ }
+
+ // returns -1 on failure, upon failure, pbbh is undefined and likely corrupted
+ int32_t GetPBaaSHeader(CPBaaSBlockHeader &pbh, const uint160 &cID) const;
+
+ // returns false on failure to read data
+ bool GetPBaaSHeader(CPBaaSBlockHeader &pbh, uint32_t idx) const
+ {
+ // search in the solution for this header index and return it if found
+ CPBaaSSolutionDescriptor descr = CConstVerusSolutionVector::GetDescriptor(nSolution);
+ int pbType;
+ if (nVersion == VERUS_V2 && CConstVerusSolutionVector::IsPBaaS(nSolution) != 0 && idx < descr.numPBaaSHeaders)
+ {
+ pbh = *(CConstVerusSolutionVector::GetFirstPBaaSHeader(nSolution) + idx);
+ return true;
+ }
+ return false;
+ }
+
+ // returns false on failure to read data
+ int32_t NumPBaaSHeaders() const
+ {
+ // search in the solution for this header index and return it if found
+ CPBaaSSolutionDescriptor descr = CConstVerusSolutionVector::GetDescriptor(nSolution);
+ return descr.numPBaaSHeaders;
+ }
+
+ // this can save a new header into an empty space or update an existing header
+ bool SavePBaaSHeader(CPBaaSBlockHeader &pbh, uint32_t idx)
+ {
+ CPBaaSBlockHeader pbbh = CPBaaSBlockHeader();
+ int ix;
+
+ CVerusSolutionVector sv = CVerusSolutionVector(nSolution);
+
+ if (sv.IsPBaaS() && !pbh.IsNull() && idx < sv.GetNumPBaaSHeaders() && (((ix = GetPBaaSHeader(pbbh, pbh.chainID)) == -1) || ix == idx))
+ {
+ sv.SetPBaaSHeader(pbh, idx);
+ return true;
+ }
+ return false;
+ }
+
+ bool UpdatePBaaSHeader(const CPBaaSBlockHeader &pbh)
+ {
+ CPBaaSBlockHeader pbbh = CPBaaSBlockHeader();
+ uint32_t idx;
+
+ // what we are updating, must be present
+ if (!pbh.IsNull() && (idx = GetPBaaSHeader(pbbh, pbh.chainID)) != -1)
+ {
+ CVerusSolutionVector(nSolution).SetPBaaSHeader(pbh, idx);
+ return true;
+ }
+ return false;
+ }
+
+ void DeletePBaaSHeader(uint32_t idx)
+ {
+ CVerusSolutionVector sv = CVerusSolutionVector(nSolution);
+ CPBaaSSolutionDescriptor descr = sv.Descriptor();
+ if (idx < descr.numPBaaSHeaders)
+ {
+ CPBaaSBlockHeader pbh;
+ // if we weren't last, move the one that was last to our prior space
+ if (idx < (descr.numPBaaSHeaders - 1))
+ {
+ sv.GetPBaaSHeader(pbh, descr.numPBaaSHeaders - 1);
+ }
+ sv.SetPBaaSHeader(pbh, idx);
+
+ descr.numPBaaSHeaders--;
+ sv.SetDescriptor(descr);
+ }
+ }
+
+ // returns the index of the new header if added, otherwise, -1
+ int32_t AddPBaaSHeader(const CPBaaSBlockHeader &pbh);
+
+ // add the parts of this block header that can be represented by a PBaaS header to the solution
+ int32_t AddPBaaSHeader(uint256 hashPrevMMRRoot, const uint160 &cID)
+ {
+
+ CPBaaSBlockHeader pbbh = CPBaaSBlockHeader(cID, CPBaaSPreHeader(*this), hashPrevMMRRoot);
+ return AddPBaaSHeader(pbbh);
+ }
+
+ bool AddUpdatePBaaSHeader(uint256 mmvRoot);
+ bool AddUpdatePBaaSHeader(const CPBaaSBlockHeader &pbh);
+
+ // clears everything except version, time, and solution, which are shared across all merge mined blocks
+ void ClearNonCanonicalData()
+ {
+ hashPrevBlock = uint256();
+ hashMerkleRoot = uint256();
+ hashFinalSaplingRoot = uint256();
+ nBits = 0;
+ nNonce = uint256();
+ }
+
+ // this confirms that the current header's data matches what would be expected from its preheader hash in the
+ // solution
+ bool CheckNonCanonicalData() const;
+ bool CheckNonCanonicalData(uint160 &cID) const;
+
uint256 GetHash() const
{
return (this->*hashFunction)();
}
+ // return a node from this block header, including hash of merkle root and block hash as well as compact chain power, to put into an MMR
+ CMMRPowerNode GetMMRNode() const;
+ void AddMerkleProofBridge(CMerkleBranch &branch) const;
+ void AddBlockProofBridge(CMerkleBranch &branch) const;
+ uint256 GetPrevMMRRoot() const;
+
uint256 GetSHA256DHash() const;
static void SetSHA256DHash();
uint256 GetVerusHash() const;
static void SetVerusHash();
- bool GetRawVerusPOSHash(uint256 &value, int32_t nHeight) const;
- uint256 GetVerusEntropyHash(int32_t nHeight) const;
-
uint256 GetVerusV2Hash() const;
+ static void SetVerusV2Hash();
+
+ bool GetRawVerusPOSHash(uint256 &ret, int32_t nHeight) const;
+ bool GetVerusPOSHash(arith_uint256 &ret, int32_t nHeight, CAmount value) const; // value is amount of stake tx
+ uint256 GetVerusEntropyHash(int32_t nHeight) const;
int64_t GetBlockTime() const
{
bool IsVerusPOSBlock() const
{
- return nNonce.IsPOSNonce();
+ return nNonce.IsPOSNonce(nVersion) && GetVerusPOSTarget() != 0;
}
void SetVerusPOSTarget(uint32_t nBits)
{
- CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
+ if (nVersion == VERUS_V2)
+ {
+ CVerusHashV2Writer hashWriter = CVerusHashV2Writer(SER_GETHASH, PROTOCOL_VERSION);
- arith_uint256 arNonce = UintToArith256(nNonce);
+ arith_uint256 arNonce = UintToArith256(nNonce);
- // printf("before svpt: %s\n", ArithToUint256(arNonce).GetHex().c_str());
+ // printf("before svpt: %s\n", ArithToUint256(arNonce).GetHex().c_str());
- arNonce = (arNonce & CPOSNonce::entropyMask) | nBits;
+ arNonce = (arNonce & CPOSNonce::entropyMask) | nBits;
- // printf("after clear: %s\n", ArithToUint256(arNonce).GetHex().c_str());
+ // printf("after clear: %s\n", ArithToUint256(arNonce).GetHex().c_str());
- hashWriter << ArithToUint256(arNonce);
- nNonce = CPOSNonce(ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | arNonce));
+ hashWriter << ArithToUint256(arNonce);
+ nNonce = CPOSNonce(ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | arNonce));
- // printf(" after svpt: %s\n", nNonce.GetHex().c_str());
+ // printf(" after svpt: %s\n", nNonce.GetHex().c_str());
+ }
+ else
+ {
+ CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
+
+ arith_uint256 arNonce = UintToArith256(nNonce);
+
+ // printf("before svpt: %s\n", ArithToUint256(arNonce).GetHex().c_str());
+
+ arNonce = (arNonce & CPOSNonce::entropyMask) | nBits;
+
+ // printf("after clear: %s\n", ArithToUint256(arNonce).GetHex().c_str());
+
+ hashWriter << ArithToUint256(arNonce);
+ nNonce = CPOSNonce(ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | arNonce));
+
+ // printf(" after svpt: %s\n", nNonce.GetHex().c_str());
+ }
+ }
+
+ bool SetVersionByHeight(uint32_t height)
+ {
+ CVerusSolutionVector vsv = CVerusSolutionVector(nSolution);
+ if (vsv.SetVersionByHeight(height) && vsv.Version() > 0)
+ {
+ nVersion = VERUS_V2;
+ }
+ }
+
+ static uint32_t GetVersionByHeight(uint32_t height)
+ {
+ if (CVerusSolutionVector::GetVersionByHeight(height) > 0)
+ {
+ return VERUS_V2;
+ }
+ else
+ {
+ return CURRENT_VERSION;
+ }
}
};
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(*(CBlockHeader*)this);
READWRITE(compatVec);
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(*(CBlockHeader*)this);
READWRITE(vtx);
}
block.nVersion = nVersion;
block.hashPrevBlock = hashPrevBlock;
block.hashMerkleRoot = hashMerkleRoot;
- block.hashReserved = hashReserved;
+ block.hashFinalSaplingRoot = hashFinalSaplingRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
- nVersion = this->nVersion;
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
- READWRITE(hashReserved);
+ READWRITE(hashFinalSaplingRoot);
READWRITE(nTime);
READWRITE(nBits);
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (!(nType & SER_GETHASH))
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ int nVersion = s.GetVersion();
+ if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vHave);
}