fix: increase it for headers2 only

This commit is contained in:
UdjinM6 2024-09-04 21:56:55 +03:00 committed by pasta
parent e23410ffdd
commit 303bc7af99
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
7 changed files with 35 additions and 28 deletions

View File

@ -1039,12 +1039,12 @@ static bool IsLimitedPeer(const Peer& peer)
}
/** Get maximum number of headers that can be included in one batch */
static uint16_t GetHeadersLimit(const CNode& pfrom)
static uint16_t GetHeadersLimit(const CNode& pfrom, const std::string& msg_type)
{
if (pfrom.GetCommonVersion() >= INCREASE_MAX_HEADERS_VERSION) {
return MAX_HEADERS_RESULTS;
if (pfrom.GetCommonVersion() >= INCREASE_MAX_HEADERS2_VERSION && msg_type == NetMsgType::GETHEADERS2) {
return MAX_HEADERS2_RESULTS;
}
return MAX_HEADERS_RESULTS_OLD;
return MAX_HEADERS_RESULTS;
}
static void PushInv(Peer& peer, const CInv& inv)
@ -2961,8 +2961,8 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
}
// Consider fetching more headers.
if (nCount == GetHeadersLimit(pfrom)) {
std::string msg_type = UsesCompressedHeaders(peer) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
std::string msg_type = UsesCompressedHeaders(peer) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS;
if (nCount == GetHeadersLimit(pfrom, msg_type)) {
// Headers message had its maximum size; the peer may have more headers.
if (MaybeSendGetHeaders(pfrom, msg_type, m_chainman.ActiveChain().GetLocator(pindexLast), peer)) {
LogPrint(BCLog::NET, "more %s (%d) to end to peer=%d (startheight:%d)\n",
@ -2970,7 +2970,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
}
}
UpdatePeerStateForReceivedHeaders(pfrom, pindexLast, received_new_header, nCount == GetHeadersLimit(pfrom));
UpdatePeerStateForReceivedHeaders(pfrom, pindexLast, received_new_header, nCount == GetHeadersLimit(pfrom, msg_type));
// Consider immediately downloading blocks.
HeadersDirectFetchBlocks(pfrom, peer, pindexLast);
@ -4065,7 +4065,7 @@ void PeerManagerImpl::ProcessMessage(
}
const auto send_headers = [this /* for m_connman */, &hashStop, &pindex, &nodestate, &pfrom, &msgMaker](auto msg_type, auto& v_headers, auto callback) {
int nLimit = GetHeadersLimit(pfrom);
int nLimit = GetHeadersLimit(pfrom, msg_type);
for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex)) {
v_headers.push_back(callback(pindex));
@ -4573,7 +4573,7 @@ void PeerManagerImpl::ProcessMessage(
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
unsigned int nCount = ReadCompactSize(vRecv);
if (nCount > GetHeadersLimit(pfrom)) {
if (nCount > GetHeadersLimit(pfrom, msg_type)) {
Misbehaving(pfrom.GetId(), 20, strprintf("headers message size = %u", nCount));
return;
}

View File

@ -996,7 +996,7 @@ static RPCHelpMan getblockheaders()
"If verbose is true, each item is an Object with information about a single blockheader.\n",
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
{"count", RPCArg::Type::NUM, /* default */ strprintf("%s", MAX_HEADERS_RESULTS), ""},
{"count", RPCArg::Type::NUM, /* default */ strprintf("%s", MAX_HEADERS2_RESULTS), ""},
{"verbose", RPCArg::Type::BOOL, /* default */ "true", "true for a json object, false for the hex-encoded data"},
},
{
@ -1054,11 +1054,11 @@ static RPCHelpMan getblockheaders()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
int nCount = MAX_HEADERS_RESULTS;
int nCount = MAX_HEADERS2_RESULTS;
if (!request.params[1].isNull())
nCount = request.params[1].get_int();
if (nCount <= 0 || nCount > (int)MAX_HEADERS_RESULTS)
if (nCount <= 0 || nCount > (int)MAX_HEADERS2_RESULTS)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Count is out of range");
bool fVerbose = true;
@ -1134,7 +1134,7 @@ static RPCHelpMan getmerkleblocks()
{
{"filter", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded bloom filter"},
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
{"count", RPCArg::Type::NUM, /* default */ strprintf("%s", MAX_HEADERS_RESULTS), ""},
{"count", RPCArg::Type::NUM, /* default */ strprintf("%s", MAX_HEADERS2_RESULTS), ""},
},
RPCResult{
RPCResult::Type::ARR, "", "",
@ -1163,11 +1163,11 @@ static RPCHelpMan getmerkleblocks()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
int nCount = MAX_HEADERS_RESULTS;
int nCount = MAX_HEADERS2_RESULTS;
if (!request.params[2].isNull())
nCount = request.params[2].get_int();
if (nCount <= 0 || nCount > (int)MAX_HEADERS_RESULTS) {
if (nCount <= 0 || nCount > (int)MAX_HEADERS2_RESULTS) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Count is out of range");
}

View File

@ -85,9 +85,8 @@ static const int MAX_SCRIPTCHECK_THREADS = 15;
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
* less than this number, we reached its tip. Changing this value is a protocol upgrade. */
static const unsigned int MAX_HEADERS_RESULTS = 8000;
/** Superseded with new value in protocol version INCREASE_MAX_HEADERS_VERSION */
static const unsigned int MAX_HEADERS_RESULTS_OLD = 2000;
static const unsigned int MAX_HEADERS_RESULTS = 2000;
static const unsigned int MAX_HEADERS2_RESULTS = 8000;
static const int64_t DEFAULT_MAX_TIP_AGE = 6 * 60 * 60; // ~144 blocks behind -> 2 x fork detection time, was 24 * 60 * 60 in bitcoin

View File

@ -58,8 +58,8 @@ static const int NO_LEGACY_ISLOCK_PROTO_VERSION = 70231;
//! Inventory type for DSQ messages added
static const int DSQ_INV_VERSION = 70234;
//! Maximum header count was increased from 2000 -> 8000 in this version
static const int INCREASE_MAX_HEADERS_VERSION = 70235;
//! Maximum header count for HEADRES2 message was increased from 2000 to 8000 in this version
static const int INCREASE_MAX_HEADERS2_VERSION = 70235;
// Make sure that none of the values above collide with `ADDRV2_FORMAT`.

View File

@ -11,6 +11,7 @@ from test_framework.messages import (
msg_ping,
ser_string,
MAX_HEADERS_RESULTS,
MAX_HEADERS2_RESULTS,
MAX_INV_SIZE,
MAX_PROTOCOL_MESSAGE_LENGTH,
msg_getdata,
@ -156,6 +157,10 @@ class InvalidMessagesTest(BitcoinTestFramework):
size = MAX_HEADERS_RESULTS + 1
self.test_oversized_msg(msg_headers([CBlockHeader()] * size), size)
def test_oversized_headers2_msg(self):
size = MAX_HEADERS2_RESULTS + 1
self.test_oversized_msg(msg_headers2([CBlockHeader()] * size), size)
def test_resource_exhaustion(self):
self.log.info("Test node stays up despite many large junk messages")
conn = self.nodes[0].add_p2p_connection(P2PDataStore())

View File

@ -42,7 +42,8 @@ MAX_MONEY = 21000000 * COIN
BIP125_SEQUENCE_NUMBER = 0xfffffffd # Sequence number that is BIP 125 opt-in and BIP 68-opt-out
MAX_PROTOCOL_MESSAGE_LENGTH = 3 * 1024 * 1024 # Maximum length of incoming protocol messages
MAX_HEADERS_RESULTS = 8000 # Number of headers sent in one getheaders result
MAX_HEADERS_RESULTS = 2000 # Number of headers sent in one getheaders result
MAX_HEADERS2_RESULTS = 8000 # Number of headers2 sent in one getheaders2 result
MAX_INV_SIZE = 50000 # Maximum number of entries in an 'inv' protocol message
NODE_NETWORK = (1 << 0)

View File

@ -32,6 +32,7 @@ from test_framework.messages import (
CBlockHeader,
CompressibleBlockHeader,
MAX_HEADERS_RESULTS,
MAX_HEADERS2_RESULTS,
NODE_HEADERS_COMPRESSED,
msg_addr,
msg_addrv2,
@ -91,8 +92,8 @@ logger = logging.getLogger("TestFramework.p2p")
# The minimum P2P version that this test framework supports
MIN_P2P_VERSION_SUPPORTED = 60001
# The P2P version that this test framework implements and sends in its `version` message
# Version 70231 drops supports for legacy InstantSend locks
P2P_VERSION = 70231
# Version 70234 increased max header count for HEADERS2 message from 2000 to 8000
P2P_VERSION = 70234
# The services that this test framework offers in its `version` message
P2P_SERVICES = NODE_NETWORK | NODE_HEADERS_COMPRESSED
# The P2P user agent string that this test framework sends in its `version` message
@ -712,7 +713,7 @@ class P2PDataStore(P2PInterface):
else:
logger.debug('getdata message type {} received.'.format(hex(inv.type)))
def _compute_requested_block_headers(self, locator, hash_stop):
def _compute_requested_block_headers(self, locator, hash_stop, use_headers2):
# Assume that the most recent block added is the tip
if not self.block_store:
return
@ -733,14 +734,15 @@ class P2PDataStore(P2PInterface):
break
# Truncate the list if there are too many headers
headers_list = headers_list[:-MAX_HEADERS_RESULTS - 1:-1]
max_results = MAX_HEADERS2_RESULTS if use_headers2 else MAX_HEADERS_RESULTS
headers_list = headers_list[:-max_results - 1:-1]
return headers_list
def on_getheaders2(self, message):
"""Search back through our block store for the locator, and reply with a compressed headers message if found."""
headers_list = self._compute_requested_block_headers(message.locator, message.hashstop)
headers_list = self._compute_requested_block_headers(message.locator, message.hashstop, True)
compressible_headers_list = [CompressibleBlockHeader(h) for h in headers_list] if headers_list else None
response = msg_headers2(compressible_headers_list)
@ -750,7 +752,7 @@ class P2PDataStore(P2PInterface):
def on_getheaders(self, message):
"""Search back through our block store for the locator, and reply with a headers message if found."""
headers_list = self._compute_requested_block_headers(message.locator, message.hashstop)
headers_list = self._compute_requested_block_headers(message.locator, message.hashstop, False)
response = msg_headers(headers_list)
if response is not None: