|
|
|
@ -92,7 +92,7 @@ void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -92,7 +92,7 @@ void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
|
|
|
|
* in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards. |
|
|
|
|
*/ |
|
|
|
|
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams); |
|
|
|
|
static void CheckBlockIndex(); |
|
|
|
|
static void CheckBlockIndex(const Consensus::Params& consensusParams); |
|
|
|
|
|
|
|
|
|
/** Constant stuff for coinbase transactions we create: */ |
|
|
|
|
CScript COINBASE_FLAGS; |
|
|
|
@ -998,7 +998,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
@@ -998,7 +998,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ |
|
|
|
|
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) |
|
|
|
|
bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) |
|
|
|
|
{ |
|
|
|
|
CBlockIndex *pindexSlow = NULL; |
|
|
|
|
|
|
|
|
@ -1044,7 +1044,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
@@ -1044,7 +1044,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
|
|
|
|
|
|
|
|
|
|
if (pindexSlow) { |
|
|
|
|
CBlock block; |
|
|
|
|
if (ReadBlockFromDisk(block, pindexSlow)) { |
|
|
|
|
if (ReadBlockFromDisk(block, pindexSlow, consensusParams)) { |
|
|
|
|
BOOST_FOREACH(const CTransaction &tx, block.vtx) { |
|
|
|
|
if (tx.GetHash() == hash) { |
|
|
|
|
txOut = tx; |
|
|
|
@ -1089,7 +1089,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHea
@@ -1089,7 +1089,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHea
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) |
|
|
|
|
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) |
|
|
|
|
{ |
|
|
|
|
block.SetNull(); |
|
|
|
|
|
|
|
|
@ -1107,15 +1107,15 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
@@ -1107,15 +1107,15 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check the header
|
|
|
|
|
if (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) |
|
|
|
|
if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) |
|
|
|
|
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex) |
|
|
|
|
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams) |
|
|
|
|
{ |
|
|
|
|
if (!ReadBlockFromDisk(block, pindex->GetBlockPos())) |
|
|
|
|
if (!ReadBlockFromDisk(block, pindex->GetBlockPos(), consensusParams)) |
|
|
|
|
return false; |
|
|
|
|
if (block.GetHash() != pindex->GetBlockHash()) |
|
|
|
|
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", |
|
|
|
@ -2064,13 +2064,14 @@ void static UpdateTip(CBlockIndex *pindexNew) {
@@ -2064,13 +2064,14 @@ void static UpdateTip(CBlockIndex *pindexNew) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Disconnect chainActive's tip. You want to manually re-limit mempool size after this */ |
|
|
|
|
bool static DisconnectTip(CValidationState &state) { |
|
|
|
|
bool static DisconnectTip(CValidationState& state, const Consensus::Params& consensusParams) |
|
|
|
|
{ |
|
|
|
|
CBlockIndex *pindexDelete = chainActive.Tip(); |
|
|
|
|
assert(pindexDelete); |
|
|
|
|
mempool.check(pcoinsTip); |
|
|
|
|
// Read block from disk.
|
|
|
|
|
CBlock block; |
|
|
|
|
if (!ReadBlockFromDisk(block, pindexDelete)) |
|
|
|
|
if (!ReadBlockFromDisk(block, pindexDelete, consensusParams)) |
|
|
|
|
return AbortNode(state, "Failed to read block"); |
|
|
|
|
// Apply the block atomically to the chain state.
|
|
|
|
|
int64_t nStart = GetTimeMicros(); |
|
|
|
@ -2125,13 +2126,14 @@ static int64_t nTimePostConnect = 0;
@@ -2125,13 +2126,14 @@ static int64_t nTimePostConnect = 0;
|
|
|
|
|
* corresponding to pindexNew, to bypass loading it again from disk. |
|
|
|
|
*/ |
|
|
|
|
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, const CBlock *pblock) { |
|
|
|
|
const CChainParams& chainparams = Params(); |
|
|
|
|
assert(pindexNew->pprev == chainActive.Tip()); |
|
|
|
|
mempool.check(pcoinsTip); |
|
|
|
|
// Read block from disk.
|
|
|
|
|
int64_t nTime1 = GetTimeMicros(); |
|
|
|
|
CBlock block; |
|
|
|
|
if (!pblock) { |
|
|
|
|
if (!ReadBlockFromDisk(block, pindexNew)) |
|
|
|
|
if (!ReadBlockFromDisk(block, pindexNew, chainparams.GetConsensus())) |
|
|
|
|
return AbortNode(state, "Failed to read block"); |
|
|
|
|
pblock = █ |
|
|
|
|
} |
|
|
|
@ -2257,6 +2259,7 @@ static void PruneBlockIndexCandidates() {
@@ -2257,6 +2259,7 @@ static void PruneBlockIndexCandidates() {
|
|
|
|
|
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. |
|
|
|
|
*/ |
|
|
|
|
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, const CBlock *pblock) { |
|
|
|
|
const CChainParams& chainparams = Params(); |
|
|
|
|
AssertLockHeld(cs_main); |
|
|
|
|
bool fInvalidFound = false; |
|
|
|
|
const CBlockIndex *pindexOldTip = chainActive.Tip(); |
|
|
|
@ -2265,7 +2268,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
@@ -2265,7 +2268,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
|
|
|
|
|
// Disconnect active blocks which are no longer in the best chain.
|
|
|
|
|
bool fBlocksDisconnected = false; |
|
|
|
|
while (chainActive.Tip() && chainActive.Tip() != pindexFork) { |
|
|
|
|
if (!DisconnectTip(state)) |
|
|
|
|
if (!DisconnectTip(state, chainparams.GetConsensus())) |
|
|
|
|
return false; |
|
|
|
|
fBlocksDisconnected = true; |
|
|
|
|
} |
|
|
|
@ -2333,7 +2336,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
@@ -2333,7 +2336,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
|
|
|
|
|
bool ActivateBestChain(CValidationState &state, const CBlock *pblock) { |
|
|
|
|
CBlockIndex *pindexNewTip = NULL; |
|
|
|
|
CBlockIndex *pindexMostWork = NULL; |
|
|
|
|
const CChainParams& chainParams = Params(); |
|
|
|
|
const CChainParams& chainparams = Params(); |
|
|
|
|
do { |
|
|
|
|
boost::this_thread::interruption_point(); |
|
|
|
|
|
|
|
|
@ -2360,7 +2363,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
@@ -2360,7 +2363,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
|
|
|
|
|
// Relay inventory, but don't relay old inventory during initial block download.
|
|
|
|
|
int nBlockEstimate = 0; |
|
|
|
|
if (fCheckpointsEnabled) |
|
|
|
|
nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints()); |
|
|
|
|
nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()); |
|
|
|
|
{ |
|
|
|
|
LOCK(cs_vNodes); |
|
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes) |
|
|
|
@ -2372,7 +2375,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
@@ -2372,7 +2375,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
|
|
|
|
|
uiInterface.NotifyBlockTip(hashNewTip); |
|
|
|
|
} |
|
|
|
|
} while(pindexMostWork != chainActive.Tip()); |
|
|
|
|
CheckBlockIndex(); |
|
|
|
|
CheckBlockIndex(chainparams.GetConsensus()); |
|
|
|
|
|
|
|
|
|
// Write changes periodically to disk, after relay.
|
|
|
|
|
if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) { |
|
|
|
@ -2382,7 +2385,8 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
@@ -2382,7 +2385,8 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { |
|
|
|
|
bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex) |
|
|
|
|
{ |
|
|
|
|
AssertLockHeld(cs_main); |
|
|
|
|
|
|
|
|
|
// Mark the block itself as invalid.
|
|
|
|
@ -2397,7 +2401,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
@@ -2397,7 +2401,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
|
|
|
|
|
setBlockIndexCandidates.erase(pindexWalk); |
|
|
|
|
// ActivateBestChain considers blocks already in chainActive
|
|
|
|
|
// unconditionally valid already, so force disconnect away from it.
|
|
|
|
|
if (!DisconnectTip(state)) { |
|
|
|
|
if (!DisconnectTip(state, consensusParams)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -2899,6 +2903,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
@@ -2899,6 +2903,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
|
|
|
|
|
|
|
|
|
|
bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) |
|
|
|
|
{ |
|
|
|
|
const CChainParams& chainparams = Params(); |
|
|
|
|
// Preliminary checks
|
|
|
|
|
bool checked = CheckBlock(*pblock, state); |
|
|
|
|
|
|
|
|
@ -2916,7 +2921,7 @@ bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock*
@@ -2916,7 +2921,7 @@ bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock*
|
|
|
|
|
if (pindex && pfrom) { |
|
|
|
|
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); |
|
|
|
|
} |
|
|
|
|
CheckBlockIndex(); |
|
|
|
|
CheckBlockIndex(chainparams.GetConsensus()); |
|
|
|
|
if (!ret) |
|
|
|
|
return error("%s: AcceptBlock FAILED", __func__); |
|
|
|
|
} |
|
|
|
@ -3248,6 +3253,7 @@ CVerifyDB::~CVerifyDB()
@@ -3248,6 +3253,7 @@ CVerifyDB::~CVerifyDB()
|
|
|
|
|
|
|
|
|
|
bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) |
|
|
|
|
{ |
|
|
|
|
const CChainParams& chainparams = Params(); |
|
|
|
|
LOCK(cs_main); |
|
|
|
|
if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) |
|
|
|
|
return true; |
|
|
|
@ -3272,7 +3278,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
@@ -3272,7 +3278,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
|
|
|
|
|
break; |
|
|
|
|
CBlock block; |
|
|
|
|
// check level 0: read from disk
|
|
|
|
|
if (!ReadBlockFromDisk(block, pindex)) |
|
|
|
|
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
|
|
|
|
|
if (nCheckLevel >= 1 && !CheckBlock(block, state)) |
|
|
|
@ -3312,7 +3318,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
@@ -3312,7 +3318,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
|
|
|
|
|
uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)))); |
|
|
|
|
pindex = chainActive.Next(pindex); |
|
|
|
|
CBlock block; |
|
|
|
|
if (!ReadBlockFromDisk(block, pindex)) |
|
|
|
|
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)) |
|
|
|
|
return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); |
|
|
|
@ -3485,7 +3491,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
@@ -3485,7 +3491,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
|
|
|
|
|
std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head); |
|
|
|
|
while (range.first != range.second) { |
|
|
|
|
std::multimap<uint256, CDiskBlockPos>::iterator it = range.first; |
|
|
|
|
if (ReadBlockFromDisk(block, it->second)) |
|
|
|
|
if (ReadBlockFromDisk(block, it->second, chainparams.GetConsensus())) |
|
|
|
|
{ |
|
|
|
|
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), |
|
|
|
|
head.ToString()); |
|
|
|
@ -3512,9 +3518,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
@@ -3512,9 +3518,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
|
|
|
|
|
return nLoaded > 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void static CheckBlockIndex() |
|
|
|
|
void static CheckBlockIndex(const Consensus::Params& consensusParams) |
|
|
|
|
{ |
|
|
|
|
const Consensus::Params& consensusParams = Params().GetConsensus(); |
|
|
|
|
if (!fCheckBlockIndex) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -3796,7 +3801,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -3796,7 +3801,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void static ProcessGetData(CNode* pfrom) |
|
|
|
|
void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams) |
|
|
|
|
{ |
|
|
|
|
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin(); |
|
|
|
|
|
|
|
|
@ -3851,7 +3856,7 @@ void static ProcessGetData(CNode* pfrom)
@@ -3851,7 +3856,7 @@ void static ProcessGetData(CNode* pfrom)
|
|
|
|
|
{ |
|
|
|
|
// Send block from disk
|
|
|
|
|
CBlock block; |
|
|
|
|
if (!ReadBlockFromDisk(block, (*mi).second)) |
|
|
|
|
if (!ReadBlockFromDisk(block, (*mi).second, consensusParams)) |
|
|
|
|
assert(!"cannot load block from disk"); |
|
|
|
|
if (inv.type == MSG_BLOCK) |
|
|
|
|
pfrom->PushMessage("block", block); |
|
|
|
@ -4243,7 +4248,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -4243,7 +4248,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
LogPrint("net", "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id); |
|
|
|
|
|
|
|
|
|
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); |
|
|
|
|
ProcessGetData(pfrom); |
|
|
|
|
ProcessGetData(pfrom, chainparams.GetConsensus()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -4509,7 +4514,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -4509,7 +4514,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexLast), uint256()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CheckBlockIndex(); |
|
|
|
|
CheckBlockIndex(chainparams.GetConsensus()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing
|
|
|
|
@ -4793,6 +4798,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -4793,6 +4798,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
// requires LOCK(cs_vRecvMsg)
|
|
|
|
|
bool ProcessMessages(CNode* pfrom) |
|
|
|
|
{ |
|
|
|
|
const CChainParams& chainparams = Params(); |
|
|
|
|
//if (fDebug)
|
|
|
|
|
// LogPrintf("%s(%u messages)\n", __func__, pfrom->vRecvMsg.size());
|
|
|
|
|
|
|
|
|
@ -4807,7 +4813,7 @@ bool ProcessMessages(CNode* pfrom)
@@ -4807,7 +4813,7 @@ bool ProcessMessages(CNode* pfrom)
|
|
|
|
|
bool fOk = true; |
|
|
|
|
|
|
|
|
|
if (!pfrom->vRecvGetData.empty()) |
|
|
|
|
ProcessGetData(pfrom); |
|
|
|
|
ProcessGetData(pfrom, chainparams.GetConsensus()); |
|
|
|
|
|
|
|
|
|
// this maintains the order of responses
|
|
|
|
|
if (!pfrom->vRecvGetData.empty()) return fOk; |
|
|
|
@ -4834,7 +4840,7 @@ bool ProcessMessages(CNode* pfrom)
@@ -4834,7 +4840,7 @@ bool ProcessMessages(CNode* pfrom)
|
|
|
|
|
it++; |
|
|
|
|
|
|
|
|
|
// Scan for message start
|
|
|
|
|
if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) { |
|
|
|
|
if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), MESSAGE_START_SIZE) != 0) { |
|
|
|
|
LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id); |
|
|
|
|
fOk = false; |
|
|
|
|
break; |
|
|
|
@ -4842,7 +4848,7 @@ bool ProcessMessages(CNode* pfrom)
@@ -4842,7 +4848,7 @@ bool ProcessMessages(CNode* pfrom)
|
|
|
|
|
|
|
|
|
|
// Read header
|
|
|
|
|
CMessageHeader& hdr = msg.hdr; |
|
|
|
|
if (!hdr.IsValid(Params().MessageStart())) |
|
|
|
|
if (!hdr.IsValid(chainparams.MessageStart())) |
|
|
|
|
{ |
|
|
|
|
LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id); |
|
|
|
|
continue; |
|
|
|
|