Skip to content

Commit 8346004

Browse files
committed
Merge bitcoin/bitcoin#23077: Full CJDNS support
420695c contrib: recognize CJDNS seeds as such (Vasil Dimov) f9c2833 net: take the first 4 random bits from CJDNS addresses in GetGroup() (Vasil Dimov) 29ff79c net: relay CJDNS addresses even if we are not connected to CJDNS (Vasil Dimov) d96f8d3 net: don't skip CJDNS from GetNetworkNames() (Vasil Dimov) c2d751a net: take CJDNS into account in CNetAddr::GetReachabilityFrom() (Vasil Dimov) 9b43b3b test: extend feature_proxy.py to test CJDNS (Vasil Dimov) 508eb25 test: remove default argument of feature_proxy.py:node_test() (Vasil Dimov) 6387f39 net: recognize CJDNS addresses as such (Vasil Dimov) e6890fc net: don't skip CJDNS from GetNetworksInfo() (Vasil Dimov) e9d90d3 net: introduce a new config option to enable CJDNS (Vasil Dimov) 78f456c net: recognize CJDNS from ParseNetwork() (Vasil Dimov) de01e31 net: use -proxy for connecting to the CJDNS network (Vasil Dimov) aedd02e net: 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: ACK 420695c jonatack: re-ACK 420695c per `git range-diff 23ae793 4fbff39 420695c` laanwj: Code review ACK 420695c Tree-SHA512: 21559886271aa84671d52b120fa3fa5a50fdcf0fcb26e5b32049c56fab0d606438d19dd366a9c8ce612d3894237ae6d552ead3338b326487e3534399b88a317a
2 parents aecc08f + 420695c commit 8346004

File tree

11 files changed

+135
-26
lines changed

11 files changed

+135
-26
lines changed

contrib/seeds/generate-seeds.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def name_to_bip155(addr):
6161
raise ValueError(f'Invalid I2P {vchAddr}')
6262
elif '.' in addr: # IPv4
6363
return (BIP155Network.IPV4, bytes((int(x) for x in addr.split('.'))))
64-
elif ':' in addr: # IPv6
64+
elif ':' in addr: # IPv6 or CJDNS
6565
sub = [[], []] # prefix, suffix
6666
x = 0
6767
addr = addr.split(':')
@@ -77,7 +77,14 @@ def name_to_bip155(addr):
7777
sub[x].append(val & 0xff)
7878
nullbytes = 16 - len(sub[0]) - len(sub[1])
7979
assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
80-
return (BIP155Network.IPV6, bytes(sub[0] + ([0] * nullbytes) + sub[1]))
80+
addr_bytes = bytes(sub[0] + ([0] * nullbytes) + sub[1])
81+
if addr_bytes[0] == 0xfc:
82+
# Assume that seeds with fc00::/8 addresses belong to CJDNS,
83+
# not to the publicly unroutable "Unique Local Unicast" network, see
84+
# RFC4193: https://datatracker.ietf.org/doc/html/rfc4193#section-8
85+
return (BIP155Network.CJDNS, addr_bytes)
86+
else:
87+
return (BIP155Network.IPV6, addr_bytes)
8188
else:
8289
raise ValueError('Could not parse address %s' % addr)
8390

src/init.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ void SetupServerArgs(ArgsManager& argsman)
422422
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);
423423
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
424424
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);
425+
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);
425426
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);
426427
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
427428
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)
12941295
}
12951296
}
12961297

1298+
if (!args.IsArgSet("-cjdnsreachable")) {
1299+
SetReachable(NET_CJDNS, false);
1300+
}
1301+
// Now IsReachable(NET_CJDNS) is true if:
1302+
// 1. -cjdnsreachable is given and
1303+
// 2.1. -onlynet is not given or
1304+
// 2.2. -onlynet=cjdns is given
1305+
12971306
// Check for host lookup allowed before parsing any network related parameters
12981307
fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
12991308

