Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 820 Lines • ▼ Show 20 Lines | private: | ||||
* -blockreconstructionextratxn/DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN of | * -blockreconstructionextratxn/DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN of | ||||
* these are kept in a ring buffer | * these are kept in a ring buffer | ||||
*/ | */ | ||||
std::vector<std::pair<TxHash, CTransactionRef>> | std::vector<std::pair<TxHash, CTransactionRef>> | ||||
vExtraTxnForCompact GUARDED_BY(g_cs_orphans); | vExtraTxnForCompact GUARDED_BY(g_cs_orphans); | ||||
/** Offset into vExtraTxnForCompact to insert the next tx */ | /** Offset into vExtraTxnForCompact to insert the next tx */ | ||||
size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0; | size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0; | ||||
void ProcessBlockAvailability(NodeId nodeid) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
void UpdateBlockAvailability(NodeId nodeid, const BlockHash &hash) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool CanDirectFetch(const Consensus::Params &consensusParams) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool BlockRequestAllowed(const CBlockIndex *pindex, | |||||
const Consensus::Params &consensusParams) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool AlreadyHaveBlock(const BlockHash &block_hash) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool AlreadyHaveProof(const avalanche::ProofId &proofid); | |||||
void ProcessGetBlockData(const Config &config, CNode &pfrom, Peer &peer, | |||||
const CInv &inv, CConnman &connman); | |||||
bool PrepareBlockFilterRequest( | |||||
CNode &peer, const CChainParams &chain_params, | |||||
BlockFilterType filter_type, uint32_t start_height, | |||||
const BlockHash &stop_hash, uint32_t max_height_diff, | |||||
const CBlockIndex *&stop_index, BlockFilterIndex *&filter_index); | |||||
void ProcessGetCFilters(CNode &peer, CDataStream &vRecv, | |||||
const CChainParams &chain_params, | |||||
CConnman &connman); | |||||
void ProcessGetCFHeaders(CNode &peer, CDataStream &vRecv, | |||||
const CChainParams &chain_params, | |||||
CConnman &connman); | |||||
void ProcessGetCFCheckPt(CNode &peer, CDataStream &vRecv, | |||||
const CChainParams &chain_params, | |||||
CConnman &connman); | |||||
/** | /** | ||||
* Checks if address relay is permitted with peer. If needed, initializes | * Checks if address relay is permitted with peer. If needed, initializes | ||||
* the m_addr_known bloom filter and sets m_addr_relay_enabled to true. | * the m_addr_known bloom filter and sets m_addr_relay_enabled to true. | ||||
* | * | ||||
* @return True if address relay is enabled with peer | * @return True if address relay is enabled with peer | ||||
* False if address relay is disallowed | * False if address relay is disallowed | ||||
*/ | */ | ||||
bool SetupAddressRelay(CNode &node, Peer &peer); | bool SetupAddressRelay(CNode &node, Peer &peer); | ||||
▲ Show 20 Lines • Show All 293 Lines • ▼ Show 20 Lines | bool PeerManagerImpl::MarkBlockAsInFlight( | ||||
if (pit) { | if (pit) { | ||||
*pit = &itInFlight->second.second; | *pit = &itInFlight->second.second; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** Check whether the last unknown block a peer advertised is not yet known. */ | |||||
static void ProcessBlockAvailability(NodeId nodeid) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
CNodeState *state = State(nodeid); | |||||
assert(state != nullptr); | |||||
if (!state->hashLastUnknownBlock.IsNull()) { | |||||
const CBlockIndex *pindex = | |||||
g_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock); | |||||
if (pindex && pindex->nChainWork > 0) { | |||||
if (state->pindexBestKnownBlock == nullptr || | |||||
pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { | |||||
state->pindexBestKnownBlock = pindex; | |||||
} | |||||
state->hashLastUnknownBlock.SetNull(); | |||||
} | |||||
} | |||||
} | |||||
/** Update tracking information about which blocks a peer is assumed to have. */ | |||||
static void UpdateBlockAvailability(NodeId nodeid, const BlockHash &hash) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
CNodeState *state = State(nodeid); | |||||
assert(state != nullptr); | |||||
ProcessBlockAvailability(nodeid); | |||||
const CBlockIndex *pindex = g_chainman.m_blockman.LookupBlockIndex(hash); | |||||
if (pindex && pindex->nChainWork > 0) { | |||||
// An actually better block was announced. | |||||
if (state->pindexBestKnownBlock == nullptr || | |||||
pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { | |||||
state->pindexBestKnownBlock = pindex; | |||||
} | |||||
} else { | |||||
// An unknown block was announced; just assume that the latest one is | |||||
// the best one. | |||||
state->hashLastUnknownBlock = hash; | |||||
} | |||||
} | |||||
void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid) { | void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
CNodeState *nodestate = State(nodeid); | CNodeState *nodestate = State(nodeid); | ||||
if (!nodestate) { | if (!nodestate) { | ||||
LogPrint(BCLog::NET, "node state unavailable: peer=%d\n", nodeid); | LogPrint(BCLog::NET, "node state unavailable: peer=%d\n", nodeid); | ||||
return; | return; | ||||
} | } | ||||
if (!nodestate->fProvidesHeaderAndIDs) { | if (!nodestate->fProvidesHeaderAndIDs) { | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | bool PeerManagerImpl::TipMayBeStale() { | ||||
if (m_last_tip_update == 0) { | if (m_last_tip_update == 0) { | ||||
m_last_tip_update = GetTime(); | m_last_tip_update = GetTime(); | ||||
} | } | ||||
return m_last_tip_update < | return m_last_tip_update < | ||||
GetTime() - consensusParams.nPowTargetSpacing * 3 && | GetTime() - consensusParams.nPowTargetSpacing * 3 && | ||||
mapBlocksInFlight.empty(); | mapBlocksInFlight.empty(); | ||||
} | } | ||||
static bool CanDirectFetch(const Consensus::Params &consensusParams) | bool PeerManagerImpl::CanDirectFetch(const Consensus::Params &consensusParams) { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
return ::ChainActive().Tip()->GetBlockTime() > | return ::ChainActive().Tip()->GetBlockTime() > | ||||
GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20; | GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20; | ||||
} | } | ||||
static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) | static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
if (state->pindexBestKnownBlock && | if (state->pindexBestKnownBlock && | ||||
pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight)) { | pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight)) { | ||||
return true; | return true; | ||||
} | } | ||||
if (state->pindexBestHeaderSent && | if (state->pindexBestHeaderSent && | ||||
pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight)) { | pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight)) { | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
/** Check whether the last unknown block a peer advertised is not yet known. */ | |||||
void PeerManagerImpl::ProcessBlockAvailability(NodeId nodeid) { | |||||
CNodeState *state = State(nodeid); | |||||
assert(state != nullptr); | |||||
if (!state->hashLastUnknownBlock.IsNull()) { | |||||
const CBlockIndex *pindex = | |||||
g_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock); | |||||
if (pindex && pindex->nChainWork > 0) { | |||||
if (state->pindexBestKnownBlock == nullptr || | |||||
pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { | |||||
state->pindexBestKnownBlock = pindex; | |||||
} | |||||
state->hashLastUnknownBlock.SetNull(); | |||||
} | |||||
} | |||||
} | |||||
/** Update tracking information about which blocks a peer is assumed to have. */ | |||||
void PeerManagerImpl::UpdateBlockAvailability(NodeId nodeid, | |||||
const BlockHash &hash) { | |||||
CNodeState *state = State(nodeid); | |||||
assert(state != nullptr); | |||||
ProcessBlockAvailability(nodeid); | |||||
const CBlockIndex *pindex = g_chainman.m_blockman.LookupBlockIndex(hash); | |||||
if (pindex && pindex->nChainWork > 0) { | |||||
// An actually better block was announced. | |||||
if (state->pindexBestKnownBlock == nullptr || | |||||
pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { | |||||
state->pindexBestKnownBlock = pindex; | |||||
} | |||||
} else { | |||||
// An unknown block was announced; just assume that the latest one is | |||||
// the best one. | |||||
state->hashLastUnknownBlock = hash; | |||||
} | |||||
} | |||||
void PeerManagerImpl::FindNextBlocksToDownload( | void PeerManagerImpl::FindNextBlocksToDownload( | ||||
NodeId nodeid, unsigned int count, | NodeId nodeid, unsigned int count, | ||||
std::vector<const CBlockIndex *> &vBlocks, NodeId &nodeStaller) { | std::vector<const CBlockIndex *> &vBlocks, NodeId &nodeStaller) { | ||||
if (count == 0) { | if (count == 0) { | ||||
return; | return; | ||||
} | } | ||||
vBlocks.reserve(vBlocks.size() + count); | vBlocks.reserve(vBlocks.size() + count); | ||||
▲ Show 20 Lines • Show All 601 Lines • ▼ Show 20 Lines | |||||
// | // | ||||
// blockchain -> download logic notification | // blockchain -> download logic notification | ||||
// | // | ||||
// To prevent fingerprinting attacks, only send blocks/headers outside of the | // To prevent fingerprinting attacks, only send blocks/headers outside of the | ||||
// active chain if they are no more than a month older (both in time, and in | // active chain if they are no more than a month older (both in time, and in | ||||
// best equivalent proof of work) than the best header chain we know about and | // best equivalent proof of work) than the best header chain we know about and | ||||
// we fully-validated them at some point. | // we fully-validated them at some point. | ||||
static bool BlockRequestAllowed(const CBlockIndex *pindex, | bool PeerManagerImpl::BlockRequestAllowed( | ||||
const Consensus::Params &consensusParams) | const CBlockIndex *pindex, const Consensus::Params &consensusParams) { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (::ChainActive().Contains(pindex)) { | if (::ChainActive().Contains(pindex)) { | ||||
return true; | return true; | ||||
} | } | ||||
return pindex->IsValid(BlockValidity::SCRIPTS) && | return pindex->IsValid(BlockValidity::SCRIPTS) && | ||||
(pindexBestHeader != nullptr) && | (pindexBestHeader != nullptr) && | ||||
(pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < | (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < | ||||
STALE_RELAY_AGE_LIMIT) && | STALE_RELAY_AGE_LIMIT) && | ||||
▲ Show 20 Lines • Show All 280 Lines • ▼ Show 20 Lines | if (m_orphanage.HaveTx(txid)) { | ||||
if (m_recent_confirmed_transactions->contains(txid)) { | if (m_recent_confirmed_transactions->contains(txid)) { | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
return recentRejects->contains(txid) || m_mempool.exists(txid); | return recentRejects->contains(txid) || m_mempool.exists(txid); | ||||
} | } | ||||
static bool AlreadyHaveBlock(const BlockHash &block_hash) | bool PeerManagerImpl::AlreadyHaveBlock(const BlockHash &block_hash) { | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
return g_chainman.m_blockman.LookupBlockIndex(block_hash) != nullptr; | return g_chainman.m_blockman.LookupBlockIndex(block_hash) != nullptr; | ||||
} | } | ||||
static bool AlreadyHaveProof(const avalanche::ProofId &proofid) { | bool PeerManagerImpl::AlreadyHaveProof(const avalanche::ProofId &proofid) { | ||||
assert(g_avalanche); | assert(g_avalanche); | ||||
const bool hasProof = g_avalanche->withPeerManager( | const bool hasProof = g_avalanche->withPeerManager( | ||||
[&proofid](avalanche::PeerManager &pm) { return pm.exists(proofid); }); | [&proofid](avalanche::PeerManager &pm) { return pm.exists(proofid); }); | ||||
LOCK(cs_rejectedProofs); | LOCK(cs_rejectedProofs); | ||||
return hasProof || rejectedProofs->contains(proofid); | return hasProof || rejectedProofs->contains(proofid); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | for (auto &[id, peer] : m_peer_map) { | ||||
} | } | ||||
}; | }; | ||||
for (unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) { | for (unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) { | ||||
PushAddress(*best[i].second, addr, insecure_rand); | PushAddress(*best[i].second, addr, insecure_rand); | ||||
} | } | ||||
} | } | ||||
static void ProcessGetBlockData(const Config &config, CNode &pfrom, Peer &peer, | void PeerManagerImpl::ProcessGetBlockData(const Config &config, CNode &pfrom, | ||||
const CInv &inv, CConnman &connman) { | Peer &peer, const CInv &inv, | ||||
CConnman &connman) { | |||||
const Consensus::Params &consensusParams = | const Consensus::Params &consensusParams = | ||||
config.GetChainParams().GetConsensus(); | config.GetChainParams().GetConsensus(); | ||||
const BlockHash hash(inv.hash); | const BlockHash hash(inv.hash); | ||||
bool send = false; | bool send = false; | ||||
std::shared_ptr<const CBlock> a_recent_block; | std::shared_ptr<const CBlock> a_recent_block; | ||||
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block; | std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block; | ||||
▲ Show 20 Lines • Show All 701 Lines • ▼ Show 20 Lines | |||||
* @param[in] max_height_diff The maximum number of items permitted to | * @param[in] max_height_diff The maximum number of items permitted to | ||||
* request, as specified in BIP 157 | * request, as specified in BIP 157 | ||||
* @param[out] stop_index The CBlockIndex for the stop_hash block, if the | * @param[out] stop_index The CBlockIndex for the stop_hash block, if the | ||||
* request can be serviced. | * request can be serviced. | ||||
* @param[out] filter_index The filter index, if the request can be | * @param[out] filter_index The filter index, if the request can be | ||||
* serviced. | * serviced. | ||||
* @return True if the request can be serviced. | * @return True if the request can be serviced. | ||||
*/ | */ | ||||
static bool PrepareBlockFilterRequest( | bool PeerManagerImpl::PrepareBlockFilterRequest( | ||||
CNode &peer, const CChainParams &chain_params, BlockFilterType filter_type, | CNode &peer, const CChainParams &chain_params, BlockFilterType filter_type, | ||||
uint32_t start_height, const BlockHash &stop_hash, uint32_t max_height_diff, | uint32_t start_height, const BlockHash &stop_hash, uint32_t max_height_diff, | ||||
const CBlockIndex *&stop_index, BlockFilterIndex *&filter_index) { | const CBlockIndex *&stop_index, BlockFilterIndex *&filter_index) { | ||||
const bool supported_filter_type = | const bool supported_filter_type = | ||||
(filter_type == BlockFilterType::BASIC && | (filter_type == BlockFilterType::BASIC && | ||||
(peer.GetLocalServices() & NODE_COMPACT_FILTERS)); | (peer.GetLocalServices() & NODE_COMPACT_FILTERS)); | ||||
if (!supported_filter_type) { | if (!supported_filter_type) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* May disconnect from the peer in the case of a bad request. | * May disconnect from the peer in the case of a bad request. | ||||
* | * | ||||
* @param[in] peer The peer that we received the request from | * @param[in] peer The peer that we received the request from | ||||
* @param[in] vRecv The raw message received | * @param[in] vRecv The raw message received | ||||
* @param[in] chain_params Chain parameters | * @param[in] chain_params Chain parameters | ||||
* @param[in] connman Pointer to the connection manager | * @param[in] connman Pointer to the connection manager | ||||
*/ | */ | ||||
static void ProcessGetCFilters(CNode &peer, CDataStream &vRecv, | void PeerManagerImpl::ProcessGetCFilters(CNode &peer, CDataStream &vRecv, | ||||
const CChainParams &chain_params, | const CChainParams &chain_params, | ||||
CConnman &connman) { | CConnman &connman) { | ||||
uint8_t filter_type_ser; | uint8_t filter_type_ser; | ||||
uint32_t start_height; | uint32_t start_height; | ||||
BlockHash stop_hash; | BlockHash stop_hash; | ||||
vRecv >> filter_type_ser >> start_height >> stop_hash; | vRecv >> filter_type_ser >> start_height >> stop_hash; | ||||
const BlockFilterType filter_type = | const BlockFilterType filter_type = | ||||
static_cast<BlockFilterType>(filter_type_ser); | static_cast<BlockFilterType>(filter_type_ser); | ||||
Show All 28 Lines | |||||
* | * | ||||
* May disconnect from the peer in the case of a bad request. | * May disconnect from the peer in the case of a bad request. | ||||
* | * | ||||
* @param[in] peer The peer that we received the request from | * @param[in] peer The peer that we received the request from | ||||
* @param[in] vRecv The raw message received | * @param[in] vRecv The raw message received | ||||
* @param[in] chain_params Chain parameters | * @param[in] chain_params Chain parameters | ||||
* @param[in] connman Pointer to the connection manager | * @param[in] connman Pointer to the connection manager | ||||
*/ | */ | ||||
static void ProcessGetCFHeaders(CNode &peer, CDataStream &vRecv, | void PeerManagerImpl::ProcessGetCFHeaders(CNode &peer, CDataStream &vRecv, | ||||
const CChainParams &chain_params, | const CChainParams &chain_params, | ||||
CConnman &connman) { | CConnman &connman) { | ||||
uint8_t filter_type_ser; | uint8_t filter_type_ser; | ||||
uint32_t start_height; | uint32_t start_height; | ||||
BlockHash stop_hash; | BlockHash stop_hash; | ||||
vRecv >> filter_type_ser >> start_height >> stop_hash; | vRecv >> filter_type_ser >> start_height >> stop_hash; | ||||
const BlockFilterType filter_type = | const BlockFilterType filter_type = | ||||
static_cast<BlockFilterType>(filter_type_ser); | static_cast<BlockFilterType>(filter_type_ser); | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* May disconnect from the peer in the case of a bad request. | * May disconnect from the peer in the case of a bad request. | ||||
* | * | ||||
* @param[in] peer The peer that we received the request from | * @param[in] peer The peer that we received the request from | ||||
* @param[in] vRecv The raw message received | * @param[in] vRecv The raw message received | ||||
* @param[in] chain_params Chain parameters | * @param[in] chain_params Chain parameters | ||||
* @param[in] connman Pointer to the connection manager | * @param[in] connman Pointer to the connection manager | ||||
*/ | */ | ||||
static void ProcessGetCFCheckPt(CNode &peer, CDataStream &vRecv, | void PeerManagerImpl::ProcessGetCFCheckPt(CNode &peer, CDataStream &vRecv, | ||||
const CChainParams &chain_params, | const CChainParams &chain_params, | ||||
CConnman &connman) { | CConnman &connman) { | ||||
uint8_t filter_type_ser; | uint8_t filter_type_ser; | ||||
BlockHash stop_hash; | BlockHash stop_hash; | ||||
vRecv >> filter_type_ser >> stop_hash; | vRecv >> filter_type_ser >> stop_hash; | ||||
const BlockFilterType filter_type = | const BlockFilterType filter_type = | ||||
static_cast<BlockFilterType>(filter_type_ser); | static_cast<BlockFilterType>(filter_type_ser); | ||||
▲ Show 20 Lines • Show All 3,644 Lines • Show Last 20 Lines |