mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 06:43:45 +01:00
Merge #15437: p2p: Remove BIP61 reject messages
fa25f43ac5p2p: Remove BIP61 reject messages (MarcoFalke) Pull request description: Reject messages (BIP 61) appear in the following settings: * Parsing of reject messages (in case `-debug=net` is set, off by default). This has only been used for a single `LogPrint` call for several releases now. Such logging is completely meaningless to us and should thus be removed. * The sending of reject messages (in case `-enablebip61` is set, off by default). This can be used to debug a node that is under our control. Instead of hacking this debugging into the p2p protocol, it could be more easily achieved by parsing the debug log. (Use `-printtoconsole` to have it as stream, or read from the `debug.log` file like our python function `assert_debug_log` in the test framework does) Having to maintain all of this logic and code to accommodate debugging, which can be achieved by other means a lot easier, is a burden. It makes review on net processing changes a lot harder, since the reject message logic has to be carried around without introducing any errors or DOS vectors. ACKs for top commit: jnewbery: utACKfa25f43ac5laanwj: I'm still not 100% convinced that I like getting rid of BIP61 conceptually, but apparently everyone wants it, code review ACKfa25f43ac5. ryanofsky: Code review ACKfa25f43ac5Tree-SHA512: daf55254202925e56be3d6cfb3c1c804e7a82cecb1dd1e5bd7b472bae989fd68ac4f21ec53fc46751353056fd645f7f877bebcb0b40920257991423a3d99e0be
This commit is contained in:
@@ -193,12 +193,6 @@ namespace {
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
struct CBlockReject {
|
||||
unsigned char chRejectCode;
|
||||
std::string strRejectReason;
|
||||
uint256 hashBlock;
|
||||
};
|
||||
|
||||
/**
|
||||
* Maintain validation-specific state about nodes, protected by cs_main, instead
|
||||
* by CNode's own locks. This simplifies asynchronous operation, where
|
||||
@@ -216,8 +210,6 @@ struct CNodeState {
|
||||
bool fShouldBan;
|
||||
//! String name of this peer (debugging/logging purposes).
|
||||
const std::string name;
|
||||
//! List of asynchronously-determined block rejections to notify this peer about.
|
||||
std::vector<CBlockReject> rejects;
|
||||
//! The best known block we know this peer has announced.
|
||||
const CBlockIndex *pindexBestKnownBlock;
|
||||
//! The hash of the last unknown block this peer has announced.
|
||||
@@ -1093,8 +1085,9 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para
|
||||
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
|
||||
}
|
||||
|
||||
PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler &scheduler, bool enable_bip61)
|
||||
: connman(connmanIn), m_banman(banman), m_stale_tip_check_time(0), m_enable_bip61(enable_bip61) {
|
||||
PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler& scheduler)
|
||||
: connman(connmanIn), m_banman(banman), m_stale_tip_check_time(0)
|
||||
{
|
||||
// Initialize global variables that cannot be constructed at startup.
|
||||
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
|
||||
|
||||
@@ -1244,8 +1237,6 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
|
||||
if (state.IsInvalid()) {
|
||||
// Don't send reject message with code 0 or an internal reject code.
|
||||
if (it != mapBlockSource.end() && State(it->second.first) && state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) {
|
||||
CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), hash};
|
||||
State(it->second.first)->rejects.push_back(reject);
|
||||
MaybePunishNode(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second);
|
||||
}
|
||||
}
|
||||
@@ -1859,7 +1850,7 @@ void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_se
|
||||
}
|
||||
}
|
||||
|
||||
bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc, bool enable_bip61)
|
||||
bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
|
||||
{
|
||||
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
|
||||
if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0)
|
||||
@@ -1883,38 +1874,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
}
|
||||
}
|
||||
|
||||
if (strCommand == NetMsgType::REJECT)
|
||||
{
|
||||
if (LogAcceptCategory(BCLog::NET)) {
|
||||
try {
|
||||
std::string strMsg; unsigned char ccode; std::string strReason;
|
||||
vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, MAX_REJECT_MESSAGE_LENGTH);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << strMsg << " code " << itostr(ccode) << ": " << strReason;
|
||||
|
||||
if (strMsg == NetMsgType::BLOCK || strMsg == NetMsgType::TX)
|
||||
{
|
||||
uint256 hash;
|
||||
vRecv >> hash;
|
||||
ss << ": hash " << hash.ToString();
|
||||
}
|
||||
LogPrint(BCLog::NET, "Reject %s\n", SanitizeString(ss.str()));
|
||||
} catch (const std::ios_base::failure&) {
|
||||
// Avoid feedback loops by preventing reject messages from triggering a new reject message.
|
||||
LogPrint(BCLog::NET, "Unparseable reject message received\n");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strCommand == NetMsgType::VERSION) {
|
||||
// Each connection can only send one version message
|
||||
if (pfrom->nVersion != 0)
|
||||
{
|
||||
if (enable_bip61) {
|
||||
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
|
||||
}
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->GetId(), 1);
|
||||
return false;
|
||||
@@ -1942,10 +1905,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
if (!pfrom->fInbound && !pfrom->fFeeler && !pfrom->m_manual_connection && !HasAllDesirableServiceFlags(nServices))
|
||||
{
|
||||
LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->GetId(), nServices, GetDesirableServiceFlags(nServices));
|
||||
if (enable_bip61) {
|
||||
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
|
||||
strprintf("Expected to offer services %08x", GetDesirableServiceFlags(nServices))));
|
||||
}
|
||||
pfrom->fDisconnect = true;
|
||||
return false;
|
||||
}
|
||||
@@ -1953,10 +1912,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
if (nVersion < MIN_PEER_PROTO_VERSION) {
|
||||
// disconnect from peers older than this proto version
|
||||
LogPrint(BCLog::NET, "peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion);
|
||||
if (enable_bip61) {
|
||||
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
|
||||
strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION)));
|
||||
}
|
||||
pfrom->fDisconnect = true;
|
||||
return false;
|
||||
}
|
||||
@@ -2628,10 +2583,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
|
||||
pfrom->GetId(),
|
||||
FormatStateMessage(state));
|
||||
if (enable_bip61 && state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) { // Never send AcceptToMemoryPool's internal codes over P2P
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
|
||||
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash));
|
||||
}
|
||||
MaybePunishNode(pfrom->GetId(), state, /*via_compact_block*/ false);
|
||||
}
|
||||
return true;
|
||||
@@ -2811,7 +2762,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
} // cs_main
|
||||
|
||||
if (fProcessBLOCKTXN)
|
||||
return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, connman, interruptMsgProc, enable_bip61);
|
||||
return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, connman, interruptMsgProc);
|
||||
|
||||
if (fRevertToHeaderProcessing) {
|
||||
// Headers received from HB compact block peers are permitted to be
|
||||
@@ -3238,18 +3189,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PeerLogicValidation::SendRejectsAndCheckIfBanned(CNode* pnode, bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
bool PeerLogicValidation::CheckIfBanned(CNode* pnode)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
CNodeState &state = *State(pnode->GetId());
|
||||
|
||||
if (enable_bip61) {
|
||||
for (const CBlockReject& reject : state.rejects) {
|
||||
connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, std::string(NetMsgType::BLOCK), reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
|
||||
}
|
||||
}
|
||||
state.rejects.clear();
|
||||
|
||||
if (state.fShouldBan) {
|
||||
state.fShouldBan = false;
|
||||
if (pnode->HasPermission(PF_NOBAN))
|
||||
@@ -3358,7 +3302,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
|
||||
bool fRet = false;
|
||||
try
|
||||
{
|
||||
fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams, connman, interruptMsgProc, m_enable_bip61);
|
||||
fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams, connman, interruptMsgProc);
|
||||
if (interruptMsgProc)
|
||||
return false;
|
||||
if (!pfrom->vRecvGetData.empty())
|
||||
@@ -3366,9 +3310,6 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
|
||||
}
|
||||
catch (const std::ios_base::failure& e)
|
||||
{
|
||||
if (m_enable_bip61) {
|
||||
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
|
||||
}
|
||||
if (strstr(e.what(), "end of data")) {
|
||||
// Allow exceptions from under-length message on vRecv
|
||||
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
|
||||
@@ -3399,7 +3340,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
|
||||
}
|
||||
|
||||
LOCK(cs_main);
|
||||
SendRejectsAndCheckIfBanned(pfrom, m_enable_bip61);
|
||||
CheckIfBanned(pfrom);
|
||||
|
||||
return fMoreWork;
|
||||
}
|
||||
@@ -3598,11 +3539,12 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
||||
}
|
||||
}
|
||||
|
||||
TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
|
||||
TRY_LOCK(cs_main, lockMain);
|
||||
if (!lockMain)
|
||||
return true;
|
||||
|
||||
if (SendRejectsAndCheckIfBanned(pto, m_enable_bip61)) return true;
|
||||
if (CheckIfBanned(pto)) return true;
|
||||
|
||||
CNodeState &state = *State(pto->GetId());
|
||||
|
||||
// Address refresh broadcast
|
||||
|
||||
Reference in New Issue
Block a user