8
8
from test_framework .address import ADDRESS_BCRT1_UNSPENDABLE
9
9
from test_framework .test_framework import BitcoinTestFramework
10
10
from test_framework .messages import CTransaction , hash256
11
- from test_framework .util import assert_equal
11
+ from test_framework .util import assert_equal , connect_nodes
12
12
from io import BytesIO
13
13
14
- ADDRESS = "tcp://127.0.0.1:28332"
15
-
16
14
def hash256_reversed (byte_str ):
17
15
return hash256 (byte_str )[::- 1 ]
18
16
@@ -43,66 +41,62 @@ def skip_test_if_missing_module(self):
43
41
self .skip_if_no_py3_zmq ()
44
42
self .skip_if_no_bitcoind_zmq ()
45
43
46
- def setup_nodes (self ):
44
+ def run_test (self ):
47
45
import zmq
46
+ self .ctx = zmq .Context ()
47
+ try :
48
+ self .test_basic ()
49
+ self .test_reorg ()
50
+ finally :
51
+ # Destroy the ZMQ context.
52
+ self .log .debug ("Destroying ZMQ context" )
53
+ self .ctx .destroy (linger = None )
48
54
49
- # Initialize ZMQ context and socket.
55
+ def test_basic ( self ):
50
56
# All messages are received in the same socket which means
51
57
# that this test fails if the publishing order changes.
52
58
# Note that the publishing order is not defined in the documentation and
53
59
# is subject to change.
54
- self .zmq_context = zmq .Context ()
55
- socket = self .zmq_context .socket (zmq .SUB )
60
+ import zmq
61
+ address = 'tcp://127.0.0.1:28332'
62
+ socket = self .ctx .socket (zmq .SUB )
56
63
socket .set (zmq .RCVTIMEO , 60000 )
57
- socket .connect (ADDRESS )
64
+ socket .connect (address )
58
65
59
66
# Subscribe to all available topics.
60
- self .hashblock = ZMQSubscriber (socket , b"hashblock" )
61
- self .hashtx = ZMQSubscriber (socket , b"hashtx" )
62
- self .rawblock = ZMQSubscriber (socket , b"rawblock" )
63
- self .rawtx = ZMQSubscriber (socket , b"rawtx" )
64
-
65
- self .extra_args = [
66
- ["-zmqpub%s=%s" % (sub .topic .decode (), ADDRESS ) for sub in [self .hashblock , self .hashtx , self .rawblock , self .rawtx ]],
67
- [],
68
- ]
69
- self .add_nodes (self .num_nodes , self .extra_args )
70
- self .start_nodes ()
71
- self .import_deterministic_coinbase_privkeys ()
67
+ hashblock = ZMQSubscriber (socket , b"hashblock" )
68
+ hashtx = ZMQSubscriber (socket , b"hashtx" )
69
+ rawblock = ZMQSubscriber (socket , b"rawblock" )
70
+ rawtx = ZMQSubscriber (socket , b"rawtx" )
72
71
73
- def run_test (self ):
74
- try :
75
- self ._zmq_test ()
76
- finally :
77
- # Destroy the ZMQ context.
78
- self .log .debug ("Destroying ZMQ context" )
79
- self .zmq_context .destroy (linger = None )
72
+ self .restart_node (0 , ["-zmqpub%s=%s" % (sub .topic .decode (), address ) for sub in [hashblock , hashtx , rawblock , rawtx ]])
73
+ connect_nodes (self .nodes [0 ], 1 )
80
74
81
- def _zmq_test (self ):
82
75
num_blocks = 5
83
76
self .log .info ("Generate %(n)d blocks (and %(n)d coinbase txes)" % {"n" : num_blocks })
84
77
genhashes = self .nodes [0 ].generatetoaddress (num_blocks , ADDRESS_BCRT1_UNSPENDABLE )
78
+
85
79
self .sync_all ()
86
80
87
81
for x in range (num_blocks ):
88
82
# Should receive the coinbase txid.
89
- txid = self . hashtx .receive ()
83
+ txid = hashtx .receive ()
90
84
91
85
# Should receive the coinbase raw transaction.
92
- hex = self . rawtx .receive ()
86
+ hex = rawtx .receive ()
93
87
tx = CTransaction ()
94
88
tx .deserialize (BytesIO (hex ))
95
89
tx .calc_sha256 ()
96
90
assert_equal (tx .hash , txid .hex ())
97
91
98
92
# Should receive the generated block hash.
99
- hash = self . hashblock .receive ().hex ()
93
+ hash = hashblock .receive ().hex ()
100
94
assert_equal (genhashes [x ], hash )
101
95
# The block should only have the coinbase txid.
102
96
assert_equal ([txid .hex ()], self .nodes [1 ].getblock (hash )["tx" ])
103
97
104
98
# Should receive the generated raw block.
105
- block = self . rawblock .receive ()
99
+ block = rawblock .receive ()
106
100
assert_equal (genhashes [x ], hash256_reversed (block [:80 ]).hex ())
107
101
108
102
if self .is_wallet_compiled ():
@@ -111,23 +105,47 @@ def _zmq_test(self):
111
105
self .sync_all ()
112
106
113
107
# Should receive the broadcasted txid.
114
- txid = self . hashtx .receive ()
108
+ txid = hashtx .receive ()
115
109
assert_equal (payment_txid , txid .hex ())
116
110
117
111
# Should receive the broadcasted raw transaction.
118
- hex = self . rawtx .receive ()
112
+ hex = rawtx .receive ()
119
113
assert_equal (payment_txid , hash256_reversed (hex ).hex ())
120
114
121
115
122
116
self .log .info ("Test the getzmqnotifications RPC" )
123
117
assert_equal (self .nodes [0 ].getzmqnotifications (), [
124
- {"type" : "pubhashblock" , "address" : ADDRESS , "hwm" : 1000 },
125
- {"type" : "pubhashtx" , "address" : ADDRESS , "hwm" : 1000 },
126
- {"type" : "pubrawblock" , "address" : ADDRESS , "hwm" : 1000 },
127
- {"type" : "pubrawtx" , "address" : ADDRESS , "hwm" : 1000 },
118
+ {"type" : "pubhashblock" , "address" : address , "hwm" : 1000 },
119
+ {"type" : "pubhashtx" , "address" : address , "hwm" : 1000 },
120
+ {"type" : "pubrawblock" , "address" : address , "hwm" : 1000 },
121
+ {"type" : "pubrawtx" , "address" : address , "hwm" : 1000 },
128
122
])
129
123
130
124
assert_equal (self .nodes [1 ].getzmqnotifications (), [])
131
125
126
+ def test_reorg (self ):
127
+ import zmq
128
+ address = 'tcp://127.0.0.1:28333'
129
+ socket = self .ctx .socket (zmq .SUB )
130
+ socket .set (zmq .RCVTIMEO , 60000 )
131
+ socket .connect (address )
132
+ hashblock = ZMQSubscriber (socket , b'hashblock' )
133
+
134
+ # Should only notify the tip if a reorg occurs
135
+ self .restart_node (0 , ['-zmqpub%s=%s' % (hashblock .topic .decode (), address )])
136
+
137
+ # Generate 1 block in nodes[0] and receive all notifications
138
+ self .nodes [0 ].generatetoaddress (1 , ADDRESS_BCRT1_UNSPENDABLE )
139
+ assert_equal (self .nodes [0 ].getbestblockhash (), hashblock .receive ().hex ())
140
+
141
+ # Generate 2 blocks in nodes[1]
142
+ self .nodes [1 ].generatetoaddress (2 , ADDRESS_BCRT1_UNSPENDABLE )
143
+
144
+ # nodes[0] will reorg chain after connecting back nodes[1]
145
+ connect_nodes (self .nodes [0 ], 1 )
146
+
147
+ # Should receive nodes[1] tip
148
+ assert_equal (self .nodes [1 ].getbestblockhash (), hashblock .receive ().hex ())
149
+
132
150
if __name__ == '__main__' :
133
151
ZMQTest ().main ()
0 commit comments