rpc: addnode arg to use BIP324 v2 p2p

Co-authored-by: Pieter Wuille <bitcoin-dev@wuille.net>
This commit is contained in:
dhruv 2021-12-28 13:26:20 -08:00 committed by Pieter Wuille
parent 62d21ee097
commit c73cd42363
6 changed files with 48 additions and 29 deletions

View file

@ -2452,7 +2452,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// Perform cheap checks before locking a mutex. // Perform cheap checks before locking a mutex.
else if (!dnsseed && !use_seednodes) { else if (!dnsseed && !use_seednodes) {
LOCK(m_added_nodes_mutex); LOCK(m_added_nodes_mutex);
if (m_added_nodes.empty()) { if (m_added_node_params.empty()) {
add_fixed_seeds_now = true; add_fixed_seeds_now = true;
LogPrintf("Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided\n"); LogPrintf("Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided\n");
} }
@ -2725,11 +2725,11 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() const
{ {
std::vector<AddedNodeInfo> ret; std::vector<AddedNodeInfo> ret;
std::list<std::string> lAddresses(0); std::list<AddedNodeParams> lAddresses(0);
{ {
LOCK(m_added_nodes_mutex); LOCK(m_added_nodes_mutex);
ret.reserve(m_added_nodes.size()); ret.reserve(m_added_node_params.size());
std::copy(m_added_nodes.cbegin(), m_added_nodes.cend(), std::back_inserter(lAddresses)); std::copy(m_added_node_params.cbegin(), m_added_node_params.cend(), std::back_inserter(lAddresses));
} }
@ -2749,9 +2749,9 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() const
} }
} }
for (const std::string& strAddNode : lAddresses) { for (const auto& addr : lAddresses) {
CService service(LookupNumeric(strAddNode, GetDefaultPort(strAddNode))); CService service(LookupNumeric(addr.m_added_node, GetDefaultPort(addr.m_added_node)));
AddedNodeInfo addedNode{strAddNode, CService(), false, false}; AddedNodeInfo addedNode{addr, CService(), false, false};
if (service.IsValid()) { if (service.IsValid()) {
// strAddNode is an IP:port // strAddNode is an IP:port
auto it = mapConnected.find(service); auto it = mapConnected.find(service);
@ -2762,7 +2762,7 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() const
} }
} else { } else {
// strAddNode is a name // strAddNode is a name
auto it = mapConnectedByName.find(strAddNode); auto it = mapConnectedByName.find(addr.m_added_node);
if (it != mapConnectedByName.end()) { if (it != mapConnectedByName.end()) {
addedNode.resolvedAddress = it->second.second; addedNode.resolvedAddress = it->second.second;
addedNode.fConnected = true; addedNode.fConnected = true;
@ -2792,7 +2792,7 @@ void CConnman::ThreadOpenAddedConnections()
} }
tried = true; tried = true;
CAddress addr(CService(), NODE_NONE); CAddress addr(CService(), NODE_NONE);
OpenNetworkConnection(addr, false, &grant, info.strAddedNode.c_str(), ConnectionType::MANUAL, /*use_v2transport=*/false); OpenNetworkConnection(addr, false, &grant, info.m_params.m_added_node.c_str(), ConnectionType::MANUAL, info.m_params.m_use_v2transport);
if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
return; return;
} }
@ -3384,23 +3384,23 @@ std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addres
return cache_entry.m_addrs_response_cache; return cache_entry.m_addrs_response_cache;
} }
bool CConnman::AddNode(const std::string& strNode) bool CConnman::AddNode(const AddedNodeParams& add)
{ {
LOCK(m_added_nodes_mutex); LOCK(m_added_nodes_mutex);
for (const std::string& it : m_added_nodes) { for (const auto& it : m_added_node_params) {
if (strNode == it) return false; if (add.m_added_node == it.m_added_node) return false;
} }
m_added_nodes.push_back(strNode); m_added_node_params.push_back(add);
return true; return true;
} }
bool CConnman::RemoveAddedNode(const std::string& strNode) bool CConnman::RemoveAddedNode(const std::string& strNode)
{ {
LOCK(m_added_nodes_mutex); LOCK(m_added_nodes_mutex);
for(std::vector<std::string>::iterator it = m_added_nodes.begin(); it != m_added_nodes.end(); ++it) { for (auto it = m_added_node_params.begin(); it != m_added_node_params.end(); ++it) {
if (strNode == *it) { if (strNode == it->m_added_node) {
m_added_nodes.erase(it); m_added_node_params.erase(it);
return true; return true;
} }
} }

View file

@ -98,9 +98,13 @@ static constexpr bool DEFAULT_V2_TRANSPORT{false};
typedef int64_t NodeId; typedef int64_t NodeId;
struct AddedNodeInfo struct AddedNodeParams {
{ std::string m_added_node;
std::string strAddedNode; bool m_use_v2transport;
};
struct AddedNodeInfo {
AddedNodeParams m_params;
CService resolvedAddress; CService resolvedAddress;
bool fConnected; bool fConnected;
bool fInbound; bool fInbound;
@ -1075,7 +1079,11 @@ public:
vWhitelistedRange = connOptions.vWhitelistedRange; vWhitelistedRange = connOptions.vWhitelistedRange;
{ {
LOCK(m_added_nodes_mutex); LOCK(m_added_nodes_mutex);
m_added_nodes = connOptions.m_added_nodes;
for (const std::string& added_node : connOptions.m_added_nodes) {
// -addnode cli arg does not currently have a way to signal BIP324 support
m_added_node_params.push_back({added_node, false});
}
} }
m_onion_binds = connOptions.onion_binds; m_onion_binds = connOptions.onion_binds;
} }
@ -1162,7 +1170,7 @@ public:
// Count the number of block-relay-only peers we have over our limit. // Count the number of block-relay-only peers we have over our limit.
int GetExtraBlockRelayCount() const; int GetExtraBlockRelayCount() const;
bool AddNode(const std::string& node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex); bool AddNode(const AddedNodeParams& add) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
bool RemoveAddedNode(const std::string& node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex); bool RemoveAddedNode(const std::string& node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
std::vector<AddedNodeInfo> GetAddedNodeInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex); std::vector<AddedNodeInfo> GetAddedNodeInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
@ -1387,7 +1395,10 @@ private:
const NetGroupManager& m_netgroupman; const NetGroupManager& m_netgroupman;
std::deque<std::string> m_addr_fetches GUARDED_BY(m_addr_fetches_mutex); std::deque<std::string> m_addr_fetches GUARDED_BY(m_addr_fetches_mutex);
Mutex m_addr_fetches_mutex; Mutex m_addr_fetches_mutex;
std::vector<std::string> m_added_nodes GUARDED_BY(m_added_nodes_mutex);
// connection string and whether to use v2 p2p
std::vector<AddedNodeParams> m_added_node_params GUARDED_BY(m_added_nodes_mutex);
mutable Mutex m_added_nodes_mutex; mutable Mutex m_added_nodes_mutex;
std::vector<CNode*> m_nodes GUARDED_BY(m_nodes_mutex); std::vector<CNode*> m_nodes GUARDED_BY(m_nodes_mutex);
std::list<CNode*> m_nodes_disconnected; std::list<CNode*> m_nodes_disconnected;

View file

@ -301,6 +301,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "addpeeraddress", 2, "tried"}, { "addpeeraddress", 2, "tried"},
{ "sendmsgtopeer", 0, "peer_id" }, { "sendmsgtopeer", 0, "peer_id" },
{ "stop", 0, "wait" }, { "stop", 0, "wait" },
{ "addnode", 2, "v2transport" },
}; };
// clang-format on // clang-format on

