Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <net_processing.h> | #include <net_processing.h> | ||||
#include <addrman.h> | #include <addrman.h> | ||||
#include <avalanche/processor.h> | #include <avalanche/processor.h> | ||||
#include <banman.h> | #include <banman.h> | ||||
#include <blockdb.h> | #include <blockdb.h> | ||||
#include <blockencodings.h> | #include <blockencodings.h> | ||||
#include <blockfilter.h> | |||||
#include <blockvalidity.h> | #include <blockvalidity.h> | ||||
#include <chain.h> | #include <chain.h> | ||||
#include <chainparams.h> | #include <chainparams.h> | ||||
#include <config.h> | #include <config.h> | ||||
#include <consensus/validation.h> | #include <consensus/validation.h> | ||||
#include <hash.h> | #include <hash.h> | ||||
#include <index/blockfilterindex.h> | |||||
#include <merkleblock.h> | #include <merkleblock.h> | ||||
#include <netbase.h> | #include <netbase.h> | ||||
#include <netmessagemaker.h> | #include <netmessagemaker.h> | ||||
#include <policy/fees.h> | #include <policy/fees.h> | ||||
#include <policy/policy.h> | #include <policy/policy.h> | ||||
#include <primitives/block.h> | #include <primitives/block.h> | ||||
#include <primitives/transaction.h> | #include <primitives/transaction.h> | ||||
#include <random.h> | #include <random.h> | ||||
▲ Show 20 Lines • Show All 132 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; | ||||
/** Interval between compact filter checkpoints. See BIP 157. */ | |||||
static constexpr int CFCHECKPT_INTERVAL = 1000; | |||||
// Internal stuff | // Internal stuff | ||||
namespace { | namespace { | ||||
/** Number of nodes with fSyncStarted. */ | /** Number of nodes with fSyncStarted. */ | ||||
int nSyncStarted GUARDED_BY(cs_main) = 0; | int nSyncStarted GUARDED_BY(cs_main) = 0; | ||||
/** | /** | ||||
* Sources of received blocks, saved to be able to punish them when processing | * Sources of received blocks, saved to be able to punish them when processing | ||||
* happens afterwards. | * happens afterwards. | ||||
▲ Show 20 Lines • Show All 2,051 Lines • ▼ Show 20 Lines | while (!done && !orphan_work_set.empty()) { | ||||
EraseOrphanTx(orphanTxId); | EraseOrphanTx(orphanTxId); | ||||
done = true; | done = true; | ||||
} | } | ||||
g_mempool.check(&::ChainstateActive().CoinsTip()); | g_mempool.check(&::ChainstateActive().CoinsTip()); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Validation logic for compact filters request handling. | |||||
* | |||||
* 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] chain_params Chain parameters | |||||
* @param[in] filter_type The filter type the request is for. Must be | |||||
* basic filters. | |||||
* @param[in] stop_hash The stop_hash for the request | |||||
* @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. | |||||
*/ | |||||
static bool PrepareBlockFilterRequest(CNode *pfrom, | |||||
const CChainParams &chain_params, | |||||
BlockFilterType filter_type, | |||||
const BlockHash &stop_hash, | |||||
const CBlockIndex *&stop_index, | |||||
const BlockFilterIndex *&filter_index) { | |||||
const bool supported_filter_type = | |||||
(filter_type == BlockFilterType::BASIC && | |||||
gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)); | |||||
if (!supported_filter_type) { | |||||
LogPrint(BCLog::NET, | |||||
"peer %d requested unsupported block filter type: %d\n", | |||||
pfrom->GetId(), static_cast<uint8_t>(filter_type)); | |||||
pfrom->fDisconnect = true; | |||||
return false; | |||||
} | |||||
{ | |||||
LOCK(cs_main); | |||||
stop_index = LookupBlockIndex(stop_hash); | |||||
// Check that the stop block exists and the peer would be allowed to | |||||
// fetch it. | |||||
if (!stop_index || | |||||
!BlockRequestAllowed(stop_index, chain_params.GetConsensus())) { | |||||
LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n", | |||||
pfrom->GetId(), stop_hash.ToString()); | |||||
pfrom->fDisconnect = true; | |||||
return false; | |||||
} | |||||
} | |||||
filter_index = GetBlockFilterIndex(filter_type); | |||||
if (!filter_index) { | |||||
LogPrint(BCLog::NET, "Filter index for supported type %s not found\n", | |||||
BlockFilterTypeName(filter_type)); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
/** | |||||
* Handle a getcfcheckpt 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 ProcessGetCFCheckPt(CNode *pfrom, CDataStream &vRecv, | |||||
const CChainParams &chain_params, | |||||
CConnman *connman) { | |||||
uint8_t filter_type_ser; | |||||
BlockHash stop_hash; | |||||
vRecv >> filter_type_ser >> stop_hash; | |||||
const BlockFilterType filter_type = | |||||
static_cast<BlockFilterType>(filter_type_ser); | |||||
const CBlockIndex *stop_index; | |||||
const BlockFilterIndex *filter_index; | |||||
if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, stop_hash, | |||||
stop_index, filter_index)) { | |||||
return; | |||||
} | |||||
std::vector<uint256> headers(stop_index->nHeight / CFCHECKPT_INTERVAL); | |||||
// Populate headers. | |||||
const CBlockIndex *block_index = stop_index; | |||||
for (int i = headers.size() - 1; i >= 0; i--) { | |||||
int height = (i + 1) * CFCHECKPT_INTERVAL; | |||||
block_index = block_index->GetAncestor(height); | |||||
if (!filter_index->LookupFilterHeader(block_index, headers[i])) { | |||||
LogPrint(BCLog::NET, | |||||
"Failed to find block filter header in index: " | |||||
"filter_type=%s, block_hash=%s\n", | |||||
BlockFilterTypeName(filter_type), | |||||
block_index->GetBlockHash().ToString()); | |||||
return; | |||||
} | |||||
} | |||||
CSerializedNetMsg msg = CNetMsgMaker(pfrom->GetSendVersion()) | |||||
.Make(NetMsgType::CFCHECKPT, filter_type_ser, | |||||
stop_index->GetBlockHash(), headers); | |||||
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", | ||||
SanitizeString(msg_type), vRecv.size(), pfrom->GetId()); | SanitizeString(msg_type), vRecv.size(), pfrom->GetId()); | ||||
if (gArgs.IsArgSet("-dropmessagestest") && | if (gArgs.IsArgSet("-dropmessagestest") && | ||||
▲ Show 20 Lines • Show All 1,606 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::GETCFCHECKPT) { | |||||
ProcessGetCFCheckPt(pfrom, vRecv, chainparams, connman); | |||||
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; | ||||
vRecv >> vInv; | vRecv >> vInv; | ||||
if (vInv.size() <= | if (vInv.size() <= | ||||
MAX_PEER_TX_IN_FLIGHT + MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | MAX_PEER_TX_IN_FLIGHT + MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | ||||
▲ Show 20 Lines • Show All 1,121 Lines • Show Last 20 Lines |