0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-09 10:43:19 -05:00

Merge #19725: [RPC] Add connection type to getpeerinfo, improve logs

a512925e19 [doc] Release notes (Amiti Uttarwar)
50f94b34a3 [rpc] Deprecate getpeerinfo addnode field (Amiti Uttarwar)
df091b9b50 [refactor] Rename test file to allow any getpeerinfo deprecations. (Amiti Uttarwar)
395acfa83a [rpc] Add connection type to getpeerinfo RPC, update tests (Amiti Uttarwar)
49c10a9ca4 [log] Add connection type to log statement (Amiti Uttarwar)

Pull request description:

  After #19316, we can more directly expose information about the connection type on the `getpeerinfo` RPC. Doing so also makes the existing addnode field redundant, so this PR begins the process of deprecating this field.

  This PR also includes one commit that improves a log message, as both use a shared function to return the connection type as a string.

  Suggested by sdaftuar- https://github.com/bitcoin/bitcoin/pull/19316#discussion_r468001604 & https://github.com/bitcoin/bitcoin/pull/19316#discussion_r468018093

ACKs for top commit:
  jnewbery:
    Code review ACK a512925e19.
  sipa:
    utACK a512925e19
  guggero:
    Tested and code review ACK a512925e.
  MarcoFalke:
    cr ACK a512925e19 🌇
  promag:
    Code review ACK a512925e19.

Tree-SHA512: 601a7a38aee235ee59aca690784f886dc2ae4e418b2e6422c4b58cd597376c00f74910f66920b08a08a0bec28bf8022e71a1435785ff6ba8a188954261aba78e
This commit is contained in:
MarcoFalke 2020-09-26 17:24:33 +02:00
commit 4f45ea1f73
No known key found for this signature in database
GPG key ID: D2EA4850E7528B25
9 changed files with 99 additions and 32 deletions

View file

@ -105,6 +105,17 @@ will trigger BIP 125 (replace-by-fee) opt-in. (#11413)
- The `testmempoolaccept` RPC returns `vsize` and a `fee` object with the `base` fee - The `testmempoolaccept` RPC returns `vsize` and a `fee` object with the `base` fee
if the transaction passes validation. (#19940) if the transaction passes validation. (#19940)
- The `getpeerinfo` RPC now returns a `connection_type` field. This indicates
the type of connection established with the peer. It will return one of six
options. For more information, see the `getpeerinfo` help documentation.
(#19725)
- The `getpeerinfo` RPC no longer returns the `addnode` field by default. This
field will be fully removed in the next major release. It can be accessed
with the configuration option `-deprecatedrpc=getpeerinfo_addnode`. However,
it is recommended to instead use the `connection_type` field (it will return
`manual` when addnode is true). (#19725)
- The `walletcreatefundedpsbt` RPC call will now fail with - The `walletcreatefundedpsbt` RPC call will now fail with
`Insufficient funds` when inputs are manually selected but are not enough to cover `Insufficient funds` when inputs are manually selected but are not enough to cover
the outputs and fee. Additional inputs can automatically be added through the the outputs and fee. Additional inputs can automatically be added through the

View file

@ -488,6 +488,26 @@ void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNet
} }
} }
std::string CNode::ConnectionTypeAsString() const
{
switch (m_conn_type) {
case ConnectionType::INBOUND:
return "inbound";
case ConnectionType::MANUAL:
return "manual";
case ConnectionType::FEELER:
return "feeler";
case ConnectionType::OUTBOUND_FULL_RELAY:
return "outbound-full-relay";
case ConnectionType::BLOCK_RELAY:
return "block-relay-only";
case ConnectionType::ADDR_FETCH:
return "addr-fetch";
} // no default case, so the compiler can warn about missing cases
assert(false);
}
std::string CNode::GetAddrName() const { std::string CNode::GetAddrName() const {
LOCK(cs_addrName); LOCK(cs_addrName);
return addrName; return addrName;
@ -582,6 +602,8 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
// Leave string empty if addrLocal invalid (not filled in yet) // Leave string empty if addrLocal invalid (not filled in yet)
CService addrLocalUnlocked = GetAddrLocal(); CService addrLocalUnlocked = GetAddrLocal();
stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToString() : ""; stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToString() : "";
stats.m_conn_type_string = ConnectionTypeAsString();
} }
#undef X #undef X

