Some code refactoring and cleanup
This commit is contained in:
388
src/main.cpp
388
src/main.cpp
@@ -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
|
||||
|
||||
12
src/main.h
12
src/main.h
@@ -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) */
|
||||
|
||||
@@ -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)));
|
||||
//}
|
||||
|
||||
69
src/pos.cpp
69
src/pos.cpp
@@ -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});
|
||||
}
|
||||
|
||||
|
||||
30
src/pow.cpp
30
src/pow.cpp
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user