Some code refactoring and cleanup

This commit is contained in:
lateminer
2018-10-02 01:04:31 +03:00
parent 3f46f91ace
commit 3a29ae6903
10 changed files with 283 additions and 313 deletions

View File

@@ -968,8 +968,8 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
CAmount nValueOut = 0;
BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
if (txout.IsEmpty() && !tx.IsCoinBase() && !tx.IsCoinStake())
return state.DoS(100, error("CheckTransaction(): txout empty for user transaction"));
if (txout.IsEmpty() && !tx.IsCoinBase() && !tx.IsCoinStake())
return state.DoS(100, error("CheckTransaction(): txout empty for user transaction"));
if (txout.nValue < 0)
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
if (txout.nValue > MAX_MONEY)
@@ -1076,7 +1076,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// Coinstake is also only valid in a block, not as a loose transaction
if (tx.IsCoinStake())
return state.DoS(100, error("AcceptToMemoryPool: coinstake as individual tx"),
REJECT_INVALID, "coinstake");
REJECT_INVALID, "coinstake");
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
string reason;
@@ -1098,7 +1098,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// For the same reasons as in the case with non-final transactions
if (tx.nTime > FutureDrift(GetAdjustedTime())) {
return state.DoS(0, false, REJECT_NONSTANDARD, "time-too-new");
return state.DoS(0, false, REJECT_NONSTANDARD, "time-too-new");
}
// is it already in the memory pool?
@@ -1701,8 +1701,8 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
bool ReadFromDisk(CTransaction& tx, CDiskTxPos& txindex, CBlockTreeDB& txdb, COutPoint prevout)
{
if (!txdb.ReadTxIndex(prevout.hash, txindex)){
LogPrintf("no tx index %s \n", prevout.hash.ToString());
return false;
LogPrintf("no tx index %s \n", prevout.hash.ToString());
return false;
}
if (!ReadFromDisk(tx, txindex))
return false;
@@ -1735,7 +1735,7 @@ bool ReadFromDisk(CTransaction& tx, CDiskTxPos& txindex)
CAmount GetProofOfWorkSubsidy()
{
return 10000 * COIN;
return 10000 * COIN;
}
CAmount GetProofOfStakeSubsidy()
@@ -1952,7 +1952,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
class CachingTransactionSignatureCheckerWithBlockReader : public CachingTransactionSignatureChecker, public BaseBlockReader
{
typedef std::pair<uint256, CTransaction> CoinbaseCacheItem;
typedef std::pair<uint256, CTransaction> CoinbaseCacheItem;
typedef boost::multi_index_container<
CoinbaseCacheItem,
boost::multi_index::indexed_by<
@@ -1961,12 +1961,12 @@ class CachingTransactionSignatureCheckerWithBlockReader : public CachingTransact
boost::multi_index::member<CoinbaseCacheItem, uint256, &CoinbaseCacheItem::first>
>
>
> CoinbaseCacheContainer;
> CoinbaseCacheContainer;
int nHeight;
uint256 hash;
mutable boost::mutex mutexCache;
mutable boost::mutex mutexCache;
mutable CoinbaseCacheContainer cacheCoinbase; // block hash -> block coinbase
void UpdateCache(const CoinbaseCacheItem& coinbase) const;
@@ -2005,8 +2005,8 @@ CTransaction CachingTransactionSignatureCheckerWithBlockReader::GetBlockCoinbase
return CTransaction();
CBlockIndex* pblockindex = chainActive[nHeight];
{
{
boost::lock_guard<boost::mutex> lock(mutexCache);
CoinbaseCacheContainer::nth_index<1>::type::iterator it = cacheCoinbase.get<1>().find(*pblockindex->phashBlock);
if (it != cacheCoinbase.get<1>().end())
@@ -2022,7 +2022,7 @@ CTransaction CachingTransactionSignatureCheckerWithBlockReader::GetBlockCoinbase
CTransaction CachingTransactionSignatureCheckerWithBlockReader::ReadBlockCoinbase(CBlockIndex* pblockindex) const
{
CBlock block;
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
@@ -2100,7 +2100,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
// Check transaction timestamp
if (coins->nTime > tx.nTime)
return state.DoS(100, error("CheckInputs() : transaction timestamp earlier than input transaction"),
REJECT_INVALID, "bad-txns-time-earlier-than-input");
REJECT_INVALID, "bad-txns-time-earlier-than-input");
// Check for negative or overflow input values
nValueIn += coins->vout[prevout.n].nValue;
@@ -2134,7 +2134,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
{
if (!tx.IsCoinBase())
{
int height = GetSpendHeight(inputs);
int height = GetSpendHeight(inputs);
if (!Consensus::CheckTxInputs(tx, state, inputs, height))
return false;
@@ -2350,13 +2350,13 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), hash, k), CAddressUnspentValue()));
} else if(out.scriptPubKey.IsPayToPublicKey()){
uint160 uhashBytes = Hash160(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34);
uint160 uhashBytes = Hash160(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34);
// record receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, uhashBytes, pindex->nHeight, i, hash, k, false), out.nValue));
// record receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, uhashBytes, pindex->nHeight, i, hash, k, false), out.nValue));
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uhashBytes, hash, k), CAddressUnspentValue()));
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uhashBytes, hash, k), CAddressUnspentValue()));
} else {
continue;
@@ -2425,13 +2425,13 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight, tx.nTime)));
} else if(prevout.scriptPubKey.IsPayToPublicKey()){
uint160 uhashBytes = Hash160(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34);
uint160 uhashBytes = Hash160(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34);
// record receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, uhashBytes, pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
// record receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, uhashBytes, pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uhashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight, tx.nTime)));
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uhashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight, tx.nTime)));
} else {
continue;
@@ -2549,17 +2549,15 @@ static int64_t nTimeIndex = 0;
static int64_t nTimeCallbacks = 0;
static int64_t nTimeTotal = 0;
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck)
{
const CChainParams& chainparams = Params();
const uint256& hash = pindex->GetBlockHash();
AssertLockHeld(cs_main);
int64_t nTimeStart = GetTimeMicros();
// Check it again in case a previous version let a bad block in
if (!CheckBlock(block, state, hash, !fJustCheck, !fJustCheck, !fJustCheck))
return false;
if (!CheckBlock(block, state, chainparams.GetConsensus(), !fJustCheck, !fJustCheck, !fJustCheck))
return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
// verify that the view's current state corresponds to the previous block
uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash();
@@ -2567,17 +2565,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
if (hash == chainparams.GetConsensus().hashGenesisBlock) {
if (!fJustCheck)
view.SetBestBlock(pindex->GetBlockHash());
return true;
if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) {
if (!fJustCheck)
view.SetBestBlock(pindex->GetBlockHash());
return true;
}
// Check difficulty
if (block.nBits != GetNextTargetRequired(pindex->pprev, &block, block.IsProofOfStake(), chainparams.GetConsensus()))
return state.DoS(100, error("%s: incorrect difficulty", __func__),
REJECT_INVALID, "bad-diffbits");
return state.DoS(100, error("%s: incorrect difficulty", __func__),
REJECT_INVALID, "bad-diffbits");
pindex->nStakeModifier = ComputeStakeModifier(pindex->pprev, block.IsProofOfStake() ? block.vtx[1].vin[0].prevout.hash : pindex->GetBlockHash());
@@ -2589,7 +2586,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state.DoS(100, error("%s: kernel input unavailable", __func__),
REJECT_INVALID, "bad-cs-kernel");
// Check proof-of-stake min confirmations
// Check proof-of-stake min confirmations
if (pindex->nHeight - coins->nHeight < chainparams.GetConsensus().nStakeMinConfirmations)
return state.DoS(100,
error("%s: tried to stake at depth %d", __func__, pindex->nHeight - coins->nHeight),
@@ -2658,13 +2655,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
flags |= SCRIPT_VERIFY_LOW_S;
// Start enforcing CHECKLOCKTIMEVERIFY, (BIP65) since protocol v3
if (block.GetBlockTime() > chainparams.GetConsensus().nProtocolV3Time) {
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
flags |= SCRIPT_VERIFY_NULLDUMMY;
}
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
// int nLockTimeFlags = 0;
// if (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) {
// flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
@@ -2679,7 +2675,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
std::vector<int> prevheights;
CAmount nFees = 0;
CAmount nActualStakeReward = 0;
CAmount nActualStakeReward = 0;
int nInputs = 0;
unsigned int nSigOps = 0;
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
@@ -2709,45 +2705,44 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (fAddressIndex || fSpentIndex)
{
for (size_t j = 0; j < tx.vin.size(); j++) {
for (size_t j = 0; j < tx.vin.size(); j++) {
const CTxIn input = tx.vin[j];
const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
uint160 hashBytes;
int addressType;
const CTxIn input = tx.vin[j];
const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
uint160 hashBytes;
int addressType;
if (prevout.scriptPubKey.IsPayToScriptHash()) {
hashBytes = uint160(vector <unsigned char>(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
addressType = 2;
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
hashBytes = uint160(vector <unsigned char>(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
addressType = 1;
} else if (prevout.scriptPubKey.IsPayToPublicKey()) {
hashBytes = Hash160(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34);
addressType = 1;
}
else {
hashBytes.SetNull();
addressType = 0;
}
if (prevout.scriptPubKey.IsPayToScriptHash()) {
hashBytes = uint160(vector <unsigned char>(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
addressType = 2;
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
hashBytes = uint160(vector <unsigned char>(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
addressType = 1;
} else if (prevout.scriptPubKey.IsPayToPublicKey()) {
hashBytes = Hash160(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34);
addressType = 1;
}
else {
hashBytes.SetNull();
addressType = 0;
}
if (fAddressIndex && addressType > 0) {
if (fAddressIndex && addressType > 0) {
// record spending activity
addressIndex.push_back(make_pair(CAddressIndexKey(addressType, hashBytes, pindex->nHeight, i, txhash, j, true), prevout.nValue * -1));
// record spending activity
addressIndex.push_back(make_pair(CAddressIndexKey(addressType, hashBytes, pindex->nHeight, i, txhash, j, true), prevout.nValue * -1));
// remove address from unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(addressType, hashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue()));
}
// remove address from unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(addressType, hashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue()));
}
if (fSpentIndex) {
// add the spent index to determine the txid and input that spent an output
// and to find the amount and address from an input
spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->nHeight, prevout.nValue, addressType, hashBytes)));
}
}
if (fSpentIndex) {
// add the spent index to determine the txid and input that spent an output
// and to find the amount and address from an input
spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->nHeight, prevout.nValue, addressType, hashBytes)));
}
}
}
if (fStrictPayToScriptHash)
@@ -2761,8 +2756,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
REJECT_INVALID, "bad-blk-sigops");
}
if (tx.IsCoinStake())
nActualStakeReward = tx.GetValueOut()-view.GetValueIn(tx);
if (tx.IsCoinStake())
nActualStakeReward = tx.GetValueOut()-view.GetValueIn(tx);
else
nFees += view.GetValueIn(tx)-tx.GetValueOut();
@@ -2797,17 +2792,17 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight, tx.nTime)));
} else if(out.scriptPubKey.IsPayToPublicKey()){
uint160 uhashBytes = Hash160(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34);
uint160 uhashBytes = Hash160(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34);
// record receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, uhashBytes, pindex->nHeight, i, txhash, k, false), out.nValue));
// record receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, uhashBytes, pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uhashBytes, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight, tx.nTime)));
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uhashBytes, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight, tx.nTime)));
}else{
} else {
continue;
continue;
}
@@ -2834,7 +2829,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
block.vtx[0].GetValueOut(), blockReward),
REJECT_INVALID, "bad-cb-amount");
}
if (block.IsProofOfStake() && block.GetBlockTime() > chainparams.GetConsensus().nProtocolV3Time) {
CAmount blockReward = nFees + GetProofOfStakeSubsidy();
if (nActualStakeReward > blockReward)
@@ -3182,7 +3177,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
{
CCoinsViewCache view(pcoinsTip);
bool rv = ConnectBlock(*pblock, state, pindexNew, view);
bool rv = ConnectBlock(*pblock, state, pindexNew, view, chainparams);
GetMainSignals().BlockChecked(*pblock, state);
if (!rv) {
if (state.IsInvalid())
@@ -3395,14 +3390,14 @@ static void NotifyHeaderTip() {
* or an activated best chain. pblock is either NULL or a pointer to a block
* that is already loaded (to avoid loading it again from disk).
*/
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock, const uint256 *phash) {
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock) {
CBlockIndex *pindexMostWork = NULL;
CBlockIndex *pindexNewTip = NULL;
do {
boost::this_thread::interruption_point();
if (ShutdownRequested())
break;
CBlockIndex *pindexNewTip = NULL;
const CBlockIndex *pindexFork;
bool fInitialDownload;
{
@@ -3417,7 +3412,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
return true;
bool fInvalidFound = false;
if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && (*phash) == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound))
if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound))
return false;
if (fInvalidFound) {
@@ -3561,57 +3556,58 @@ bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex) {
// age (trust score) of competing branches.
bool GetCoinAge(const CTransaction& tx, CBlockTreeDB& txdb, const CBlockIndex* pindexPrev, uint64_t& nCoinAge)
{
arith_uint256 bnCentSecond = 0; // coin age in the unit of cent-seconds
nCoinAge = 0;
arith_uint256 bnCentSecond = 0; // coin age in the unit of cent-seconds
nCoinAge = 0;
if (tx.IsCoinBase())
return true;
if (tx.IsCoinBase())
return true;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// First try finding the previous transaction in database
CTransaction txPrev;
CDiskTxPos txindex;
if (!ReadFromDisk(txPrev, txindex, *pblocktree, txin.prevout))
continue; // previous transaction not in main chain
if (tx.nTime < txPrev.nTime)
return false; // Transaction timestamp violation
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// First try finding the previous transaction in database
CTransaction txPrev;
CDiskTxPos txindex;
if (!ReadFromDisk(txPrev, txindex, *pblocktree, txin.prevout))
continue; // previous transaction not in main chain
if (tx.nTime < txPrev.nTime)
return false; // Transaction timestamp violation
if (Params().GetConsensus().IsProtocolV3(tx.nTime))
{
int nSpendDepth;
if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, Params().GetConsensus().nStakeMinConfirmations - 1, nSpendDepth))
{
LogPrint("coinage", "coin age skip nSpendDepth=%d\n", nSpendDepth + 1);
continue; // only count coins meeting min confirmations requirement
}
}
else
{
// Read block header
CBlock block;
const CDiskBlockPos& pos = CDiskBlockPos(txindex.nFile, txindex.nPos);
if (!ReadBlockFromDisk(block, pos, Params().GetConsensus()))
return false; // unable to read block of previous transaction
if (block.GetBlockTime() + Params().GetConsensus().nStakeMinAge > tx.nTime)
continue; // only count coins meeting min age requirement
}
if (Params().GetConsensus().IsProtocolV3(tx.nTime))
{
int nSpendDepth;
if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, Params().GetConsensus().nStakeMinConfirmations - 1, nSpendDepth))
{
LogPrint("coinage", "coin age skip nSpendDepth=%d\n", nSpendDepth + 1);
continue; // only count coins meeting min confirmations requirement
}
}
else
{
// Read block header
CBlock block;
const CDiskBlockPos& pos = CDiskBlockPos(txindex.nFile, txindex.nPos);
if (!ReadBlockFromDisk(block, pos, Params().GetConsensus()))
return false; // unable to read block of previous transaction
if (block.GetBlockTime() + Params().GetConsensus().nStakeMinAge > tx.nTime)
continue; // only count coins meeting min age requirement
}
int64_t nValueIn = txPrev.vout[txin.prevout.n].nValue;
bnCentSecond += arith_uint256(nValueIn) * (tx.nTime-txPrev.nTime) / CENT;
int64_t nValueIn = txPrev.vout[txin.prevout.n].nValue;
bnCentSecond += arith_uint256(nValueIn) * (tx.nTime-txPrev.nTime) / CENT;
LogPrint("coinage", "coin age nValueIn=%d nTimeDiff=%d bnCentSecond=%s\n", nValueIn, tx.nTime - txPrev.nTime, bnCentSecond.ToString());
}
LogPrint("coinage", "coin age nValueIn=%d nTimeDiff=%d bnCentSecond=%s\n", nValueIn, tx.nTime - txPrev.nTime, bnCentSecond.ToString());
}
arith_uint256 bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60);
LogPrint("coinage", "coin age bnCoinDay=%s\n", bnCoinDay.ToString());
nCoinAge = bnCoinDay.GetLow64();
return true;
arith_uint256 bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60);
LogPrint("coinage", "coin age bnCoinDay=%s\n", bnCoinDay.ToString());
nCoinAge = bnCoinDay.GetLow64();
return true;
}
static CBlockIndex* AddToBlockIndex(const CBlockHeader& block, const uint256& hash)
static CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
{
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator it = mapBlockIndex.find(hash);
if (it != mapBlockIndex.end())
return it->second;
@@ -3645,8 +3641,8 @@ static CBlockIndex* AddToBlockIndex(const CBlockHeader& block, const uint256& ha
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos)
{
if (block.IsProofOfStake())
pindexNew->SetProofOfStake();
if (block.IsProofOfStake())
pindexNew->SetProofOfStake();
pindexNew->nTx = block.vtx.size();
pindexNew->nChainTx = 0;
pindexNew->nFile = pos.nFile;
@@ -3778,7 +3774,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
return true;
}
static bool CheckBlockSignature(const CBlock& block, const uint256& hash)
static bool CheckBlockSignature(const CBlock& block)
{
if (block.IsProofOfWork())
return block.vchBlockSig.empty();
@@ -3797,7 +3793,7 @@ static bool CheckBlockSignature(const CBlock& block, const uint256& hash)
if (whichType == TX_PUBKEY)
{
vector<unsigned char>& vchPubKey = vSolutions[0];
return CPubKey(vchPubKey).Verify(hash, block.vchBlockSig);
return CPubKey(vchPubKey).Verify(block.GetHash(), block.vchBlockSig);
}
else
{
@@ -3809,6 +3805,8 @@ static bool CheckBlockSignature(const CBlock& block, const uint256& hash)
opcodetype opcode;
vector<unsigned char> vchPushValue;
uint256 hash = block.GetHash();
if (!script.GetOp(pc, opcode, vchPushValue))
return false;
if (opcode != OP_RETURN)
@@ -3823,26 +3821,21 @@ static bool CheckBlockSignature(const CBlock& block, const uint256& hash)
return false;
}
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW)
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW)
{
if (block.nVersion < 7 && Params().GetConsensus().IsProtocolV2(block.GetBlockTime()))
return state.Invalid(error("%s: rejected nVersion=%d block", __func__, block.nVersion),
REJECT_OBSOLETE, "bad-version");
if (block.nVersion < 7 && Params().GetConsensus().IsProtocolV2(block.GetBlockTime()))
return state.Invalid(error("%s: rejected nVersion=%d block", __func__, block.nVersion),
REJECT_OBSOLETE, "bad-version");
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus()))
if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(), block.nBits, consensusParams))
return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),
REJECT_INVALID, "high-hash");
// Check timestamp
if (block.GetBlockTime() > FutureDrift(GetAdjustedTime()))
return state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),
REJECT_INVALID, "time-too-new");
return true;
}
bool CheckBlock(const CBlock& block, CValidationState& state, const uint256& hash, bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig)
bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig)
{
// These are checks that are independent of context.
@@ -3851,7 +3844,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const uint256& has
// Check that the header is valid (particularly PoW). This is mostly
// redundant with the call in AcceptBlockHeader.
if (!CheckBlockHeader(block, state, block.IsProofOfWork()))
if (!CheckBlockHeader(block, state, consensusParams, block.IsProofOfWork()))
return false;
// Check the merkle root.
@@ -3894,7 +3887,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const uint256& has
// Check coinstake timestamp
if (block.IsProofOfStake() && !CheckCoinStakeTimestamp(block.GetBlockTime(), block.vtx[1].nTime))
return state.DoS(50, error("CheckBlock(): coinstake timestamp violation nTimeBlock=%d nTimeTx=%u", block.GetBlockTime(), block.vtx[1].nTime),
REJECT_INVALID, "bad-cs-time");
REJECT_INVALID, "bad-cs-time");
if (block.IsProofOfStake())
{
@@ -3914,9 +3907,9 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const uint256& has
}
// Check proof-of-stake block signature
if (fCheckSig && !CheckBlockSignature(block, hash))
if (fCheckSig && !CheckBlockSignature(block))
return state.DoS(100, error("CheckBlock(): bad proof-of-stake block signature"),
REJECT_INVALID, "bad-block-signature");
REJECT_INVALID, "bad-block-signature");
// Check transactions
BOOST_FOREACH(const CTransaction& tx, block.vtx){
@@ -3945,7 +3938,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const uint256& has
return true;
}
static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidationState& state, const CChainParams& chainparams, const uint256& hash)
static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidationState& state, const CChainParams& chainparams)
{
if (*pindexPrev->phashBlock == chainparams.GetConsensus().hashGenesisBlock)
return true;
@@ -3959,36 +3952,39 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati
return true;
}
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev, const uint256& hash)
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev)
{
const Consensus::Params& consensusParams = Params().GetConsensus();
if (hash == consensusParams.hashGenesisBlock)
return true;
assert(pindexPrev);
int nHeight = pindexPrev->nHeight+1;
uint256 hash = block.GetHash();
if (hash == consensusParams.hashGenesisBlock)
return true;
assert(pindexPrev);
int nHeight = pindexPrev->nHeight+1;
if (chainActive.Height() - nHeight >= consensusParams.nMaxReorganizationDepth)
return state.DoS(1, error("%s: forked chain older than max reorganization depth (height %d)", __func__, nHeight));
return state.DoS(1, error("%s: forked chain older than max reorganization depth (height %d)", __func__, nHeight));
// Preliminary check difficulty in pos-only stage
if (chainActive.Height() > consensusParams.nLastPOWBlock && nHeight > consensusParams.nLastPOWBlock && block.nBits != GetNextTargetRequired(pindexPrev, &block, true, consensusParams))
return state.DoS(100, error("%s: incorrect difficulty", __func__),
REJECT_INVALID, "bad-diffbits");
REJECT_INVALID, "bad-diffbits");
// Preliminary check of pos timestamp
if (nHeight > consensusParams.nLastPOWBlock && !CheckStakeBlockTimestamp(block.GetBlockTime()))
return state.DoS(100, error("%s: incorrect pos block timestamp", __func__),
REJECT_INVALID, "bad-pos-time");
REJECT_INVALID, "bad-pos-time");
// Check timestamp against prev
if (block.GetBlockTime() <= pindexPrev->GetPastTimeLimit())
return state.Invalid(error("%s: block's timestamp is too early", __func__),
REJECT_INVALID, "time-too-old");
// Check timestamp
if (block.GetBlockTime() > FutureDrift(GetAdjustedTime()))
return state.Invalid(error("%s: block timestamp too far in the future", __func__),
REJECT_INVALID, "time-too-new");
return true;
}
@@ -3998,7 +3994,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
const Consensus::Params& consensusParams = Params().GetConsensus();
if (block.IsProofOfWork() && nHeight > consensusParams.nLastPOWBlock)
return state.DoS(100, error("%s : reject proof-of-work at height %d", __func__, nHeight), REJECT_INVALID, "bad-pow-height");
return state.DoS(100, error("%s : reject proof-of-work at height %d", __func__, nHeight), REJECT_INVALID, "bad-pow-height");
// Start enforcing BIP113 (Median Time Past) using versionbits logic.
int nLockTimeFlags = 0;
@@ -4013,7 +4009,6 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
}
// Enforce rule that the coinbase starts with serialized block height
{
CScript expect = CScript() << nHeight;
if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
@@ -4025,10 +4020,11 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
return true;
}
static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const uint256& hash, const CChainParams& chainparams, CBlockIndex** ppindex=NULL)
static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex=NULL)
{
AssertLockHeld(cs_main);
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator miSelf = mapBlockIndex.find(hash);
CBlockIndex *pindex = NULL;
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
@@ -4043,8 +4039,8 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state
return true;
}
if (!CheckBlockHeader(block, state))
return false;
if (!CheckBlockHeader(block, state, chainparams.GetConsensus()))
return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
// Get prev block index
CBlockIndex* pindexPrev = NULL;
@@ -4056,17 +4052,17 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state
return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
assert(pindexPrev);
if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, hash))
if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams))
return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str());
if (!ContextualCheckBlockHeader(block, state, pindexPrev, hash))
if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev))
return false;
}
if (pindex == NULL)
pindex = AddToBlockIndex(block, hash);
pindex = AddToBlockIndex(block);
if (pindex->nHeight > chainparams.GetConsensus().nLastPOWBlock)
pindex->SetProofOfStake();
pindex->SetProofOfStake();
if (ppindex)
*ppindex = pindex;
@@ -4075,14 +4071,14 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state
}
/** Store block on disk. If dbp is non-NULL, the file is known to already reside on disk */
static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, const uint256& hash)
static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp)
{
AssertLockHeld(cs_main);
CBlockIndex *pindexDummy = NULL;
CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
if (!AcceptBlockHeader(block, state, hash, chainparams, &pindex))
if (!AcceptBlockHeader(block, state, chainparams, &pindex))
return false;
// Try to process all requested blocks that we don't have, but only
@@ -4106,7 +4102,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
if (fTooFarAhead) return true; // Block height is too high
}
if ((!CheckBlock(block, state, hash)) || !ContextualCheckBlock(block, state, pindex->pprev)) {
if ((!CheckBlock(block, state, chainparams.GetConsensus())) || !ContextualCheckBlock(block, state, pindex->pprev)) {
if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
@@ -4160,7 +4156,7 @@ bool static IsCanonicalBlockSignature(const CBlock* pblock)
return IsLowDERSignature(pblock->vchBlockSig, NULL, false);
}
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, const uint256& hash)
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp)
{
if (!IsCanonicalBlockSignature(pblock)) {
if (pfrom && pfrom->nVersion >= CANONICAL_BLOCK_SIG_VERSION)
@@ -4171,12 +4167,12 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c
{
LOCK(cs_main);
bool fRequested = MarkBlockAsReceived(hash);
bool fRequested = MarkBlockAsReceived(pblock->GetHash());
fRequested |= fForceProcessing;
// Store to disk
CBlockIndex *pindex = NULL;
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fRequested, dbp, hash);
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fRequested, dbp);
if (pindex && pfrom) {
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
}
@@ -4187,7 +4183,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c
NotifyHeaderTip();
if (!ActivateBestChain(state, chainparams, pblock, &hash))
if (!ActivateBestChain(state, chainparams, pblock))
return error("%s: ActivateBestChain failed", __func__);
return true;
@@ -4197,7 +4193,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
{
AssertLockHeld(cs_main);
assert(pindexPrev && pindexPrev == chainActive.Tip());
if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, block.GetHash()))
if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams))
return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str());
CCoinsViewCache viewNew(pcoinsTip);
@@ -4205,15 +4201,14 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
indexDummy.pprev = pindexPrev;
indexDummy.nHeight = pindexPrev->nHeight + 1;
uint256 hash = block.GetHash();
// NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, pindexPrev, hash))
return false;
if (!CheckBlock(block, state, hash, fCheckPOW, fCheckMerkleRoot))
return false;
if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev))
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state));
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
if (!ContextualCheckBlock(block, state, pindexPrev))
return false;
if (!ConnectBlock(block, state, &indexDummy, viewNew, true))
return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state));
if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true))
return false;
assert(state.IsValid());
@@ -4558,8 +4553,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 1: verify block validity
uint256 hash = block.GetHash();
if (nCheckLevel >= 1 && !CheckBlock(block, state, hash))
if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus()))
return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) {
@@ -4598,7 +4592,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
CBlock block;
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
if (!ConnectBlock(block, state, pindex, coins))
if (!ConnectBlock(block, state, pindex, coins, chainparams))
return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
}
@@ -4682,7 +4676,6 @@ bool InitBlockIndex(const CChainParams& chainparams)
if (!fReindex) {
try {
CBlock &block = const_cast<CBlock&>(chainparams.GenesisBlock());
const uint256& hash = chainparams.GetConsensus().hashGenesisBlock;
// Start new block file
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos;
@@ -4691,10 +4684,10 @@ bool InitBlockIndex(const CChainParams& chainparams)
return error("LoadBlockIndex(): FindBlockPos failed");
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
return error("LoadBlockIndex(): writing genesis block to disk failed");
CBlockIndex *pindex = AddToBlockIndex(block, hash);
CBlockIndex *pindex = AddToBlockIndex(block);
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("LoadBlockIndex(): genesis block not accepted");
if (!ActivateBestChain(state, chainparams, &block, &hash))
if (!ActivateBestChain(state, chainparams, &block))
return error("LoadBlockIndex(): genesis block cannot be activated");
// Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
@@ -4765,7 +4758,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) {
LOCK(cs_main);
CValidationState state;
if (AcceptBlock(block, state, chainparams, NULL, true, dbp, hash))
if (AcceptBlock(block, state, chainparams, NULL, true, dbp))
nLoaded++;
if (state.IsError())
break;
@@ -4799,7 +4792,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
head.ToString());
LOCK(cs_main);
CValidationState dummy;
if (AcceptBlock(block, dummy, chainparams, NULL, true, &it->second, hash))
if (AcceptBlock(block, dummy, chainparams, NULL, true, &it->second))
{
nLoaded++;
queue.push_back(block.GetHash());
@@ -5373,7 +5366,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->nTimeOffset = nTimeOffset;
if (GetBoolArg("-synctime", false))
AddTimeData(pfrom->addr, nTimeOffset);
AddTimeData(pfrom->addr, nTimeOffset);
}
@@ -5835,8 +5828,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
Misbehaving(pfrom->GetId(), 20);
return error("non-continuous headers sequence");
}
uint256 hash = header.GetHash();
if (!AcceptBlockHeader(header, state, hash, chainparams, &pindexLast)) {
if (!AcceptBlockHeader(header, state, chainparams, &pindexLast)) {
int nDoS;
if (state.IsInvalid(nDoS)) {
if (nDoS > 0)
@@ -5926,7 +5918,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Such an unrequested block may still be processed, subject to the
// conditions in AcceptBlock().
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL, inv.hash);
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL);
int nDoS;
if (state.IsInvalid(nDoS)) {
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes

View File

@@ -214,7 +214,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals);
* @param[out] dbp The already known disk position of pblock, or NULL if not yet stored.
* @return True if state.IsValid()
*/
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, const uint256& hash);
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp);
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */
@@ -254,7 +254,7 @@ std::string GetWarnings(const std::string& strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false);
/** Find the best known block, and make it the tip of the block chain */
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL, const uint256 *phash = NULL);
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL);
CAmount GetProofOfWorkSubsidy();
CAmount GetProofOfStakeSubsidy();
@@ -801,14 +801,14 @@ bool ReadFromDisk(CTransaction& tx, CDiskTxPos& txindex);
bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL);
/** Apply the effects of this block (with given index) on the UTXO set represented by coins */
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, const CChainParams& chainparams, bool fJustCheck = false);
/** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = false);
bool CheckBlock(const CBlock& block, CValidationState& state, const uint256& hash, bool fCheckPOW = true, bool fCheckMerkleRoot = true, bool fCheckSig = true);
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = false);
bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true, bool fCheckSig = true);
/** Context-dependent validity checks */
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev, const uint256& hash);
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindexPrev);
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev);
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */

