Skip to content

Commit 85ff09e

Browse files
committed
qa: Add feature_onion.py
1 parent a855538 commit 85ff09e

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

test/functional/feature_onion.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2020 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""Test bitcoind with 'onion'-tagged peers.
6+
7+
Tested inbound and outbound peers.
8+
"""
9+
10+
import os
11+
12+
from test_framework.p2p import P2PInterface
13+
from test_framework.socks5 import Socks5Configuration, Socks5Server
14+
from test_framework.test_framework import BitcoinTestFramework
15+
from test_framework.util import (
16+
PORT_MIN,
17+
PORT_RANGE,
18+
assert_equal,
19+
)
20+
21+
22+
class OnionTest(BitcoinTestFramework):
23+
def set_test_params(self):
24+
self.num_nodes = 2
25+
self.setup_clean_chain = True
26+
27+
def setup_network(self):
28+
self.add_nodes(self.num_nodes)
29+
self.start_nodes()
30+
31+
def test_connections(self, in_clearnet=0, in_onion=0, out_onion=0):
32+
self.restart_node(0, ['-bind={}=onion'.format(self.bind_onion), self.arg_onion])
33+
self.restart_node(1)
34+
35+
for i in range(in_clearnet):
36+
self.nodes[0].add_p2p_connection(P2PInterface())
37+
38+
if in_onion > 0:
39+
if in_onion > 1:
40+
self.log.warning("Maximum 1 inbound 'onion'-tagged connection is supported.")
41+
in_onion = 1
42+
self.nodes[1].addnode(self.bind_onion, 'onetry')
43+
44+
# Create a connection to a dummy Socks5 server just before
45+
# the getnetworkinfo RPC, as such connections are short-lived.
46+
if out_onion > 0:
47+
if out_onion > 1:
48+
self.log.warning("Maximum 1 outbound onion connection is supported.")
49+
out_onion = 1
50+
self.nodes[0].addnode('bitcoinostk4e4re.onion:18444', 'onetry')
51+
52+
network_info = self.nodes[0].getnetworkinfo()
53+
assert_equal(network_info["connections"], in_clearnet + in_onion + out_onion)
54+
assert_equal(network_info["connections_in"], in_clearnet + in_onion)
55+
assert_equal(network_info["connections_out"], out_onion)
56+
assert_equal(network_info["connections_onion_only"], in_clearnet == 0 and (in_onion + out_onion) > 0)
57+
58+
def run_test(self):
59+
port = PORT_MIN + 2 * PORT_RANGE + (os.getpid() % 1000)
60+
self.bind_onion = '127.0.0.1:{}'.format(port)
61+
62+
proxy_conf = Socks5Configuration()
63+
port += 1
64+
proxy_conf.addr = ('127.0.0.1', port)
65+
proxy_conf.unauth = True
66+
Socks5Server(proxy_conf).start()
67+
self.arg_onion = '-onion={0[0]}:{0[1]}'.format(proxy_conf.addr)
68+
69+
self.log.info("Checking a node without any peers...")
70+
self.test_connections(in_clearnet=0, in_onion=0, out_onion=0)
71+
72+
self.log.info("Checking onion only connections...")
73+
self.test_connections(in_clearnet=0, in_onion=0, out_onion=1)
74+
self.test_connections(in_clearnet=0, in_onion=1, out_onion=0)
75+
self.test_connections(in_clearnet=0, in_onion=1, out_onion=1)
76+
77+
self.log.info("Checking clearnet only connections...")
78+
self.test_connections(in_clearnet=1, in_onion=0, out_onion=0)
79+
self.test_connections(in_clearnet=2, in_onion=0, out_onion=0)
80+
81+
self.log.info("Checking mixed type connections...")
82+
self.test_connections(in_clearnet=1, in_onion=0, out_onion=1)
83+
self.test_connections(in_clearnet=1, in_onion=1, out_onion=0)
84+
self.test_connections(in_clearnet=1, in_onion=1, out_onion=1)
85+
self.test_connections(in_clearnet=2, in_onion=0, out_onion=1)
86+
self.test_connections(in_clearnet=2, in_onion=1, out_onion=0)
87+
self.test_connections(in_clearnet=2, in_onion=1, out_onion=1)
88+
89+
90+
if __name__ == '__main__':
91+
OnionTest().main()

test/functional/test_framework/socks5.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import socket
88
import threading
9+
import time
910
import queue
1011
import logging
1112

@@ -116,6 +117,8 @@ def handle(self):
116117
cmdin = Socks5Command(cmd, atyp, addr, port, username, password)
117118
self.serv.queue.put(cmdin)
118119
logger.info('Proxy: %s', cmdin)
120+
# Some tests, e.g., feature_onion.py, require prolonged lifetime of a connection.
121+
time.sleep(0.25)
119122
# Fall through to disconnect
120123
except Exception as e:
121124
logger.exception("socks5 request handling failed.")

test/functional/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
'feature_dersig.py',
226226
'feature_cltv.py',
227227
'rpc_uptime.py',
228+
'feature_onion.py',
228229
'wallet_resendwallettransactions.py',
229230
'wallet_fallbackfee.py',
230231
'rpc_dumptxoutset.py',

0 commit comments

Comments
 (0)