Changes for most chain power rule

This commit is contained in:
miketout
2018-09-28 01:38:14 -07:00
parent f82b75eb8b
commit 4b729ec577
51 changed files with 666 additions and 444 deletions

View File

@@ -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;
}