Any projects which want to use Hush code from now on will need to be licensed as GPLv3 or we will send the lawyers: https://www.softwarefreedom.org/ Notably, Komodo (KMD) is licensed as GPLv2 and is no longer compatible to receive code changes, without causing legal issues. MIT projects, such as Zcash, also cannot pull in changes from the Hush Full Node without permission from The Hush Developers, which may in some circumstances grant an MIT license on a case-by-case basis.
283 lines
8.0 KiB
C++
283 lines
8.0 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2013 The Bitcoin Core developers
|
|
// Copyright (c) 2019-2020 The Hush developers
|
|
// Distributed under the GPLv3 software license, see the accompanying
|
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
|
|
/******************************************************************************
|
|
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
* *
|
|
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
* the top-level directory of this distribution for the individual copyright *
|
|
* holder information and the developer policies on copyright and licensing. *
|
|
* *
|
|
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
* SuperNET software, including this file may be copied, modified, propagated *
|
|
* or distributed except according to the terms contained in the LICENSE file *
|
|
* *
|
|
* Removal or modification of this copyright notice is prohibited. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
#ifndef BITCOIN_PRIMITIVES_BLOCK_H
|
|
#define BITCOIN_PRIMITIVES_BLOCK_H
|
|
|
|
#include "primitives/transaction.h"
|
|
//#include "primitives/nonce.h"
|
|
#include "serialize.h"
|
|
#include "uint256.h"
|
|
#include "arith_uint256.h"
|
|
|
|
/** 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.
|
|
*/
|
|
class CBlockHeader
|
|
{
|
|
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 uint256 (CBlockHeader::*hashFunction)() const;
|
|
static void SetHashAlgo();
|
|
|
|
int32_t nVersion;
|
|
uint256 hashPrevBlock;
|
|
uint256 hashMerkleRoot;
|
|
uint256 hashFinalSaplingRoot;
|
|
uint32_t nTime;
|
|
uint32_t nBits;
|
|
uint256 nNonce;
|
|
|
|
std::vector<unsigned char> nSolution;
|
|
|
|
CBlockHeader()
|
|
{
|
|
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(hashFinalSaplingRoot);
|
|
READWRITE(nTime);
|
|
READWRITE(nBits);
|
|
READWRITE(nNonce);
|
|
READWRITE(nSolution);
|
|
}
|
|
|
|
void SetNull()
|
|
{
|
|
nVersion = CBlockHeader::CURRENT_VERSION;
|
|
hashPrevBlock.SetNull();
|
|
hashMerkleRoot.SetNull();
|
|
hashFinalSaplingRoot.SetNull();
|
|
nTime = 0;
|
|
nBits = 0;
|
|
nNonce = uint256();
|
|
nSolution.clear();
|
|
}
|
|
|
|
bool IsNull() const
|
|
{
|
|
return (nBits == 0);
|
|
}
|
|
|
|
uint256 GetHash() const
|
|
{
|
|
return (this->*hashFunction)();
|
|
}
|
|
|
|
uint256 GetSHA256DHash() const;
|
|
static void SetSHA256DHash();
|
|
|
|
|
|
|
|
|
|
int64_t GetBlockTime() const
|
|
{
|
|
return (int64_t)nTime;
|
|
}
|
|
|
|
};
|
|
|
|
// this class is used to address the type mismatch that existed between nodes, where block headers
|
|
// were being serialized by senders as CBlock and deserialized as CBlockHeader + an assumed extra
|
|
// compact value. although it was working, I made this because it did break, and makes the connection
|
|
// between CBlock and CBlockHeader more brittle.
|
|
// by using this intentionally specified class instead, we remove an instability in the code that could break
|
|
// due to unrelated changes, but stay compatible with the old method.
|
|
class CNetworkBlockHeader : public CBlockHeader
|
|
{
|
|
public:
|
|
std::vector<CTransaction> compatVec;
|
|
|
|
CNetworkBlockHeader() : CBlockHeader()
|
|
{
|
|
SetNull();
|
|
}
|
|
|
|
CNetworkBlockHeader(const CBlockHeader &header)
|
|
{
|
|
SetNull();
|
|
*((CBlockHeader*)this) = header;
|
|
}
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(*(CBlockHeader*)this);
|
|
READWRITE(compatVec);
|
|
}
|
|
|
|
void SetNull()
|
|
{
|
|
CBlockHeader::SetNull();
|
|
compatVec.clear();
|
|
}
|
|
};
|
|
|
|
class CBlock : public CBlockHeader
|
|
{
|
|
public:
|
|
// network and disk
|
|
std::vector<CTransaction> vtx;
|
|
|
|
// memory only
|
|
mutable std::vector<uint256> vMerkleTree;
|
|
|
|
CBlock()
|
|
{
|
|
SetNull();
|
|
}
|
|
|
|
CBlock(const CBlockHeader &header)
|
|
{
|
|
SetNull();
|
|
*((CBlockHeader*)this) = header;
|
|
}
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(*(CBlockHeader*)this);
|
|
READWRITE(vtx);
|
|
}
|
|
|
|
void SetNull()
|
|
{
|
|
CBlockHeader::SetNull();
|
|
vtx.clear();
|
|
vMerkleTree.clear();
|
|
}
|
|
|
|
CBlockHeader GetBlockHeader() const
|
|
{
|
|
CBlockHeader block;
|
|
block.nVersion = nVersion;
|
|
block.hashPrevBlock = hashPrevBlock;
|
|
block.hashMerkleRoot = hashMerkleRoot;
|
|
block.hashFinalSaplingRoot = hashFinalSaplingRoot;
|
|
block.nTime = nTime;
|
|
block.nBits = nBits;
|
|
block.nNonce = nNonce;
|
|
block.nSolution = nSolution;
|
|
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;
|
|
};
|
|
|
|
|
|
uint256 BuildMerkleTree(bool* fMutated, const std::vector<uint256> leaves,
|
|
std::vector<uint256> &vMerkleTree);
|
|
|
|
std::vector<uint256> GetMerkleBranch(int nIndex, int nLeaves, const std::vector<uint256> &vMerkleTree);
|
|
|
|
|
|
/**
|
|
* Custom serializer for CBlockHeader that omits the nonce and solution, for use
|
|
* as input to Equihash.
|
|
*/
|
|
class CEquihashInput : private CBlockHeader
|
|
{
|
|
public:
|
|
CEquihashInput(const CBlockHeader &header)
|
|
{
|
|
CBlockHeader::SetNull();
|
|
*((CBlockHeader*)this) = header;
|
|
}
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(this->nVersion);
|
|
READWRITE(hashPrevBlock);
|
|
READWRITE(hashMerkleRoot);
|
|
READWRITE(hashFinalSaplingRoot);
|
|
READWRITE(nTime);
|
|
READWRITE(nBits);
|
|
}
|
|
};
|
|
|
|
|
|
/** 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();
|
|
}
|
|
|
|
friend bool operator==(const CBlockLocator& a, const CBlockLocator& b) {
|
|
return (a.vHave == b.vHave);
|
|
}
|
|
};
|
|
|
|
#endif // BITCOIN_PRIMITIVES_BLOCK_H
|