Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wvla],[CXXFLAGS="$CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wshadow],[CXXFLAGS="$CXXFLAGS -Wshadow"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[CXXFLAGS="$CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])

## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
## unknown options if any other warning is produced. Test the -Wfoo case, and
Expand Down
16 changes: 10 additions & 6 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ BITCOIN_CORE_H = \
bip39.h \
bip39_english.h \
blockencodings.h \
blocksigner.h \
bloom.h \
cachemap.h \
cachemultimap.h \
Expand Down Expand Up @@ -163,6 +164,7 @@ BITCOIN_CORE_H = \
key.h \
keepass.h \
keystore.h \
kernel.h \
dbwrapper.h \
limitedmap.h \
llmq/quorums.h \
Expand Down Expand Up @@ -265,6 +267,7 @@ libdash_server_a_SOURCES = \
batchedlogger.cpp \
bloom.cpp \
blockencodings.cpp \
blocksigner.cpp \
chain.cpp \
checkpoints.cpp \
dsnotificationinterface.cpp \
Expand All @@ -279,6 +282,7 @@ libdash_server_a_SOURCES = \
httpserver.cpp \
init.cpp \
instantx.cpp \
kernel.cpp \
dbwrapper.cpp \
governance.cpp \
governance-classes.cpp \
Expand Down Expand Up @@ -673,9 +677,9 @@ if EMBEDDED_LEVELDB
include Makefile.leveldb.include
endif

if ENABLE_TESTS
include Makefile.test.include
endif
#if ENABLE_TESTS
#include Makefile.test.include
#endif

if ENABLE_BENCH
include Makefile.bench.include
Expand All @@ -685,6 +689,6 @@ if ENABLE_QT
include Makefile.qt.include
endif

if ENABLE_QT_TESTS
include Makefile.qttest.include
endif
#if ENABLE_QT_TESTS
#include Makefile.qttest.include
#endif
4 changes: 3 additions & 1 deletion src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,9 @@ RES_ICONS = \
qt/res/icons/trad/verify.png \
qt/res/icons/trad/fontbigger.png \
qt/res/icons/trad/fontsmaller.png \
qt/res/icons/trad/network_disabled.png
qt/res/icons/trad/network_disabled.png \
qt/res/icons/staking_active.png \
qt/res/icons/staking_inactive.png

BITCOIN_QT_BASE_CPP = \
qt/bantablemodel.cpp \
Expand Down
83 changes: 83 additions & 0 deletions src/blocksigner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <blocksigner.h>
#include <keystore.h>
#include <primitives/block.h>
#include <utilstrencodings.h>
#include <messagesigner.h>
#include <util.h>

typedef std::vector<uint8_t> valtype;

bool SignBlockWithKey(CBlock& block, const CKey& key)
{
if (!key.Sign(block.GetHash(), block.vchBlockSig))
return error("%s: failed to sign block hash with key", __func__);

return true;
}

bool GetKeyIDFromUTXO(const CTxOut& txout, CKeyID& keyID)
{
std::vector<valtype> vSolutions;
txnouttype whichType;
if (!Solver(txout.scriptPubKey, whichType, vSolutions))
return false;
if (whichType == TX_PUBKEY) {
keyID = CPubKey(vSolutions[0]).GetID();
} else if (whichType == TX_PUBKEYHASH) {
keyID = CKeyID(uint160(vSolutions[0]));
}

return true;
}

bool SignBlock(CBlock& block, const CKeyStore& keystore)
{
std::vector<valtype> vSolutions;
CKeyID keyID;
if (block.IsProofOfWork()) {
bool fFoundID = false;
for (const CTxOut& txout :block.vtx[0]->vout) {
if (!GetKeyIDFromUTXO(txout, keyID))
continue;
fFoundID = true;
break;
}
if (!fFoundID)
return error("%s: failed to find key for PoW", __func__);
} else {
if (!GetKeyIDFromUTXO(block.vtx[1]->vout[1], keyID))
return error("%s: failed to find key for PoS", __func__);
}

CKey key;
if (!keystore.GetKey(keyID, key))
return error("%s: failed to get key from keystore", __func__);

return SignBlockWithKey(block, key);
}

