Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show First 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | |||||
* Average delay between feefilter broadcasts in seconds. | * Average delay between feefilter broadcasts in seconds. | ||||
*/ | */ | ||||
static constexpr unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60; | static constexpr unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60; | ||||
/** | /** | ||||
* Maximum feefilter broadcast delay after significant change. | * Maximum feefilter broadcast delay after significant change. | ||||
*/ | */ | ||||
static constexpr unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60; | static constexpr unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60; | ||||
/** | /** | ||||
* Maximum number of compact filters that may be requested with one | |||||
* getcfilters. See BIP 157. | |||||
*/ | |||||
static constexpr uint32_t MAX_GETCFILTERS_SIZE = 1000; | |||||
/** | |||||
* Maximum number of cf hashes that may be requested with one getcfheaders. See | * Maximum number of cf hashes that may be requested with one getcfheaders. See | ||||
* BIP 157. | * BIP 157. | ||||
*/ | */ | ||||
static constexpr uint32_t MAX_GETCFHEADERS_SIZE = 2000; | static constexpr uint32_t MAX_GETCFHEADERS_SIZE = 2000; | ||||
// Internal stuff | // Internal stuff | ||||
namespace { | namespace { | ||||
/** Number of nodes with fSyncStarted. */ | /** Number of nodes with fSyncStarted. */ | ||||
▲ Show 20 Lines • Show All 2,076 Lines • ▼ Show 20 Lines | |||||
* 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( | static bool PrepareBlockFilterRequest( | ||||
CNode *pfrom, const CChainParams &chain_params, BlockFilterType filter_type, | CNode &pfrom, 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 && | ||||
gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)); | gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)); | ||||
if (!supported_filter_type) { | if (!supported_filter_type) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"peer %d requested unsupported block filter type: %d\n", | "peer %d requested unsupported block filter type: %d\n", | ||||
pfrom->GetId(), static_cast<uint8_t>(filter_type)); | pfrom.GetId(), static_cast<uint8_t>(filter_type)); | ||||
pfrom->fDisconnect = true; | pfrom.fDisconnect = true; | ||||
return false; | return false; | ||||
} | } | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
stop_index = LookupBlockIndex(stop_hash); | stop_index = LookupBlockIndex(stop_hash); | ||||
// Check that the stop block exists and the peer would be allowed to | // Check that the stop block exists and the peer would be allowed to | ||||
// fetch it. | // fetch it. | ||||
if (!stop_index || | if (!stop_index || | ||||
!BlockRequestAllowed(stop_index, chain_params.GetConsensus())) { | !BlockRequestAllowed(stop_index, chain_params.GetConsensus())) { | ||||
LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n", | LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n", | ||||
pfrom->GetId(), stop_hash.ToString()); | pfrom.GetId(), stop_hash.ToString()); | ||||
pfrom->fDisconnect = true; | pfrom.fDisconnect = true; | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
uint32_t stop_height = stop_index->nHeight; | uint32_t stop_height = stop_index->nHeight; | ||||
if (start_height > stop_height) { | if (start_height > stop_height) { | ||||
LogPrint( | LogPrint( | ||||
BCLog::NET, | BCLog::NET, | ||||
"peer %d sent invalid getcfilters/getcfheaders with " /* Continued | "peer %d sent invalid getcfilters/getcfheaders with " /* Continued | ||||
*/ | */ | ||||
"start height %d and stop height %d\n", | "start height %d and stop height %d\n", | ||||
pfrom->GetId(), start_height, stop_height); | pfrom.GetId(), start_height, stop_height); | ||||
pfrom->fDisconnect = true; | pfrom.fDisconnect = true; | ||||
return false; | return false; | ||||
} | } | ||||
if (stop_height - start_height >= max_height_diff) { | if (stop_height - start_height >= max_height_diff) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"peer %d requested too many cfilters/cfheaders: %d / %d\n", | "peer %d requested too many cfilters/cfheaders: %d / %d\n", | ||||
pfrom->GetId(), stop_height - start_height + 1, | pfrom.GetId(), stop_height - start_height + 1, | ||||
max_height_diff); | max_height_diff); | ||||
pfrom->fDisconnect = true; | pfrom.fDisconnect = true; | ||||
return false; | return false; | ||||
} | } | ||||
filter_index = GetBlockFilterIndex(filter_type); | filter_index = GetBlockFilterIndex(filter_type); | ||||
if (!filter_index) { | 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] pfrom 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 | |||||
*/ | |||||
static void ProcessGetCFilters(CNode &pfrom, CDataStream &vRecv, | |||||
const CChainParams &chain_params, | |||||
CConnman &connman) { | |||||
uint8_t filter_type_ser; | |||||
uint32_t start_height; | |||||
BlockHash stop_hash; | |||||
vRecv >> filter_type_ser >> start_height >> stop_hash; | |||||
const BlockFilterType filter_type = | |||||
static_cast<BlockFilterType>(filter_type_ser); | |||||
const CBlockIndex *stop_index; | |||||
BlockFilterIndex *filter_index; | |||||
if (!PrepareBlockFilterRequest( | |||||
pfrom, chain_params, filter_type, start_height, stop_hash, | |||||
MAX_GETCFILTERS_SIZE, stop_index, filter_index)) { | |||||
return; | |||||
} | |||||
std::vector<BlockFilter> filters; | |||||
if (!filter_index->LookupFilterRange(start_height, stop_index, filters)) { | |||||
LogPrint(BCLog::NET, | |||||
"Failed to find block filter in index: filter_type=%s, " | |||||
"start_height=%d, stop_hash=%s\n", | |||||
BlockFilterTypeName(filter_type), start_height, | |||||
stop_hash.ToString()); | |||||
return; | |||||
} | |||||
for (const auto &filter : filters) { | |||||
CSerializedNetMsg msg = CNetMsgMaker(pfrom.GetSendVersion()) | |||||
.Make(NetMsgType::CFILTER, filter); | |||||
connman.PushMessage(&pfrom, std::move(msg)); | |||||
} | |||||
} | |||||
/** | |||||
* Handle a cfheaders request. | * Handle a cfheaders request. | ||||
* | * | ||||
* 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] pfrom The peer that we received the request from | * @param[in] pfrom 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 *pfrom, CDataStream &vRecv, | static void ProcessGetCFHeaders(CNode &pfrom, 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 27 Lines | if (!filter_index->LookupFilterHashRange(start_height, stop_index, | ||||
"Failed to find block filter hashes in index: filter_type=%s, " | "Failed to find block filter hashes in index: filter_type=%s, " | ||||
"start_height=%d, stop_hash=%s\n", | "start_height=%d, stop_hash=%s\n", | ||||
BlockFilterTypeName(filter_type), start_height, | BlockFilterTypeName(filter_type), start_height, | ||||
stop_hash.ToString()); | stop_hash.ToString()); | ||||
return; | return; | ||||
} | } | ||||
CSerializedNetMsg msg = | CSerializedNetMsg msg = | ||||
CNetMsgMaker(pfrom->GetSendVersion()) | CNetMsgMaker(pfrom.GetSendVersion()) | ||||
.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(pfrom, std::move(msg)); | connman.PushMessage(&pfrom, std::move(msg)); | ||||
} | } | ||||
/** | /** | ||||
* Handle a getcfcheckpt request. | * Handle a getcfcheckpt request. | ||||
* | * | ||||
* 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] pfrom The peer that we received the request from | * @param[in] pfrom 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 *pfrom, CDataStream &vRecv, | static void ProcessGetCFCheckPt(CNode &pfrom, 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 All 19 Lines | for (int i = headers.size() - 1; i >= 0; i--) { | ||||
"Failed to find block filter header in index: " | "Failed to find block filter header in index: " | ||||
"filter_type=%s, block_hash=%s\n", | "filter_type=%s, block_hash=%s\n", | ||||
BlockFilterTypeName(filter_type), | BlockFilterTypeName(filter_type), | ||||
block_index->GetBlockHash().ToString()); | block_index->GetBlockHash().ToString()); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
CSerializedNetMsg msg = CNetMsgMaker(pfrom->GetSendVersion()) | CSerializedNetMsg msg = CNetMsgMaker(pfrom.GetSendVersion()) | ||||
.Make(NetMsgType::CFCHECKPT, filter_type_ser, | .Make(NetMsgType::CFCHECKPT, filter_type_ser, | ||||
stop_index->GetBlockHash(), headers); | stop_index->GetBlockHash(), headers); | ||||
connman->PushMessage(pfrom, std::move(msg)); | connman.PushMessage(&pfrom, std::move(msg)); | ||||
} | } | ||||
bool ProcessMessage(const Config &config, CNode *pfrom, | bool ProcessMessage(const Config &config, CNode *pfrom, | ||||
const std::string &msg_type, CDataStream &vRecv, | const std::string &msg_type, CDataStream &vRecv, | ||||
int64_t nTimeReceived, CConnman *connman, BanMan *banman, | int64_t nTimeReceived, CConnman *connman, BanMan *banman, | ||||
const std::atomic<bool> &interruptMsgProc) { | const std::atomic<bool> &interruptMsgProc) { | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", | LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", | ||||
▲ Show 20 Lines • Show All 1,608 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::FEEFILTER) { | ||||
pfrom->m_tx_relay->minFeeFilter = newFeeFilter; | pfrom->m_tx_relay->minFeeFilter = newFeeFilter; | ||||
} | } | ||||
LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", | LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", | ||||
CFeeRate(newFeeFilter).ToString(), pfrom->GetId()); | CFeeRate(newFeeFilter).ToString(), pfrom->GetId()); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
if (msg_type == NetMsgType::GETCFILTERS) { | |||||
ProcessGetCFilters(*pfrom, vRecv, chainparams, *connman); | |||||
return true; | |||||
} | |||||
if (msg_type == NetMsgType::GETCFHEADERS) { | if (msg_type == NetMsgType::GETCFHEADERS) { | ||||
ProcessGetCFHeaders(pfrom, vRecv, chainparams, connman); | ProcessGetCFHeaders(*pfrom, vRecv, chainparams, *connman); | ||||
return true; | return true; | ||||
} | } | ||||
if (msg_type == NetMsgType::GETCFCHECKPT) { | if (msg_type == NetMsgType::GETCFCHECKPT) { | ||||
ProcessGetCFCheckPt(pfrom, vRecv, chainparams, connman); | ProcessGetCFCheckPt(*pfrom, vRecv, chainparams, *connman); | ||||
return true; | return true; | ||||
} | } | ||||
if (msg_type == NetMsgType::NOTFOUND) { | if (msg_type == NetMsgType::NOTFOUND) { | ||||
// Remove the NOTFOUND transactions from the peer | // Remove the NOTFOUND transactions from the peer | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CNodeState *state = State(pfrom->GetId()); | CNodeState *state = State(pfrom->GetId()); | ||||
std::vector<CInv> vInv; | std::vector<CInv> vInv; | ||||
▲ Show 20 Lines • Show All 1,124 Lines • Show Last 20 Lines |