Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show First 20 Lines • Show All 168 Lines • ▼ Show 20 Lines | |||||
int nSyncStarted GUARDED_BY(cs_main) = 0; | int nSyncStarted GUARDED_BY(cs_main) = 0; | ||||
/** | /** | ||||
* Sources of received blocks, saved to be able to send them reject messages or | * Sources of received blocks, saved to be able to send them reject messages or | ||||
* ban them when processing happens afterwards. | * ban them when processing happens afterwards. | ||||
* Set mapBlockSource[hash].second to false if the node should not be punished | * Set mapBlockSource[hash].second to false if the node should not be punished | ||||
* if the block is invalid. | * if the block is invalid. | ||||
*/ | */ | ||||
std::map<uint256, std::pair<NodeId, bool>> mapBlockSource GUARDED_BY(cs_main); | std::map<BlockHash, std::pair<NodeId, bool>> mapBlockSource GUARDED_BY(cs_main); | ||||
/** | /** | ||||
* Filter for transactions that were recently rejected by AcceptToMemoryPool. | * Filter for transactions that were recently rejected by AcceptToMemoryPool. | ||||
* These are not rerequested until the chain tip changes, at which point the | * These are not rerequested until the chain tip changes, at which point the | ||||
* entire filter is reset. | * entire filter is reset. | ||||
* | * | ||||
* Without this filter we'd be re-requesting txs from each of our peers, | * Without this filter we'd be re-requesting txs from each of our peers, | ||||
* increasing bandwidth consumption considerably. For instance, with 100 peers, | * increasing bandwidth consumption considerably. For instance, with 100 peers, | ||||
Show All 10 Lines | |||||
*/ | */ | ||||
std::unique_ptr<CRollingBloomFilter> recentRejects GUARDED_BY(cs_main); | std::unique_ptr<CRollingBloomFilter> recentRejects GUARDED_BY(cs_main); | ||||
uint256 hashRecentRejectsChainTip GUARDED_BY(cs_main); | uint256 hashRecentRejectsChainTip GUARDED_BY(cs_main); | ||||
/** | /** | ||||
* Blocks that are in flight, and that are in the queue to be downloaded. | * Blocks that are in flight, and that are in the queue to be downloaded. | ||||
*/ | */ | ||||
struct QueuedBlock { | struct QueuedBlock { | ||||
uint256 hash; | BlockHash hash; | ||||
//! Optional. | //! Optional. | ||||
const CBlockIndex *pindex; | const CBlockIndex *pindex; | ||||
//! Whether this block has validated headers at the time of request. | //! Whether this block has validated headers at the time of request. | ||||
bool fValidatedHeaders; | bool fValidatedHeaders; | ||||
//! Optional, used for CMPCTBLOCK downloads | //! Optional, used for CMPCTBLOCK downloads | ||||
std::unique_ptr<PartiallyDownloadedBlock> partialBlock; | std::unique_ptr<PartiallyDownloadedBlock> partialBlock; | ||||
}; | }; | ||||
std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> | std::map<BlockHash, std::pair<NodeId, std::list<QueuedBlock>::iterator>> | ||||
mapBlocksInFlight GUARDED_BY(cs_main); | mapBlocksInFlight GUARDED_BY(cs_main); | ||||
/** Stack of nodes which we have set to announce using compact blocks */ | /** Stack of nodes which we have set to announce using compact blocks */ | ||||
std::list<NodeId> lNodesAnnouncingHeaderAndIDs GUARDED_BY(cs_main); | std::list<NodeId> lNodesAnnouncingHeaderAndIDs GUARDED_BY(cs_main); | ||||
/** Number of preferable block download peers. */ | /** Number of preferable block download peers. */ | ||||
int nPreferredDownload GUARDED_BY(cs_main) = 0; | int nPreferredDownload GUARDED_BY(cs_main) = 0; | ||||
▲ Show 20 Lines • Show All 297 Lines • ▼ Show 20 Lines | if (fLogIPs) { | ||||
PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid); | PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid); | ||||
} | } | ||||
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid); | LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid); | ||||
} | } | ||||
// Returns a bool indicating whether we requested this block. | // Returns a bool indicating whether we requested this block. | ||||
// Also used if a block was /not/ received and timed out or started with another | // Also used if a block was /not/ received and timed out or started with another | ||||
// peer. | // peer. | ||||
static bool MarkBlockAsReceived(const uint256 &hash) | static bool MarkBlockAsReceived(const BlockHash &hash) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
std::map<uint256, | std::map<BlockHash, | ||||
std::pair<NodeId, std::list<QueuedBlock>::iterator>>::iterator | std::pair<NodeId, std::list<QueuedBlock>::iterator>>::iterator | ||||
itInFlight = mapBlocksInFlight.find(hash); | itInFlight = mapBlocksInFlight.find(hash); | ||||
if (itInFlight != mapBlocksInFlight.end()) { | if (itInFlight != mapBlocksInFlight.end()) { | ||||
CNodeState *state = State(itInFlight->second.first); | CNodeState *state = State(itInFlight->second.first); | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
state->nBlocksInFlightValidHeaders -= | state->nBlocksInFlightValidHeaders -= | ||||
itInFlight->second.second->fValidatedHeaders; | itInFlight->second.second->fValidatedHeaders; | ||||
if (state->nBlocksInFlightValidHeaders == 0 && | if (state->nBlocksInFlightValidHeaders == 0 && | ||||
Show All 16 Lines | static bool MarkBlockAsReceived(const BlockHash &hash) | ||||
return false; | return false; | ||||
} | } | ||||
// returns false, still setting pit, if the block was already in flight from the | // returns false, still setting pit, if the block was already in flight from the | ||||
// same peer | // same peer | ||||
// pit will only be valid as long as the same cs_main lock is being held. | // pit will only be valid as long as the same cs_main lock is being held. | ||||
static bool | static bool | ||||
MarkBlockAsInFlight(const Config &config, NodeId nodeid, const uint256 &hash, | MarkBlockAsInFlight(const Config &config, NodeId nodeid, const BlockHash &hash, | ||||
const Consensus::Params &consensusParams, | const Consensus::Params &consensusParams, | ||||
const CBlockIndex *pindex = nullptr, | const CBlockIndex *pindex = nullptr, | ||||
std::list<QueuedBlock>::iterator **pit = nullptr) | std::list<QueuedBlock>::iterator **pit = nullptr) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
CNodeState *state = State(nodeid); | CNodeState *state = State(nodeid); | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
// Short-circuit most stuff in case it is from the same node. | // Short-circuit most stuff in case it is from the same node. | ||||
std::map<uint256, | std::map<BlockHash, | ||||
std::pair<NodeId, std::list<QueuedBlock>::iterator>>::iterator | std::pair<NodeId, std::list<QueuedBlock>::iterator>>::iterator | ||||
itInFlight = mapBlocksInFlight.find(hash); | itInFlight = mapBlocksInFlight.find(hash); | ||||
if (itInFlight != mapBlocksInFlight.end() && | if (itInFlight != mapBlocksInFlight.end() && | ||||
itInFlight->second.first == nodeid) { | itInFlight->second.first == nodeid) { | ||||
if (pit) { | if (pit) { | ||||
*pit = &itInFlight->second.second; | *pit = &itInFlight->second.second; | ||||
} | } | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 880 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* Handle invalid block rejection and consequent peer banning, maintain which | * Handle invalid block rejection and consequent peer banning, maintain which | ||||
* peers announce compact blocks. | * peers announce compact blocks. | ||||
*/ | */ | ||||
void PeerLogicValidation::BlockChecked(const CBlock &block, | void PeerLogicValidation::BlockChecked(const CBlock &block, | ||||
const CValidationState &state) { | const CValidationState &state) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const uint256 hash(block.GetHash()); | const BlockHash hash = block.GetHash(); | ||||
std::map<uint256, std::pair<NodeId, bool>>::iterator it = | std::map<BlockHash, std::pair<NodeId, bool>>::iterator it = | ||||
mapBlockSource.find(hash); | mapBlockSource.find(hash); | ||||
if (state.IsInvalid()) { | if (state.IsInvalid()) { | ||||
// Don't send reject message with code 0 or an internal reject code. | // Don't send reject message with code 0 or an internal reject code. | ||||
if (it != mapBlockSource.end() && State(it->second.first) && | if (it != mapBlockSource.end() && State(it->second.first) && | ||||
state.GetRejectCode() > 0 && | state.GetRejectCode() > 0 && | ||||
state.GetRejectCode() < REJECT_INTERNAL) { | state.GetRejectCode() < REJECT_INTERNAL) { | ||||
CBlockReject reject = { | CBlockReject reject = { | ||||
▲ Show 20 Lines • Show All 1,727 Lines • ▼ Show 20 Lines | if (strCommand == NetMsgType::CMPCTBLOCK) { | ||||
// If this was a new header with more work than our tip, update the | // If this was a new header with more work than our tip, update the | ||||
// peer's last block announcement time | // peer's last block announcement time | ||||
if (received_new_header && | if (received_new_header && | ||||
pindex->nChainWork > ::ChainActive().Tip()->nChainWork) { | pindex->nChainWork > ::ChainActive().Tip()->nChainWork) { | ||||
nodestate->m_last_block_announcement = GetTime(); | nodestate->m_last_block_announcement = GetTime(); | ||||
} | } | ||||
std::map<uint256, | std::map<BlockHash, | ||||
std::pair<NodeId, std::list<QueuedBlock>::iterator>>:: | std::pair<NodeId, std::list<QueuedBlock>::iterator>>:: | ||||
iterator blockInFlightIt = | iterator blockInFlightIt = | ||||
mapBlocksInFlight.find(pindex->GetBlockHash()); | mapBlocksInFlight.find(pindex->GetBlockHash()); | ||||
bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end(); | bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end(); | ||||
if (pindex->nStatus.hasData()) { | if (pindex->nStatus.hasData()) { | ||||
// Nothing to do here | // Nothing to do here | ||||
return true; | return true; | ||||
▲ Show 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | if (strCommand == NetMsgType::BLOCKTXN) { | ||||
BlockTransactions resp; | BlockTransactions resp; | ||||
vRecv >> resp; | vRecv >> resp; | ||||
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | ||||
bool fBlockRead = false; | bool fBlockRead = false; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
std::map<uint256, | std::map<BlockHash, | ||||
std::pair<NodeId, std::list<QueuedBlock>::iterator>>:: | std::pair<NodeId, std::list<QueuedBlock>::iterator>>:: | ||||
iterator it = mapBlocksInFlight.find(resp.blockhash); | iterator it = mapBlocksInFlight.find(resp.blockhash); | ||||
if (it == mapBlocksInFlight.end() || | if (it == mapBlocksInFlight.end() || | ||||
!it->second.second->partialBlock || | !it->second.second->partialBlock || | ||||
it->second.first != pfrom->GetId()) { | it->second.first != pfrom->GetId()) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"Peer %d sent us block transactions for block " | "Peer %d sent us block transactions for block " | ||||
"we weren't expecting\n", | "we weren't expecting\n", | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | if (strCommand == NetMsgType::BLOCK) { | ||||
pblock->GetHash().ToString(), pfrom->GetId()); | pblock->GetHash().ToString(), pfrom->GetId()); | ||||
// Process all blocks from whitelisted peers, even if not requested, | // Process all blocks from whitelisted peers, even if not requested, | ||||
// unless we're still syncing with the network. Such an unrequested | // unless we're still syncing with the network. Such an unrequested | ||||
// block may still be processed, subject to the conditions in | // block may still be processed, subject to the conditions in | ||||
// AcceptBlock(). | // AcceptBlock(). | ||||
bool forceProcessing = pfrom->HasPermission(PF_NOBAN) && | bool forceProcessing = pfrom->HasPermission(PF_NOBAN) && | ||||
!::ChainstateActive().IsInitialBlockDownload(); | !::ChainstateActive().IsInitialBlockDownload(); | ||||
const uint256 hash(pblock->GetHash()); | const BlockHash hash = pblock->GetHash(); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Also always process if we requested the block explicitly, as we | // Also always process if we requested the block explicitly, as we | ||||
// may need it even though it is not a candidate for a new best tip. | // may need it even though it is not a candidate for a new best tip. | ||||
forceProcessing |= MarkBlockAsReceived(hash); | forceProcessing |= MarkBlockAsReceived(hash); | ||||
// mapBlockSource is only used for sending reject messages and DoS | // mapBlockSource is only used for sending reject messages and DoS | ||||
// scores, so the race between here and cs_main in ProcessNewBlock | // scores, so the race between here and cs_main in ProcessNewBlock | ||||
// is fine. | // is fine. | ||||
mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true)); | mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true)); | ||||
} | } | ||||
bool fNewBlock = false; | bool fNewBlock = false; | ||||
ProcessNewBlock(config, pblock, forceProcessing, &fNewBlock); | ProcessNewBlock(config, pblock, forceProcessing, &fNewBlock); | ||||
if (fNewBlock) { | if (fNewBlock) { | ||||
pfrom->nLastBlockTime = GetTime(); | pfrom->nLastBlockTime = GetTime(); | ||||
} else { | } else { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
mapBlockSource.erase(pblock->GetHash()); | mapBlockSource.erase(hash); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
// Ignore avalanche requests while importing | // Ignore avalanche requests while importing | ||||
if (strCommand == NetMsgType::AVAPOLL && !fImporting && !fReindex && | if (strCommand == NetMsgType::AVAPOLL && !fImporting && !fReindex && | ||||
g_avalanche && | g_avalanche && | ||||
gArgs.GetBoolArg("-enableavalanche", AVALANCHE_DEFAULT_ENABLED)) { | gArgs.GetBoolArg("-enableavalanche", AVALANCHE_DEFAULT_ENABLED)) { | ||||
▲ Show 20 Lines • Show All 1,523 Lines • Show Last 20 Lines |