15
15
2-101: bury that block with 100 blocks so the coinbase transaction
16
16
output can be spent
17
17
102: a block containing a transaction spending the coinbase
18
- transaction output. The transaction has an invalid signature.
18
+ transaction output. The transaction has an invalid signature.
19
19
103-2202: bury the bad block with just over two weeks' worth of blocks
20
20
(2100 blocks)
21
21
29
29
block 200. node2 will reject block 102 since it's assumed valid, but it
30
30
isn't buried by at least two weeks' work.
31
31
"""
32
+ import time
32
33
33
- from test_framework .mininode import *
34
- from test_framework .test_framework import BitcoinTestFramework
35
- from test_framework .util import *
36
- from test_framework .blocktools import create_block , create_coinbase
34
+ from test_framework .blocktools import (create_block , create_coinbase )
37
35
from test_framework .key import CECKey
38
- from test_framework .script import *
36
+ from test_framework .mininode import (CBlockHeader ,
37
+ COutPoint ,
38
+ CTransaction ,
39
+ CTxIn ,
40
+ CTxOut ,
41
+ NetworkThread ,
42
+ NodeConn ,
43
+ SingleNodeConnCB ,
44
+ msg_block ,
45
+ msg_headers )
46
+ from test_framework .script import (CScript , OP_TRUE )
47
+ from test_framework .test_framework import BitcoinTestFramework
48
+ from test_framework .util import (start_node , p2p_port , assert_equal )
39
49
40
50
class BaseNode (SingleNodeConnCB ):
41
51
def __init__ (self ):
42
- SingleNodeConnCB .__init__ (self )
43
- self .last_inv = None
44
- self .last_headers = None
45
- self .last_block = None
46
- self .last_getdata = None
47
- self .block_announced = False
48
- self .last_getheaders = None
49
- self .disconnected = False
50
- self .last_blockhash_announced = None
51
-
52
- def on_close (self , conn ):
53
- self .disconnected = True
54
-
55
- def wait_for_disconnect (self , timeout = 60 ):
56
- test_function = lambda : self .disconnected
57
- assert (wait_until (test_function , timeout = timeout ))
58
- return
52
+ super ().__init__ ()
59
53
60
54
def send_header_for_blocks (self , new_blocks ):
61
55
headers_message = msg_headers ()
62
- headers_message .headers = [ CBlockHeader (b ) for b in new_blocks ]
56
+ headers_message .headers = [CBlockHeader (b ) for b in new_blocks ]
63
57
self .send_message (headers_message )
64
58
65
- class SendHeadersTest (BitcoinTestFramework ):
59
+ class AssumeValidTest (BitcoinTestFramework ):
66
60
def __init__ (self ):
67
61
super ().__init__ ()
68
62
self .setup_clean_chain = True
@@ -72,8 +66,34 @@ def setup_network(self):
72
66
# Start node0. We don't start the other nodes yet since
73
67
# we need to pre-mine a block with an invalid transaction
74
68
# signature so we can pass in the block hash as assumevalid.
75
- self .nodes = []
76
- self .nodes .append (start_node (0 , self .options .tmpdir ))
69
+ self .nodes = [start_node (0 , self .options .tmpdir )]
70
+
71
+ def send_blocks_until_disconnected (self , node ):
72
+ """Keep sending blocks to the node until we're disconnected."""
73
+ for i in range (len (self .blocks )):
74
+ try :
75
+ node .send_message (msg_block (self .blocks [i ]))
76
+ except IOError as e :
77
+ assert str (e ) == 'Not connected, no pushbuf'
78
+ break
79
+
80
+ def assert_blockchain_height (self , node , height ):
81
+ """Wait until the blockchain is no longer advancing and verify it's reached the expected height."""
82
+ last_height = node .getblock (node .getbestblockhash ())['height' ]
83
+ timeout = 10
84
+ while True :
85
+ time .sleep (0.25 )
86
+ current_height = node .getblock (node .getbestblockhash ())['height' ]
87
+ if current_height != last_height :
88
+ last_height = current_height
89
+ if timeout < 0 :
90
+ assert False , "blockchain too short after timeout: %d" % current_height
91
+ timeout - 0.25
92
+ continue
93
+ elif current_height > height :
94
+ assert False , "blockchain too long: %d" % current_height
95
+ elif current_height == height :
96
+ break
77
97
78
98
def run_test (self ):
79
99
@@ -83,7 +103,7 @@ def run_test(self):
83
103
connections .append (NodeConn ('127.0.0.1' , p2p_port (0 ), self .nodes [0 ], node0 ))
84
104
node0 .add_connection (connections [0 ])
85
105
86
- NetworkThread ().start () # Start up network handling in another thread
106
+ NetworkThread ().start () # Start up network handling in another thread
87
107
node0 .wait_for_verack ()
88
108
89
109
# Build the blockchain
@@ -120,7 +140,7 @@ def run_test(self):
120
140
# Create a transaction spending the coinbase output with an invalid (null) signature
121
141
tx = CTransaction ()
122
142
tx .vin .append (CTxIn (COutPoint (self .block1 .vtx [0 ].sha256 , 0 ), scriptSig = b"" ))
123
- tx .vout .append (CTxOut (49 * 100000000 , CScript ([OP_TRUE ])))
143
+ tx .vout .append (CTxOut (49 * 100000000 , CScript ([OP_TRUE ])))
124
144
tx .calc_sha256 ()
125
145
126
146
block102 = create_block (self .tip , create_coinbase (height ), self .block_time )
@@ -166,25 +186,19 @@ def run_test(self):
166
186
node1 .send_header_for_blocks (self .blocks [2000 :])
167
187
node2 .send_header_for_blocks (self .blocks [0 :200 ])
168
188
169
- # Send 102 blocks to node0. Block 102 will be rejected.
170
- for i in range (101 ):
171
- node0 .send_message (msg_block (self .blocks [i ]))
172
- node0 .sync_with_ping () # make sure the most recent block is synced
173
- node0 .send_message (msg_block (self .blocks [101 ]))
174
- assert_equal (self .nodes [0 ].getblock (self .nodes [0 ].getbestblockhash ())['height' ], 101 )
189
+ # Send blocks to node0. Block 102 will be rejected.
190
+ self .send_blocks_until_disconnected (node0 )
191
+ self .assert_blockchain_height (self .nodes [0 ], 101 )
175
192
176
- # Send 3102 blocks to node1. All blocks will be accepted.
193
+ # Send all blocks to node1. All blocks will be accepted.
177
194
for i in range (2202 ):
178
195
node1 .send_message (msg_block (self .blocks [i ]))
179
- node1 .sync_with_ping () # make sure the most recent block is synced
196
+ node1 .sync_with_ping () # make sure the most recent block is synced
180
197
assert_equal (self .nodes [1 ].getblock (self .nodes [1 ].getbestblockhash ())['height' ], 2202 )
181
198
182
- # Send 102 blocks to node2. Block 102 will be rejected.
183
- for i in range (101 ):
184
- node2 .send_message (msg_block (self .blocks [i ]))
185
- node2 .sync_with_ping () # make sure the most recent block is synced
186
- node2 .send_message (msg_block (self .blocks [101 ]))
187
- assert_equal (self .nodes [2 ].getblock (self .nodes [2 ].getbestblockhash ())['height' ], 101 )
199
+ # Send blocks to node2. Block 102 will be rejected.
200
+ self .send_blocks_until_disconnected (node2 )
201
+ self .assert_blockchain_height (self .nodes [2 ], 101 )
188
202
189
203
if __name__ == '__main__' :
190
- SendHeadersTest ().main ()
204
+ AssumeValidTest ().main ()
0 commit comments