mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
merge bitcoin#23077: Full CJDNS support
This commit is contained in:
parent
7596a7320a
commit
f9d1a9a00d
@ -54,7 +54,7 @@ def name_to_bip155(addr):
|
|||||||
raise ValueError('Invalid onion %s' % vchAddr)
|
raise ValueError('Invalid onion %s' % vchAddr)
|
||||||
elif '.' in addr: # IPv4
|
elif '.' in addr: # IPv4
|
||||||
return (BIP155Network.IPV4, bytes((int(x) for x in addr.split('.'))))
|
return (BIP155Network.IPV4, bytes((int(x) for x in addr.split('.'))))
|
||||||
elif ':' in addr: # IPv6
|
elif ':' in addr: # IPv6 or CJDNS
|
||||||
sub = [[], []] # prefix, suffix
|
sub = [[], []] # prefix, suffix
|
||||||
x = 0
|
x = 0
|
||||||
addr = addr.split(':')
|
addr = addr.split(':')
|
||||||
@ -70,7 +70,14 @@ def name_to_bip155(addr):
|
|||||||
sub[x].append(val & 0xff)
|
sub[x].append(val & 0xff)
|
||||||
nullbytes = 16 - len(sub[0]) - len(sub[1])
|
nullbytes = 16 - len(sub[0]) - len(sub[1])
|
||||||
assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
|
assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
|
||||||
return (BIP155Network.IPV6, bytes(sub[0] + ([0] * nullbytes) + sub[1]))
|
addr_bytes = bytes(sub[0] + ([0] * nullbytes) + sub[1])
|
||||||
|
if addr_bytes[0] == 0xfc:
|
||||||
|
# Assume that seeds with fc00::/8 addresses belong to CJDNS,
|
||||||
|
# not to the publicly unroutable "Unique Local Unicast" network, see
|
||||||
|
# RFC4193: https://datatracker.ietf.org/doc/html/rfc4193#section-8
|
||||||
|
return (BIP155Network.CJDNS, addr_bytes)
|
||||||
|
else:
|
||||||
|
return (BIP155Network.IPV6, addr_bytes)
|
||||||
else:
|
else:
|
||||||
raise ValueError('Could not parse address %s' % addr)
|
raise ValueError('Could not parse address %s' % addr)
|
||||||
|
|
||||||
|
10
src/init.cpp
10
src/init.cpp
@ -566,6 +566,7 @@ void SetupServerArgs(NodeContext& node)
|
|||||||
argsman.AddArg("-allowprivatenet", strprintf("Allow RFC1918 addresses to be relayed and connected to (default: %u)", DEFAULT_ALLOWPRIVATENET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-allowprivatenet", strprintf("Allow RFC1918 addresses to be relayed and connected to (default: %u)", DEFAULT_ALLOWPRIVATENET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
||||||
|
argsman.AddArg("-cjdnsreachable", "If set then this host is configured for CJDNS (connecting to fc00::/8 addresses would lead us to the CJDNS network) (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
@ -1785,6 +1786,14 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!args.IsArgSet("-cjdnsreachable")) {
|
||||||
|
SetReachable(NET_CJDNS, false);
|
||||||
|
}
|
||||||
|
// Now IsReachable(NET_CJDNS) is true if:
|
||||||
|
// 1. -cjdnsreachable is given and
|
||||||
|
// 2.1. -onlynet is not given or
|
||||||
|
// 2.2. -onlynet=cjdns is given
|
||||||
|
|
||||||
// Check for host lookup allowed before parsing any network related parameters
|
// Check for host lookup allowed before parsing any network related parameters
|
||||||
fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
|
fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
|
||||||
|
|
||||||
@ -1806,6 +1815,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
|||||||
SetProxy(NET_IPV4, addrProxy);
|
SetProxy(NET_IPV4, addrProxy);
|
||||||
SetProxy(NET_IPV6, addrProxy);
|
SetProxy(NET_IPV6, addrProxy);
|
||||||
SetProxy(NET_ONION, addrProxy);
|
SetProxy(NET_ONION, addrProxy);
|
||||||
|
SetProxy(NET_CJDNS, addrProxy);
|
||||||
SetNameProxy(addrProxy);
|
SetNameProxy(addrProxy);
|
||||||
SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
|
SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
|
||||||
}
|
}
|
||||||
|
34
src/net.cpp
34
src/net.cpp
@ -255,9 +255,27 @@ std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// learn a new local address
|
/**
|
||||||
bool AddLocal(const CService& addr, int nScore)
|
* If an IPv6 address belongs to the address range used by the CJDNS network and
|
||||||
|
* the CJDNS network is reachable (-cjdnsreachable config is set), then change
|
||||||
|
* the type from NET_IPV6 to NET_CJDNS.
|
||||||
|
* @param[in] service Address to potentially convert.
|
||||||
|
* @return a copy of `service` either unmodified or changed to CJDNS.
|
||||||
|
*/
|
||||||
|
CService MaybeFlipIPv6toCJDNS(const CService& service)
|
||||||
{
|
{
|
||||||
|
CService ret{service};
|
||||||
|
if (ret.m_net == NET_IPV6 && ret.m_addr[0] == 0xfc && IsReachable(NET_CJDNS)) {
|
||||||
|
ret.m_net = NET_CJDNS;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// learn a new local address
|
||||||
|
bool AddLocal(const CService& addr_, int nScore)
|
||||||
|
{
|
||||||
|
CService addr{MaybeFlipIPv6toCJDNS(addr_)};
|
||||||
|
|
||||||
if (!addr.IsRoutable() && Params().RequireRoutableExternalIP())
|
if (!addr.IsRoutable() && Params().RequireRoutableExternalIP())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -454,7 +472,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
|||||||
if (pszDest) {
|
if (pszDest) {
|
||||||
std::vector<CService> resolved;
|
std::vector<CService> resolved;
|
||||||
if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
|
if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
|
||||||
addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE);
|
const CService rnd{resolved[GetRand(resolved.size())]};
|
||||||
|
addrConnect = CAddress{MaybeFlipIPv6toCJDNS(rnd), NODE_NONE};
|
||||||
if (!addrConnect.IsValid()) {
|
if (!addrConnect.IsValid()) {
|
||||||
LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
|
LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -1210,9 +1229,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket, CMasternodeSy
|
|||||||
|
|
||||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
|
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
|
||||||
LogPrintf("Warning: Unknown socket family\n");
|
LogPrintf("Warning: Unknown socket family\n");
|
||||||
|
} else {
|
||||||
|
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};
|
||||||
}
|
}
|
||||||
|
|
||||||
const CAddress addr_bind = GetBindAddress(hSocket);
|
const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(hSocket)), NODE_NONE};
|
||||||
|
|
||||||
NetPermissionFlags permissionFlags = NetPermissionFlags::None;
|
NetPermissionFlags permissionFlags = NetPermissionFlags::None;
|
||||||
hListenSocket.AddSocketPermissionFlags(permissionFlags);
|
hListenSocket.AddSocketPermissionFlags(permissionFlags);
|
||||||
@ -3303,7 +3324,10 @@ NodeId CConnman::GetNewNodeId()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions) {
|
bool CConnman::Bind(const CService& addr_, unsigned int flags, NetPermissionFlags permissions)
|
||||||
|
{
|
||||||
|
const CService addr{MaybeFlipIPv6toCJDNS(addr_)};
|
||||||
|
|
||||||
if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) {
|
if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -676,7 +676,7 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
|
|||||||
*/
|
*/
|
||||||
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
||||||
{
|
{
|
||||||
if (!IsIPv6()) {
|
if (!IsIPv6() && !IsCJDNS()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
assert(sizeof(*pipv6Addr) == m_addr.size());
|
assert(sizeof(*pipv6Addr) == m_addr.size());
|
||||||
@ -796,8 +796,14 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
|
|||||||
vchRet.push_back((ipv4 >> 24) & 0xFF);
|
vchRet.push_back((ipv4 >> 24) & 0xFF);
|
||||||
vchRet.push_back((ipv4 >> 16) & 0xFF);
|
vchRet.push_back((ipv4 >> 16) & 0xFF);
|
||||||
return vchRet;
|
return vchRet;
|
||||||
} else if (IsTor() || IsI2P() || IsCJDNS()) {
|
} else if (IsTor() || IsI2P()) {
|
||||||
nBits = 4;
|
nBits = 4;
|
||||||
|
} else if (IsCJDNS()) {
|
||||||
|
// Treat in the same way as Tor and I2P because the address in all of
|
||||||
|
// them is "random" bytes (derived from a public key). However in CJDNS
|
||||||
|
// the first byte is a constant 0xfc, so the random bytes come after it.
|
||||||
|
// Thus skip the constant 8 bits at the start.
|
||||||
|
nBits = 12;
|
||||||
} else if (IsHeNet()) {
|
} else if (IsHeNet()) {
|
||||||
// for he.net, use /36 groups
|
// for he.net, use /36 groups
|
||||||
nBits = 36;
|
nBits = 36;
|
||||||
@ -894,6 +900,11 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
|
|||||||
case NET_I2P: return REACH_PRIVATE;
|
case NET_I2P: return REACH_PRIVATE;
|
||||||
default: return REACH_DEFAULT;
|
default: return REACH_DEFAULT;
|
||||||
}
|
}
|
||||||
|
case NET_CJDNS:
|
||||||
|
switch (ourNet) {
|
||||||
|
case NET_CJDNS: return REACH_PRIVATE;
|
||||||
|
default: return REACH_DEFAULT;
|
||||||
|
}
|
||||||
case NET_TEREDO:
|
case NET_TEREDO:
|
||||||
switch(ourNet) {
|
switch(ourNet) {
|
||||||
default: return REACH_DEFAULT;
|
default: return REACH_DEFAULT;
|
||||||
@ -995,7 +1006,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
|
|||||||
paddrin->sin_port = htons(port);
|
paddrin->sin_port = htons(port);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (IsIPv6()) {
|
if (IsIPv6() || IsCJDNS()) {
|
||||||
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
|
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
|
||||||
return false;
|
return false;
|
||||||
*addrlen = sizeof(struct sockaddr_in6);
|
*addrlen = sizeof(struct sockaddr_in6);
|
||||||
|
@ -232,7 +232,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool IsRelayable() const
|
bool IsRelayable() const
|
||||||
{
|
{
|
||||||
return IsIPv4() || IsIPv6() || IsTor() || IsI2P();
|
return IsIPv4() || IsIPv6() || IsTor() || IsI2P() || IsCJDNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -581,6 +581,8 @@ public:
|
|||||||
READWRITEAS(CNetAddr, obj);
|
READWRITEAS(CNetAddr, obj);
|
||||||
READWRITE(Using<BigEndianFormatter<2>>(obj.port));
|
READWRITE(Using<BigEndianFormatter<2>>(obj.port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend CService MaybeFlipIPv6toCJDNS(const CService& service);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SanityCheckASMap(const std::vector<bool>& asmap);
|
bool SanityCheckASMap(const std::vector<bool>& asmap);
|
||||||
|
@ -95,6 +95,9 @@ enum Network ParseNetwork(const std::string& net_in) {
|
|||||||
if (net == "i2p") {
|
if (net == "i2p") {
|
||||||
return NET_I2P;
|
return NET_I2P;
|
||||||
}
|
}
|
||||||
|
if (net == "cjdns") {
|
||||||
|
return NET_CJDNS;
|
||||||
|
}
|
||||||
return NET_UNROUTABLE;
|
return NET_UNROUTABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +122,7 @@ std::vector<std::string> GetNetworkNames(bool append_unroutable)
|
|||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
for (int n = 0; n < NET_MAX; ++n) {
|
for (int n = 0; n < NET_MAX; ++n) {
|
||||||
const enum Network network{static_cast<Network>(n)};
|
const enum Network network{static_cast<Network>(n)};
|
||||||
if (network == NET_UNROUTABLE || network == NET_CJDNS || network == NET_INTERNAL) continue;
|
if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
|
||||||
names.emplace_back(GetNetworkName(network));
|
names.emplace_back(GetNetworkName(network));
|
||||||
}
|
}
|
||||||
if (append_unroutable) {
|
if (append_unroutable) {
|
||||||
|
@ -585,7 +585,7 @@ static UniValue GetNetworksInfo()
|
|||||||
UniValue networks(UniValue::VARR);
|
UniValue networks(UniValue::VARR);
|
||||||
for (int n = 0; n < NET_MAX; ++n) {
|
for (int n = 0; n < NET_MAX; ++n) {
|
||||||
enum Network network = static_cast<enum Network>(n);
|
enum Network network = static_cast<enum Network>(n);
|
||||||
if (network == NET_UNROUTABLE || network == NET_CJDNS || network == NET_INTERNAL) continue;
|
if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
|
||||||
proxyType proxy;
|
proxyType proxy;
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
GetProxy(network, proxy);
|
GetProxy(network, proxy);
|
||||||
|
@ -441,11 +441,13 @@ BOOST_AUTO_TEST_CASE(netbase_parsenetwork)
|
|||||||
BOOST_CHECK_EQUAL(ParseNetwork("ipv6"), NET_IPV6);
|
BOOST_CHECK_EQUAL(ParseNetwork("ipv6"), NET_IPV6);
|
||||||
BOOST_CHECK_EQUAL(ParseNetwork("onion"), NET_ONION);
|
BOOST_CHECK_EQUAL(ParseNetwork("onion"), NET_ONION);
|
||||||
BOOST_CHECK_EQUAL(ParseNetwork("tor"), NET_ONION);
|
BOOST_CHECK_EQUAL(ParseNetwork("tor"), NET_ONION);
|
||||||
|
BOOST_CHECK_EQUAL(ParseNetwork("cjdns"), NET_CJDNS);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(ParseNetwork("IPv4"), NET_IPV4);
|
BOOST_CHECK_EQUAL(ParseNetwork("IPv4"), NET_IPV4);
|
||||||
BOOST_CHECK_EQUAL(ParseNetwork("IPv6"), NET_IPV6);
|
BOOST_CHECK_EQUAL(ParseNetwork("IPv6"), NET_IPV6);
|
||||||
BOOST_CHECK_EQUAL(ParseNetwork("ONION"), NET_ONION);
|
BOOST_CHECK_EQUAL(ParseNetwork("ONION"), NET_ONION);
|
||||||
BOOST_CHECK_EQUAL(ParseNetwork("TOR"), NET_ONION);
|
BOOST_CHECK_EQUAL(ParseNetwork("TOR"), NET_ONION);
|
||||||
|
BOOST_CHECK_EQUAL(ParseNetwork("CJDNS"), NET_CJDNS);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(ParseNetwork(":)"), NET_UNROUTABLE);
|
BOOST_CHECK_EQUAL(ParseNetwork(":)"), NET_UNROUTABLE);
|
||||||
BOOST_CHECK_EQUAL(ParseNetwork("tÖr"), NET_UNROUTABLE);
|
BOOST_CHECK_EQUAL(ParseNetwork("tÖr"), NET_UNROUTABLE);
|
||||||
|
@ -12,6 +12,7 @@ Test plan:
|
|||||||
- `-proxy` (proxy everything)
|
- `-proxy` (proxy everything)
|
||||||
- `-onion` (proxy just onions)
|
- `-onion` (proxy just onions)
|
||||||
- `-proxyrandomize` Circuit randomization
|
- `-proxyrandomize` Circuit randomization
|
||||||
|
- `-cjdnsreachable`
|
||||||
- Proxy configurations to test on proxy side,
|
- Proxy configurations to test on proxy side,
|
||||||
- support no authentication (other proxy)
|
- support no authentication (other proxy)
|
||||||
- support no authentication + user/pass authentication (Tor)
|
- support no authentication + user/pass authentication (Tor)
|
||||||
@ -26,6 +27,7 @@ addnode connect to IPv4
|
|||||||
addnode connect to IPv6
|
addnode connect to IPv6
|
||||||
addnode connect to onion
|
addnode connect to onion
|
||||||
addnode connect to generic DNS name
|
addnode connect to generic DNS name
|
||||||
|
addnode connect to a CJDNS address
|
||||||
|
|
||||||
- Test getnetworkinfo for each node
|
- Test getnetworkinfo for each node
|
||||||
"""
|
"""
|
||||||
@ -50,14 +52,15 @@ NET_IPV4 = "ipv4"
|
|||||||
NET_IPV6 = "ipv6"
|
NET_IPV6 = "ipv6"
|
||||||
NET_ONION = "onion"
|
NET_ONION = "onion"
|
||||||
NET_I2P = "i2p"
|
NET_I2P = "i2p"
|
||||||
|
NET_CJDNS = "cjdns"
|
||||||
|
|
||||||
# Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo()
|
# Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo()
|
||||||
NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P})
|
NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS})
|
||||||
|
|
||||||
|
|
||||||
class ProxyTest(BitcoinTestFramework):
|
class ProxyTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
self.num_nodes = 4
|
self.num_nodes = 5
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
|
|
||||||
def setup_nodes(self):
|
def setup_nodes(self):
|
||||||
@ -101,7 +104,9 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}',f'-onion={self.conf2.addr[0]}:{self.conf2.addr[1]}',
|
['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}',f'-onion={self.conf2.addr[0]}:{self.conf2.addr[1]}',
|
||||||
f'-i2psam={self.i2p_sam[0]}:{self.i2p_sam[1]}', '-i2pacceptincoming=0', '-proxyrandomize=0'],
|
f'-i2psam={self.i2p_sam[0]}:{self.i2p_sam[1]}', '-i2pacceptincoming=0', '-proxyrandomize=0'],
|
||||||
['-listen', f'-proxy={self.conf2.addr[0]}:{self.conf2.addr[1]}','-proxyrandomize=1'],
|
['-listen', f'-proxy={self.conf2.addr[0]}:{self.conf2.addr[1]}','-proxyrandomize=1'],
|
||||||
[]
|
[],
|
||||||
|
['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}','-proxyrandomize=1',
|
||||||
|
'-cjdnsreachable']
|
||||||
]
|
]
|
||||||
if self.have_ipv6:
|
if self.have_ipv6:
|
||||||
args[3] = ['-listen', f'-proxy=[{self.conf3.addr[0]}]:{self.conf3.addr[1]}','-proxyrandomize=0', '-noonion']
|
args[3] = ['-listen', f'-proxy=[{self.conf3.addr[0]}]:{self.conf3.addr[1]}','-proxyrandomize=0', '-noonion']
|
||||||
@ -113,7 +118,7 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
if peer["addr"] == addr:
|
if peer["addr"] == addr:
|
||||||
assert_equal(peer["network"], network)
|
assert_equal(peer["network"], network)
|
||||||
|
|
||||||
def node_test(self, node, proxies, auth, test_onion=True):
|
def node_test(self, node, *, proxies, auth, test_onion, test_cjdns):
|
||||||
rv = []
|
rv = []
|
||||||
addr = "15.61.23.23:1234"
|
addr = "15.61.23.23:1234"
|
||||||
self.log.debug(f"Test: outgoing IPv4 connection through node for address {addr}")
|
self.log.debug(f"Test: outgoing IPv4 connection through node for address {addr}")
|
||||||
@ -161,6 +166,21 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
rv.append(cmd)
|
rv.append(cmd)
|
||||||
self.network_test(node, addr, network=NET_ONION)
|
self.network_test(node, addr, network=NET_ONION)
|
||||||
|
|
||||||
|
if test_cjdns:
|
||||||
|
addr = "[fc00:1:2:3:4:5:6:7]:8888"
|
||||||
|
self.log.debug(f"Test: outgoing CJDNS connection through node for address {addr}")
|
||||||
|
node.addnode(addr, "onetry")
|
||||||
|
cmd = proxies[1].queue.get()
|
||||||
|
assert isinstance(cmd, Socks5Command)
|
||||||
|
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
||||||
|
assert_equal(cmd.addr, b"fc00:1:2:3:4:5:6:7")
|
||||||
|
assert_equal(cmd.port, 8888)
|
||||||
|
if not auth:
|
||||||
|
assert_equal(cmd.username, None)
|
||||||
|
assert_equal(cmd.password, None)
|
||||||
|
rv.append(cmd)
|
||||||
|
self.network_test(node, addr, network=NET_CJDNS)
|
||||||
|
|
||||||
addr = "node.noumenon:8333"
|
addr = "node.noumenon:8333"
|
||||||
self.log.debug(f"Test: outgoing DNS name connection through node for address {addr}")
|
self.log.debug(f"Test: outgoing DNS name connection through node for address {addr}")
|
||||||
node.addnode(addr, "onetry")
|
node.addnode(addr, "onetry")
|
||||||
@ -179,20 +199,33 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
# basic -proxy
|
# basic -proxy
|
||||||
self.node_test(self.nodes[0], [self.serv1, self.serv1, self.serv1, self.serv1], False)
|
self.node_test(self.nodes[0],
|
||||||
|
proxies=[self.serv1, self.serv1, self.serv1, self.serv1],
|
||||||
|
auth=False, test_onion=True, test_cjdns=False)
|
||||||
|
|
||||||
# -proxy plus -onion
|
# -proxy plus -onion
|
||||||
self.node_test(self.nodes[1], [self.serv1, self.serv1, self.serv2, self.serv1], False)
|
self.node_test(self.nodes[1],
|
||||||
|
proxies=[self.serv1, self.serv1, self.serv2, self.serv1],
|
||||||
|
auth=False, test_onion=True, test_cjdns=False)
|
||||||
|
|
||||||
# -proxy plus -onion, -proxyrandomize
|
# -proxy plus -onion, -proxyrandomize
|
||||||
rv = self.node_test(self.nodes[2], [self.serv2, self.serv2, self.serv2, self.serv2], True)
|
rv = self.node_test(self.nodes[2],
|
||||||
|
proxies=[self.serv2, self.serv2, self.serv2, self.serv2],
|
||||||
|
auth=True, test_onion=True, test_cjdns=False)
|
||||||
# Check that credentials as used for -proxyrandomize connections are unique
|
# Check that credentials as used for -proxyrandomize connections are unique
|
||||||
credentials = set((x.username,x.password) for x in rv)
|
credentials = set((x.username,x.password) for x in rv)
|
||||||
assert_equal(len(credentials), len(rv))
|
assert_equal(len(credentials), len(rv))
|
||||||
|
|
||||||
if self.have_ipv6:
|
if self.have_ipv6:
|
||||||
# proxy on IPv6 localhost
|
# proxy on IPv6 localhost
|
||||||
self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False)
|
self.node_test(self.nodes[3],
|
||||||
|
proxies=[self.serv3, self.serv3, self.serv3, self.serv3],
|
||||||
|
auth=False, test_onion=False, test_cjdns=False)
|
||||||
|
|
||||||
|
# -proxy=unauth -proxyrandomize=1 -cjdnsreachable
|
||||||
|
self.node_test(self.nodes[4],
|
||||||
|
proxies=[self.serv1, self.serv1, self.serv1, self.serv1],
|
||||||
|
auth=False, test_onion=True, test_cjdns=True)
|
||||||
|
|
||||||
def networks_dict(d):
|
def networks_dict(d):
|
||||||
r = {}
|
r = {}
|
||||||
@ -214,6 +247,7 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize)
|
assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize)
|
||||||
assert_equal(n0['onion']['reachable'], True)
|
assert_equal(n0['onion']['reachable'], True)
|
||||||
assert_equal(n0['i2p']['reachable'], False)
|
assert_equal(n0['i2p']['reachable'], False)
|
||||||
|
assert_equal(n0['cjdns']['reachable'], False)
|
||||||
|
|
||||||
n1 = networks_dict(self.nodes[1].getnetworkinfo())
|
n1 = networks_dict(self.nodes[1].getnetworkinfo())
|
||||||
assert_equal(NETWORKS, n1.keys())
|
assert_equal(NETWORKS, n1.keys())
|
||||||
@ -240,6 +274,7 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)
|
assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)
|
||||||
assert_equal(n2['onion']['reachable'], True)
|
assert_equal(n2['onion']['reachable'], True)
|
||||||
assert_equal(n2['i2p']['reachable'], False)
|
assert_equal(n2['i2p']['reachable'], False)
|
||||||
|
assert_equal(n2['cjdns']['reachable'], False)
|
||||||
|
|
||||||
if self.have_ipv6:
|
if self.have_ipv6:
|
||||||
n3 = networks_dict(self.nodes[3].getnetworkinfo())
|
n3 = networks_dict(self.nodes[3].getnetworkinfo())
|
||||||
@ -253,6 +288,22 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
assert_equal(n3[net]['proxy_randomize_credentials'], False)
|
assert_equal(n3[net]['proxy_randomize_credentials'], False)
|
||||||
assert_equal(n3['onion']['reachable'], False)
|
assert_equal(n3['onion']['reachable'], False)
|
||||||
assert_equal(n3['i2p']['reachable'], False)
|
assert_equal(n3['i2p']['reachable'], False)
|
||||||
|
assert_equal(n3['cjdns']['reachable'], False)
|
||||||
|
|
||||||
|
n4 = networks_dict(self.nodes[4].getnetworkinfo())
|
||||||
|
assert_equal(NETWORKS, n4.keys())
|
||||||
|
for net in NETWORKS:
|
||||||
|
if net == NET_I2P:
|
||||||
|
expected_proxy = ''
|
||||||
|
expected_randomize = False
|
||||||
|
else:
|
||||||
|
expected_proxy = '%s:%i' % (self.conf1.addr)
|
||||||
|
expected_randomize = True
|
||||||
|
assert_equal(n4[net]['proxy'], expected_proxy)
|
||||||
|
assert_equal(n4[net]['proxy_randomize_credentials'], expected_randomize)
|
||||||
|
assert_equal(n4['onion']['reachable'], True)
|
||||||
|
assert_equal(n4['i2p']['reachable'], False)
|
||||||
|
assert_equal(n4['cjdns']['reachable'], True)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -141,7 +141,7 @@ class TestBitcoinCli(BitcoinTestFramework):
|
|||||||
network_info = self.nodes[0].getnetworkinfo()
|
network_info = self.nodes[0].getnetworkinfo()
|
||||||
cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
|
cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
|
||||||
cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
|
cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
|
||||||
assert_equal(cli_get_info["Proxies"], "127.0.0.1:9050 (ipv4, ipv6, onion), 127.0.0.1:7656 (i2p)")
|
assert_equal(cli_get_info["Proxies"], "127.0.0.1:9050 (ipv4, ipv6, onion, cjdns), 127.0.0.1:7656 (i2p)")
|
||||||
|
|
||||||
if self.is_wallet_compiled():
|
if self.is_wallet_compiled():
|
||||||
self.log.info("Test -getinfo and dash-cli getwalletinfo return expected wallet info")
|
self.log.info("Test -getinfo and dash-cli getwalletinfo return expected wallet info")
|
||||||
|
@ -99,7 +99,7 @@ class NetTest(DashTestFramework):
|
|||||||
assert_net_servicesnames(int(info[0]["services"], 0x10), info[0]["servicesnames"])
|
assert_net_servicesnames(int(info[0]["services"], 0x10), info[0]["servicesnames"])
|
||||||
|
|
||||||
# Check dynamically generated networks list in getpeerinfo help output.
|
# Check dynamically generated networks list in getpeerinfo help output.
|
||||||
assert "(ipv4, ipv6, onion, i2p, not_publicly_routable)" in self.nodes[0].help("getpeerinfo")
|
assert "(ipv4, ipv6, onion, i2p, cjdns, not_publicly_routable)" in self.nodes[0].help("getpeerinfo")
|
||||||
# This part is slightly different comparing to the Bitcoin implementation. This is expected because we create connections on network setup a bit differently too.
|
# This part is slightly different comparing to the Bitcoin implementation. This is expected because we create connections on network setup a bit differently too.
|
||||||
# We also create more connection during the test itself to test mn specific stats
|
# We also create more connection during the test itself to test mn specific stats
|
||||||
assert_equal(peer_info[0][0]['connection_type'], 'inbound')
|
assert_equal(peer_info[0][0]['connection_type'], 'inbound')
|
||||||
@ -167,7 +167,7 @@ class NetTest(DashTestFramework):
|
|||||||
assert_net_servicesnames(int(info["localservices"], 0x10), info["localservicesnames"])
|
assert_net_servicesnames(int(info["localservices"], 0x10), info["localservicesnames"])
|
||||||
|
|
||||||
# Check dynamically generated networks list in getnetworkinfo help output.
|
# Check dynamically generated networks list in getnetworkinfo help output.
|
||||||
assert "(ipv4, ipv6, onion, i2p)" in self.nodes[0].help("getnetworkinfo")
|
assert "(ipv4, ipv6, onion, i2p, cjdns)" in self.nodes[0].help("getnetworkinfo")
|
||||||
|
|
||||||
self.log.info('Test extended connections info')
|
self.log.info('Test extended connections info')
|
||||||
# Connect nodes both ways.
|
# Connect nodes both ways.
|
||||||
@ -252,8 +252,8 @@ class NetTest(DashTestFramework):
|
|||||||
assert_equal(res[0]["port"], 8333)
|
assert_equal(res[0]["port"], 8333)
|
||||||
assert_equal(res[0]["services"], services)
|
assert_equal(res[0]["services"], services)
|
||||||
|
|
||||||
# Test for the absence of onion and I2P addresses.
|
# Test for the absence of onion, I2P and CJDNS addresses.
|
||||||
for network in ["onion", "i2p"]:
|
for network in ["onion", "i2p", "cjdns"]:
|
||||||
assert_equal(self.nodes[0].getnodeaddresses(0, network), [])
|
assert_equal(self.nodes[0].getnodeaddresses(0, network), [])
|
||||||
|
|
||||||
# Test invalid arguments.
|
# Test invalid arguments.
|
||||||
|
Loading…
Reference in New Issue
Block a user