View file

@ -114,6 +114,14 @@ struct CSerializedNetMsg
std::string m_type; std::string m_type;
}; };
const std::vector<std::string> CONNECTION_TYPE_DOC{
"outbound-full-relay (default automatic connections)",
"block-relay-only (does not relay transactions or addresses)",
"inbound (initiated by the peer)",
"manual (added via addnode RPC or -addnode/-connect configuration options)",
"addr-fetch (short-lived automatic connection for soliciting addresses)",
"feeler (short-lived automatic connection for testing addresses)"};
/** Different types of connections to a peer. This enum encapsulates the /** Different types of connections to a peer. This enum encapsulates the
* information we have available at the time of opening or accepting the * information we have available at the time of opening or accepting the
* connection. Aside from INBOUND, all types are initiated by us. */ * connection. Aside from INBOUND, all types are initiated by us. */
@ -691,6 +699,7 @@ public:
// Bind address of our side of the connection // Bind address of our side of the connection
CAddress addrBind; CAddress addrBind;
uint32_t m_mapped_as; uint32_t m_mapped_as;
std::string m_conn_type_string;
}; };
@ -1144,6 +1153,8 @@ public:
std::string GetAddrName() const; std::string GetAddrName() const;
//! Sets the addrName only if it was not previously set //! Sets the addrName only if it was not previously set
void MaybeSetAddrName(const std::string& addrNameIn); void MaybeSetAddrName(const std::string& addrNameIn);
std::string ConnectionTypeAsString() const;
}; };
/** Return a timestamp in the future (in microseconds) for exponentially distributed events. */ /** Return a timestamp in the future (in microseconds) for exponentially distributed events. */

View file

@ -3520,11 +3520,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// Making nodes which are behind NAT and can only make outgoing connections ignore // Making nodes which are behind NAT and can only make outgoing connections ignore
// the getaddr message mitigates the attack. // the getaddr message mitigates the attack.
if (!pfrom.IsInboundConn()) { if (!pfrom.IsInboundConn()) {
LogPrint(BCLog::NET, "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom.GetId()); LogPrint(BCLog::NET, "Ignoring \"getaddr\" from %s connection. peer=%d\n", pfrom.ConnectionTypeAsString(), pfrom.GetId());
return;
}
if (!pfrom.RelayAddrsWithConn()) {
LogPrint(BCLog::NET, "Ignoring \"getaddr\" from block-relay-only connection. peer=%d\n", pfrom.GetId());
return; return;
} }

View file

