Skip to content

Commit

Permalink
Port primitives
Browse files Browse the repository at this point in the history
  • Loading branch information
timemarkovqtum committed Feb 1, 2024
1 parent bb744e1 commit b905e2a
Show file tree
Hide file tree
Showing 7 changed files with 565 additions and 7 deletions.
118 changes: 117 additions & 1 deletion src/primitives/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,140 @@

#include <hash.h>
#include <tinyformat.h>
#include <util/strencodings.h>
#include <crypto/common.h>
#include <pubkey.h>
#include <streams.h>

// Used to serialize the header without signature
// Workaround due to removing serialization templates in Bitcoin Core 0.18
class CBlockHeaderSign
{
public:
CBlockHeaderSign(const CBlockHeader& header)
{
fHasProofOfDelegation = header.HasProofOfDelegation();
nVersion = header.nVersion;
hashPrevBlock = header.hashPrevBlock;
hashMerkleRoot = header.hashMerkleRoot;
nTime = header.nTime;
nBits = header.nBits;
nNonce = header.nNonce;
hashStateRoot = header.hashStateRoot;
hashUTXORoot = header.hashUTXORoot;
prevoutStake = header.prevoutStake;
vchBlockDlgt = header.GetProofOfDelegation();
}

SERIALIZE_METHODS(CBlockHeaderSign, obj) {
READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce, obj.hashStateRoot, obj.hashUTXORoot, obj.prevoutStake);
if(obj.fHasProofOfDelegation)
{
READWRITE(obj.vchBlockDlgt);
}
}

private:
bool fHasProofOfDelegation;

// header without signature
int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
uint32_t nTime;
uint32_t nBits;
uint32_t nNonce;
uint256 hashStateRoot;
uint256 hashUTXORoot;
COutPoint prevoutStake;
std::vector<unsigned char> vchBlockDlgt;
};

uint256 CBlockHeader::GetHash() const
{
return (CHashWriter{PROTOCOL_VERSION} << *this).GetHash();
}

uint256 CBlockHeader::GetHashWithoutSign() const
{
return (CHashWriter{PROTOCOL_VERSION} << CBlockHeaderSign(*this)).GetHash();
}

std::string CBlockHeader::GetWithoutSign() const
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << CBlockHeaderSign(*this);
return EncodeBase64(ss.str());
}

std::string CBlock::ToString() const
{
std::stringstream s;
s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, hashStateRoot=%s, hashUTXORoot=%s, blockSig=%s, proof=%s, prevoutStake=%s, vtx=%u)\n",
GetHash().ToString(),
nVersion,
hashPrevBlock.ToString(),
hashMerkleRoot.ToString(),
nTime, nBits, nNonce,
hashStateRoot.ToString(), // qtum
hashUTXORoot.ToString(), // qtum
HexStr(vchBlockSigDlgt),
IsProofOfStake() ? "PoS" : "PoW",
prevoutStake.ToString(),
vtx.size());
for (const auto& tx : vtx) {
s << " " << tx->ToString() << "\n";
}
return s.str();
}

std::vector<unsigned char> CBlockHeader::GetBlockSignature() const
{
if(vchBlockSigDlgt.size() < 2 * CPubKey::COMPACT_SIGNATURE_SIZE)
{
return vchBlockSigDlgt;
}

return std::vector<unsigned char>(vchBlockSigDlgt.begin(), vchBlockSigDlgt.end() - CPubKey::COMPACT_SIGNATURE_SIZE );
}

std::vector<unsigned char> CBlockHeader::GetProofOfDelegation() const
{
if(vchBlockSigDlgt.size() < 2 * CPubKey::COMPACT_SIGNATURE_SIZE)
{
return std::vector<unsigned char>();
}

return std::vector<unsigned char>(vchBlockSigDlgt.begin() + vchBlockSigDlgt.size() - CPubKey::COMPACT_SIGNATURE_SIZE, vchBlockSigDlgt.end());

}

bool CBlockHeader::HasProofOfDelegation() const
{
return vchBlockSigDlgt.size() >= 2 * CPubKey::COMPACT_SIGNATURE_SIZE;
}

void CBlockHeader::SetBlockSignature(const std::vector<unsigned char> &vchSign)
{
if(HasProofOfDelegation())
{
std::vector<unsigned char> vchPoD = GetProofOfDelegation();
vchBlockSigDlgt = vchSign;
vchBlockSigDlgt.insert(vchBlockSigDlgt.end(), vchPoD.begin(), vchPoD.end());
}
else
{
vchBlockSigDlgt = vchSign;
}
}

void CBlockHeader::SetProofOfDelegation(const std::vector<unsigned char> &vchPoD)
{
std::vector<unsigned char> vchSign = GetBlockSignature();
if(vchSign.size() != CPubKey::COMPACT_SIGNATURE_SIZE)
{
vchSign.resize(CPubKey::COMPACT_SIGNATURE_SIZE, 0);
}
vchBlockSigDlgt = vchSign;
vchBlockSigDlgt.insert(vchBlockSigDlgt.end(), vchPoD.begin(), vchPoD.end());
}
72 changes: 71 additions & 1 deletion src/primitives/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,19 @@ class CBlockHeader
uint32_t nTime;
uint32_t nBits;
uint32_t nNonce;
uint256 hashStateRoot; // qtum
uint256 hashUTXORoot; // qtum
// proof-of-stake specific fields
COutPoint prevoutStake;
std::vector<unsigned char> vchBlockSigDlgt; // The delegate is 65 bytes or 0 bytes, it can be added in the signature paramether at the end to avoid compatibility problems

