Skip to content

Commit 37a480e

Browse files
committed
[net] Add addpeeraddress RPC method
Allows addresses to be added to Address Manager for testing.
1 parent ae8051b commit 37a480e

File tree

5 files changed

+66
-22
lines changed

5 files changed

+66
-22
lines changed

src/net.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,9 +2523,9 @@ void CConnman::MarkAddressGood(const CAddress& addr)
25232523
addrman.Good(addr);
25242524
}
25252525

2526-
void CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
2526+
bool CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
25272527
{
2528-
addrman.Add(vAddr, addrFrom, nTimePenalty);
2528+
return addrman.Add(vAddr, addrFrom, nTimePenalty);
25292529
}
25302530

25312531
std::vector<CAddress> CConnman::GetAddresses(size_t max_addresses, size_t max_pct)

src/net.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ class CConnman
250250
// Addrman functions
251251
void SetServices(const CService &addr, ServiceFlags nServices);
252252
void MarkAddressGood(const CAddress& addr);
253-
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
253+
bool AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
254254
std::vector<CAddress> GetAddresses(size_t max_addresses, size_t max_pct);
255255
/**
256256
* Cache is used to minimize topology leaks, so it should

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
173173
{ "createwallet", 4, "avoid_reuse"},
174174
{ "createwallet", 5, "descriptors"},
175175
{ "getnodeaddresses", 0, "count"},
176+
{ "addpeeraddress", 1, "port"},
176177
{ "stop", 0, "wait" },
177178
};
178179
// clang-format on

src/rpc/net.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,54 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
773773
return ret;
774774
}
775775

776+
static UniValue addpeeraddress(const JSONRPCRequest& request)
777+
{
778+
RPCHelpMan{"addpeeraddress",
779+
"\nAdd the address of a potential peer to the address manager. This RPC is for testing only.\n",
780+
{
781+
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address of the peer"},
782+
{"port", RPCArg::Type::NUM, RPCArg::Optional::NO, "The port of the peer"},
783+
},
784+
RPCResult{
785+
RPCResult::Type::OBJ, "", "",
786+
{
787+
{RPCResult::Type::BOOL, "success", "whether the peer address was successfully added to the address manager"},
788+
},
789+
},
790+
RPCExamples{
791+
HelpExampleCli("addpeeraddress", "\"1.2.3.4\" 8333")
792+
+ HelpExampleRpc("addpeeraddress", "\"1.2.3.4\", 8333")
793+
},
794+
}.Check(request);
795+
796+
NodeContext& node = EnsureNodeContext(request.context);
797+
if (!node.connman) {
798+
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
799+
}
800+
801+
UniValue obj(UniValue::VOBJ);
802+
803+
std::string addr_string = request.params[0].get_str();
804+
uint16_t port = request.params[1].get_int();
805+
806+
CNetAddr net_addr;
807+
if (!LookupHost(addr_string, net_addr, false)) {
808+
obj.pushKV("success", false);
809+
return obj;
810+
}
811+
CAddress address = CAddress({net_addr, port}, ServiceFlags(NODE_NETWORK|NODE_WITNESS));
812+
address.nTime = GetAdjustedTime();
813+
// The source address is set equal to the address. This is equivalent to the peer
814+
// announcing itself.
815+
if (!node.connman->AddNewAddresses({address}, address)) {
816+
obj.pushKV("success", false);
817+
return obj;
818+
}
819+
820+
obj.pushKV("success", true);
821+
return obj;
822+
}
823+
776824
void RegisterNetRPCCommands(CRPCTable &t)
777825
{
778826
// clang-format off
@@ -792,6 +840,7 @@ static const CRPCCommand commands[] =
792840
{ "network", "clearbanned", &clearbanned, {} },
793841
{ "network", "setnetworkactive", &setnetworkactive, {"state"} },
794842
{ "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
843+
{ "hidden", "addpeeraddress", &addpeeraddress, {"address", "port"} },
795844
};
796845
// clang-format on
797846

test/functional/rpc_net.py

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
from test_framework.mininode import P2PInterface
2323
import test_framework.messages
2424
from test_framework.messages import (
25-
CAddress,
26-
msg_addr,
2725
NODE_NETWORK,
2826
NODE_WITNESS,
2927
)
@@ -154,29 +152,25 @@ def test_service_flags(self):
154152
def _test_getnodeaddresses(self):
155153
self.nodes[0].add_p2p_connection(P2PInterface())
156154

157-
# send some addresses to the node via the p2p message addr
158-
msg = msg_addr()
155+
# Add some addresses to the Address Manager over RPC. Due to the way
156+
# bucket and bucket position are calculated, some of these addresses
157+
# will collide.
159158
imported_addrs = []
160-
for i in range(256):
161-
a = "123.123.123.{}".format(i)
159+
for i in range(10000):
160+
first_octet = i >> 8
161+
second_octet = i % 256
162+
a = "{}.{}.1.1".format(first_octet, second_octet)
162163
imported_addrs.append(a)
163-
addr = CAddress()
164-
addr.time = 100000000
165-
addr.nServices = NODE_NETWORK | NODE_WITNESS
166-
addr.ip = a
167-
addr.port = 8333
168-
msg.addrs.append(addr)
169-
self.nodes[0].p2p.send_and_ping(msg)
164+
self.nodes[0].addpeeraddress(a, 8333)
170165

171166
# Obtain addresses via rpc call and check they were ones sent in before.
172167
#
173-
# All addresses added above are in the same netgroup and so are assigned
174-
# to the same bucket. Maximum possible addresses in addrman is therefore
175-
# 64, although actual number will usually be slightly less due to
176-
# BucketPosition collisions.
168+
# Maximum possible addresses in addrman is 10000, although actual
169+
# number will usually be less due to bucket and bucket position
170+
# collisions.
177171
node_addresses = self.nodes[0].getnodeaddresses(0)
178-
assert_greater_than(len(node_addresses), 50)
179-
assert_greater_than(65, len(node_addresses))
172+
assert_greater_than(len(node_addresses), 5000)
173+
assert_greater_than(10000, len(node_addresses))
180174
for a in node_addresses:
181175
assert_greater_than(a["time"], 1527811200) # 1st June 2018
182176
assert_equal(a["services"], NODE_NETWORK | NODE_WITNESS)

0 commit comments

Comments
 (0)