bool CheckBlockSignature(const CBlock& block)
{
std::vector<valtype> vSolutions;

if (block.IsProofOfWork())
return block.vchBlockSig.empty();

if (block.vchBlockSig.empty())
return error("%s: vchBlockSig is empty!", __func__);

CPubKey pubkey;
txnouttype whichType;
const CTxOut& txout = block.vtx[1]->vout[1];
if (!Solver(txout.scriptPubKey, whichType, vSolutions))
return false;
if (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) {
valtype& vchPubKey = vSolutions[0];
pubkey = CPubKey(vchPubKey);
}

if (!pubkey.IsValid())
return error("%s: invalid pubkey %s", __func__, HexStr(pubkey));

return pubkey.Verify(block.GetHash(), block.vchBlockSig);
}
13 changes: 13 additions & 0 deletions src/blocksigner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef BLOCKSIGNER_H
#define BLOCKSIGNER_H

class CBlock;
class CPubKey;
class CKey;
class CKeyStore;

bool SignBlockWithKey(CBlock& block, const CKey& key);
bool SignBlock(CBlock& block, const CKeyStore& keystore);
bool CheckBlockSignature(const CBlock& block);

#endif // BLOCKSIGNER_H
52 changes: 52 additions & 0 deletions src/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,22 @@ const CBlockIndex* CBlockIndex::GetAncestor(int height) const
return const_cast<CBlockIndex*>(this)->GetAncestor(height);
}

unsigned int CBlockIndex::GetStakeEntropyBit() const
{
unsigned int nEntropyBit = (UintToArith256(GetBlockHash()).GetLow64() & 1);
if (GetBoolArg("-printstakemodifier", false))
LogPrintf("GetStakeEntropyBit: nHeight=%u hashBlock=%s nEntropyBit=%u\n", nHeight, GetBlockHash().ToString().c_str(), nEntropyBit);

return nEntropyBit;
}

void CBlockIndex::SetStakeModifier(uint64_t nModifier, bool fGeneratedStakeModifier)
{
nStakeModifier = nModifier;
if (fGeneratedStakeModifier)
nFlags |= BLOCK_STAKE_MODIFIER;
}

void CBlockIndex::BuildSkip()
{
if (pprev)
Expand Down Expand Up @@ -148,3 +164,39 @@ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& fr
}
return sign * r.GetLow64();
}

/** Find the last common ancestor two blocks have.
* Both pa and pb must be non-nullptr. */
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb) {
if (pa->nHeight > pb->nHeight) {
pa = pa->GetAncestor(pb->nHeight);
} else if (pb->nHeight > pa->nHeight) {
pb = pb->GetAncestor(pa->nHeight);
}

while (pa != pb && pa && pb) {
pa = pa->pprev;
pb = pb->pprev;
}

// Eventually all chain branches meet at the genesis block.
assert(pa == pb);
return pa;
}

arith_uint256 CBlockIndex::GetBlockTrust() const
{
arith_uint256 bnTarget;
bnTarget.SetCompact(nBits);
if (bnTarget <= 0)
return 0;

if (IsProofOfStake()) {
// Return trust score as usual
return (arith_uint256(1) << 256) / (bnTarget + 1);
} else {
// Calculate work amount for block
arith_uint256 bnPoWTrust = ((~arith_uint256(0) >> 20) / (bnTarget + 1));
return bnPoWTrust > 1 ? bnPoWTrust : 1;
}
}
99 changes: 97 additions & 2 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
#include "pow.h"
#include "tinyformat.h"
#include "uint256.h"
#include "util.h"

#include <vector>

/**
* Maximum amount of time that a block timestamp is allowed to exceed the
* current network-adjusted time before the block will be accepted.
*/
static const int64_t MAX_FUTURE_STAKE_TIME = 15 * 60;
static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;

