7
7
Version 1 compact blocks are pre-segwit (txids)
8
8
Version 2 compact blocks are post-segwit (wtxids)
9
9
"""
10
- from decimal import Decimal
11
10
import random
12
11
13
12
from test_framework .blocktools import create_block , create_coinbase , add_witness_commitment
14
- from test_framework .messages import BlockTransactions , BlockTransactionsRequest , calculate_shortid , CBlock , CBlockHeader , CInv , COutPoint , CTransaction , CTxIn , CTxInWitness , CTxOut , FromHex , HeaderAndShortIDs , msg_block , msg_blocktxn , msg_cmpctblock , msg_getblocktxn , msg_getdata , msg_getheaders , msg_headers , msg_inv , msg_sendcmpct , msg_sendheaders , msg_tx , msg_witness_block , msg_witness_blocktxn , MSG_WITNESS_FLAG , NODE_NETWORK , NODE_WITNESS , P2PHeaderAndShortIDs , PrefilledTransaction , ser_uint256 , ToHex
13
+ from test_framework .messages import BlockTransactions , BlockTransactionsRequest , calculate_shortid , CBlock , CBlockHeader , CInv , COutPoint , CTransaction , CTxIn , CTxInWitness , CTxOut , FromHex , HeaderAndShortIDs , msg_block , msg_blocktxn , msg_cmpctblock , msg_getblocktxn , msg_getdata , msg_getheaders , msg_headers , msg_inv , msg_sendcmpct , msg_sendheaders , msg_tx , msg_witness_block , msg_witness_blocktxn , MSG_WITNESS_FLAG , NODE_NETWORK , P2PHeaderAndShortIDs , PrefilledTransaction , ser_uint256 , ToHex
15
14
from test_framework .mininode import mininode_lock , P2PInterface
16
15
from test_framework .script import CScript , OP_TRUE , OP_DROP
17
16
from test_framework .test_framework import BitcoinTestFramework
18
- from test_framework .util import assert_equal , get_bip9_status , satoshi_round , sync_blocks , wait_until
17
+ from test_framework .util import assert_equal , get_bip9_status , wait_until
19
18
20
19
# TestP2PConn: A peer we use to send messages to bitcoind, and store responses.
21
20
class TestP2PConn (P2PInterface ):
22
- def __init__ (self ):
21
+ def __init__ (self , cmpct_version ):
23
22
super ().__init__ ()
24
23
self .last_sendcmpct = []
25
24
self .block_announced = False
26
25
# Store the hashes of blocks we've seen announced.
27
26
# This is for synchronizing the p2p message traffic,
28
27
# so we can eg wait until a particular block is announced.
29
28
self .announced_blockhashes = set ()
29
+ self .cmpct_version = cmpct_version
30
30
31
31
def on_sendcmpct (self , message ):
32
32
self .last_sendcmpct .append (message )
@@ -94,11 +94,7 @@ def send_await_disconnect(self, message, timeout=30):
94
94
class CompactBlocksTest (BitcoinTestFramework ):
95
95
def set_test_params (self ):
96
96
self .setup_clean_chain = True
97
- # Node0 = pre-segwit, node1 = segwit-aware
98
- self .num_nodes = 2
99
- # This test was written assuming SegWit is activated using BIP9 at height 432 (3x confirmation window).
100
- # TODO: Rewrite this test to support SegWit being always active.
101
- self .extra_args = [["-vbparams=segwit:0:0" ], ["-vbparams=segwit:0:999999999999" , "-txindex" ]]
97
+ self .num_nodes = 1
102
98
self .utxos = []
103
99
104
100
def skip_test_if_missing_module (self ):
@@ -117,11 +113,10 @@ def build_block_on_tip(self, node, segwit=False):
117
113
118
114
# Create 10 more anyone-can-spend utxo's for testing.
119
115
def make_utxos (self ):
120
- # Doesn't matter which node we use, just use node0.
121
116
block = self .build_block_on_tip (self .nodes [0 ])
122
- self .test_node .send_and_ping (msg_block (block ))
117
+ self .segwit_node .send_and_ping (msg_block (block ))
123
118
assert int (self .nodes [0 ].getbestblockhash (), 16 ) == block .sha256
124
- self .nodes [0 ].generate (100 )
119
+ self .nodes [0 ].generatetoaddress (100 , self . nodes [ 0 ]. getnewaddress ( address_type = "bech32" ) )
125
120
126
121
total_value = block .vtx [0 ].vout [0 ].nValue
127
122
out_value = total_value // 10
@@ -135,10 +130,10 @@ def make_utxos(self):
135
130
block2 .vtx .append (tx )
136
131
block2 .hashMerkleRoot = block2 .calc_merkle_root ()
137
132
block2 .solve ()
138
- self .test_node .send_and_ping (msg_block (block2 ))
133
+ self .segwit_node .send_and_ping (msg_block (block2 ))
139
134
assert_equal (int (self .nodes [0 ].getbestblockhash (), 16 ), block2 .sha256 )
140
135
self .utxos .extend ([[tx .sha256 , i , out_value ] for i in range (10 )])
141
- return
136
+
142
137
143
138
# Test "sendcmpct" (between peers preferring the same version):
144
139
# - No compact block announcements unless sendcmpct is sent.
@@ -149,7 +144,10 @@ def make_utxos(self):
149
144
# are made with compact blocks.
150
145
# If old_node is passed in, request compact blocks with version=preferred-1
151
146
# and verify that it receives block announcements via compact block.
152
- def test_sendcmpct (self , node , test_node , preferred_version , old_node = None ):
147
+ def test_sendcmpct (self , test_node , old_node = None ):
148
+ preferred_version = test_node .cmpct_version
149
+ node = self .nodes [0 ]
150
+
153
151
# Make sure we get a SENDCMPCT message from our peer
154
152
def received_sendcmpct ():
155
153
return (len (test_node .last_sendcmpct ) > 0 )
@@ -251,23 +249,18 @@ def test_invalid_cmpctblock_message(self):
251
249
# This index will be too high
252
250
prefilled_txn = PrefilledTransaction (1 , block .vtx [0 ])
253
251
cmpct_block .prefilled_txn = [prefilled_txn ]
254
- self .test_node .send_await_disconnect (msg_cmpctblock (cmpct_block ))
252
+ self .segwit_node .send_await_disconnect (msg_cmpctblock (cmpct_block ))
255
253
assert_equal (int (self .nodes [0 ].getbestblockhash (), 16 ), block .hashPrevBlock )
256
254
257
255
# Compare the generated shortids to what we expect based on BIP 152, given
258
256
# bitcoind's choice of nonce.
259
- def test_compactblock_construction (self , node , test_node , version , use_witness_address ):
257
+ def test_compactblock_construction (self , test_node , use_witness_address = True ):
258
+ version = test_node .cmpct_version
259
+ node = self .nodes [0 ]
260
260
# Generate a bunch of transactions.
261
261
node .generate (101 )
262
262
num_transactions = 25
263
263
address = node .getnewaddress ()
264
- if use_witness_address :
265
- # Want at least one segwit spend, so move all funds to
266
- # a witness address.
267
- address = node .getnewaddress (address_type = 'bech32' )
268
- value_to_send = node .getbalance ()
269
- node .sendtoaddress (address , satoshi_round (value_to_send - Decimal (0.1 )))
270
- node .generate (1 )
271
264
272
265
segwit_tx_generated = False
273
266
for i in range (num_transactions ):
@@ -285,7 +278,7 @@ def test_compactblock_construction(self, node, test_node, version, use_witness_a
285
278
test_node .wait_for_block_announcement (tip )
286
279
287
280
# Make sure we will receive a fast-announce compact block
288
- self .request_cb_announcements (test_node , node , version )
281
+ self .request_cb_announcements (test_node )
289
282
290
283
# Now mine a block, and look at the resulting compact block.
291
284
test_node .clear_block_announcement ()
@@ -375,7 +368,9 @@ def check_compactblock_construction_from_block(self, version, header_and_shortid
375
368
# Post-segwit: upgraded nodes would only make this request of cb-version-2,
376
369
# NODE_WITNESS peers. Unupgraded nodes would still make this request of
377
370
# any cb-version-1-supporting peer.
378
- def test_compactblock_requests (self , node , test_node , version , segwit ):
371
+ def test_compactblock_requests (self , test_node , segwit = True ):
372
+ version = test_node .cmpct_version
373
+ node = self .nodes [0 ]
379
374
# Try announcing a block with an inv or header, expect a compactblock
380
375
# request
381
376
for announce in ["inv" , "header" ]:
@@ -440,7 +435,9 @@ def build_block_with_transactions(self, node, utxo, num_transactions):
440
435
# Test that we only receive getblocktxn requests for transactions that the
441
436
# node needs, and that responding to them causes the block to be
442
437
# reconstructed.
443
- def test_getblocktxn_requests (self , node , test_node , version ):
438
+ def test_getblocktxn_requests (self , test_node ):
439
+ version = test_node .cmpct_version
440
+ node = self .nodes [0 ]
444
441
with_witness = (version == 2 )
445
442
446
443
def test_getblocktxn_response (compact_block , peer , expected_result ):
@@ -523,9 +520,9 @@ def test_tip_after_message(node, peer, msg, tip):
523
520
524
521
# Incorrectly responding to a getblocktxn shouldn't cause the block to be
525
522
# permanently failed.
526
- def test_incorrect_blocktxn_response (self , node , test_node , version ):
527
- if ( len ( self . utxos ) == 0 ):
528
- self .make_utxos ()
523
+ def test_incorrect_blocktxn_response (self , test_node ):
524
+ version = test_node . cmpct_version
525
+ node = self .nodes [ 0 ]
529
526
utxo = self .utxos .pop (0 )
530
527
531
528
block = self .build_block_with_transactions (node , utxo , 10 )
@@ -579,7 +576,9 @@ def test_incorrect_blocktxn_response(self, node, test_node, version):
579
576
test_node .send_and_ping (msg_block (block ))
580
577
assert_equal (int (node .getbestblockhash (), 16 ), block .sha256 )
581
578
582
- def test_getblocktxn_handler (self , node , test_node , version ):
579
+ def test_getblocktxn_handler (self , test_node ):
580
+ version = test_node .cmpct_version
581
+ node = self .nodes [0 ]
583
582
# bitcoind will not send blocktxn responses for blocks whose height is
584
583
# more than 10 blocks deep.
585
584
MAX_GETBLOCKTXN_DEPTH = 10
@@ -626,7 +625,8 @@ def test_getblocktxn_handler(self, node, test_node, version):
626
625
assert_equal (test_node .last_message ["block" ].block .sha256 , int (block_hash , 16 ))
627
626
assert "blocktxn" not in test_node .last_message
628
627
629
- def test_compactblocks_not_at_tip (self , node , test_node ):
628
+ def test_compactblocks_not_at_tip (self , test_node ):
629
+ node = self .nodes [0 ]
630
630
# Test that requesting old compactblocks doesn't work.
631
631
MAX_CMPCTBLOCK_DEPTH = 5
632
632
new_blocks = []
@@ -681,11 +681,8 @@ def test_compactblocks_not_at_tip(self, node, test_node):
681
681
with mininode_lock :
682
682
assert "blocktxn" not in test_node .last_message
683
683
684
- def activate_segwit (self , node ):
685
- node .generate (144 * 3 )
686
- assert_equal (get_bip9_status (node , "segwit" )["status" ], 'active' )
687
-
688
- def test_end_to_end_block_relay (self , node , listeners ):
684
+ def test_end_to_end_block_relay (self , listeners ):
685
+ node = self .nodes [0 ]
689
686
utxo = self .utxos .pop (0 )
690
687
691
688
block = self .build_block_with_transactions (node , utxo , 10 )
@@ -706,7 +703,8 @@ def test_end_to_end_block_relay(self, node, listeners):
706
703
707
704
# Test that we don't get disconnected if we relay a compact block with valid header,
708
705
# but invalid transactions.
709
- def test_invalid_tx_in_compactblock (self , node , test_node , use_segwit ):
706
+ def test_invalid_tx_in_compactblock (self , test_node , use_segwit = True ):
707
+ node = self .nodes [0 ]
710
708
assert len (self .utxos )
711
709
utxo = self .utxos [0 ]
712
710
@@ -733,16 +731,18 @@ def test_invalid_tx_in_compactblock(self, node, test_node, use_segwit):
733
731
734
732
# Helper for enabling cb announcements
735
733
# Send the sendcmpct request and sync headers
736
- def request_cb_announcements (self , peer , node , version ):
734
+ def request_cb_announcements (self , peer ):
735
+ node = self .nodes [0 ]
737
736
tip = node .getbestblockhash ()
738
737
peer .get_headers (locator = [int (tip , 16 )], hashstop = 0 )
739
738
740
739
msg = msg_sendcmpct ()
741
- msg .version = version
740
+ msg .version = peer . cmpct_version
742
741
msg .announce = True
743
742
peer .send_and_ping (msg )
744
743
745
- def test_compactblock_reconstruction_multiple_peers (self , node , stalling_peer , delivery_peer ):
744
+ def test_compactblock_reconstruction_multiple_peers (self , stalling_peer , delivery_peer ):
745
+ node = self .nodes [0 ]
746
746
assert len (self .utxos )
747
747
748
748
def announce_cmpct_block (node , peer ):
@@ -793,126 +793,55 @@ def announce_cmpct_block(node, peer):
793
793
794
794
def run_test (self ):
795
795
# Setup the p2p connections
796
- self .test_node = self .nodes [0 ].add_p2p_connection (TestP2PConn ())
797
- self .segwit_node = self .nodes [1 ].add_p2p_connection (TestP2PConn (), services = NODE_NETWORK | NODE_WITNESS )
798
- self .old_node = self .nodes [1 ].add_p2p_connection (TestP2PConn (), services = NODE_NETWORK )
796
+ self .segwit_node = self .nodes [0 ].add_p2p_connection (TestP2PConn (cmpct_version = 2 ))
797
+ self .old_node = self .nodes [0 ].add_p2p_connection (TestP2PConn (cmpct_version = 1 ), services = NODE_NETWORK )
798
+ self .additional_segwit_node = self .nodes [0 ].add_p2p_connection (TestP2PConn (cmpct_version = 2 ) )
799
799
800
800
# We will need UTXOs to construct transactions in later tests.
801
801
self .make_utxos ()
802
802
803
- self .log . info ( "Running tests, pre- segwit activation:" )
803
+ assert_equal ( get_bip9_status ( self .nodes [ 0 ], " segwit" )[ "status" ], 'active' )
804
804
805
805
self .log .info ("Testing SENDCMPCT p2p message... " )
806
- self .test_sendcmpct (self .nodes [0 ], self .test_node , 1 )
807
- sync_blocks (self .nodes )
808
- self .test_sendcmpct (self .nodes [1 ], self .segwit_node , 2 , old_node = self .old_node )
809
- sync_blocks (self .nodes )
810
-
811
- self .log .info ("Testing compactblock construction..." )
812
- self .test_compactblock_construction (self .nodes [0 ], self .test_node , 1 , False )
813
- sync_blocks (self .nodes )
814
- self .test_compactblock_construction (self .nodes [1 ], self .segwit_node , 2 , False )
815
- sync_blocks (self .nodes )
816
-
817
- self .log .info ("Testing compactblock requests... " )
818
- self .test_compactblock_requests (self .nodes [0 ], self .test_node , 1 , False )
819
- sync_blocks (self .nodes )
820
- self .test_compactblock_requests (self .nodes [1 ], self .segwit_node , 2 , False )
821
- sync_blocks (self .nodes )
822
-
823
- self .log .info ("Testing getblocktxn requests..." )
824
- self .test_getblocktxn_requests (self .nodes [0 ], self .test_node , 1 )
825
- sync_blocks (self .nodes )
826
- self .test_getblocktxn_requests (self .nodes [1 ], self .segwit_node , 2 )
827
- sync_blocks (self .nodes )
828
-
829
- self .log .info ("Testing getblocktxn handler..." )
830
- self .test_getblocktxn_handler (self .nodes [0 ], self .test_node , 1 )
831
- sync_blocks (self .nodes )
832
- self .test_getblocktxn_handler (self .nodes [1 ], self .segwit_node , 2 )
833
- self .test_getblocktxn_handler (self .nodes [1 ], self .old_node , 1 )
834
- sync_blocks (self .nodes )
835
-
836
- self .log .info ("Testing compactblock requests/announcements not at chain tip..." )
837
- self .test_compactblocks_not_at_tip (self .nodes [0 ], self .test_node )
838
- sync_blocks (self .nodes )
839
- self .test_compactblocks_not_at_tip (self .nodes [1 ], self .segwit_node )
840
- self .test_compactblocks_not_at_tip (self .nodes [1 ], self .old_node )
841
- sync_blocks (self .nodes )
842
-
843
- self .log .info ("Testing handling of incorrect blocktxn responses..." )
844
- self .test_incorrect_blocktxn_response (self .nodes [0 ], self .test_node , 1 )
845
- sync_blocks (self .nodes )
846
- self .test_incorrect_blocktxn_response (self .nodes [1 ], self .segwit_node , 2 )
847
- sync_blocks (self .nodes )
848
-
849
- # End-to-end block relay tests
850
- self .log .info ("Testing end-to-end block relay..." )
851
- self .request_cb_announcements (self .test_node , self .nodes [0 ], 1 )
852
- self .request_cb_announcements (self .old_node , self .nodes [1 ], 1 )
853
- self .request_cb_announcements (self .segwit_node , self .nodes [1 ], 2 )
854
- self .test_end_to_end_block_relay (self .nodes [0 ], [self .segwit_node , self .test_node , self .old_node ])
855
- self .test_end_to_end_block_relay (self .nodes [1 ], [self .segwit_node , self .test_node , self .old_node ])
856
-
857
- self .log .info ("Testing handling of invalid compact blocks..." )
858
- self .test_invalid_tx_in_compactblock (self .nodes [0 ], self .test_node , False )
859
- self .test_invalid_tx_in_compactblock (self .nodes [1 ], self .segwit_node , False )
860
- self .test_invalid_tx_in_compactblock (self .nodes [1 ], self .old_node , False )
861
-
862
- self .log .info ("Testing reconstructing compact blocks from all peers..." )
863
- self .test_compactblock_reconstruction_multiple_peers (self .nodes [1 ], self .segwit_node , self .old_node )
864
- sync_blocks (self .nodes )
865
-
866
- # Advance to segwit activation
867
- self .log .info ("Advancing to segwit activation" )
868
- self .activate_segwit (self .nodes [1 ])
869
- self .log .info ("Running tests, post-segwit activation..." )
806
+ self .test_sendcmpct (self .segwit_node , old_node = self .old_node )
807
+ self .test_sendcmpct (self .additional_segwit_node )
870
808
871
809
self .log .info ("Testing compactblock construction..." )
872
- self .test_compactblock_construction (self .nodes [1 ], self .old_node , 1 , True )
873
- self .test_compactblock_construction (self .nodes [1 ], self .segwit_node , 2 , True )
874
- sync_blocks (self .nodes )
875
-
876
- self .log .info ("Testing compactblock requests (unupgraded node)... " )
877
- self .test_compactblock_requests (self .nodes [0 ], self .test_node , 1 , True )
878
-
879
- self .log .info ("Testing getblocktxn requests (unupgraded node)..." )
880
- self .test_getblocktxn_requests (self .nodes [0 ], self .test_node , 1 )
881
-
882
- # Need to manually sync node0 and node1, because post-segwit activation,
883
- # node1 will not download blocks from node0.
884
- self .log .info ("Syncing nodes..." )
885
- assert self .nodes [0 ].getbestblockhash () != self .nodes [1 ].getbestblockhash ()
886
- while (self .nodes [0 ].getblockcount () > self .nodes [1 ].getblockcount ()):
887
- block_hash = self .nodes [0 ].getblockhash (self .nodes [1 ].getblockcount () + 1 )
888
- self .nodes [1 ].submitblock (self .nodes [0 ].getblock (block_hash , False ))
889
- assert_equal (self .nodes [0 ].getbestblockhash (), self .nodes [1 ].getbestblockhash ())
810
+ self .test_compactblock_construction (self .old_node )
811
+ self .test_compactblock_construction (self .segwit_node )
890
812
891
813
self .log .info ("Testing compactblock requests (segwit node)... " )
892
- self .test_compactblock_requests (self .nodes [ 1 ], self . segwit_node , 2 , True )
814
+ self .test_compactblock_requests (self .segwit_node )
893
815
894
816
self .log .info ("Testing getblocktxn requests (segwit node)..." )
895
- self .test_getblocktxn_requests (self .nodes [1 ], self .segwit_node , 2 )
896
- sync_blocks (self .nodes )
817
+ self .test_getblocktxn_requests (self .segwit_node )
897
818
898
819
self .log .info ("Testing getblocktxn handler (segwit node should return witnesses)..." )
899
- self .test_getblocktxn_handler (self .nodes [1 ], self .segwit_node , 2 )
900
- self .test_getblocktxn_handler (self .nodes [1 ], self .old_node , 1 )
820
+ self .test_getblocktxn_handler (self .segwit_node )
821
+ self .test_getblocktxn_handler (self .old_node )
822
+
823
+ self .log .info ("Testing compactblock requests/announcements not at chain tip..." )
824
+ self .test_compactblocks_not_at_tip (self .segwit_node )
825
+ self .test_compactblocks_not_at_tip (self .old_node )
826
+
827
+ self .log .info ("Testing handling of incorrect blocktxn responses..." )
828
+ self .test_incorrect_blocktxn_response (self .segwit_node )
829
+
830
+ self .log .info ("Testing reconstructing compact blocks from all peers..." )
831
+ self .test_compactblock_reconstruction_multiple_peers (self .segwit_node , self .additional_segwit_node )
901
832
902
833
# Test that if we submitblock to node1, we'll get a compact block
903
834
# announcement to all peers.
904
835
# (Post-segwit activation, blocks won't propagate from node0 to node1
905
836
# automatically, so don't bother testing a block announced to node0.)
906
837
self .log .info ("Testing end-to-end block relay..." )
907
- self .request_cb_announcements (self .test_node , self .nodes [0 ], 1 )
908
- self .request_cb_announcements (self .old_node , self .nodes [1 ], 1 )
909
- self .request_cb_announcements (self .segwit_node , self .nodes [1 ], 2 )
910
- self .test_end_to_end_block_relay (self .nodes [1 ], [self .segwit_node , self .test_node , self .old_node ])
838
+ self .request_cb_announcements (self .old_node )
839
+ self .request_cb_announcements (self .segwit_node )
840
+ self .test_end_to_end_block_relay ([self .segwit_node , self .old_node ])
911
841
912
842
self .log .info ("Testing handling of invalid compact blocks..." )
913
- self .test_invalid_tx_in_compactblock (self .nodes [0 ], self .test_node , False )
914
- self .test_invalid_tx_in_compactblock (self .nodes [1 ], self .segwit_node , True )
915
- self .test_invalid_tx_in_compactblock (self .nodes [1 ], self .old_node , True )
843
+ self .test_invalid_tx_in_compactblock (self .segwit_node )
844
+ self .test_invalid_tx_in_compactblock (self .old_node )
916
845
917
846
self .log .info ("Testing invalid index in cmpctblock message..." )
918
847
self .test_invalid_cmpctblock_message ()
0 commit comments