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; | ||||
/** | |||||
* Check whether the last unknown block a peer advertised is not yet known. | |||||
*/ | |||||
void ProcessBlockAvailability(NodeId nodeid) | void ProcessBlockAvailability(NodeId nodeid) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
/** | |||||
* Update tracking information about which blocks a peer is assumed to have. | |||||
*/ | |||||
void UpdateBlockAvailability(NodeId nodeid, const BlockHash &hash) | void UpdateBlockAvailability(NodeId nodeid, const BlockHash &hash) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
bool CanDirectFetch(const Consensus::Params &consensusParams) | bool CanDirectFetch(const Consensus::Params &consensusParams) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
/** | |||||
* 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 best equivalent proof of work) than the best header chain we know | |||||
* about and we fully-validated them at some point. | |||||
*/ | |||||
bool BlockRequestAllowed(const CBlockIndex *pindex, | bool BlockRequestAllowed(const CBlockIndex *pindex, | ||||
const Consensus::Params &consensusParams) | const Consensus::Params &consensusParams) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
bool AlreadyHaveBlock(const BlockHash &block_hash) | bool AlreadyHaveBlock(const BlockHash &block_hash) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
bool AlreadyHaveProof(const avalanche::ProofId &proofid); | bool AlreadyHaveProof(const avalanche::ProofId &proofid); | ||||
void ProcessGetBlockData(const Config &config, CNode &pfrom, Peer &peer, | void ProcessGetBlockData(const Config &config, CNode &pfrom, Peer &peer, | ||||
const CInv &inv, CConnman &connman); | const CInv &inv, CConnman &connman); | ||||
/** | |||||
* Validation logic for compact filters request handling. | |||||
* | |||||
* 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] chain_params Chain parameters | |||||
* @param[in] filter_type The filter type the request is for. Must be | |||||
* basic filters. | |||||
* @param[in] start_height The start height for the request | |||||
* @param[in] stop_hash The stop_hash for the request | |||||
* @param[in] max_height_diff The maximum number of items permitted to | |||||
* request, as specified in BIP 157 | |||||
* @param[out] stop_index The CBlockIndex for the stop_hash block, if | |||||
* the request can be serviced. | |||||
* @param[out] filter_index The filter index, if the request can be | |||||
* serviced. | |||||
* @return True if the request can be serviced. | |||||
*/ | |||||
bool PrepareBlockFilterRequest( | bool PrepareBlockFilterRequest( | ||||
CNode &peer, const CChainParams &chain_params, | CNode &peer, const CChainParams &chain_params, | ||||
BlockFilterType filter_type, uint32_t start_height, | BlockFilterType filter_type, uint32_t start_height, | ||||
const BlockHash &stop_hash, uint32_t max_height_diff, | const BlockHash &stop_hash, uint32_t max_height_diff, | ||||
const CBlockIndex *&stop_index, BlockFilterIndex *&filter_index); | const CBlockIndex *&stop_index, BlockFilterIndex *&filter_index); | ||||
/** | |||||
* Handle a cfilters 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] vRecv The raw message received | |||||
* @param[in] chain_params Chain parameters | |||||
* @param[in] connman Pointer to the connection manager | |||||
*/ | |||||
void ProcessGetCFilters(CNode &peer, CDataStream &vRecv, | void ProcessGetCFilters(CNode &peer, CDataStream &vRecv, | ||||
const CChainParams &chain_params, | const CChainParams &chain_params, | ||||
CConnman &connman); | CConnman &connman); | ||||
/** | |||||
* Handle a cfheaders 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] vRecv The raw message received | |||||
* @param[in] chain_params Chain parameters | |||||
* @param[in] connman Pointer to the connection manager | |||||
*/ | |||||
void ProcessGetCFHeaders(CNode &peer, CDataStream &vRecv, | void ProcessGetCFHeaders(CNode &peer, CDataStream &vRecv, | ||||
const CChainParams &chain_params, | const CChainParams &chain_params, | ||||
CConnman &connman); | CConnman &connman); | ||||
/** | |||||
* Handle a getcfcheckpt 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] vRecv The raw message received | |||||
* @param[in] chain_params Chain parameters | |||||
* @param[in] connman Pointer to the connection manager | |||||
*/ | |||||
void ProcessGetCFCheckPt(CNode &peer, CDataStream &vRecv, | void ProcessGetCFCheckPt(CNode &peer, CDataStream &vRecv, | ||||
const CChainParams &chain_params, | const CChainParams &chain_params, | ||||
CConnman &connman); | CConnman &connman); | ||||
/** | /** | ||||
* Decide a response for an Avalanche poll about the given block. | * Decide a response for an Avalanche poll about the given block. | ||||
* | * | ||||
* @param[in] hash The hash of the block being polled for | * @param[in] hash The hash of the block being polled for | ||||
▲ Show 20 Lines • Show All 387 Lines • ▼ Show 20 Lines | static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) | ||||
} | } | ||||
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) { | void PeerManagerImpl::ProcessBlockAvailability(NodeId nodeid) { | ||||
CNodeState *state = State(nodeid); | CNodeState *state = State(nodeid); | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
if (!state->hashLastUnknownBlock.IsNull()) { | if (!state->hashLastUnknownBlock.IsNull()) { | ||||
const CBlockIndex *pindex = | const CBlockIndex *pindex = | ||||
m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock); | m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock); | ||||
if (pindex && pindex->nChainWork > 0) { | if (pindex && pindex->nChainWork > 0) { | ||||
if (state->pindexBestKnownBlock == nullptr || | if (state->pindexBestKnownBlock == nullptr || | ||||
pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { | pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { | ||||
state->pindexBestKnownBlock = pindex; | state->pindexBestKnownBlock = pindex; | ||||
} | } | ||||
state->hashLastUnknownBlock.SetNull(); | state->hashLastUnknownBlock.SetNull(); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/** Update tracking information about which blocks a peer is assumed to have. */ | |||||
void PeerManagerImpl::UpdateBlockAvailability(NodeId nodeid, | void PeerManagerImpl::UpdateBlockAvailability(NodeId nodeid, | ||||
const BlockHash &hash) { | const BlockHash &hash) { | ||||
CNodeState *state = State(nodeid); | CNodeState *state = State(nodeid); | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
ProcessBlockAvailability(nodeid); | ProcessBlockAvailability(nodeid); | ||||
const CBlockIndex *pindex = m_chainman.m_blockman.LookupBlockIndex(hash); | const CBlockIndex *pindex = m_chainman.m_blockman.LookupBlockIndex(hash); | ||||
▲ Show 20 Lines • Show All 616 Lines • ▼ Show 20 Lines | switch (state.GetResult()) { | ||||
break; | break; | ||||
} | } | ||||
if (message != "") { | if (message != "") { | ||||
LogPrint(BCLog::NET, "peer=%d: %s\n", nodeid, message); | LogPrint(BCLog::NET, "peer=%d: %s\n", nodeid, message); | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
////////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// blockchain -> download logic notification | |||||
// | |||||
// 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 | |||||
// best equivalent proof of work) than the best header chain we know about and | |||||
// we fully-validated them at some point. | |||||
bool PeerManagerImpl::BlockRequestAllowed( | bool PeerManagerImpl::BlockRequestAllowed( | ||||
const CBlockIndex *pindex, const Consensus::Params &consensusParams) { | const CBlockIndex *pindex, const Consensus::Params &consensusParams) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (m_chainman.ActiveChain().Contains(pindex)) { | if (m_chainman.ActiveChain().Contains(pindex)) { | ||||
return true; | return true; | ||||
} | } | ||||
return pindex->IsValid(BlockValidity::SCRIPTS) && | return pindex->IsValid(BlockValidity::SCRIPTS) && | ||||
(pindexBestHeader != nullptr) && | (pindexBestHeader != nullptr) && | ||||
▲ Show 20 Lines • Show All 1,071 Lines • ▼ Show 20 Lines | while (!orphan_work_set.empty()) { | ||||
m_orphanage.EraseTx(orphanTxId); | m_orphanage.EraseTx(orphanTxId); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
m_mempool.check(m_chainman.ActiveChainstate()); | m_mempool.check(m_chainman.ActiveChainstate()); | ||||
} | } | ||||
/** | |||||
* Validation logic for compact filters request handling. | |||||
* | |||||
* 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] chain_params Chain parameters | |||||
* @param[in] filter_type The filter type the request is for. Must be | |||||
* basic filters. | |||||
* @param[in] start_height The start height for the request | |||||
* @param[in] stop_hash The stop_hash for the request | |||||
* @param[in] max_height_diff The maximum number of items permitted to | |||||
* request, as specified in BIP 157 | |||||
* @param[out] stop_index The CBlockIndex for the stop_hash block, if the | |||||
* request can be serviced. | |||||
* @param[out] filter_index The filter index, if the request can be | |||||
* serviced. | |||||
* @return True if the request can be serviced. | |||||
*/ | |||||
bool PeerManagerImpl::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) { | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (!filter_index) { | ||||
LogPrint(BCLog::NET, "Filter index for supported type %s not found\n", | LogPrint(BCLog::NET, "Filter index for supported type %s not found\n", | ||||
BlockFilterTypeName(filter_type)); | BlockFilterTypeName(filter_type)); | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** | |||||
* Handle a cfilters 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] vRecv The raw message received | |||||
* @param[in] chain_params Chain parameters | |||||
* @param[in] connman Pointer to the connection manager | |||||
*/ | |||||
void PeerManagerImpl::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; | ||||
Show All 21 Lines | void PeerManagerImpl::ProcessGetCFilters(CNode &peer, CDataStream &vRecv, | ||||
for (const auto &filter : filters) { | for (const auto &filter : filters) { | ||||
CSerializedNetMsg msg = CNetMsgMaker(peer.GetCommonVersion()) | CSerializedNetMsg msg = CNetMsgMaker(peer.GetCommonVersion()) | ||||
.Make(NetMsgType::CFILTER, filter); | .Make(NetMsgType::CFILTER, filter); | ||||
connman.PushMessage(&peer, std::move(msg)); | connman.PushMessage(&peer, std::move(msg)); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Handle a cfheaders 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] vRecv The raw message received | |||||
* @param[in] chain_params Chain parameters | |||||
* @param[in] connman Pointer to the connection manager | |||||
*/ | |||||
void PeerManagerImpl::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; | ||||
Show All 36 Lines | void PeerManagerImpl::ProcessGetCFHeaders(CNode &peer, CDataStream &vRecv, | ||||
CSerializedNetMsg msg = | CSerializedNetMsg msg = | ||||
CNetMsgMaker(peer.GetCommonVersion()) | CNetMsgMaker(peer.GetCommonVersion()) | ||||
.Make(NetMsgType::CFHEADERS, filter_type_ser, | .Make(NetMsgType::CFHEADERS, filter_type_ser, | ||||
stop_index->GetBlockHash(), prev_header, filter_hashes); | stop_index->GetBlockHash(), prev_header, filter_hashes); | ||||
connman.PushMessage(&peer, std::move(msg)); | connman.PushMessage(&peer, std::move(msg)); | ||||
} | } | ||||
/** | |||||
* Handle a getcfcheckpt 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] vRecv The raw message received | |||||
* @param[in] chain_params Chain parameters | |||||
* @param[in] connman Pointer to the connection manager | |||||
*/ | |||||
void PeerManagerImpl::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; | ||||
▲ Show 20 Lines • Show All 3,651 Lines • Show Last 20 Lines |