13
13
import subprocess
14
14
import time
15
15
16
+ from .authproxy import JSONRPCException
17
+ from .mininode import NodeConn
16
18
from .util import (
17
19
assert_equal ,
18
20
get_rpc_proxy ,
19
21
rpc_url ,
20
22
wait_until ,
23
+ p2p_port ,
21
24
)
22
- from .authproxy import JSONRPCException
23
25
24
26
BITCOIND_PROC_WAIT_TIMEOUT = 60
25
27
@@ -31,9 +33,11 @@ class TestNode():
31
33
- state about the node (whether it's running, etc)
32
34
- a Python subprocess.Popen object representing the running process
33
35
- an RPC connection to the node
36
+ - one or more P2P connections to the node
37
+
34
38
35
- To make things easier for the test writer, a bit of magic is happening under the covers.
36
- Any unrecognised messages will be dispatched to the RPC connection."""
39
+ To make things easier for the test writer, any unrecognised messages will
40
+ be dispatched to the RPC connection."""
37
41
38
42
def __init__ (self , i , dirname , extra_args , rpchost , timewait , binary , stderr , mocktime , coverage_dir ):
39
43
self .index = i
@@ -63,6 +67,8 @@ def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mo
63
67
self .url = None
64
68
self .log = logging .getLogger ('TestFramework.node%d' % i )
65
69
70
+ self .p2ps = []
71
+
66
72
def __getattr__ (self , name ):
67
73
"""Dispatches any unrecognised messages to the RPC connection."""
68
74
assert self .rpc_connected and self .rpc is not None , "Error: no RPC connection"
@@ -119,6 +125,7 @@ def stop_node(self):
119
125
self .stop ()
120
126
except http .client .CannotSendRequest :
121
127
self .log .exception ("Unable to stop node." )
128
+ del self .p2ps [:]
122
129
123
130
def is_node_stopped (self ):
124
131
"""Checks whether the node has stopped.
@@ -151,6 +158,38 @@ def node_encrypt_wallet(self, passphrase):
151
158
self .encryptwallet (passphrase )
152
159
self .wait_until_stopped ()
153
160
161
+ def add_p2p_connection (self , p2p_conn , ** kwargs ):
162
+ """Add a p2p connection to the node.
163
+
164
+ This method adds the p2p connection to the self.p2ps list and also
165
+ returns the connection to the caller."""
166
+ if 'dstport' not in kwargs :
167
+ kwargs ['dstport' ] = p2p_port (self .index )
168
+ if 'dstaddr' not in kwargs :
169
+ kwargs ['dstaddr' ] = '127.0.0.1'
170
+ self .p2ps .append (p2p_conn )
171
+ kwargs .update ({'rpc' : self .rpc , 'callback' : p2p_conn })
172
+ p2p_conn .add_connection (NodeConn (** kwargs ))
173
+
174
+ return p2p_conn
175
+
176
+ @property
177
+ def p2p (self ):
178
+ """Return the first p2p connection
179
+
180
+ Convenience property - most tests only use a single p2p connection to each
181
+ node, so this saves having to write node.p2ps[0] many times."""
182
+ assert self .p2ps , "No p2p connection"
183
+ return self .p2ps [0 ]
184
+
185
+ def disconnect_p2p (self , index = 0 ):
186
+ """Close the p2p connection to the node."""
187
+ # Connection could have already been closed by other end. Calling disconnect_p2p()
188
+ # on an already disconnected p2p connection is not an error.
189
+ if self .p2ps [index ].connection is not None :
190
+ self .p2ps [index ].connection .disconnect_node ()
191
+ del self .p2ps [index ]
192
+
154
193
class TestNodeCLI ():
155
194
"""Interface to bitcoin-cli for an individual node"""
156
195
0 commit comments