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 add_outbound_p2p_connection test framework functionality"""
6
7from test_framework.p2p import P2PInterface
8from test_framework.test_framework import BitcoinTestFramework
9from test_framework.util import assert_equal
10
11
12def check_node_connections(*, node, num_in, num_out):
13    info = node.getnetworkinfo()
14    assert_equal(info["connections_in"], num_in)
15    assert_equal(info["connections_out"], num_out)
16
17
18class P2PAddConnections(BitcoinTestFramework):
19    def set_test_params(self):
20        self.num_nodes = 2
21
22    def setup_network(self):
23        self.setup_nodes()
24        # Don't connect the nodes
25
26    def run_test(self):
27        self.log.info("Add 8 outbounds to node 0")
28        for i in range(8):
29            self.log.info(f"outbound: {i}")
30            self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="outbound-full-relay")
31
32        self.log.info("Add 2 block-relay-only connections to node 0")
33        for i in range(2):
34            self.log.info(f"block-relay-only: {i}")
35            # set p2p_idx based on the outbound connections already open to the
36            # node, so add 8 to account for the previous full-relay connections
37            self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i + 8, connection_type="block-relay-only")
38
39        self.log.info("Add 2 block-relay-only connections to node 1")
40        for i in range(2):
41            self.log.info(f"block-relay-only: {i}")
42            self.nodes[1].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="block-relay-only")
43
44        self.log.info("Add 5 inbound connections to node 1")
45        for i in range(5):
46            self.log.info(f"inbound: {i}")
47            self.nodes[1].add_p2p_connection(P2PInterface())
48
49        self.log.info("Add 8 outbounds to node 1")
50        for i in range(8):
51            self.log.info(f"outbound: {i}")
52            # bump p2p_idx to account for the 2 existing outbounds on node 1
53            self.nodes[1].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i + 2)
54
55        self.log.info("Check the connections opened as expected")
56        check_node_connections(node=self.nodes[0], num_in=0, num_out=10)
57        check_node_connections(node=self.nodes[1], num_in=5, num_out=10)
58
59        self.log.info("Disconnect p2p connections & try to re-open")
60        self.nodes[0].disconnect_p2ps()
61        check_node_connections(node=self.nodes[0], num_in=0, num_out=0)
62
63        self.log.info("Add 8 outbounds to node 0")
64        for i in range(8):
65            self.log.info(f"outbound: {i}")
66            self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i)
67        check_node_connections(node=self.nodes[0], num_in=0, num_out=8)
68
69        self.log.info("Add 2 block-relay-only connections to node 0")
70        for i in range(2):
71            self.log.info(f"block-relay-only: {i}")
72            # bump p2p_idx to account for the 8 existing outbounds on node 0
73            self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i + 8, connection_type="block-relay-only")
74        check_node_connections(node=self.nodes[0], num_in=0, num_out=10)
75
76        self.log.info("Restart node 0 and try to reconnect to p2ps")
77        self.restart_node(0)
78
79        self.log.info("Add 4 outbounds to node 0")
80        for i in range(4):
81            self.log.info(f"outbound: {i}")
82            self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i)
83        check_node_connections(node=self.nodes[0], num_in=0, num_out=4)
84
85        self.log.info("Add 2 block-relay-only connections to node 0")
86        for i in range(2):
87            self.log.info(f"block-relay-only: {i}")
88            # bump p2p_idx to account for the 4 existing outbounds on node 0
89            self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i + 4, connection_type="block-relay-only")
90        check_node_connections(node=self.nodes[0], num_in=0, num_out=6)
91
92        check_node_connections(node=self.nodes[1], num_in=5, num_out=10)
93
94
95if __name__ == '__main__':
96    P2PAddConnections().main()
97