@@ -1315,6 +1324,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
13151324
SetProxy(NET_IPV4, addrProxy);
13161325
SetProxy(NET_IPV6, addrProxy);
13171326
SetProxy(NET_ONION, addrProxy);
1327+
SetProxy(NET_CJDNS, addrProxy);
13181328
SetNameProxy(addrProxy);
13191329
SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
13201330
}

src/net.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,27 @@ std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
230230
return std::nullopt;
231231
}
232232

233+
/**
234+
* If an IPv6 address belongs to the address range used by the CJDNS network and
235+
* the CJDNS network is reachable (-cjdnsreachable config is set), then change
236+
* the type from NET_IPV6 to NET_CJDNS.
237+
* @param[in] service Address to potentially convert.
238+
* @return a copy of `service` either unmodified or changed to CJDNS.
239+
*/
240+
CService MaybeFlipIPv6toCJDNS(const CService& service)
241+
{
242+
CService ret{service};
243+
if (ret.m_net == NET_IPV6 && ret.m_addr[0] == 0xfc && IsReachable(NET_CJDNS)) {
244+
ret.m_net = NET_CJDNS;
245+
}
246+
return ret;
247+
}
248+
233249
// learn a new local address
234-
bool AddLocal(const CService& addr, int nScore)
250+
bool AddLocal(const CService& addr_, int nScore)
235251
{
252+
CService addr{MaybeFlipIPv6toCJDNS(addr_)};
253+
236254
if (!addr.IsRoutable())
237255
return false;
238256

@@ -409,7 +427,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
409427
if (pszDest) {
410428
std::vector<CService> resolved;
411429
if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
412-
addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE);
430+
const CService rnd{resolved[GetRand(resolved.size())]};
431+
addrConnect = CAddress{MaybeFlipIPv6toCJDNS(rnd), NODE_NONE};
413432
if (!addrConnect.IsValid()) {
414433
LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
415434
return nullptr;
@@ -1092,9 +1111,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
10921111

10931112
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
10941113
LogPrintf("Warning: Unknown socket family\n");
1114+
} else {
1115+
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};
10951116
}
10961117

1097-
const CAddress addr_bind = GetBindAddress(hSocket);
1118+
const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(hSocket)), NODE_NONE};
10981119

10991120
NetPermissionFlags permissionFlags = NetPermissionFlags::None;
11001121
hListenSocket.AddSocketPermissionFlags(permissionFlags);
@@ -2460,7 +2481,10 @@ NodeId CConnman::GetNewNodeId()
24602481
}
24612482

24622483

2463-
bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions) {
2484+
bool CConnman::Bind(const CService& addr_, unsigned int flags, NetPermissionFlags permissions)
2485+
{
2486+
const CService addr{MaybeFlipIPv6toCJDNS(addr_)};
2487+
24642488
if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) {
24652489
return false;
24662490
}

src/netaddress.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
663663
}
664664

