[net] Add addpeeraddress RPC method
Allows addresses to be added to Address Manager for testing.
This commit is contained in:
1 parent
ae8051bbd8
commit
37a480e0cd
5 files changed
+66
-22
No files matched your search
+2
-2
@@ -2523,9 +2523,9 @@ void CConnman::MarkAddressGood(const CAddress& addr)
|
|||||||
addrman.Good(addr);
|
addrman.Good(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
|
bool CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
|
||||||
{
|
{
|
||||||
addrman.Add(vAddr, addrFrom, nTimePenalty);
|
return addrman.Add(vAddr, addrFrom, nTimePenalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CAddress> CConnman::GetAddresses(size_t max_addresses, size_t max_pct)
|
std::vector<CAddress> CConnman::GetAddresses(size_t max_addresses, size_t max_pct)
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ public:
|
|||||||
// Addrman functions
|
// Addrman functions
|
||||||
void SetServices(const CService &addr, ServiceFlags nServices);
|
void SetServices(const CService &addr, ServiceFlags nServices);
|
||||||
void MarkAddressGood(const CAddress& addr);
|
void MarkAddressGood(const CAddress& addr);
|
||||||
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
|
bool AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
|
||||||
std::vector<CAddress> GetAddresses(size_t max_addresses, size_t max_pct);
|
std::vector<CAddress> GetAddresses(size_t max_addresses, size_t max_pct);
|
||||||
/**
|
/**
|
||||||
* Cache is used to minimize topology leaks, so it should
|
* Cache is used to minimize topology leaks, so it should
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "createwallet", 4, "avoid_reuse"},
|
{ "createwallet", 4, "avoid_reuse"},
|
||||||
{ "createwallet", 5, "descriptors"},
|
{ "createwallet", 5, "descriptors"},
|
||||||
{ "getnodeaddresses", 0, "count"},
|
{ "getnodeaddresses", 0, "count"},
|
||||||
|
{ "addpeeraddress", 1, "port"},
|
||||||
{ "stop", 0, "wait" },
|
{ "stop", 0, "wait" },
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|||||||
@@ -773,6 +773,54 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UniValue addpeeraddress(const JSONRPCRequest& request)
|
||||||
|
{
|
||||||
|
RPCHelpMan{"addpeeraddress",
|
||||||
|
"\nAdd the address of a potential peer to the address manager. This RPC is for testing only.\n",
|
||||||
|
{
|
||||||
|
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address of the peer"},
|
||||||
|
{"port", RPCArg::Type::NUM, RPCArg::Optional::NO, "The port of the peer"},
|
||||||
|
},
|
||||||
|
RPCResult{
|
||||||
|
RPCResult::Type::OBJ, "", "",
|
||||||
|
{
|
||||||
|
{RPCResult::Type::BOOL, "success", "whether the peer address was successfully added to the address manager"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RPCExamples{
|
||||||
|
HelpExampleCli("addpeeraddress", "\"1.2.3.4\" 8333")
|
||||||
|
+ HelpExampleRpc("addpeeraddress", "\"1.2.3.4\", 8333")
|
||||||
|
},
|
||||||
|
}.Check(request);
|
||||||
|
|
||||||
|
NodeContext& node = EnsureNodeContext(request.context);
|
||||||
|
if (!node.connman) {
|
||||||
|
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue obj(UniValue::VOBJ);
|
||||||
|
|
||||||
|
std::string addr_string = request.params[0].get_str();
|
||||||
|
uint16_t port = request.params[1].get_int();
|
||||||
|
|
||||||
|
CNetAddr net_addr;
|
||||||
|
if (!LookupHost(addr_string, net_addr, false)) {
|
||||||
|
obj.pushKV("success", false);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
CAddress address = CAddress({net_addr, port}, ServiceFlags(NODE_NETWORK|NODE_WITNESS));
|
||||||
|
address.nTime = GetAdjustedTime();
|
||||||
|
// The source address is set equal to the address. This is equivalent to the peer
|
||||||
|
// announcing itself.
|
||||||
|
if (!node.connman->AddNewAddresses({address}, address)) {
|
||||||
|
obj.pushKV("success", false);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.pushKV("success", true);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterNetRPCCommands(CRPCTable &t)
|
void RegisterNetRPCCommands(CRPCTable &t)
|
||||||
{
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
@@ -792,6 +840,7 @@ static const CRPCCommand commands[] =
|
|||||||
{ "network", "clearbanned", &clearbanned, {} },
|
{ "network", "clearbanned", &clearbanned, {} },
|
||||||
{ "network", "setnetworkactive", &setnetworkactive, {"state"} },
|
{ "network", "setnetworkactive", &setnetworkactive, {"state"} },
|
||||||
{ "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
|
{ "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
|
||||||
|
{ "hidden", "addpeeraddress", &addpeeraddress, {"address", "port"} },
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|||||||
+13
-19
@@ -22,8 +22,6 @@ from test_framework.util import (
|
|||||||
from test_framework.mininode import P2PInterface
|
from test_framework.mininode import P2PInterface
|
||||||
import test_framework.messages
|
import test_framework.messages
|
||||||
from test_framework.messages import (
|
from test_framework.messages import (
|
||||||
CAddress,
|
|
||||||
msg_addr,
|
|
||||||
NODE_NETWORK,
|
NODE_NETWORK,
|
||||||
NODE_WITNESS,
|
NODE_WITNESS,
|
||||||
)
|
)
|
||||||
@@ -154,29 +152,25 @@ class NetTest(BitcoinTestFramework):
|
|||||||
def _test_getnodeaddresses(self):
|
def _test_getnodeaddresses(self):
|
||||||
self.nodes[0].add_p2p_connection(P2PInterface())
|
self.nodes[0].add_p2p_connection(P2PInterface())
|
||||||
|
|
||||||
# send some addresses to the node via the p2p message addr
|
# Add some addresses to the Address Manager over RPC. Due to the way
|
||||||
msg = msg_addr()
|
# bucket and bucket position are calculated, some of these addresses
|
||||||
|
# will collide.
|
||||||
imported_addrs = []
|
imported_addrs = []
|
||||||
for i in range(256):
|
for i in range(10000):
|
||||||
a = "123.123.123.{}".format(i)
|
first_octet = i >> 8
|
||||||
|
second_octet = i % 256
|
||||||
|
a = "{}.{}.1.1".format(first_octet, second_octet)
|
||||||
imported_addrs.append(a)
|
imported_addrs.append(a)
|
||||||
addr = CAddress()
|
self.nodes[0].addpeeraddress(a, 8333)
|
||||||
addr.time = 100000000
|
|
||||||
addr.nServices = NODE_NETWORK | NODE_WITNESS
|
|
||||||
addr.ip = a
|
|
||||||
addr.port = 8333
|
|
||||||
msg.addrs.append(addr)
|
|
||||||
self.nodes[0].p2p.send_and_ping(msg)
|
|
||||||
|
|
||||||
# Obtain addresses via rpc call and check they were ones sent in before.
|
# Obtain addresses via rpc call and check they were ones sent in before.
|
||||||
#
|
#
|
||||||
# All addresses added above are in the same netgroup and so are assigned
|
# Maximum possible addresses in addrman is 10000, although actual
|
||||||
# to the same bucket. Maximum possible addresses in addrman is therefore
|
# number will usually be less due to bucket and bucket position
|
||||||
# 64, although actual number will usually be slightly less due to
|
# collisions.
|
||||||
# BucketPosition collisions.
|
|
||||||
node_addresses = self.nodes[0].getnodeaddresses(0)
|
node_addresses = self.nodes[0].getnodeaddresses(0)
|
||||||
assert_greater_than(len(node_addresses), 50)
|
assert_greater_than(len(node_addresses), 5000)
|
||||||
assert_greater_than(65, len(node_addresses))
|
assert_greater_than(10000, len(node_addresses))
|
||||||
for a in node_addresses:
|
for a in node_addresses:
|
||||||
assert_greater_than(a["time"], 1527811200) # 1st June 2018
|
assert_greater_than(a["time"], 1527811200) # 1st June 2018
|
||||||
assert_equal(a["services"], NODE_NETWORK | NODE_WITNESS)
|
assert_equal(a["services"], NODE_NETWORK | NODE_WITNESS)
|
||||||
|
|||||||
Reference in new issue
Block a user