|
|
|
@ -101,7 +101,7 @@ namespace {
@@ -101,7 +101,7 @@ namespace {
|
|
|
|
|
/** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ |
|
|
|
|
struct QueuedBlock { |
|
|
|
|
uint256 hash; |
|
|
|
|
CBlockIndex* pindex; //!< Optional.
|
|
|
|
|
const CBlockIndex* pindex; //!< Optional.
|
|
|
|
|
bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request.
|
|
|
|
|
std::unique_ptr<PartiallyDownloadedBlock> partialBlock; //!< Optional, used for CMPCTBLOCK downloads
|
|
|
|
|
}; |
|
|
|
@ -156,13 +156,13 @@ struct CNodeState {
@@ -156,13 +156,13 @@ struct CNodeState {
|
|
|
|
|
//! List of asynchronously-determined block rejections to notify this peer about.
|
|
|
|
|
std::vector<CBlockReject> rejects; |
|
|
|
|
//! The best known block we know this peer has announced.
|
|
|
|
|
CBlockIndex *pindexBestKnownBlock; |
|
|
|
|
const CBlockIndex *pindexBestKnownBlock; |
|
|
|
|
//! The hash of the last unknown block this peer has announced.
|
|
|
|
|
uint256 hashLastUnknownBlock; |
|
|
|
|
//! The last full block we both have.
|
|
|
|
|
CBlockIndex *pindexLastCommonBlock; |
|
|
|
|
const CBlockIndex *pindexLastCommonBlock; |
|
|
|
|
//! The best header we have sent our peer.
|
|
|
|
|
CBlockIndex *pindexBestHeaderSent; |
|
|
|
|
const CBlockIndex *pindexBestHeaderSent; |
|
|
|
|
//! Length of current-streak of unconnecting headers announcements
|
|
|
|
|
int nUnconnectingHeaders; |
|
|
|
|
//! Whether we've started headers synchronization with this peer.
|
|
|
|
@ -331,7 +331,7 @@ bool MarkBlockAsReceived(const uint256& hash) {
@@ -331,7 +331,7 @@ bool MarkBlockAsReceived(const uint256& hash) {
|
|
|
|
|
// Requires cs_main.
|
|
|
|
|
// returns false, still setting pit, if the block was already in flight from the same peer
|
|
|
|
|
// pit will only be valid as long as the same cs_main lock is being held
|
|
|
|
|
bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Params& consensusParams, CBlockIndex *pindex = NULL, list<QueuedBlock>::iterator **pit = NULL) { |
|
|
|
|
bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Params& consensusParams, const CBlockIndex *pindex = NULL, list<QueuedBlock>::iterator **pit = NULL) { |
|
|
|
|
CNodeState *state = State(nodeid); |
|
|
|
|
assert(state != NULL); |
|
|
|
|
|
|
|
|
@ -432,7 +432,7 @@ bool CanDirectFetch(const Consensus::Params &consensusParams)
@@ -432,7 +432,7 @@ bool CanDirectFetch(const Consensus::Params &consensusParams)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Requires cs_main
|
|
|
|
|
bool PeerHasHeader(CNodeState *state, CBlockIndex *pindex) |
|
|
|
|
bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) |
|
|
|
|
{ |
|
|
|
|
if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight)) |
|
|
|
|
return true; |
|
|
|
@ -443,7 +443,7 @@ bool PeerHasHeader(CNodeState *state, CBlockIndex *pindex)
@@ -443,7 +443,7 @@ bool PeerHasHeader(CNodeState *state, CBlockIndex *pindex)
|
|
|
|
|
|
|
|
|
|
/** Find the last common ancestor two blocks have.
|
|
|
|
|
* Both pa and pb must be non-NULL. */ |
|
|
|
|
CBlockIndex* LastCommonAncestor(CBlockIndex* pa, CBlockIndex* pb) { |
|
|
|
|
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb) { |
|
|
|
|
if (pa->nHeight > pb->nHeight) { |
|
|
|
|
pa = pa->GetAncestor(pb->nHeight); |
|
|
|
|
} else if (pb->nHeight > pa->nHeight) { |
|
|
|
@ -462,7 +462,7 @@ CBlockIndex* LastCommonAncestor(CBlockIndex* pa, CBlockIndex* pb) {
@@ -462,7 +462,7 @@ CBlockIndex* LastCommonAncestor(CBlockIndex* pa, CBlockIndex* pb) {
|
|
|
|
|
|
|
|
|
|
/** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has
|
|
|
|
|
* at most count entries. */ |
|
|
|
|
void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBlockIndex*>& vBlocks, NodeId& nodeStaller, const Consensus::Params& consensusParams) { |
|
|
|
|
void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller, const Consensus::Params& consensusParams) { |
|
|
|
|
if (count == 0) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
@ -490,8 +490,8 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBl
@@ -490,8 +490,8 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBl
|
|
|
|
|
if (state->pindexLastCommonBlock == state->pindexBestKnownBlock) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
std::vector<CBlockIndex*> vToFetch; |
|
|
|
|
CBlockIndex *pindexWalk = state->pindexLastCommonBlock; |
|
|
|
|
std::vector<const CBlockIndex*> vToFetch; |
|
|
|
|
const CBlockIndex *pindexWalk = state->pindexLastCommonBlock; |
|
|
|
|
// Never fetch further than the best block we know the peer has, or more than BLOCK_DOWNLOAD_WINDOW + 1 beyond the last
|
|
|
|
|
// linked block we have in common with this peer. The +1 is so we can detect stalling, namely if we would be able to
|
|
|
|
|
// download that next block if the window were 1 larger.
|
|
|
|
@ -514,7 +514,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBl
@@ -514,7 +514,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBl
|
|
|
|
|
// are not yet downloaded and not in flight to vBlocks. In the mean time, update
|
|
|
|
|
// pindexLastCommonBlock as long as all ancestors are already downloaded, or if it's
|
|
|
|
|
// already part of our chain (and therefore don't need it even if pruned).
|
|
|
|
|
BOOST_FOREACH(CBlockIndex* pindex, vToFetch) { |
|
|
|
|
BOOST_FOREACH(const CBlockIndex* pindex, vToFetch) { |
|
|
|
|
if (!pindex->IsValid(BLOCK_VALID_TREE)) { |
|
|
|
|
// We consider the chain that this peer is on invalid.
|
|
|
|
|
return; |
|
|
|
@ -1049,7 +1049,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
@@ -1049,7 +1049,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t GetFetchFlags(CNode* pfrom, CBlockIndex* pprev, const Consensus::Params& chainparams) { |
|
|
|
|
uint32_t GetFetchFlags(CNode* pfrom, const CBlockIndex* pprev, const Consensus::Params& chainparams) { |
|
|
|
|
uint32_t nFetchFlags = 0; |
|
|
|
|
if ((pfrom->GetLocalServices() & NODE_WITNESS) && State(pfrom->GetId())->fHaveWitness) { |
|
|
|
|
nFetchFlags |= MSG_WITNESS_FLAG; |
|
|
|
@ -1456,7 +1456,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -1456,7 +1456,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
LOCK(cs_main); |
|
|
|
|
|
|
|
|
|
// Find the last block the caller has in the main chain
|
|
|
|
|
CBlockIndex* pindex = FindForkInGlobalIndex(chainActive, locator); |
|
|
|
|
const CBlockIndex* pindex = FindForkInGlobalIndex(chainActive, locator); |
|
|
|
|
|
|
|
|
|
// Send the rest of the chain
|
|
|
|
|
if (pindex) |
|
|
|
@ -1552,7 +1552,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -1552,7 +1552,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CNodeState *nodestate = State(pfrom->GetId()); |
|
|
|
|
CBlockIndex* pindex = NULL; |
|
|
|
|
const CBlockIndex* pindex = NULL; |
|
|
|
|
if (locator.IsNull()) |
|
|
|
|
{ |
|
|
|
|
// If locator is null, return the hashStop block
|
|
|
|
@ -1775,7 +1775,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -1775,7 +1775,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CBlockIndex *pindex = NULL; |
|
|
|
|
const CBlockIndex *pindex = NULL; |
|
|
|
|
CValidationState state; |
|
|
|
|
if (!ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) { |
|
|
|
|
int nDoS; |
|
|
|
@ -2051,7 +2051,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -2051,7 +2051,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CBlockIndex *pindexLast = NULL; |
|
|
|
|
const CBlockIndex *pindexLast = NULL; |
|
|
|
|
{ |
|
|
|
|
LOCK(cs_main); |
|
|
|
|
CNodeState *nodestate = State(pfrom->GetId()); |
|
|
|
@ -2128,8 +2128,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -2128,8 +2128,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
// If this set of headers is valid and ends in a block with at least as
|
|
|
|
|
// much work as our tip, download as much as possible.
|
|
|
|
|
if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainWork <= pindexLast->nChainWork) { |
|
|
|
|
vector<CBlockIndex *> vToFetch; |
|
|
|
|
CBlockIndex *pindexWalk = pindexLast; |
|
|
|
|
vector<const CBlockIndex *> vToFetch; |
|
|
|
|
const CBlockIndex *pindexWalk = pindexLast; |
|
|
|
|
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
|
|
|
|
|
while (pindexWalk && !chainActive.Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) { |
|
|
|
|
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) && |
|
|
|
@ -2151,7 +2151,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -2151,7 +2151,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|
|
|
|
} else { |
|
|
|
|
vector<CInv> vGetData; |
|
|
|
|
// Download as much as possible, from earliest to latest.
|
|
|
|
|
BOOST_REVERSE_FOREACH(CBlockIndex *pindex, vToFetch) { |
|
|
|
|
BOOST_REVERSE_FOREACH(const CBlockIndex *pindex, vToFetch) { |
|
|
|
|
if (nodestate->nBlocksInFlight >= MAX_BLOCKS_IN_TRANSIT_PER_PEER) { |
|
|
|
|
// Can't download any more from this peer
|
|
|
|
|
break; |
|
|
|
@ -2740,7 +2740,7 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
@@ -2740,7 +2740,7 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
|
|
|
|
|
bool fRevertToInv = ((!state.fPreferHeaders && |
|
|
|
|
(!state.fPreferHeaderAndIDs || pto->vBlockHashesToAnnounce.size() > 1)) || |
|
|
|
|
pto->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE); |
|
|
|
|
CBlockIndex *pBestIndex = NULL; // last header queued for delivery
|
|
|
|
|
const CBlockIndex *pBestIndex = NULL; // last header queued for delivery
|
|
|
|
|
ProcessBlockAvailability(pto->id); // ensure pindexBestKnownBlock is up-to-date
|
|
|
|
|
|
|
|
|
|
if (!fRevertToInv) { |
|
|
|
@ -2751,7 +2751,7 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
@@ -2751,7 +2751,7 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
|
|
|
|
|
BOOST_FOREACH(const uint256 &hash, pto->vBlockHashesToAnnounce) { |
|
|
|
|
BlockMap::iterator mi = mapBlockIndex.find(hash); |
|
|
|
|
assert(mi != mapBlockIndex.end()); |
|
|
|
|
CBlockIndex *pindex = mi->second; |
|
|
|
|
const CBlockIndex *pindex = mi->second; |
|
|
|
|
if (chainActive[pindex->nHeight] != pindex) { |
|
|
|
|
// Bail out if we reorged away from this block
|
|
|
|
|
fRevertToInv = true; |
|
|
|
@ -2828,7 +2828,7 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
@@ -2828,7 +2828,7 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
|
|
|
|
|
const uint256 &hashToAnnounce = pto->vBlockHashesToAnnounce.back(); |
|
|
|
|
BlockMap::iterator mi = mapBlockIndex.find(hashToAnnounce); |
|
|
|
|
assert(mi != mapBlockIndex.end()); |
|
|
|
|
CBlockIndex *pindex = mi->second; |
|
|
|
|
const CBlockIndex *pindex = mi->second; |
|
|
|
|
|
|
|
|
|
// Warn if we're announcing a block that is not on the main chain.
|
|
|
|
|
// This should be very rare and could be optimized out.
|
|
|
|
@ -3013,10 +3013,10 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
@@ -3013,10 +3013,10 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
|
|
|
|
|
//
|
|
|
|
|
vector<CInv> vGetData; |
|
|
|
|
if (!pto->fClient && (fFetch || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { |
|
|
|
|
vector<CBlockIndex*> vToDownload; |
|
|
|
|
vector<const CBlockIndex*> vToDownload; |
|
|
|
|
NodeId staller = -1; |
|
|
|
|
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams); |
|
|
|
|
BOOST_FOREACH(CBlockIndex *pindex, vToDownload) { |
|
|
|
|
BOOST_FOREACH(const CBlockIndex *pindex, vToDownload) { |
|
|
|
|
uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams); |
|
|
|
|
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash())); |
|
|
|
|
MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); |
|
|
|
|