View File

@@ -89,7 +89,7 @@ int64_t GetMaxTransactionTime(CBlock* pblock)
{
int64_t maxTransactionTime = 0;
for (std::vector<CTransaction>::const_iterator it(pblock->vtx.begin()); it != pblock->vtx.end(); ++it)
maxTransactionTime = std::max(maxTransactionTime, (int64_t)it->nTime);
maxTransactionTime = std::max(maxTransactionTime, (int64_t)it->nTime);
return maxTransactionTime;
}
@@ -109,12 +109,12 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
int nHeight = chainActive.Tip()->nHeight + 1;
if (!fProofOfStake)
{
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
}
else
{
txNew.vin[0].scriptSig = (CScript() << nHeight) + COINBASE_FLAGS;
txNew.vout[0].SetEmpty();
txNew.vin[0].scriptSig = (CScript() << nHeight) + COINBASE_FLAGS;
txNew.vout[0].SetEmpty();
}
// Add dummy coinbase tx as first transaction
@@ -166,7 +166,7 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
// -regtest only: allow overriding block.nVersion with
// -blockversion=N to test forking scenarios
if (chainparams.MineBlocksOnDemand())
pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
int64_t nLockTimeCutoff = pblock->GetBlockTime();
@@ -302,25 +302,25 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
}
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
// LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps);
// LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps);
// Compute final coinbase transaction.
if (!fProofOfStake) {
txNew.vout[0].nValue = nFees + GetProofOfWorkSubsidy();
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
pblocktemplate->vTxFees[0] = -nFees;
}
txNew.nTime = pblock->nTime;
if (!fProofOfStake) {
txNew.vout[0].nValue = nFees + GetProofOfWorkSubsidy();
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
pblocktemplate->vTxFees[0] = -nFees;
}
txNew.nTime = pblock->nTime;
pblock->vtx[0] = txNew;
if (pFees)
*pFees = nFees;
*pFees = nFees;
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
pblock->nTime = max(pindexPrev->GetPastTimeLimit()+1, GetMaxTransactionTime(pblock));
if (!fProofOfStake)
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
pblock->nBits = GetNextTargetRequired(pindexPrev, pblock, fProofOfStake, Params().GetConsensus());
pblock->nNonce = 0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
@@ -358,8 +358,7 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned
// Internal miner
//
static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams, const uint256& hash)
static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams)
{
LogPrintf("%s\n", pblock->ToString());
LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
@@ -376,7 +375,7 @@ static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainpar
// Process this block the same as if we had received it from another node
CValidationState state;
if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, hash))
if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL))
return error("BitcoinMiner: ProcessNewBlock, block not accepted");
return true;
@@ -457,18 +456,18 @@ void static BitcoinMiner(const CChainParams& chainparams)
while (true) {
// Check if something found
unsigned int nHashesDone = 0;
char scratchpad[SCRYPT_SCRATCHPAD_SIZE];
while(true)
{
scrypt_1024_1_1_256_sp(BEGIN(pblock->nVersion), BEGIN(thash), scratchpad);
unsigned int nHashesDone = 0;
char scratchpad[SCRYPT_SCRATCHPAD_SIZE];
while(true)
{
scrypt_1024_1_1_256_sp(BEGIN(pblock->nVersion), BEGIN(thash), scratchpad);
if (UintToArith256(thash) <= hashTarget)
{
SetThreadPriority(THREAD_PRIORITY_NORMAL);
LogPrintf("BitcoinMiner:\n");
LogPrintf("proof-of-work found \n powhash: %s \ntarget: %s\n", thash.GetHex(), hashTarget.GetHex());
ProcessBlockFound(pblock, chainparams, thash);
ProcessBlockFound(pblock, chainparams);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
coinbaseScript->KeepScript();
@@ -481,7 +480,7 @@ void static BitcoinMiner(const CChainParams& chainparams)
pblock->nNonce += 1;
nHashesDone += 1;
if ((pblock->nNonce & 0xFF) == 0)
break;
break;
}
// Check for stop or if block needs to be rebuilt
@@ -549,19 +548,17 @@ bool SignBlock(CBlock& block, CWallet& wallet, int64_t& nFees)
// if we are trying to sign
// something except proof-of-stake block template
if (!block.vtx[0].vout[0].IsEmpty()){
LogPrintf("something except proof-of-stake block\n");
return false;
LogPrintf("something except proof-of-stake block\n");
return false;
}
// if we are trying to sign
// a complete proof-of-stake block
if (block.IsProofOfStake()){
LogPrintf("trying to sign a complete proof-of-stake block\n");
return true;
LogPrintf("trying to sign a complete proof-of-stake block\n");
return true;
}
static int64_t nLastCoinStakeSearchTime = GetAdjustedTime(); // startup timestamp
CKey key;
@@ -607,7 +604,6 @@ bool SignBlock(CBlock& block, CWallet& wallet, int64_t& nFees)
void ThreadStakeMiner(CWallet *pwallet, const CChainParams& chainparams)
{
SetThreadPriority(THREAD_PRIORITY_LOWEST);
// Make this thread recognisable as the mining thread
@@ -693,31 +689,9 @@ bool CheckStake(CBlock* pblock, CWallet& wallet, const CChainParams& chainparams
}
// Process this block the same as if we had received it from another node
if (!ProcessBlockFound(pblock, chainparams, pblock->GetHash()))
if (!ProcessBlockFound(pblock, chainparams))
return error("CheckStake() : ProcessBlock, block not accepted");
}
return true;
}
//void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams)
//{
// static boost::thread_group* minerThreads = NULL;
//
// if (nThreads < 0)
// nThreads = GetNumCores();
//
// if (minerThreads != NULL)
// {
// minerThreads->interrupt_all();
// delete minerThreads;
// minerThreads = NULL;
// }
//
// if (nThreads == 0 || !fGenerate)
// return;
//
// minerThreads = new boost::thread_group();
// for (int i = 0; i < nThreads; i++)
// minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams)));
//}

View File

@@ -80,9 +80,13 @@ bool CheckStakeKernelHash(const CBlockIndex* pindexPrev, unsigned int nBits, con
arith_uint256 bnTarget;
bnTarget.SetCompact(nBits);
uint256 nStakeModifier = pindexPrev->nStakeModifier;
// Calculate hash
CHashWriter ss(SER_GETHASH, 0);
ss << pindexPrev->nStakeModifier << txPrev->nTime << prevout.hash << prevout.n << nTimeTx;
CDataStream ss(SER_GETHASH, 0);
ss << nStakeModifier;
ss << txPrev->nTime << prevout.hash << prevout.n << nTimeTx;
uint256 hashProofOfStake = ss.GetHash();
// Now check if proof-of-stake hash meets target protocol
@@ -94,16 +98,16 @@ bool CheckStakeKernelHash(const CBlockIndex* pindexPrev, unsigned int nBits, con
bool IsConfirmedInNPrevBlocks(const CDiskTxPos& txindex, const CBlockIndex* pindexFrom, int nMaxDepth, int& nActualDepth)
{
for (const CBlockIndex* pindex = pindexFrom; pindex && pindexFrom->nHeight - pindex->nHeight < nMaxDepth; pindex = pindex->pprev)
{
if (pindex->nDataPos == txindex.nPos && pindex->nFile == txindex.nFile)
{
nActualDepth = pindexFrom->nHeight - pindex->nHeight;
return true;
}
}
for (const CBlockIndex* pindex = pindexFrom; pindex && pindexFrom->nHeight - pindex->nHeight < nMaxDepth; pindex = pindex->pprev)
{
if (pindex->nDataPos == txindex.nPos && pindex->nFile == txindex.nFile)
{
nActualDepth = pindexFrom->nHeight - pindex->nHeight;
return true;
}
}
return false;
return false;
}
// Check kernel hash target and coinstake signature
@@ -168,31 +172,31 @@ bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTime, co
auto it=cache.find(prevout);
if(it == cache.end()) {
CTransaction txPrev;
CDiskTxPos txindex;
if (!ReadFromDisk(txPrev, txindex, *pblocktree, prevout))
return false;
CTransaction txPrev;
CDiskTxPos txindex;
if (!ReadFromDisk(txPrev, txindex, *pblocktree, prevout))
return false;
// Read block header
CBlock block;
const CDiskBlockPos& pos = CDiskBlockPos(txindex.nFile, txindex.nPos);
if (!ReadBlockFromDisk(block, pos, Params().GetConsensus()))
return false;
// Read block header
CBlock block;
const CDiskBlockPos& pos = CDiskBlockPos(txindex.nFile, txindex.nPos);
if (!ReadBlockFromDisk(block, pos, Params().GetConsensus()))
return false;
int nDepth;
if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, Params().GetConsensus().nStakeMinConfirmations - 1, nDepth))
return false;
int nDepth;
if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, Params().GetConsensus().nStakeMinConfirmations - 1, nDepth))
return false;
if (pBlockTime)
*pBlockTime = block.GetBlockTime();
if (pBlockTime)
*pBlockTime = block.GetBlockTime();
return CheckStakeKernelHash(pindexPrev, nBits, new CCoins(txPrev, pindexPrev->nHeight), prevout, nTime);
}else{
//found in cache
const CStakeCache& stake = it->second;
if (pBlockTime)
*pBlockTime = stake.blockFrom.GetBlockTime();
return CheckStakeKernelHash(pindexPrev, nBits, new CCoins(stake.txPrev, pindexPrev->nHeight), prevout, nTime);
return CheckStakeKernelHash(pindexPrev, nBits, new CCoins(txPrev, pindexPrev->nHeight), prevout, nTime);
} else {
//found in cache
const CStakeCache& stake = it->second;
if (pBlockTime)
*pBlockTime = stake.blockFrom.GetBlockTime();
return CheckStakeKernelHash(pindexPrev, nBits, new CCoins(stake.txPrev, pindexPrev->nHeight), prevout, nTime);
}
}
@@ -214,4 +218,3 @@ void CacheKernel(std::map<COutPoint, CStakeCache>& cache, const COutPoint& prevo
CStakeCache c(block, txindex, txPrev);
cache.insert({prevout, c});
}

