PoS improvements
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#include "utilstrencodings.h"
|
||||
#include "crypto/common.h"
|
||||
|
||||
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH;
|
||||
|
||||
// default hash algorithm for block
|
||||
uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash;
|
||||
|
||||
@@ -43,6 +45,47 @@ void CBlockHeader::SetVerusHash()
|
||||
CBlockHeader::hashFunction = &CBlockHeader::GetVerusHash;
|
||||
}
|
||||
|
||||
// returns false if unable to fast calculate the VerusPOSHash from the header. it can still be calculated from the block
|
||||
// in that case
|
||||
bool CBlockHeader::GetVerusPOSHash(uint256 &value, int32_t nHeight) const
|
||||
{
|
||||
// if below the required height or no storage space in the solution, we can't get
|
||||
// a cached txid value to calculate the POSHash from the header
|
||||
if (!(CPOSNonce::NewNonceActive(nHeight) && IsVerusPOSBlock()))
|
||||
return false;
|
||||
|
||||
// if we can calculate, this assumes the protocol that the POSHash calculation is:
|
||||
// hashWriter << ASSETCHAINS_MAGIC;
|
||||
// hashWriter << nNonce; (nNonce is:
|
||||
// (high 128 bits == low 128 bits of verus hash of low 128 bits of nonce)
|
||||
// (low 32 bits == compact PoS difficult)
|
||||
// (mid 96 bits == low 96 bits of HASH(pastHash, txid, voutnum)
|
||||
// pastHash is hash of height - 100, either PoW hash of block or PoS hash, if new PoS
|
||||
// )
|
||||
// hashWriter << height;
|
||||
// return hashWriter.GetHash();
|
||||
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
|
||||
hashWriter << ASSETCHAINS_MAGIC;
|
||||
hashWriter << nNonce;
|
||||
hashWriter << nHeight;
|
||||
value = hashWriter.GetHash();
|
||||
return true;
|
||||
}
|
||||
|
||||
// depending on the height of the block and its type, this returns the POS hash or the POW hash
|
||||
uint256 CBlockHeader::GetVerusEntropyHash(int32_t height) const
|
||||
{
|
||||
uint256 retVal;
|
||||
// if we qualify as PoW, use PoW hash, regardless of PoS state
|
||||
if (GetVerusPOSHash(retVal, height))
|
||||
{
|
||||
// POS hash
|
||||
return retVal;
|
||||
}
|
||||
return GetHash();
|
||||
}
|
||||
|
||||
uint256 CBlock::BuildMerkleTree(bool* fMutated) const
|
||||
{
|
||||
/* WARNING! If you're reading this because you're learning about crypto
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define BITCOIN_PRIMITIVES_BLOCK_H
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
#include "primitives/nonce.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "arith_uint256.h"
|
||||
@@ -33,7 +34,7 @@ public:
|
||||
uint256 hashReserved;
|
||||
uint32_t nTime;
|
||||
uint32_t nBits;
|
||||
uint256 nNonce;
|
||||
CPOSNonce nNonce;
|
||||
std::vector<unsigned char> nSolution;
|
||||
|
||||
CBlockHeader()
|
||||
@@ -84,6 +85,9 @@ public:
|
||||
uint256 GetVerusHash() const;
|
||||
static void SetVerusHash();
|
||||
|
||||
bool GetVerusPOSHash(uint256 &value, int32_t nHeight) const;
|
||||
uint256 GetVerusEntropyHash(int32_t nHeight) const;
|
||||
|
||||
uint256 GetVerusV2Hash() const;
|
||||
|
||||
int64_t GetBlockTime() const
|
||||
@@ -105,11 +109,7 @@ public:
|
||||
|
||||
bool IsVerusPOSBlock() const
|
||||
{
|
||||
arith_uint256 arNonce = UintToArith256(nNonce);
|
||||
arith_uint256 tmpNonce = ((arNonce << 128) >> 128);
|
||||
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
hashWriter << ArithToUint256(tmpNonce);
|
||||
return (nNonce == ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce));
|
||||
return nNonce.IsPOSNonce();
|
||||
}
|
||||
|
||||
void SetVerusPOSTarget(int32_t nBits)
|
||||
|
||||
68
src/primitives/nonce.cpp
Normal file
68
src/primitives/nonce.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2018 Michael Toutonghi
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "hash.h"
|
||||
#include "nonce.h"
|
||||
#include <cstring>
|
||||
|
||||
extern char ASSETCHAINS_SYMBOL[65];
|
||||
|
||||
bool CPOSNonce::NewPOSActive(int32_t height)
|
||||
{
|
||||
if ((strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0) || (height < (96480 + 100)))
|
||||
return false;
|
||||
else if ((strcmp(ASSETCHAINS_SYMBOL, "VRSCTEST") == 0) && (height < (1000 + 100)))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPOSNonce::NewNonceActive(int32_t height)
|
||||
{
|
||||
if ((strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0) || (height < 96480))
|
||||
return false;
|
||||
else if ((strcmp(ASSETCHAINS_SYMBOL, "VRSCTEST") == 0) && (height < 1000))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPOSNonce::SetPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum)
|
||||
{
|
||||
// get low 96 bits of past hash and put it in top 96 bits of low 128 bits of nonce
|
||||
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
|
||||
// first hash the pastHash, txid, and voutNum, to create a combined 96 bits, which will be used in the nonce
|
||||
hashWriter << pastHash;
|
||||
hashWriter << txid;
|
||||
hashWriter << voutNum;
|
||||
|
||||
arith_uint256 arNonce = (UintToArith256(*this) & 0xffffffff) |
|
||||
((UintToArith256(hashWriter.GetHash()) & UintToArith256(uint256S("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))) << 32);
|
||||
|
||||
hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
hashWriter << ArithToUint256(arNonce);
|
||||
|
||||
*this = CPOSNonce(ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | arNonce));
|
||||
}
|
||||
|
||||
bool CPOSNonce::CheckPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum)
|
||||
{
|
||||
// get low 96 bits of past hash and put it in top 96 bits of low 128 bits of nonce
|
||||
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
|
||||
// first hash the pastHash, txid, and voutNum, to create a combined 96 bits, which will be used in the nonce
|
||||
hashWriter << pastHash;
|
||||
hashWriter << txid;
|
||||
hashWriter << voutNum;
|
||||
|
||||
arith_uint256 arNonce = (UintToArith256(*this) & 0xffffffff) |
|
||||
((UintToArith256(hashWriter.GetHash()) & UintToArith256(uint256S("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))) << 32);
|
||||
|
||||
hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
hashWriter << ArithToUint256(arNonce);
|
||||
|
||||
return UintToArith256(*this) == (UintToArith256(hashWriter.GetHash()) << 128 | arNonce);
|
||||
}
|
||||
|
||||
66
src/primitives/nonce.h
Normal file
66
src/primitives/nonce.h
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2018 Michael Toutonghi
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_PRIMITIVES_NONCE_H
|
||||
#define BITCOIN_PRIMITIVES_NONCE_H
|
||||
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "arith_uint256.h"
|
||||
|
||||
|
||||
/** For POS blocks, the nNonce of a block header holds the entropy source for the POS contest
|
||||
* in the latest VerusHash protocol, implemented at block below
|
||||
*
|
||||
* */
|
||||
class CPOSNonce : public uint256
|
||||
{
|
||||
public:
|
||||
static bool NewPOSActive(int32_t height);
|
||||
static bool NewNonceActive(int32_t height);
|
||||
|
||||
CPOSNonce() {}
|
||||
CPOSNonce(const base_blob<256> &b) : uint256(b) {}
|
||||
CPOSNonce(const std::vector<unsigned char> &vch) : uint256(vch) {}
|
||||
|
||||
int32_t GetPOSTarget() const
|
||||
{
|
||||
uint32_t nBits = 0;
|
||||
|
||||
for (const unsigned char *p = begin() + 3; p >= begin(); p--)
|
||||
{
|
||||
nBits <<= 8;
|
||||
nBits += *p;
|
||||
}
|
||||
return nBits;
|
||||
}
|
||||
|
||||
bool IsPOSNonce() const
|
||||
{
|
||||
arith_uint256 arNonce = UintToArith256(*this);
|
||||
arith_uint256 tmpNonce = ((arNonce << 128) >> 128);
|
||||
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
hashWriter << ArithToUint256(tmpNonce);
|
||||
return (*this == ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce));
|
||||
}
|
||||
|
||||
void SetPOSTarget(int32_t nBits)
|
||||
{
|
||||
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
arith_uint256 tmpNonce;
|
||||
|
||||
arith_uint256 arNonce = UintToArith256(*this);
|
||||
arNonce = ((arNonce >> 32) << 32) | nBits;
|
||||
|
||||
tmpNonce = ((arNonce << 128) >> 128);
|
||||
hashWriter << ArithToUint256(tmpNonce);
|
||||
|
||||
(uint256 &)(*this) = ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce);
|
||||
}
|
||||
|
||||
void SetPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum);
|
||||
bool CheckPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_PRIMITIVES_NONCE_H
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "arith_uint256.h"
|
||||
#include "consensus/consensus.h"
|
||||
#include "hash.h"
|
||||
#include "nonce.h"
|
||||
|
||||
#ifndef __APPLE__
|
||||
#include <stdint.h>
|
||||
@@ -474,25 +475,39 @@ public:
|
||||
}
|
||||
|
||||
// verus hash will be the same for a given txid, output number, block height, and blockhash of 100 blocks past
|
||||
static uint256 _GetVerusPOSHash(const uint256 &txid, int32_t voutNum, int32_t height, const uint256 &pastHash, int64_t value)
|
||||
static uint256 _GetVerusPOSHash(CPOSNonce *pNonce, const uint256 &txid, int32_t voutNum, int32_t height, const uint256 &pastHash, int64_t value)
|
||||
{
|
||||
pNonce->SetPOSEntropy(pastHash, txid, voutNum);
|
||||
CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
|
||||
hashWriter << ASSETCHAINS_MAGIC;
|
||||
hashWriter << pastHash;
|
||||
hashWriter << height;
|
||||
hashWriter << txid;
|
||||
hashWriter << voutNum;
|
||||
return hashWriter.GetHash();
|
||||
|
||||
// we only use the new style of POS hash after changeover and 100 blocks of enforced proper nonce updating
|
||||
if (CPOSNonce::NewPOSActive(height))
|
||||
{
|
||||
hashWriter << *pNonce;
|
||||
hashWriter << height;
|
||||
return hashWriter.GetHash();
|
||||
}
|
||||
else
|
||||
{
|
||||
hashWriter << pastHash;
|
||||
hashWriter << height;
|
||||
hashWriter << txid;
|
||||
hashWriter << voutNum;
|
||||
return hashWriter.GetHash();
|
||||
}
|
||||
}
|
||||
|
||||
uint256 GetVerusPOSHash(int32_t voutNum, int32_t height, const uint256 &pastHash) const
|
||||
// Nonce is modified to include the transaction information
|
||||
uint256 GetVerusPOSHash(CPOSNonce *pNonce, int32_t voutNum, int32_t height, const uint256 &pastHash) const
|
||||
{
|
||||
uint256 txid = GetHash();
|
||||
|
||||
if (voutNum >= vout.size())
|
||||
return uint256S("ff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
|
||||
|
||||
return ArithToUint256(UintToArith256(_GetVerusPOSHash(txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue)) / vout[voutNum].nValue);
|
||||
return ArithToUint256(UintToArith256(_GetVerusPOSHash(pNonce, txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue)) / vout[voutNum].nValue);
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
Reference in New Issue
Block a user