Changes for most chain power rule
This commit is contained in:
128
src/chain.h
128
src/chain.h
@@ -6,6 +6,8 @@
|
||||
#ifndef BITCOIN_CHAIN_H
|
||||
#define BITCOIN_CHAIN_H
|
||||
|
||||
class CChainPower;
|
||||
|
||||
#include "arith_uint256.h"
|
||||
#include "primitives/block.h"
|
||||
#include "pow.h"
|
||||
@@ -103,6 +105,101 @@ enum BlockStatus: uint32_t {
|
||||
//! Blocks with this validity are assumed to satisfy all consensus rules.
|
||||
static const BlockStatus BLOCK_VALID_CONSENSUS = BLOCK_VALID_SCRIPTS;
|
||||
|
||||
class CBlockIndex;
|
||||
|
||||
// This class provides an accumulator for both the chainwork and the chainPOS value
|
||||
// CChainPower's can be compared, and the comparison ensures that work and proof of stake power
|
||||
// are both used equally to determine which chain has the most work. This makes an attack
|
||||
// that involves mining in secret completely ineffective, even before dPOW, unless a large part
|
||||
// of the staking supply is also controlled. It also enables a faster deterministic convergence,
|
||||
// aided by both POS and POW.
|
||||
class CChainPower
|
||||
{
|
||||
public:
|
||||
arith_uint256 chainWork;
|
||||
arith_uint256 chainStake;
|
||||
int32_t nHeight;
|
||||
|
||||
CChainPower() : nHeight(0), chainStake(0), chainWork(0) {}
|
||||
CChainPower(CBlockIndex *pblockIndex);
|
||||
CChainPower(CBlockIndex *pblockIndex, const arith_uint256 &stake, const arith_uint256 &work);
|
||||
CChainPower(int32_t height) : nHeight(height), chainStake(0), chainWork(0) {}
|
||||
CChainPower(int32_t height, const arith_uint256 &stake, const arith_uint256 &work) :
|
||||
nHeight(height), chainStake(stake), chainWork(work) {}
|
||||
|
||||
CChainPower &operator=(const CChainPower &chainPower)
|
||||
{
|
||||
chainWork = chainPower.chainWork;
|
||||
chainStake = chainPower.chainStake;
|
||||
nHeight = chainPower.nHeight;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CChainPower &operator+=(const CChainPower &chainPower)
|
||||
{
|
||||
this->chainWork += chainPower.chainWork;
|
||||
this->chainStake += chainPower.chainStake;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend CChainPower operator+(const CChainPower &chainPowerA, const CChainPower &chainPowerB)
|
||||
{
|
||||
CChainPower result = CChainPower(chainPowerA);
|
||||
result.chainWork += chainPowerB.chainWork;
|
||||
result.chainStake += chainPowerB.chainStake;
|
||||
return result;
|
||||
}
|
||||
|
||||
friend CChainPower operator-(const CChainPower &chainPowerA, const CChainPower &chainPowerB)
|
||||
{
|
||||
CChainPower result = CChainPower(chainPowerA);
|
||||
result.chainWork -= chainPowerB.chainWork;
|
||||
result.chainStake -= chainPowerB.chainStake;
|
||||
return result;
|
||||
}
|
||||
|
||||
friend CChainPower operator*(const CChainPower &chainPower, int32_t x)
|
||||
{
|
||||
CChainPower result = CChainPower(chainPower);
|
||||
result.chainWork *= x;
|
||||
result.chainStake *= x;
|
||||
return result;
|
||||
}
|
||||
|
||||
CChainPower &addStake(const arith_uint256 &nChainStake)
|
||||
{
|
||||
chainStake += nChainStake;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CChainPower &addWork(const arith_uint256 &nChainWork)
|
||||
{
|
||||
chainWork += nChainWork;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const CChainPower &p1, const CChainPower &p2);
|
||||
|
||||
friend bool operator!=(const CChainPower &p1, const CChainPower &p2)
|
||||
{
|
||||
return !(p1 == p2);
|
||||
}
|
||||
|
||||
friend bool operator<(const CChainPower &p1, const CChainPower &p2);
|
||||
|
||||
friend bool operator<=(const CChainPower &p1, const CChainPower &p2);
|
||||
|
||||
friend bool operator>(const CChainPower &p1, const CChainPower &p2)
|
||||
{
|
||||
return !(p1 <= p2);
|
||||
}
|
||||
|
||||
friend bool operator>=(const CChainPower &p1, const CChainPower &p2)
|
||||
{
|
||||
return !(p1 < p2);
|
||||
}
|
||||
};
|
||||
|
||||
/** The block chain is a tree shaped structure starting with the
|
||||
* genesis block at the root, with each block potentially having multiple
|
||||
* candidates to be the next block. A blockindex may have multiple pprev pointing
|
||||
@@ -121,7 +218,6 @@ public:
|
||||
CBlockIndex* pskip;
|
||||
|
||||
//! height of the entry in the chain. The genesis block has height 0
|
||||
int nHeight;
|
||||
int64_t newcoins,zfunds; int8_t segid; // jl777 fields
|
||||
//! Which # file this block is stored in (blk?????.dat)
|
||||
int nFile;
|
||||
@@ -133,7 +229,7 @@ public:
|
||||
unsigned int nUndoPos;
|
||||
|
||||
//! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
|
||||
arith_uint256 nChainWork;
|
||||
CChainPower chainPower;
|
||||
|
||||
//! Number of transactions in this block.
|
||||
//! Note: in a potential headers-first mode, this number cannot be relied upon
|
||||
@@ -195,11 +291,10 @@ public:
|
||||
segid = -2;
|
||||
pprev = NULL;
|
||||
pskip = NULL;
|
||||
nHeight = 0;
|
||||
nFile = 0;
|
||||
nDataPos = 0;
|
||||
nUndoPos = 0;
|
||||
nChainWork = arith_uint256();
|
||||
chainPower = CChainPower();
|
||||
nTx = 0;
|
||||
nChainTx = 0;
|
||||
nStatus = 0;
|
||||
@@ -239,6 +334,16 @@ public:
|
||||
nSolution = block.nSolution;
|
||||
}
|
||||
|
||||
int32_t SetHeight(int32_t height)
|
||||
{
|
||||
this->chainPower.nHeight = height;
|
||||
}
|
||||
|
||||
inline int32_t GetHeight() const
|
||||
{
|
||||
return this->chainPower.nHeight;
|
||||
}
|
||||
|
||||
CDiskBlockPos GetBlockPos() const {
|
||||
CDiskBlockPos ret;
|
||||
if (nStatus & BLOCK_HAVE_DATA) {
|
||||
@@ -301,7 +406,7 @@ public:
|
||||
std::string ToString() const
|
||||
{
|
||||
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||
pprev, nHeight,
|
||||
pprev, this->chainPower.nHeight,
|
||||
hashMerkleRoot.ToString(),
|
||||
GetBlockHash().ToString());
|
||||
}
|
||||
@@ -353,7 +458,7 @@ class CDiskBlockIndex : public CBlockIndex
|
||||
public:
|
||||
uint256 hashPrev;
|
||||
|
||||
CDiskBlockIndex() {
|
||||
CDiskBlockIndex() : CBlockIndex() {
|
||||
hashPrev = uint256();
|
||||
}
|
||||
|
||||
@@ -369,7 +474,10 @@ public:
|
||||
if (!(s.GetType() & SER_GETHASH))
|
||||
READWRITE(VARINT(nVersion));
|
||||
|
||||
READWRITE(VARINT(nHeight));
|
||||
if (ser_action.ForRead()) {
|
||||
chainPower = CChainPower();
|
||||
}
|
||||
READWRITE(VARINT(chainPower.nHeight));
|
||||
READWRITE(VARINT(nStatus));
|
||||
READWRITE(VARINT(nTx));
|
||||
if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO))
|
||||
@@ -478,18 +586,18 @@ public:
|
||||
|
||||
/** Efficiently check whether a block is present in this chain. */
|
||||
bool Contains(const CBlockIndex *pindex) const {
|
||||
return (*this)[pindex->nHeight] == pindex;
|
||||
return (*this)[pindex->GetHeight()] == pindex;
|
||||
}
|
||||
|
||||
/** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
|
||||
CBlockIndex *Next(const CBlockIndex *pindex) const {
|
||||
if (Contains(pindex))
|
||||
return (*this)[pindex->nHeight + 1];
|
||||
return (*this)[pindex->GetHeight() + 1];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
|
||||
/** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->GetHeight() : -1. */
|
||||
int Height() const {
|
||||
return vChain.size() - 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user