From 30bc8fab6833e0447ceadd3fff1566a680e33a98 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 21 Aug 2020 15:17:42 +0200 Subject: [PATCH 1/4] net: save high-bandwidth mode states in CNodeStats --- src/net.cpp | 2 ++ src/net.h | 6 ++++++ src/net_processing.cpp | 10 +++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 5b533d7d17e..2c41b314ffb 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -563,6 +563,8 @@ void CNode::copyStats(CNodeStats &stats, const std::vector &m_asmap) } stats.fInbound = IsInboundConn(); stats.m_manual_connection = IsManualConn(); + X(m_bip152_highbandwidth_to); + X(m_bip152_highbandwidth_from); X(nStartingHeight); { LOCK(cs_vSend); diff --git a/src/net.h b/src/net.h index 5a8e57b68b2..46050000928 100644 --- a/src/net.h +++ b/src/net.h @@ -681,6 +681,8 @@ public: std::string cleanSubVer; bool fInbound; bool m_manual_connection; + bool m_bip152_highbandwidth_to; + bool m_bip152_highbandwidth_from; int nStartingHeight; uint64_t nSendBytes; mapMsgCmdSize mapSendBytesPerMsgCmd; @@ -942,6 +944,10 @@ protected: public: uint256 hashContinue; std::atomic nStartingHeight{-1}; + // We selected peer as (compact blocks) high-bandwidth peer (BIP152) + std::atomic m_bip152_highbandwidth_to{false}; + // Peer selected us as (compact blocks) high-bandwidth peer (BIP152) + std::atomic m_bip152_highbandwidth_from{false}; // flood relay std::vector vAddrToSend; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index d2a76550ea5..fb9978664cd 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -670,11 +670,15 @@ static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connma // blocks using compact encodings. connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [&connman, nCMPCTBLOCKVersion](CNode* pnodeStop){ connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/false, nCMPCTBLOCKVersion)); + // save BIP152 bandwidth state: we select peer to be low-bandwidth + pnodeStop->m_bip152_highbandwidth_to = false; return true; }); lNodesAnnouncingHeaderAndIDs.pop_front(); } connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/true, nCMPCTBLOCKVersion)); + // save BIP152 bandwidth state: we select peer to be high-bandwidth + pfrom->m_bip152_highbandwidth_to = true; lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId()); return true; }); @@ -2652,8 +2656,12 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat State(pfrom.GetId())->fProvidesHeaderAndIDs = true; State(pfrom.GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2; } - if (State(pfrom.GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) // ignore later version announces + 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); From a7ed00f8bbc07dfc09f9e0a5bae10a1afe7612bb Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 21 Aug 2020 15:20:21 +0200 Subject: [PATCH 2/4] rpc: expose high-bandwidth mode states via getpeerinfo --- src/rpc/net.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index def21b119ef..8e0cb176289 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -116,6 +116,8 @@ static RPCHelpMan getpeerinfo() {RPCResult::Type::NUM, "version", "The peer version, such as 70001"}, {RPCResult::Type::STR, "subver", "The string version"}, {RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"}, + {RPCResult::Type::BOOL, "bip152_hb_to", "Whether we selected peer as (compact blocks) high-bandwidth peer"}, + {RPCResult::Type::BOOL, "bip152_hb_from", "Whether peer selected us as (compact blocks) high-bandwidth peer"}, {RPCResult::Type::BOOL, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n" "(DEPRECATED, returned only if the config option -deprecatedrpc=getpeerinfo_addnode is passed)"}, {RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + "."}, @@ -198,6 +200,8 @@ static RPCHelpMan getpeerinfo() // their ver message. obj.pushKV("subver", stats.cleanSubVer); obj.pushKV("inbound", stats.fInbound); + obj.pushKV("bip152_hb_to", stats.m_bip152_highbandwidth_to); + obj.pushKV("bip152_hb_from", stats.m_bip152_highbandwidth_from); if (IsDeprecatedRPCEnabled("getpeerinfo_addnode")) { // addnode is deprecated in v0.21 for removal in v0.22 obj.pushKV("addnode", stats.m_manual_connection); From dab6583307ceb7dd94affcc3482ddcc1a5747147 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 21 Aug 2020 16:51:11 +0200 Subject: [PATCH 3/4] doc: release note for new getpeerinfo fields "bip152_hb_{from,to}" Co-authored-by: Jon Atack --- doc/release-notes-19776.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 doc/release-notes-19776.md diff --git a/doc/release-notes-19776.md b/doc/release-notes-19776.md new file mode 100644 index 00000000000..5553c5a7bde --- /dev/null +++ b/doc/release-notes-19776.md @@ -0,0 +1,9 @@ +Updated RPCs +------------ + +- The `getpeerinfo` RPC returns two new boolean fields, `bip152_hb_to` and + `bip152_hb_from`, that respectively indicate whether we selected a peer to be + in compact blocks high-bandwidth mode or whether a peer selected us as a + compact blocks high-bandwidth peer. High-bandwidth peers send new block + announcements via a `cmpctblock` message rather than the usual inv/headers + announcements. See BIP 152 for more details. (#19776) From 343dc4760fd2407895fc8b3417a504b194429156 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sun, 23 Aug 2020 01:44:54 +0200 Subject: [PATCH 4/4] test: add test for high-bandwidth mode states in getpeerinfo --- test/functional/p2p_compactblocks.py | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py index 506b4800390..2a320dbd991 100755 --- a/test/functional/p2p_compactblocks.py +++ b/test/functional/p2p_compactblocks.py @@ -768,6 +768,34 @@ class CompactBlocksTest(BitcoinTestFramework): stalling_peer.send_and_ping(msg) assert_equal(int(node.getbestblockhash(), 16), block.sha256) + def test_highbandwidth_mode_states_via_getpeerinfo(self): + # create new p2p connection for a fresh state w/o any prior sendcmpct messages sent + hb_test_node = self.nodes[0].add_p2p_connection(TestP2PConn(cmpct_version=2)) + + # assert the RPC getpeerinfo boolean fields `bip152_hb_{to, from}` + # match the given parameters for the last peer of a given node + def assert_highbandwidth_states(node, hb_to, hb_from): + peerinfo = node.getpeerinfo()[-1] + assert_equal(peerinfo['bip152_hb_to'], hb_to) + assert_equal(peerinfo['bip152_hb_from'], hb_from) + + # initially, neither node has selected the other peer as high-bandwidth yet + assert_highbandwidth_states(self.nodes[0], hb_to=False, hb_from=False) + + # peer requests high-bandwidth mode by sending sendcmpct(1) + hb_test_node.send_and_ping(msg_sendcmpct(announce=True, version=2)) + assert_highbandwidth_states(self.nodes[0], hb_to=False, hb_from=True) + + # peer generates a block and sends it to node, which should + # select the peer as high-bandwidth (up to 3 peers according to BIP 152) + block = self.build_block_on_tip(self.nodes[0]) + hb_test_node.send_and_ping(msg_block(block)) + assert_highbandwidth_states(self.nodes[0], hb_to=True, hb_from=True) + + # peer requests low-bandwidth mode by sending sendcmpct(0) + hb_test_node.send_and_ping(msg_sendcmpct(announce=False, version=2)) + assert_highbandwidth_states(self.nodes[0], hb_to=True, hb_from=False) + def run_test(self): # Setup the p2p connections self.segwit_node = self.nodes[0].add_p2p_connection(TestP2PConn(cmpct_version=2)) @@ -823,6 +851,9 @@ class CompactBlocksTest(BitcoinTestFramework): self.log.info("Testing invalid index in cmpctblock message...") self.test_invalid_cmpctblock_message() + self.log.info("Testing high-bandwidth mode states via getpeerinfo...") + self.test_highbandwidth_mode_states_via_getpeerinfo() + if __name__ == '__main__': CompactBlocksTest().main()