Merge #20599: net processing: Tolerate sendheaders and sendcmpct messages before verack

b316dcb758 [net processing] Tolerate sendheaders and sendcmpct messages before verack (John Newbery)

Pull request description:

  BIP 130 (sendheaders) and BIP 152 (compact blocks) do not specify at
  which stage the `sendheaders` or `sendcmpct` messages should be sent.
  Therefore we should tolerate them being sent before the version-verack
  handshake is complete.

ACKs for top commit:
  MarcoFalke:
    review ACK b316dcb758 📒
  jonatack:
    Code review re-ACK b316dcb758 per `git range-diff b103fdcb 82d0a43 b316dcb`, rebase only
  luke-jr:
    utACK b316dcb758, only code movement from after verack check to before

Tree-SHA512: a8da3990a786a53c195a33cd278eb9d1b6b09e9a33717674d5bc6ef5629811189216f3eda1a3dd11f6972b9680c7b7a532bf7343b6e7440009dd831bef128e1d
This commit is contained in:
MarcoFalke 2020-12-14 17:10:49 +01:00
commit fff7d056a9
No known key found for this signature in database
GPG key ID: D2EA4850E7528B25

View file

@ -2503,6 +2503,39 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
if (msg_type == NetMsgType::SENDHEADERS) {
LOCK(cs_main);
State(pfrom.GetId())->fPreferHeaders = true;
return;
}
if (msg_type == NetMsgType::SENDCMPCT) {
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = 0;
vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
if (nCMPCTBLOCKVersion == 1 || ((pfrom.GetLocalServices() & NODE_WITNESS) && nCMPCTBLOCKVersion == 2)) {
LOCK(cs_main);
// fProvidesHeaderAndIDs is used to "lock in" version of compact blocks we send (fWantsCmpctWitness)
if (!State(pfrom.GetId())->fProvidesHeaderAndIDs) {
State(pfrom.GetId())->fProvidesHeaderAndIDs = true;
State(pfrom.GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
}
if (State(pfrom.GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) { // ignore later version announces
State(pfrom.GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
// save whether peer selects us as BIP152 high-bandwidth peer
// (receiving sendcmpct(1) signals high-bandwidth, sendcmpct(0) low-bandwidth)
pfrom.m_bip152_highbandwidth_from = fAnnounceUsingCMPCTBLOCK;
}
if (!State(pfrom.GetId())->fSupportsDesiredCmpctVersion) {
if (pfrom.GetLocalServices() & NODE_WITNESS)
State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
else
State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
}
}
return;
}
// Feature negotiation of wtxidrelay must happen between VERSION and VERACK
// to avoid relay problems from switching after a connection is up.
if (msg_type == NetMsgType::WTXIDRELAY) {
@ -2600,39 +2633,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
if (msg_type == NetMsgType::SENDHEADERS) {
LOCK(cs_main);
State(pfrom.GetId())->fPreferHeaders = true;
return;
}
if (msg_type == NetMsgType::SENDCMPCT) {
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = 0;
vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
if (nCMPCTBLOCKVersion == 1 || ((pfrom.GetLocalServices() & NODE_WITNESS) && nCMPCTBLOCKVersion == 2)) {
LOCK(cs_main);
// fProvidesHeaderAndIDs is used to "lock in" version of compact blocks we send (fWantsCmpctWitness)
if (!State(pfrom.GetId())->fProvidesHeaderAndIDs) {
State(pfrom.GetId())->fProvidesHeaderAndIDs = true;
State(pfrom.GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
}
if (State(pfrom.GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) { // ignore later version announces
State(pfrom.GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
// save whether peer selects us as BIP152 high-bandwidth peer
// (receiving sendcmpct(1) signals high-bandwidth, sendcmpct(0) low-bandwidth)
pfrom.m_bip152_highbandwidth_from = fAnnounceUsingCMPCTBLOCK;
}
if (!State(pfrom.GetId())->fSupportsDesiredCmpctVersion) {
if (pfrom.GetLocalServices() & NODE_WITNESS)
State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
else
State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
}
}
return;
}
if (msg_type == NetMsgType::INV) {
std::vector<CInv> vInv;
vRecv >> vInv;