mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-18 22:35:39 +01:00
Merge bitcoin/bitcoin#23077: Full CJDNS support
420695c193contrib: recognize CJDNS seeds as such (Vasil Dimov)f9c28330a0net: take the first 4 random bits from CJDNS addresses in GetGroup() (Vasil Dimov)29ff79c0a2net: relay CJDNS addresses even if we are not connected to CJDNS (Vasil Dimov)d96f8d304cnet: don't skip CJDNS from GetNetworkNames() (Vasil Dimov)c2d751abbanet: take CJDNS into account in CNetAddr::GetReachabilityFrom() (Vasil Dimov)9b43b3b257test: extend feature_proxy.py to test CJDNS (Vasil Dimov)508eb258fdtest: remove default argument of feature_proxy.py:node_test() (Vasil Dimov)6387f397b3net: recognize CJDNS addresses as such (Vasil Dimov)e6890fcb44net: don't skip CJDNS from GetNetworksInfo() (Vasil Dimov)e9d90d3c11net: introduce a new config option to enable CJDNS (Vasil Dimov)78f456c576net: recognize CJDNS from ParseNetwork() (Vasil Dimov)de01e312b3net: use -proxy for connecting to the CJDNS network (Vasil Dimov)aedd02ef27net: make it possible to connect to CJDNS addresses (Vasil Dimov) Pull request description: CJDNS overview ===== CJDNS is like a distributed, shared VPN with multiple entry points where every participant can reach any other participant. All participants use addresses from the `fc00::/8` network (reserved IPv6 range). Installation and configuration is done outside of applications, similarly to VPN (either in the host/OS or on the network router). Motivation ===== Even without this PR it is possible to connect two Bitcoin Core nodes through CJDNS manually by using e.g. `-addnode` in environments where CJDNS is set up. However, this PR is necessary for address relay to work properly and automatic connections to be made to CJDNS peers. I.e. to make CJDNS a first class citizen network like IPv4, IPv6, Tor and I2P. Considerations ===== An address from the `fc00::/8` network, could mean two things: 1. Part of a local network, as defined in RFC 4193. Like `10.0.0.0/8`. Bitcoin Core could be running on a machine with such address and have peers with those (e.g. in a local network), but those addresses are not relayed to other peers because they are not globally routable on the internet. 2. Part of the CJDNS network. This is like Tor or I2P - if we have connectivity to that network then we could reach such peers and we do relay them to other peers. So, Bitcoin Core needs to be able to tell which one is it when it encounters a bare `fc00::/8` address, e.g. from `-externalip=` or by looking up the machine's own addresses. Thus a new config option is introduced `-cjdnsreacable`: * `-cjdnsreacable=0`: it is assumed a `fc00::/8` address is a private IPv6 (1.) * `-cjdnsreacable=1`: it is assumed a `fc00::/8` address is a CJDNS one (2.) After setting up CJDNS outside of Bitcoin Core, a node operator only needs to enable this option. Addresses from P2P relay/gossip don't need that because they are properly tagged as IPv6 or as CJDNS. For testing ===== ``` [fc32:17ea:e415:c3bf:9808:149d:b5a2:c9aa]:8333 [fc68:7026:cb27:b014:5910:e609:dcdb:22a2]:8333 [fcb3:dc50:e1ae:7998:7dc0:7fa6:4582:8e46]:8333 [fcc7:be49:ccd1:dc91:3125:f0da:457d:8ce]:8333 [fcf2:d9e:3a25:4eef:8f84:251b:1b4d:c596]:8333 ``` ACKs for top commit: dunxen: ACK420695cjonatack: re-ACK420695c193per `git range-diff23ae7934fbff39 420695c` laanwj: Code review ACK420695c193Tree-SHA512: 21559886271aa84671d52b120fa3fa5a50fdcf0fcb26e5b32049c56fab0d606438d19dd366a9c8ce612d3894237ae6d552ead3338b326487e3534399b88a317a
This commit is contained in:
@@ -61,7 +61,7 @@ def name_to_bip155(addr):
|
||||
raise ValueError(f'Invalid I2P {vchAddr}')
|
||||
elif '.' in addr: # IPv4
|
||||
return (BIP155Network.IPV4, bytes((int(x) for x in addr.split('.'))))
|
||||
elif ':' in addr: # IPv6
|
||||
elif ':' in addr: # IPv6 or CJDNS
|
||||
sub = [[], []] # prefix, suffix
|
||||
x = 0
|
||||
addr = addr.split(':')
|
||||
@@ -77,7 +77,14 @@ def name_to_bip155(addr):
|
||||
sub[x].append(val & 0xff)
|
||||
nullbytes = 16 - len(sub[0]) - len(sub[1])
|
||||
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:
|
||||
raise ValueError('Could not parse address %s' % addr)
|
||||
|
||||
|
||||
10
src/init.cpp
10
src/init.cpp
@@ -422,6 +422,7 @@ void SetupServerArgs(ArgsManager& argsman)
|
||||
argsman.AddArg("-asmap=<file>", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME), 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, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), signetBaseParams->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("-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);
|
||||
@@ -1294,6 +1295,14 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
|
||||
|
||||
@@ -1315,6 +1324,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
SetProxy(NET_IPV4, addrProxy);
|
||||
SetProxy(NET_IPV6, addrProxy);
|
||||
SetProxy(NET_ONION, addrProxy);
|
||||
SetProxy(NET_CJDNS, addrProxy);
|
||||
SetNameProxy(addrProxy);
|
||||
SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
|
||||
}
|
||||
|
||||
34
src/net.cpp
34
src/net.cpp
@@ -230,9 +230,27 @@ std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
|
||||
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())
|
||||
return false;
|
||||
|
||||
@@ -409,7 +427,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
||||
if (pszDest) {
|
||||
std::vector<CService> resolved;
|
||||
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()) {
|
||||
LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
|
||||
return nullptr;
|
||||
@@ -1092,9 +1111,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
|
||||
|
||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
|
||||
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;
|
||||
hListenSocket.AddSocketPermissionFlags(permissionFlags);
|
||||
@@ -2460,7 +2481,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)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -663,7 +663,7 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get our IPv6 address.
|
||||
* Try to get our IPv6 (or CJDNS) address.
|
||||
*
|
||||
* @param[out] pipv6Addr The in6_addr struct to which to copy.
|
||||
*
|
||||
@@ -674,7 +674,7 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
|
||||
*/
|
||||
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
||||
{
|
||||
if (!IsIPv6()) {
|
||||
if (!IsIPv6() && !IsCJDNS()) {
|
||||
return false;
|
||||
}
|
||||
assert(sizeof(*pipv6Addr) == m_addr.size());
|
||||
@@ -794,8 +794,14 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
|
||||
vchRet.push_back((ipv4 >> 24) & 0xFF);
|
||||
vchRet.push_back((ipv4 >> 16) & 0xFF);
|
||||
return vchRet;
|
||||
} else if (IsTor() || IsI2P() || IsCJDNS()) {
|
||||
} else if (IsTor() || IsI2P()) {
|
||||
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()) {
|
||||
// for he.net, use /36 groups
|
||||
nBits = 36;
|
||||
@@ -892,6 +898,11 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
|
||||
case NET_I2P: return REACH_PRIVATE;
|
||||
default: return REACH_DEFAULT;
|
||||
}
|
||||
case NET_CJDNS:
|
||||
switch (ourNet) {
|
||||
case NET_CJDNS: return REACH_PRIVATE;
|
||||
default: return REACH_DEFAULT;
|
||||
}
|
||||
case NET_TEREDO:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
@@ -993,7 +1004,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
|
||||
paddrin->sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
if (IsIPv6()) {
|
||||
if (IsIPv6() || IsCJDNS()) {
|
||||
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
|
||||
return false;
|
||||
*addrlen = sizeof(struct sockaddr_in6);
|
||||
|
||||
@@ -224,7 +224,7 @@ public:
|
||||
*/
|
||||
bool IsRelayable() const
|
||||
{
|
||||
return IsIPv4() || IsIPv6() || IsTor() || IsI2P();
|
||||
return IsIPv4() || IsIPv6() || IsTor() || IsI2P() || IsCJDNS();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -550,6 +550,7 @@ public:
|
||||
}
|
||||
|
||||
friend class CServiceHash;
|
||||
friend CService MaybeFlipIPv6toCJDNS(const CService& service);
|
||||
};
|
||||
|
||||
class CServiceHash
|
||||
|
||||
@@ -96,6 +96,9 @@ enum Network ParseNetwork(const std::string& net_in) {
|
||||
if (net == "i2p") {
|
||||
return NET_I2P;
|
||||
}
|
||||
if (net == "cjdns") {
|
||||
return NET_CJDNS;
|
||||
}
|
||||
return NET_UNROUTABLE;
|
||||
}
|
||||
|
||||
@@ -120,7 +123,7 @@ std::vector<std::string> GetNetworkNames(bool append_unroutable)
|
||||
std::vector<std::string> names;
|
||||
for (int n = 0; n < NET_MAX; ++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));
|
||||
}
|
||||
if (append_unroutable) {
|
||||
|
||||
@@ -566,7 +566,7 @@ static UniValue GetNetworksInfo()
|
||||
UniValue networks(UniValue::VARR);
|
||||
for (int n = 0; n < NET_MAX; ++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;
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
GetProxy(network, proxy);
|
||||
|
||||
@@ -339,11 +339,13 @@ BOOST_AUTO_TEST_CASE(netbase_parsenetwork)
|
||||
BOOST_CHECK_EQUAL(ParseNetwork("ipv6"), NET_IPV6);
|
||||
BOOST_CHECK_EQUAL(ParseNetwork("onion"), 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("IPv6"), NET_IPV6);
|
||||
BOOST_CHECK_EQUAL(ParseNetwork("ONION"), 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("tÖr"), NET_UNROUTABLE);
|
||||
|
||||
@@ -12,6 +12,7 @@ Test plan:
|
||||
- `-proxy` (proxy everything)
|
||||
- `-onion` (proxy just onions)
|
||||
- `-proxyrandomize` Circuit randomization
|
||||
- `-cjdnsreachable`
|
||||
- Proxy configurations to test on proxy side,
|
||||
- support no authentication (other proxy)
|
||||
- support no authentication + user/pass authentication (Tor)
|
||||
@@ -26,6 +27,7 @@ addnode connect to IPv4
|
||||
addnode connect to IPv6
|
||||
addnode connect to onion
|
||||
addnode connect to generic DNS name
|
||||
addnode connect to a CJDNS address
|
||||
|
||||
- Test getnetworkinfo for each node
|
||||
"""
|
||||
@@ -50,14 +52,15 @@ NET_IPV4 = "ipv4"
|
||||
NET_IPV6 = "ipv6"
|
||||
NET_ONION = "onion"
|
||||
NET_I2P = "i2p"
|
||||
NET_CJDNS = "cjdns"
|
||||
|
||||
# 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):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 4
|
||||
self.num_nodes = 5
|
||||
self.setup_clean_chain = True
|
||||
|
||||
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]}',
|
||||
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.conf1.addr[0]}:{self.conf1.addr[1]}','-proxyrandomize=1',
|
||||
'-cjdnsreachable']
|
||||
]
|
||||
if self.have_ipv6:
|
||||
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:
|
||||
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 = []
|
||||
addr = "15.61.23.23:1234"
|
||||
self.log.debug(f"Test: outgoing IPv4 connection through node for address {addr}")
|
||||
@@ -161,6 +166,21 @@ class ProxyTest(BitcoinTestFramework):
|
||||
rv.append(cmd)
|
||||
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"
|
||||
self.log.debug(f"Test: outgoing DNS name connection through node for address {addr}")
|
||||
node.addnode(addr, "onetry")
|
||||
@@ -179,20 +199,33 @@ class ProxyTest(BitcoinTestFramework):
|
||||
|
||||
def run_test(self):
|
||||
# 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
|
||||
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
|
||||
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
|
||||
credentials = set((x.username,x.password) for x in rv)
|
||||
assert_equal(len(credentials), len(rv))
|
||||
|
||||
if self.have_ipv6:
|
||||
# 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):
|
||||
r = {}
|
||||
@@ -214,6 +247,7 @@ class ProxyTest(BitcoinTestFramework):
|
||||
assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize)
|
||||
assert_equal(n0['onion']['reachable'], True)
|
||||
assert_equal(n0['i2p']['reachable'], False)
|
||||
assert_equal(n0['cjdns']['reachable'], False)
|
||||
|
||||
n1 = networks_dict(self.nodes[1].getnetworkinfo())
|
||||
assert_equal(NETWORKS, n1.keys())
|
||||
@@ -240,6 +274,7 @@ class ProxyTest(BitcoinTestFramework):
|
||||
assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)
|
||||
assert_equal(n2['onion']['reachable'], True)
|
||||
assert_equal(n2['i2p']['reachable'], False)
|
||||
assert_equal(n2['cjdns']['reachable'], False)
|
||||
|
||||
if self.have_ipv6:
|
||||
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['onion']['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__':
|
||||
|
||||
@@ -136,7 +136,7 @@ class TestBitcoinCli(BitcoinTestFramework):
|
||||
network_info = self.nodes[0].getnetworkinfo()
|
||||
cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
|
||||
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():
|
||||
self.log.info("Test -getinfo and bitcoin-cli getwalletinfo return expected wallet info")
|
||||
|
||||
@@ -106,7 +106,7 @@ class NetTest(BitcoinTestFramework):
|
||||
assert_equal(peer_info[1][1]['connection_type'], 'inbound')
|
||||
|
||||
# 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")
|
||||
|
||||
def test_getnettotals(self):
|
||||
self.log.info("Test getnettotals")
|
||||
@@ -157,7 +157,7 @@ class NetTest(BitcoinTestFramework):
|
||||
assert_net_servicesnames(int(info["localservices"], 0x10), info["localservicesnames"])
|
||||
|
||||
# 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")
|
||||
|
||||
def test_getaddednodeinfo(self):
|
||||
self.log.info("Test getaddednodeinfo")
|
||||
@@ -228,8 +228,8 @@ class NetTest(BitcoinTestFramework):
|
||||
assert_equal(res[0]["port"], 8333)
|
||||
assert_equal(res[0]["services"], P2P_SERVICES)
|
||||
|
||||
# Test for the absence of onion and I2P addresses.
|
||||
for network in ["onion", "i2p"]:
|
||||
# Test for the absence of onion, I2P and CJDNS addresses.
|
||||
for network in ["onion", "i2p", "cjdns"]:
|
||||
assert_equal(self.nodes[0].getnodeaddresses(0, network), [])
|
||||
|
||||
# Test invalid arguments.
|
||||
|
||||
Reference in New Issue
Block a user