View File

@@ -30,26 +30,26 @@ static arith_uint256 GetTargetLimit(int64_t nTime, bool fProofOfStake, const Con
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, bool fProofOfStake, const Consensus::Params& params)
{
unsigned int nTargetLimit = UintToArith256(params.powLimit).GetCompact();
unsigned int nTargetLimit = UintToArith256(params.powLimit).GetCompact();
// Genesis block
if (pindexLast == NULL)
return nTargetLimit;
// Genesis block
if (pindexLast == NULL)
return nTargetLimit;
const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
if (pindexPrev->pprev == NULL)
return nTargetLimit; // first block
const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
if (pindexPrevPrev->pprev == NULL)
return nTargetLimit; // second block
const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
if (pindexPrev->pprev == NULL)
return nTargetLimit; // first block
const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
if (pindexPrevPrev->pprev == NULL)
return nTargetLimit; // second block
return CalculateNextTargetRequired(pindexPrev, pindexPrevPrev->GetBlockTime(), params);
return CalculateNextTargetRequired(pindexPrev, pindexPrevPrev->GetBlockTime(), params);
}
unsigned int CalculateNextTargetRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
if (params.fPowNoRetargeting)
return pindexLast->nBits;
if (params.fPowNoRetargeting)
return pindexLast->nBits;
int64_t nActualSpacing = pindexLast->GetBlockTime() - nFirstBlockTime;
int64_t nTargetSpacing = params.IsProtocolV2(pindexLast->GetBlockTime()) ? params.nTargetSpacing : params.nTargetSpacingV1;
@@ -73,6 +73,7 @@ unsigned int CalculateNextTargetRequired(const CBlockIndex* pindexLast, int64_t
return bnNew.GetCompact();
}
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
bool fNegative;
@@ -83,8 +84,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&
// Check range
if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
return error("CheckProofOfWork(): nBits below minimum work");
return error("CheckProofOfWork(): nBits below minimum work");
// Check proof of work matches claimed amount
if (UintToArith256(hash) > bnTarget)

