Skip to content

Commit

Permalink
Merge bitcoin#19776: net, rpc: expose high bandwidth mode state via g…
Browse files Browse the repository at this point in the history
…etpeerinfo

343dc47 test: add test for high-bandwidth mode states in getpeerinfo (Sebastian Falbesoner)
dab6583 doc: release note for new getpeerinfo fields "bip152_hb_{from,to}" (Sebastian Falbesoner)
a7ed00f rpc: expose high-bandwidth mode states via getpeerinfo (Sebastian Falbesoner)
30bc8fa net: save high-bandwidth mode states in CNodeStats (Sebastian Falbesoner)

Pull request description:

  Fixes bitcoin#19676, "_For every peer expose through getpeerinfo RPC whether or not we selected them as HB peers, and whether or not they selected us as HB peers._" See [BIP152](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki), in particular the [protocol flow diagram](https://github.com/bitcoin/bips/raw/master/bip-0152/protocol-flow.png).  The newly introduced states are changed on the following places in the code:
  * on reception of a `SENDCMPCT` message with valid version, the field `m_highbandwidth_from` is changed depending on the first integer parameter in the message (1=high bandwidth, 0=low bandwidth), i.e. it just mirrors the field `CNodeState.fPreferHeaderAndIDs`.
  * after adding a `SENDCMPCT` message to the send queue, the field `m_highbandwidth_to` is changed depending on how the first integer parameter is set (same as above)

  Note that after receiving `VERACK`, the node also sends `SENDCMPCT`, but that is only to announce the preferred version and never selects high-bandwidth mode, hence there is no need to change the state variables there, which are initialized to `false` anyways.

ACKs for top commit:
  naumenkogs:
    reACK 343dc47
  jonatack:
    re-ACK 343dc47 per `git range-diff 7ea6499 4df1d12 343dc47`

Tree-SHA512: f4999e6a935266812c2259a9b5dc459710037d3c9e938006d282557cc225e56128f72965faffb207fc60c6531fab1206db976dd8729a69e8ca29d4835317b99f
  • Loading branch information
MarcoFalke authored and vijaydasmp committed Dec 12, 2023
1 parent a38dac8 commit 635d2fb
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 1 deletion.
9 changes: 9 additions & 0 deletions doc/release-notes-19776.md
Original file line number Diff line number Diff line change
@@ -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)
2 changes: 2 additions & 0 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,8 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
}
X(fInbound);
X(m_manual_connection);
X(m_bip152_highbandwidth_to);
X(m_bip152_highbandwidth_from);
X(nStartingHeight);
{
LOCK(cs_vSend);
Expand Down
6 changes: 6 additions & 0 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,8 @@ class CNodeStats
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;
Expand Down Expand Up @@ -1145,6 +1147,10 @@ class CNode
public:
uint256 hashContinue;
std::atomic<int> nStartingHeight{-1};
// We selected peer as (compact blocks) high-bandwidth peer (BIP152)
std::atomic<bool> m_bip152_highbandwidth_to{false};
// Peer selected us as (compact blocks) high-bandwidth peer (BIP152)
std::atomic<bool> m_bip152_highbandwidth_from{false};

// flood relay
std::vector<CAddress> vAddrToSend;
Expand Down
5 changes: 4 additions & 1 deletion src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,12 +839,15 @@ void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid)
m_connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [this, nCMPCTBLOCKVersion](CNode* pnodeStop){
AssertLockHeld(cs_main);
m_connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetSendVersion()).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();
}
m_connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/true, nCMPCTBLOCKVersion));
lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId());
// save BIP152 bandwidth state: we select peer to be high-bandwidth
pfrom->m_bip152_highbandwidth_to = true;
return true;
});
}
Expand Down
4 changes: 4 additions & 0 deletions src/rpc/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
{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"},
{RPCResult::Type::BOOL, "masternode", "Whether connection was due to masternode connection attempt"},
{RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
Expand Down Expand Up @@ -205,6 +207,8 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
obj.pushKV("inbound", stats.fInbound);
obj.pushKV("addnode", stats.m_manual_connection);
obj.pushKV("masternode", stats.m_masternode_connection);
obj.pushKV("bip152_hb_to", stats.m_bip152_highbandwidth_to);
obj.pushKV("bip152_hb_from", stats.m_bip152_highbandwidth_from);
obj.pushKV("startingheight", stats.nStartingHeight);
if (fStateStats) {
obj.pushKV("banscore", statestats.m_misbehavior_score);
Expand Down
32 changes: 32 additions & 0 deletions test/functional/p2p_compactblocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,34 @@ def announce_cmpct_block(node, peer):
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.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(cmpct_version=1))
Expand Down Expand Up @@ -809,5 +837,9 @@ def run_test(self):
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()

0 comments on commit 635d2fb

Please sign in to comment.