/**
Expand Down Expand Up @@ -179,6 +181,9 @@ class CBlockIndex
//! pointer to the index of some further predecessor of this block
CBlockIndex* pskip;

//ppcoin: trust score of block chain
uint256 bnChainTrust;

//! height of the entry in the chain. The genesis block has height 0
int nHeight;

Expand All @@ -204,7 +209,24 @@ class CBlockIndex
unsigned int nChainTx;

//! Verification status of this block. See enum BlockStatus
unsigned int nStatus;
uint32_t nStatus;

unsigned int nFlags; // ppcoin: block index flags
enum {
BLOCK_PROOF_OF_STAKE = (1 << 0), // is proof-of-stake block
BLOCK_STAKE_ENTROPY = (1 << 1), // entropy bit for stake modifier
BLOCK_STAKE_MODIFIER = (1 << 2), // regenerated stake modifier
};

// proof-of-stake specific fields
arith_uint256 GetBlockTrust() const;
uint64_t nStakeModifier; // hash modifier for proof-of-stake
unsigned int nStakeModifierChecksum; // checksum of index; in-memeory only
COutPoint prevoutStake;
unsigned int nStakeTime;
uint256 hashProofOfStake;
int64_t nMint;
int64_t nMoneySupply;

//! block header
int nVersion;
Expand Down Expand Up @@ -235,6 +257,15 @@ class CBlockIndex
nSequenceId = 0;
nTimeMax = 0;

nMint = 0;
bnChainTrust = uint256();
nMoneySupply = 0;
nFlags = 0;
nStakeModifier = 0;
nStakeModifierChecksum = 0;
prevoutStake.SetNull();
nStakeTime = 0;

nVersion = 0;
hashMerkleRoot = uint256();
nTime = 0;
Expand All @@ -247,7 +278,7 @@ class CBlockIndex
SetNull();
}

CBlockIndex(const CBlockHeader& block)
CBlockIndex(const CBlock& block)
{
SetNull();

Expand All @@ -256,6 +287,24 @@ class CBlockIndex
nTime = block.nTime;
nBits = block.nBits;
nNonce = block.nNonce;

//Proof of Stake
bnChainTrust = uint256();
nMint = 0;
nMoneySupply = 0;
nFlags = 0;
nStakeModifier = 0;
nStakeModifierChecksum = 0;
hashProofOfStake = uint256();

if (block.IsProofOfStake()) {
SetProofOfStake();
prevoutStake = block.vtx[1]->vin[0].prevout;
nStakeTime = block.nTime;
} else {
prevoutStake.SetNull();
nStakeTime = 0;
}
}

CDiskBlockPos GetBlockPos() const {
Expand Down Expand Up @@ -320,6 +369,38 @@ class CBlockIndex
return pbegin[(pend - pbegin)/2];
}

bool IsProofOfWork() const
{
return !(nFlags & BLOCK_PROOF_OF_STAKE);
}

bool IsProofOfStake() const
{
return (nFlags & BLOCK_PROOF_OF_STAKE);
}

void SetProofOfStake()
{
nFlags |= BLOCK_PROOF_OF_STAKE;
}

unsigned int GetStakeEntropyBit() const;

bool SetStakeEntropyBit(unsigned int nEntropyBit)
{
if (nEntropyBit > 1)
return false;
nFlags |= (nEntropyBit ? BLOCK_STAKE_ENTROPY : 0);
return true;
}

bool GeneratedStakeModifier() const
{
return (nFlags & BLOCK_STAKE_MODIFIER);
}

void SetStakeModifier(uint64_t nModifier, bool fGeneratedStakeModifier);

std::string ToString() const
{
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
Expand Down Expand Up @@ -398,6 +479,20 @@ class CDiskBlockIndex : public CBlockIndex
if (nStatus & BLOCK_HAVE_UNDO)
READWRITE(VARINT(nUndoPos));

READWRITE(nMint);
READWRITE(nMoneySupply);
READWRITE(nFlags);
READWRITE(nStakeModifier);
if (IsProofOfStake()) {
READWRITE(prevoutStake);
READWRITE(nStakeTime);
READWRITE(hashProofOfStake);
} else {
const_cast<CDiskBlockIndex*>(this)->prevoutStake.SetNull();
const_cast<CDiskBlockIndex*>(this)->nStakeTime = 0;
const_cast<CDiskBlockIndex*>(this)->hashProofOfStake = uint256();
}

// block hash
READWRITE(hash);
// block header
Expand Down
Loading