CBlockHeader()
{
SetNull();
}
virtual ~CBlockHeader(){};

SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce, obj.hashStateRoot, obj.hashUTXORoot, obj.prevoutStake, obj.vchBlockSigDlgt); }

void SetNull()
{
Expand All @@ -44,6 +50,10 @@ class CBlockHeader
nTime = 0;
nBits = 0;
nNonce = 0;
hashStateRoot.SetNull(); // qtum
hashUTXORoot.SetNull(); // qtum
vchBlockSigDlgt.clear();
prevoutStake.SetNull();
}

bool IsNull() const
Expand All @@ -53,6 +63,10 @@ class CBlockHeader

uint256 GetHash() const;

uint256 GetHashWithoutSign() const;

std::string GetWithoutSign() const;

NodeSeconds Time() const
{
return NodeSeconds{std::chrono::seconds{nTime}};
Expand All @@ -62,6 +76,53 @@ class CBlockHeader
{
return (int64_t)nTime;
}

// ppcoin: two types of block: proof-of-work or proof-of-stake
virtual bool IsProofOfStake() const //qtum
{
return !prevoutStake.IsNull();
}

virtual bool IsProofOfWork() const
{
return !IsProofOfStake();
}

virtual uint32_t StakeTime() const
{
uint32_t ret = 0;
if(IsProofOfStake())
{
ret = nTime;
}
return ret;
}

void SetBlockSignature(const std::vector<unsigned char>& vchSign);
std::vector<unsigned char> GetBlockSignature() const;

void SetProofOfDelegation(const std::vector<unsigned char>& vchPoD);
std::vector<unsigned char> GetProofOfDelegation() const;

bool HasProofOfDelegation() const;

CBlockHeader& operator=(const CBlockHeader& other) //qtum
{
if (this != &other)
{
this->nVersion = other.nVersion;
this->hashPrevBlock = other.hashPrevBlock;
this->hashMerkleRoot = other.hashMerkleRoot;
this->nTime = other.nTime;
this->nBits = other.nBits;
this->nNonce = other.nNonce;
this->hashStateRoot = other.hashStateRoot;
this->hashUTXORoot = other.hashUTXORoot;
this->vchBlockSigDlgt = other.vchBlockSigDlgt;
this->prevoutStake = other.prevoutStake;
}
return *this;
}
};


Expand Down Expand Up @@ -97,6 +158,11 @@ class CBlock : public CBlockHeader
fChecked = false;
}

std::pair<COutPoint, unsigned int> GetProofOfStake() const //qtum
{
return IsProofOfStake()? std::make_pair(prevoutStake, nTime) : std::make_pair(COutPoint(), (unsigned int)0);
}

CBlockHeader GetBlockHeader() const
{
CBlockHeader block;
Expand All @@ -106,6 +172,10 @@ class CBlock : public CBlockHeader
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
block.hashStateRoot = hashStateRoot; // qtum
block.hashUTXORoot = hashUTXORoot; // qtum
block.vchBlockSigDlgt = vchBlockSigDlgt;
block.prevoutStake = prevoutStake;
return block;
}

Expand Down
75 changes: 75 additions & 0 deletions src/primitives/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ uint256 CTransaction::ComputeWitnessHash() const
return (CHashWriter{0} << *this).GetHash();
}

CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash{}, m_witness_hash{} {}
CTransaction::CTransaction(const CMutableTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
CTransaction::CTransaction(CMutableTransaction&& tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}

Expand Down Expand Up @@ -120,3 +121,77 @@ std::string CTransaction::ToString() const
str += " " + tx_out.ToString() + "\n";
return str;
}

///////////////////////////////////////////////////////////// qtum
bool CTransaction::HasCreateOrCall() const{
for(const CTxOut& v : vout){
if(v.scriptPubKey.HasOpCreate() || v.scriptPubKey.HasOpCall()){
return true;
}
}
return false;
}



bool CTransaction::HasOpSpend() const{
for(const CTxIn& i : vin){
if(i.scriptSig.HasOpSpend()){
return true;
}
}
return false;
}
/////////////////////////////////////////////////////////////

bool CTransaction::HasOpCreate() const
{
for(const CTxOut& v : vout){
if(v.scriptPubKey.HasOpCreate()){
return true;
}
}
return false;
}

template <class T>
bool hasOpCall(const T& txTo)
{
for(const CTxOut& v : txTo.vout){
if(v.scriptPubKey.HasOpCall()){
return true;
}
}
return false;
}

bool CTransaction::HasOpCall() const
{
return hasOpCall(*this);
}

bool CMutableTransaction::HasOpCall() const
{
return hasOpCall(*this);
}

template <class T>
bool hasOpSender(const T& txTo)
{
for(const CTxOut& v : txTo.vout){
if(v.scriptPubKey.HasOpSender()){
return true;
}
}
return false;
}

bool CTransaction::HasOpSender() const
{
return hasOpSender(*this);
}

bool CMutableTransaction::HasOpSender() const
{
return hasOpSender(*this);
}
Loading

0 comments on commit b905e2a

Please sign in to comment.