View file

@ -289,11 +289,12 @@ static RPCHelpMan addnode()
{ {
{"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The address of the peer to connect to"}, {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The address of the peer to connect to"},
{"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once"}, {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once"},
{"v2transport", RPCArg::Type::BOOL, RPCArg::Default{false}, "Attempt to connect using BIP324 v2 transport protocol (ignored for 'remove' command)"},
}, },
RPCResult{RPCResult::Type::NONE, "", ""}, RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{ RPCExamples{
HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"") HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\" true")
+ HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"") + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\" true")
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
@ -307,17 +308,22 @@ static RPCHelpMan addnode()
CConnman& connman = EnsureConnman(node); CConnman& connman = EnsureConnman(node);
const std::string node_arg{request.params[0].get_str()}; const std::string node_arg{request.params[0].get_str()};
bool use_v2transport = self.Arg<bool>(2);
if (use_v2transport && !(node.connman->GetLocalServices() & NODE_P2P_V2)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Error: v2transport requested but not enabled (see -v2transport)");
}
if (command == "onetry") if (command == "onetry")
{ {
CAddress addr; CAddress addr;
connman.OpenNetworkConnection(addr, /*fCountFailure=*/false, /*grantOutbound=*/nullptr, node_arg.c_str(), ConnectionType::MANUAL, /*use_v2transport=*/false); connman.OpenNetworkConnection(addr, /*fCountFailure=*/false, /*grantOutbound=*/nullptr, node_arg.c_str(), ConnectionType::MANUAL, use_v2transport);
return UniValue::VNULL; return UniValue::VNULL;
} }
if (command == "add") if (command == "add")
{ {
if (!connman.AddNode(node_arg)) { if (!connman.AddNode({node_arg, use_v2transport})) {
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added"); throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
} }
} }
@ -475,7 +481,7 @@ static RPCHelpMan getaddednodeinfo()
if (!request.params[0].isNull()) { if (!request.params[0].isNull()) {
bool found = false; bool found = false;
for (const AddedNodeInfo& info : vInfo) { for (const AddedNodeInfo& info : vInfo) {
if (info.strAddedNode == request.params[0].get_str()) { if (info.m_params.m_added_node == request.params[0].get_str()) {
vInfo.assign(1, info); vInfo.assign(1, info);
found = true; found = true;
break; break;
@ -490,7 +496,7 @@ static RPCHelpMan getaddednodeinfo()
for (const AddedNodeInfo& info : vInfo) { for (const AddedNodeInfo& info : vInfo) {
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV("addednode", info.strAddedNode); obj.pushKV("addednode", info.m_params.m_added_node);
obj.pushKV("connected", info.fConnected); obj.pushKV("connected", info.fConnected);
UniValue addresses(UniValue::VARR); UniValue addresses(UniValue::VARR);
if (info.fConnected) { if (info.fConnected) {

View file

@ -682,6 +682,7 @@ TMPL_INST(nullptr, std::optional<bool>, maybe_arg ? std::optional{maybe_arg->get
TMPL_INST(nullptr, const std::string*, maybe_arg ? &maybe_arg->get_str() : nullptr;); TMPL_INST(nullptr, const std::string*, maybe_arg ? &maybe_arg->get_str() : nullptr;);
// Required arg or optional arg with default value. // Required arg or optional arg with default value.
TMPL_INST(CheckRequiredOrDefault, bool, CHECK_NONFATAL(maybe_arg)->get_bool(););
TMPL_INST(CheckRequiredOrDefault, int, CHECK_NONFATAL(maybe_arg)->getInt<int>();); TMPL_INST(CheckRequiredOrDefault, int, CHECK_NONFATAL(maybe_arg)->getInt<int>(););
TMPL_INST(CheckRequiredOrDefault, uint64_t, CHECK_NONFATAL(maybe_arg)->getInt<uint64_t>();); TMPL_INST(CheckRequiredOrDefault, uint64_t, CHECK_NONFATAL(maybe_arg)->getInt<uint64_t>(););
TMPL_INST(CheckRequiredOrDefault, const std::string&, CHECK_NONFATAL(maybe_arg)->get_str();); TMPL_INST(CheckRequiredOrDefault, const std::string&, CHECK_NONFATAL(maybe_arg)->get_str(););

View file

@ -61,7 +61,7 @@ FUZZ_TARGET(connman, .init = initialize_connman)
random_string = fuzzed_data_provider.ConsumeRandomLengthString(64); random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
}, },
[&] { [&] {
connman.AddNode(random_string); connman.AddNode({random_string, fuzzed_data_provider.ConsumeBool()});
}, },
[&] { [&] {
connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>());