@ -116,7 +116,9 @@ static RPCHelpMan getpeerinfo()
{RPCResult::Type::NUM, "version", "The peer version, such as 70001"}, {RPCResult::Type::NUM, "version", "The peer version, such as 70001"},
{RPCResult::Type::STR, "subver", "The string version"}, {RPCResult::Type::STR, "subver", "The string version"},
{RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"}, {RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
{RPCResult::Type::BOOL, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection"}, {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") + "."},
{RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"}, {RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
{RPCResult::Type::NUM, "banscore", "The ban score (DEPRECATED, returned only if config option -deprecatedrpc=banscore is passed)"}, {RPCResult::Type::NUM, "banscore", "The ban score (DEPRECATED, returned only if config option -deprecatedrpc=banscore is passed)"},
{RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"}, {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
@ -196,7 +198,10 @@ static RPCHelpMan getpeerinfo()
// their ver message. // their ver message.
obj.pushKV("subver", stats.cleanSubVer); obj.pushKV("subver", stats.cleanSubVer);
obj.pushKV("inbound", stats.fInbound); obj.pushKV("inbound", stats.fInbound);
obj.pushKV("addnode", stats.m_manual_connection); if (IsDeprecatedRPCEnabled("getpeerinfo_addnode")) {
// addnode is deprecated in v0.21 for removal in v0.22
obj.pushKV("addnode", stats.m_manual_connection);
}
obj.pushKV("startingheight", stats.nStartingHeight); obj.pushKV("startingheight", stats.nStartingHeight);
if (fStateStats) { if (fStateStats) {
if (IsDeprecatedRPCEnabled("banscore")) { if (IsDeprecatedRPCEnabled("banscore")) {
@ -232,6 +237,7 @@ static RPCHelpMan getpeerinfo()
recvPerMsgCmd.pushKV(i.first, i.second); recvPerMsgCmd.pushKV(i.first, i.second);
} }
obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd); obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
obj.pushKV("connection_type", stats.m_conn_type_string);
ret.push_back(obj); ret.push_back(obj);
} }

View file

@ -1,24 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) 2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test deprecation of getpeerinfo RPC banscore field."""
from test_framework.test_framework import BitcoinTestFramework
class GetpeerinfoBanscoreDeprecationTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.extra_args = [[], ["-deprecatedrpc=banscore"]]
def run_test(self):
self.log.info("Test getpeerinfo by default no longer returns a banscore field")
assert "banscore" not in self.nodes[0].getpeerinfo()[0].keys()
self.log.info("Test getpeerinfo returns banscore with -deprecatedrpc=banscore")
assert "banscore" in self.nodes[1].getpeerinfo()[0].keys()
if __name__ == "__main__":
GetpeerinfoBanscoreDeprecationTest().main()

View file

@ -0,0 +1,39 @@
#!/usr/bin/env python3
# Copyright (c) 2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test deprecation of getpeerinfo RPC fields."""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import connect_nodes
class GetpeerinfoDeprecationTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.extra_args = [[], ["-deprecatedrpc=banscore"]]
def run_test(self):
self.test_banscore_deprecation()
self.test_addnode_deprecation()
def test_banscore_deprecation(self):
self.log.info("Test getpeerinfo by default no longer returns a banscore field")
assert "banscore" not in self.nodes[0].getpeerinfo()[0].keys()
self.log.info("Test getpeerinfo returns banscore with -deprecatedrpc=banscore")
assert "banscore" in self.nodes[1].getpeerinfo()[0].keys()
def test_addnode_deprecation(self):
self.restart_node(1, ["-deprecatedrpc=getpeerinfo_addnode"])
connect_nodes(self.nodes[0], 1)
self.log.info("Test getpeerinfo by default no longer returns an addnode field")
assert "addnode" not in self.nodes[0].getpeerinfo()[0].keys()
self.log.info("Test getpeerinfo returns addnode with -deprecatedrpc=addnode")
assert "addnode" in self.nodes[1].getpeerinfo()[0].keys()
if __name__ == "__main__":
GetpeerinfoDeprecationTest().main()

View file

@ -175,6 +175,12 @@ class NetTest(BitcoinTestFramework):
for info in peer_info: for info in peer_info:
assert_net_servicesnames(int(info[0]["services"], 0x10), info[0]["servicesnames"]) assert_net_servicesnames(int(info[0]["services"], 0x10), info[0]["servicesnames"])
assert_equal(peer_info[0][0]['connection_type'], 'inbound')
assert_equal(peer_info[0][1]['connection_type'], 'manual')
assert_equal(peer_info[1][0]['connection_type'], 'manual')
assert_equal(peer_info[1][1]['connection_type'], 'inbound')
def test_service_flags(self): def test_service_flags(self):
self.log.info("Test service flags") self.log.info("Test service flags")
self.nodes[0].add_p2p_connection(P2PInterface(), services=(1 << 4) | (1 << 63)) self.nodes[0].add_p2p_connection(P2PInterface(), services=(1 << 4) | (1 << 63))

View file

@ -251,7 +251,7 @@ BASE_SCRIPTS = [
'feature_config_args.py', 'feature_config_args.py',
'feature_settings.py', 'feature_settings.py',
'rpc_getdescriptorinfo.py', 'rpc_getdescriptorinfo.py',
'rpc_getpeerinfo_banscore_deprecation.py', 'rpc_getpeerinfo_deprecation.py',
'rpc_help.py', 'rpc_help.py',
'feature_help.py', 'feature_help.py',
'feature_shutdown.py', 'feature_shutdown.py',