40
40
it's missing an intermediate block.
41
41
Node1 should reorg to this longer chain.
42
42
43
+ 4b.Send 288 more blocks on the longer chain.
44
+ Node0 should process all but the last block (too far ahead in height).
45
+ Send all headers to Node1, and then send the last block in that chain.
46
+ Node1 should accept the block because it's coming from a whitelisted peer.
47
+
43
48
5. Send a duplicate of the block in #3 to Node0.
44
49
Node0 should not process the block because it is unrequested, and stay on
45
50
the shorter chain.
@@ -126,13 +131,15 @@ def run_test(self):
126
131
# 2. Send one block that builds on each tip.
127
132
# This should be accepted.
128
133
blocks_h2 = [] # the height 2 blocks on each node's chain
134
+ block_time = time .time () + 1
129
135
for i in xrange (2 ):
130
- blocks_h2 .append (create_block (tips [i ], create_coinbase (), time . time () + 1 ))
136
+ blocks_h2 .append (create_block (tips [i ], create_coinbase (), block_time ))
131
137
blocks_h2 [i ].solve ()
138
+ block_time += 1
132
139
test_node .send_message (msg_block (blocks_h2 [0 ]))
133
140
white_node .send_message (msg_block (blocks_h2 [1 ]))
134
141
135
- time .sleep (1 )
142
+ time .sleep (0.5 )
136
143
assert_equal (self .nodes [0 ].getblockcount (), 2 )
137
144
assert_equal (self .nodes [1 ].getblockcount (), 2 )
138
145
print "First height 2 block accepted by both nodes"
@@ -145,7 +152,7 @@ def run_test(self):
145
152
test_node .send_message (msg_block (blocks_h2f [0 ]))
146
153
white_node .send_message (msg_block (blocks_h2f [1 ]))
147
154
148
- time .sleep (1 ) # Give time to process the block
155
+ time .sleep (0.5 ) # Give time to process the block
149
156
for x in self .nodes [0 ].getchaintips ():
150
157
if x ['hash' ] == blocks_h2f [0 ].hash :
151
158
assert_equal (x ['status' ], "headers-only" )
@@ -164,7 +171,7 @@ def run_test(self):
164
171
test_node .send_message (msg_block (blocks_h3 [0 ]))
165
172
white_node .send_message (msg_block (blocks_h3 [1 ]))
166
173
167
- time .sleep (1 )
174
+ time .sleep (0.5 )
168
175
# Since the earlier block was not processed by node0, the new block
169
176
# can't be fully validated.
170
177
for x in self .nodes [0 ].getchaintips ():
@@ -182,6 +189,45 @@ def run_test(self):
182
189
assert_equal (self .nodes [1 ].getblockcount (), 3 )
183
190
print "Successfully reorged to length 3 chain from whitelisted peer"
184
191
192
+ # 4b. Now mine 288 more blocks and deliver; all should be processed but
193
+ # the last (height-too-high) on node0. Node1 should process the tip if
194
+ # we give it the headers chain leading to the tip.
195
+ tips = blocks_h3
196
+ headers_message = msg_headers ()
197
+ all_blocks = [] # node0's blocks
198
+ for j in xrange (2 ):
199
+ for i in xrange (288 ):
200
+ next_block = create_block (tips [j ].sha256 , create_coinbase (), tips [j ].nTime + 1 )
201
+ next_block .solve ()
202
+ if j == 0 :
203
+ test_node .send_message (msg_block (next_block ))
204
+ all_blocks .append (next_block )
205
+ else :
206
+ headers_message .headers .append (CBlockHeader (next_block ))
207
+ tips [j ] = next_block
208
+
209
+ time .sleep (2 )
210
+ for x in all_blocks :
211
+ try :
212
+ self .nodes [0 ].getblock (x .hash )
213
+ if x == all_blocks [287 ]:
214
+ raise AssertionError ("Unrequested block too far-ahead should have been ignored" )
215
+ except :
216
+ if x == all_blocks [287 ]:
217
+ print "Unrequested block too far-ahead not processed"
218
+ else :
219
+ raise AssertionError ("Unrequested block with more work should have been accepted" )
220
+
221
+ headers_message .headers .pop () # Ensure the last block is unrequested
222
+ white_node .send_message (headers_message ) # Send headers leading to tip
223
+ white_node .send_message (msg_block (tips [1 ])) # Now deliver the tip
224
+ try :
225
+ time .sleep (0.5 )
226
+ self .nodes [1 ].getblock (tips [1 ].hash )
227
+ print "Unrequested block far ahead of tip accepted from whitelisted peer"
228
+ except :
229
+ raise AssertionError ("Unrequested block from whitelisted peer not accepted" )
230
+
185
231
# 5. Test handling of unrequested block on the node that didn't process
186
232
# Should still not be processed (even though it has a child that has more
187
233
# work).
@@ -204,21 +250,20 @@ def run_test(self):
204
250
test_node .last_getdata = None
205
251
test_node .send_message (msg_inv ([CInv (2 , blocks_h3 [0 ].sha256 )]))
206
252
207
- time .sleep (1 )
253
+ time .sleep (0.5 )
208
254
with mininode_lock :
209
255
getdata = test_node .last_getdata
210
256
211
- # Check that the getdata is for the right block
212
- assert_equal (len (getdata .inv ), 1 )
257
+ # Check that the getdata includes the right block
213
258
assert_equal (getdata .inv [0 ].hash , blocks_h2f [0 ].sha256 )
214
259
print "Inv at tip triggered getdata for unprocessed block"
215
260
216
261
# 7. Send the missing block for the third time (now it is requested)
217
262
test_node .send_message (msg_block (blocks_h2f [0 ]))
218
263
219
- time .sleep (1 )
220
- assert_equal (self .nodes [0 ].getblockcount (), 3 )
221
- print "Successfully reorged to length 3 chain from non-whitelisted peer"
264
+ time .sleep (2 )
265
+ assert_equal (self .nodes [0 ].getblockcount (), 290 )
266
+ print "Successfully reorged to longer chain from non-whitelisted peer"
222
267
223
268
[ c .disconnect_node () for c in connections ]
224
269
0 commit comments