mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 10:43:19 -03:00
a52837b9e9
6eecba475e
net_processing: make MaybePunishNodeFor{Block,Tx} return void (Pieter Wuille)ae60d485da
net_processing: remove Misbehavior score and increments (Pieter Wuille)6457c31197
net_processing: make all Misbehaving increments = 100 (Pieter Wuille)5120ab1478
net_processing: drop 8 headers threshold for incoming BIP130 (Pieter Wuille)944c54290d
net_processing: drop Misbehavior for unconnecting headers (Pieter Wuille)9f66ac7cf1
net_processing: do not treat non-connecting headers as response (Pieter Wuille) Pull request description: So far, discouragement of peers triggers when their misbehavior score exceeds 100 points. Most types of misbehavior increment the score by 100, triggering immediate discouragement, but some types do not. This PR makes all increments equal to either 100 (meaning any misbehavior will immediately cause disconnection and discouragement) or 0 (making the behavior effectively unconditionally allowed), and then removes the logic for score accumulation. This simplifies the code a bit, but also makes protocol expectations clearer: if a peer misbehaves, they get disconnected. There is no good reason why certain types of protocol violations should be permitted 4 times (howmuch=20) or 9 times (howmuch=10), while many others are never allowed. Furthermore, the distinction between these looks arbitrary. The specific types of misbehavior that are changed to 100 are: * Sending us a `block` which does not connect to our header tree (which necessarily must have been unsollicited). [used to be score 10] * Sending us a `headers` with a non-continuous headers sequence. [used to be score 20] * Sending us more than 1000 addresses in a single `addr` or `addrv2` message [used to be score 20] * Sending us more than 50000 invs in a single `inv` message [used to be score 20] * Sending us more than 2000 headers in a single `headers` message [used to be score 20] The specific types of misbehavior that are changed to 0 are: * Sending us 10 (*) separate BIP130 headers announcements that do not connect to our block tree [used to be score 20] * Sending us more than 8 headers in a single `headers` message (which thus does not get treated as a BIP130 announcement) that does not connect to our block tree. [used to be score 10] I believe that none of these behaviors are unavoidable, except for the one marked (*) which can in theory happen still due to interaction between BIP130 and variations in system clocks (the max 2 hour in the future rule). This one has been removed entirely. In order to remove the impact of the bug it was designed to deal with, without relying on misbehavior, a separate improvement is included that makes `getheaders`-tracking more accurate. In another unrelated improvement, this also gets rid of the 8 header limit heuristic to determine whether an incoming non-connecting `headers` is a potential BIP130 announcement, as this rule is no longer needed to prevent spurious Misbehavior. Instead, any non-connecting `headers` is now treated as a potential announcement. ACKs for top commit: sr-gi: ACK [6eecba4
](6eecba475e
) achow101: ACK6eecba475e
mzumsande: Code Review ACK6eecba475e
glozow: light code review / concept ACK6eecba475e
Tree-SHA512: e11e8a652c4ec048d8961086110a3594feefbb821e13f45c14ef81016377be0db44b5311751ef635d6e026def1960aff33f644e78ece11cfb54f2b7daa96f946
148 lines
6.2 KiB
C++
148 lines
6.2 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2022 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#ifndef BITCOIN_NET_PROCESSING_H
|
|
#define BITCOIN_NET_PROCESSING_H
|
|
|
|
#include <net.h>
|
|
#include <validationinterface.h>
|
|
|
|
#include <chrono>
|
|
|
|
class AddrMan;
|
|
class CChainParams;
|
|
class CTxMemPool;
|
|
class ChainstateManager;
|
|
|
|
namespace node {
|
|
class Warnings;
|
|
} // namespace node
|
|
|
|
/** Whether transaction reconciliation protocol should be enabled by default. */
|
|
static constexpr bool DEFAULT_TXRECONCILIATION_ENABLE{false};
|
|
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
|
|
static const uint32_t DEFAULT_MAX_ORPHAN_TRANSACTIONS{100};
|
|
/** Default number of non-mempool transactions to keep around for block reconstruction. Includes
|
|
orphan, replaced, and rejected transactions. */
|
|
static const uint32_t DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN{100};
|
|
static const bool DEFAULT_PEERBLOOMFILTERS = false;
|
|
static const bool DEFAULT_PEERBLOCKFILTERS = false;
|
|
/** Maximum number of outstanding CMPCTBLOCK requests for the same block. */
|
|
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK = 3;
|
|
|
|
struct CNodeStateStats {
|
|
int nSyncHeight = -1;
|
|
int nCommonHeight = -1;
|
|
int m_starting_height = -1;
|
|
std::chrono::microseconds m_ping_wait;
|
|
std::vector<int> vHeightInFlight;
|
|
bool m_relay_txs;
|
|
CAmount m_fee_filter_received;
|
|
uint64_t m_addr_processed = 0;
|
|
uint64_t m_addr_rate_limited = 0;
|
|
bool m_addr_relay_enabled{false};
|
|
ServiceFlags their_services;
|
|
int64_t presync_height{-1};
|
|
std::chrono::seconds time_offset{0};
|
|
};
|
|
|
|
struct PeerManagerInfo {
|
|
std::chrono::seconds median_outbound_time_offset{0s};
|
|
bool ignores_incoming_txs{false};
|
|
};
|
|
|
|
class PeerManager : public CValidationInterface, public NetEventsInterface
|
|
{
|
|
public:
|
|
struct Options {
|
|
//! Whether this node is running in -blocksonly mode
|
|
bool ignore_incoming_txs{DEFAULT_BLOCKSONLY};
|
|
//! Whether transaction reconciliation protocol is enabled
|
|
bool reconcile_txs{DEFAULT_TXRECONCILIATION_ENABLE};
|
|
//! Maximum number of orphan transactions kept in memory
|
|
uint32_t max_orphan_txs{DEFAULT_MAX_ORPHAN_TRANSACTIONS};
|
|
//! Number of non-mempool transactions to keep around for block reconstruction. Includes
|
|
//! orphan, replaced, and rejected transactions.
|
|
uint32_t max_extra_txs{DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN};
|
|
//! Whether all P2P messages are captured to disk
|
|
bool capture_messages{false};
|
|
//! Whether or not the internal RNG behaves deterministically (this is
|
|
//! a test-only option).
|
|
bool deterministic_rng{false};
|
|
};
|
|
|
|
static std::unique_ptr<PeerManager> make(CConnman& connman, AddrMan& addrman,
|
|
BanMan* banman, ChainstateManager& chainman,
|
|
CTxMemPool& pool, node::Warnings& warnings, Options opts);
|
|
virtual ~PeerManager() { }
|
|
|
|
/**
|
|
* Attempt to manually fetch block from a given peer. We must already have the header.
|
|
*
|
|
* @param[in] peer_id The peer id
|
|
* @param[in] block_index The blockindex
|
|
* @returns std::nullopt if a request was successfully made, otherwise an error message
|
|
*/
|
|
virtual std::optional<std::string> FetchBlock(NodeId peer_id, const CBlockIndex& block_index) = 0;
|
|
|
|
/** Begin running background tasks, should only be called once */
|
|
virtual void StartScheduledTasks(CScheduler& scheduler) = 0;
|
|
|
|
/** Get statistics from node state */
|
|
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const = 0;
|
|
|
|
/** Get peer manager info. */
|
|
virtual PeerManagerInfo GetInfo() const = 0;
|
|
|
|
/** Relay transaction to all peers. */
|
|
virtual void RelayTransaction(const uint256& txid, const uint256& wtxid) = 0;
|
|
|
|
/** Send ping message to all peers */
|
|
virtual void SendPings() = 0;
|
|
|
|
/** Set the height of the best block and its time (seconds since epoch). */
|
|
virtual void SetBestBlock(int height, std::chrono::seconds time) = 0;
|
|
|
|
/* Public for unit testing. */
|
|
virtual void UnitTestMisbehaving(NodeId peer_id) = 0;
|
|
|
|
/**
|
|
* Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound.
|
|
* Public for unit testing.
|
|
*/
|
|
virtual void CheckForStaleTipAndEvictPeers() = 0;
|
|
|
|
/** Process a single message from a peer. Public for fuzz testing */
|
|
virtual void ProcessMessage(CNode& pfrom, const std::string& msg_type, DataStream& vRecv,
|
|
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex) = 0;
|
|
|
|
/** This function is used for testing the stale tip eviction logic, see denialofservice_tests.cpp */
|
|
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds) = 0;
|
|
|
|
/**
|
|
* Gets the set of service flags which are "desirable" for a given peer.
|
|
*
|
|
* These are the flags which are required for a peer to support for them
|
|
* to be "interesting" to us, ie for us to wish to use one of our few
|
|
* outbound connection slots for or for us to wish to prioritize keeping
|
|
* their connection around.
|
|
*
|
|
* Relevant service flags may be peer- and state-specific in that the
|
|
* version of the peer may determine which flags are required (eg in the
|
|
* case of NODE_NETWORK_LIMITED where we seek out NODE_NETWORK peers
|
|
* unless they set NODE_NETWORK_LIMITED and we are out of IBD, in which
|
|
* case NODE_NETWORK_LIMITED suffices).
|
|
*
|
|
* Thus, generally, avoid calling with 'services' == NODE_NONE, unless
|
|
* state-specific flags must absolutely be avoided. When called with
|
|
* 'services' == NODE_NONE, the returned desirable service flags are
|
|
* guaranteed to not change dependent on state - ie they are suitable for
|
|
* use when describing peers which we know to be desirable, but for which
|
|
* we do not have a confirmed set of service flags.
|
|
*/
|
|
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const = 0;
|
|
};
|
|
|
|
#endif // BITCOIN_NET_PROCESSING_H
|