View File

@@ -177,7 +177,7 @@ UniValue generate(const UniValue& params, bool fHelp)
}
CValidationState state;
uint256 hash = pblock->GetHash();
if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, hash))
if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(hash.GetHex());
@@ -707,7 +707,7 @@ UniValue submitblock(const UniValue& params, bool fHelp)
CValidationState state;
submitblock_StateCatcher sc(hash);
RegisterValidationInterface(&sc);
bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, hash);
bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL);
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{

View File

@@ -57,7 +57,8 @@ BOOST_AUTO_TEST_CASE(May15)
// After May 15'th, big blocks are OK:
forkingBlock.nTime = tMay15; // Invalidates PoW
BOOST_CHECK(CheckBlock(forkingBlock, state, forkingBlock.GetHash(), false, false));
const CChainParams& chainparams = Params();
BOOST_CHECK(CheckBlock(forkingBlock, state, chainparams.GetConsensus(), false, false));
}
SetMockTime(0);

View File

@@ -114,7 +114,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
pblock->nNonce = blockinfo[i].nonce;
CValidationState state;
BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, pblock->GetHash()));
BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL));
BOOST_CHECK(state.IsValid());
pblock->hashPrevBlock = pblock->GetHash();
}

View File

@@ -111,7 +111,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
CValidationState state;
ProcessNewBlock(state, chainparams, NULL, &block, true, NULL, block.GetHash());
ProcessNewBlock(state, chainparams, NULL, &block, true, NULL);
CBlock result = block;
delete pblocktemplate;

View File

@@ -679,8 +679,8 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
if (it2 != mapTx.end())
continue;
const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
if (nCheckFrequency != 0) assert(coins);
if (!coins || (coins->IsCoinBase() || coins->IsCoinStake() && ((signed long)nMemPoolHeight) - coins->nHeight < Params().GetConsensus().nCoinbaseMaturity)) {
if (nCheckFrequency != 0) assert(coins);
if ((!coins || (coins->IsCoinBase() || coins->IsCoinStake()) && ((signed long)nMemPoolHeight) - coins->nHeight < Params().GetConsensus().nCoinbaseMaturity)) {
transactionsToRemove.push_back(tx);
break;
}