665665
/**
666-
* Try to get our IPv6 address.
666+
* Try to get our IPv6 (or CJDNS) address.
667667
*
668668
* @param[out] pipv6Addr The in6_addr struct to which to copy.
669669
*
@@ -674,7 +674,7 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
674674
*/
675675
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
676676
{
677-
if (!IsIPv6()) {
677+
if (!IsIPv6() && !IsCJDNS()) {
678678
return false;
679679
}
680680
assert(sizeof(*pipv6Addr) == m_addr.size());
@@ -794,8 +794,14 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
794794
vchRet.push_back((ipv4 >> 24) & 0xFF);
795795
vchRet.push_back((ipv4 >> 16) & 0xFF);
796796
return vchRet;
797-
} else if (IsTor() || IsI2P() || IsCJDNS()) {
797+
} else if (IsTor() || IsI2P()) {
798798
nBits = 4;
799+
} else if (IsCJDNS()) {
800+
// Treat in the same way as Tor and I2P because the address in all of
801+
// them is "random" bytes (derived from a public key). However in CJDNS
802+
// the first byte is a constant 0xfc, so the random bytes come after it.
803+
// Thus skip the constant 8 bits at the start.
804+
nBits = 12;
799805
} else if (IsHeNet()) {
800806
// for he.net, use /36 groups
801807
nBits = 36;
@@ -892,6 +898,11 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
892898
case NET_I2P: return REACH_PRIVATE;
893899
default: return REACH_DEFAULT;
894900
}
901+
case NET_CJDNS:
902+
switch (ourNet) {
903+
case NET_CJDNS: return REACH_PRIVATE;
904+
default: return REACH_DEFAULT;
905+
}
895906
case NET_TEREDO:
896907
switch(ourNet) {
897908
default: return REACH_DEFAULT;
@@ -993,7 +1004,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
9931004
paddrin->sin_port = htons(port);
9941005
return true;
9951006
}
996-
if (IsIPv6()) {
1007+
if (IsIPv6() || IsCJDNS()) {
9971008
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
9981009
return false;
9991010
*addrlen = sizeof(struct sockaddr_in6);

src/netaddress.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ class CNetAddr
224224
*/
225225
bool IsRelayable() const
226226
{
227-
return IsIPv4() || IsIPv6() || IsTor() || IsI2P();
227+
return IsIPv4() || IsIPv6() || IsTor() || IsI2P() || IsCJDNS();
228228
}
229229

230230
/**
@@ -550,6 +550,7 @@ class CService : public CNetAddr
550550
}
551551

552552
friend class CServiceHash;
553+
friend CService MaybeFlipIPv6toCJDNS(const CService& service);
553554
};
554555

555556
class CServiceHash

src/netbase.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ enum Network ParseNetwork(const std::string& net_in) {
9696
if (net == "i2p") {
9797
return NET_I2P;
9898
}
99+
if (net == "cjdns") {
100+
return NET_CJDNS;
101+
}
99102
return NET_UNROUTABLE;
100103
}
101104

@@ -120,7 +123,7 @@ std::vector<std::string> GetNetworkNames(bool append_unroutable)
120123
std::vector<std::string> names;
121124
for (int n = 0; n < NET_MAX; ++n) {
122125
const enum Network network{static_cast<Network>(n)};
123-
if (network == NET_UNROUTABLE || network == NET_CJDNS || network == NET_INTERNAL) continue;
126+
if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
124127
names.emplace_back(GetNetworkName(network));
125128
}
126129
if (append_unroutable) {

src/rpc/net.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ static UniValue GetNetworksInfo()
566566
UniValue networks(UniValue::VARR);
567567
for (int n = 0; n < NET_MAX; ++n) {
568568
enum Network network = static_cast<enum Network>(n);
569-
if (network == NET_UNROUTABLE || network == NET_CJDNS || network == NET_INTERNAL) continue;
569+
if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
570570
proxyType proxy;
571571
UniValue obj(UniValue::VOBJ);
572572
GetProxy(network, proxy);

src/test/netbase_tests.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,13 @@ BOOST_AUTO_TEST_CASE(netbase_parsenetwork)
339339
BOOST_CHECK_EQUAL(ParseNetwork("ipv6"), NET_IPV6);
340340
BOOST_CHECK_EQUAL(ParseNetwork("onion"), NET_ONION);
341341
BOOST_CHECK_EQUAL(ParseNetwork("tor"), NET_ONION);
342+
BOOST_CHECK_EQUAL(ParseNetwork("cjdns"), NET_CJDNS);
342343

343344
BOOST_CHECK_EQUAL(ParseNetwork("IPv4"), NET_IPV4);
344345
BOOST_CHECK_EQUAL(ParseNetwork("IPv6"), NET_IPV6);
345346
BOOST_CHECK_EQUAL(ParseNetwork("ONION"), NET_ONION);
346347
BOOST_CHECK_EQUAL(ParseNetwork("TOR"), NET_ONION);
348+
BOOST_CHECK_EQUAL(ParseNetwork("CJDNS"), NET_CJDNS);
347349

348350
BOOST_CHECK_EQUAL(ParseNetwork(":)"), NET_UNROUTABLE);
349351
BOOST_CHECK_EQUAL(ParseNetwork("tÖr"), NET_UNROUTABLE);

test/functional/feature_proxy.py

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- `-proxy` (proxy everything)
1313
- `-onion` (proxy just onions)
1414
- `-proxyrandomize` Circuit randomization
15+
- `-cjdnsreachable`
1516
- Proxy configurations to test on proxy side,
1617
- support no authentication (other proxy)
1718
- support no authentication + user/pass authentication (Tor)
@@ -26,6 +27,7 @@
2627
addnode connect to IPv6
2728
addnode connect to onion
2829
addnode connect to generic DNS name
30+
addnode connect to a CJDNS address
2931
3032
- Test getnetworkinfo for each node
3133
"""
@@ -50,14 +52,15 @@
5052
NET_IPV6 = "ipv6"
5153
NET_ONION = "onion"
5254
NET_I2P = "i2p"
55+
NET_CJDNS = "cjdns"
5356

5457
# Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo()
55-
NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P})
58+
NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS})
5659

5760

5861
class ProxyTest(BitcoinTestFramework):
5962
def set_test_params(self):
60-
self.num_nodes = 4
63+
self.num_nodes = 5
6164
self.setup_clean_chain = True
6265

6366
def setup_nodes(self):
@@ -101,7 +104,9 @@ def setup_nodes(self):
101104
['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}',f'-onion={self.conf2.addr[0]}:{self.conf2.addr[1]}',
102105
f'-i2psam={self.i2p_sam[0]}:{self.i2p_sam[1]}', '-i2pacceptincoming=0', '-proxyrandomize=0'],
103106
['-listen', f'-proxy={self.conf2.addr[0]}:{self.conf2.addr[1]}','-proxyrandomize=1'],
104-
[]
107+
[],
108+
['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}','-proxyrandomize=1',
109+
'-cjdnsreachable']
105110
]
106111
if self.have_ipv6:
107112
args[3] = ['-listen', f'-proxy=[{self.conf3.addr[0]}]:{self.conf3.addr[1]}','-proxyrandomize=0', '-noonion']
@@ -113,7 +118,7 @@ def network_test(self, node, addr, network):
113118
if peer["addr"] == addr:
114119
assert_equal(peer["network"], network)
115120

116-
def node_test(self, node, proxies, auth, test_onion=True):
121+
def node_test(self, node, *, proxies, auth, test_onion, test_cjdns):
117122
rv = []
118123
addr = "15.61.23.23:1234"
119124
self.log.debug(f"Test: outgoing IPv4 connection through node for address {addr}")
@@ -161,6 +166,21 @@ def node_test(self, node, proxies, auth, test_onion=True):
161166
rv.append(cmd)
162167
self.network_test(node, addr, network=NET_ONION)
163168

169+
if test_cjdns:
170+
addr = "[fc00:1:2:3:4:5:6:7]:8888"
171+
self.log.debug(f"Test: outgoing CJDNS connection through node for address {addr}")
172+
node.addnode(addr, "onetry")
173+
cmd = proxies[1].queue.get()
174+
assert isinstance(cmd, Socks5Command)
175+
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
176+
assert_equal(cmd.addr, b"fc00:1:2:3:4:5:6:7")
177+
assert_equal(cmd.port, 8888)
178+
if not auth:
179+
assert_equal(cmd.username, None)
180+
assert_equal(cmd.password, None)
181+
rv.append(cmd)
182+
self.network_test(node, addr, network=NET_CJDNS)
183+
164184
addr = "node.noumenon:8333"
165185
self.log.debug(f"Test: outgoing DNS name connection through node for address {addr}")
166186
node.addnode(addr, "onetry")
@@ -179,20 +199,33 @@ def node_test(self, node, proxies, auth, test_onion=True):
179199

180200
def run_test(self):
181201
# basic -proxy
182-
self.node_test(self.nodes[0], [self.serv1, self.serv1, self.serv1, self.serv1], False)
202+
self.node_test(self.nodes[0],
203+
proxies=[self.serv1, self.serv1, self.serv1, self.serv1],
204+
auth=False, test_onion=True, test_cjdns=False)
183205

184206
# -proxy plus -onion
185-
self.node_test(self.nodes[1], [self.serv1, self.serv1, self.serv2, self.serv1], False)
207+
self.node_test(self.nodes[1],
208+
proxies=[self.serv1, self.serv1, self.serv2, self.serv1],
209+
auth=False, test_onion=True, test_cjdns=False)
186210

187211
# -proxy plus -onion, -proxyrandomize
188-
rv = self.node_test(self.nodes[2], [self.serv2, self.serv2, self.serv2, self.serv2], True)
212+
rv = self.node_test(self.nodes[2],
213+
proxies=[self.serv2, self.serv2, self.serv2, self.serv2],
214+
auth=True, test_onion=True, test_cjdns=False)
189215
# Check that credentials as used for -proxyrandomize connections are unique
190216
credentials = set((x.username,x.password) for x in rv)
191217
assert_equal(len(credentials), len(rv))
192218

193219
if self.have_ipv6:
194220
# proxy on IPv6 localhost
195-
self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False)
221+
self.node_test(self.nodes[3],
222+
proxies=[self.serv3, self.serv3, self.serv3, self.serv3],
223+
auth=False, test_onion=False, test_cjdns=False)
224+
225+
# -proxy=unauth -proxyrandomize=1 -cjdnsreachable
226+
self.node_test(self.nodes[4],
227+
proxies=[self.serv1, self.serv1, self.serv1, self.serv1],
228+
auth=False, test_onion=True, test_cjdns=True)
196229

197230
def networks_dict(d):
198231
r = {}
@@ -214,6 +247,7 @@ def networks_dict(d):
214247
assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize)
215248
assert_equal(n0['onion']['reachable'], True)
216249
assert_equal(n0['i2p']['reachable'], False)
250+
assert_equal(n0['cjdns']['reachable'], False)
217251

218252
n1 = networks_dict(self.nodes[1].getnetworkinfo())
219253
assert_equal(NETWORKS, n1.keys())
@@ -240,6 +274,7 @@ def networks_dict(d):
240274
assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)
241275
assert_equal(n2['onion']['reachable'], True)
242276
assert_equal(n2['i2p']['reachable'], False)
277+
assert_equal(n2['cjdns']['reachable'], False)
243278

244279
if self.have_ipv6:
245280
n3 = networks_dict(self.nodes[3].getnetworkinfo())
@@ -253,6 +288,22 @@ def networks_dict(d):
253288
assert_equal(n3[net]['proxy_randomize_credentials'], False)
254289
assert_equal(n3['onion']['reachable'], False)
255290
assert_equal(n3['i2p']['reachable'], False)
291+
assert_equal(n3['cjdns']['reachable'], False)
292+
293+
n4 = networks_dict(self.nodes[4].getnetworkinfo())
294+
assert_equal(NETWORKS, n4.keys())
295+
for net in NETWORKS:
296+
if net == NET_I2P:
297+
expected_proxy = ''
298+
expected_randomize = False
299+
else:
300+
expected_proxy = '%s:%i' % (self.conf1.addr)
301+
expected_randomize = True
302+
assert_equal(n4[net]['proxy'], expected_proxy)
303+
assert_equal(n4[net]['proxy_randomize_credentials'], expected_randomize)
304+
assert_equal(n4['onion']['reachable'], True)
305+
assert_equal(n4['i2p']['reachable'], False)
306+
assert_equal(n4['cjdns']['reachable'], True)
256307

257308

258309
if __name__ == '__main__':

test/functional/interface_bitcoin_cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def run_test(self):
136136
network_info = self.nodes[0].getnetworkinfo()
137137
cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
138138
cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
139-
assert_equal(cli_get_info["Proxies"], "127.0.0.1:9050 (ipv4, ipv6, onion), 127.0.0.1:7656 (i2p)")
139+
assert_equal(cli_get_info["Proxies"], "127.0.0.1:9050 (ipv4, ipv6, onion, cjdns), 127.0.0.1:7656 (i2p)")
140140

141141
if self.is_wallet_compiled():
142142
self.log.info("Test -getinfo and bitcoin-cli getwalletinfo return expected wallet info")

0 commit comments

Comments
 (0)