@@ -74,6 +74,10 @@ def serialize(self, with_witness=False):
7474 def normal_serialize (self ):
7575 return super ().serialize ()
7676
77+
78+ DUPLICATE_COINBASE_SCRIPT_SIG = b'\x01 \x78 ' # Valid for block at height 120
79+
80+
7781class FullBlockTest (BitcoinTestFramework ):
7882 def set_test_params (self ):
7983 self .num_nodes = 1
@@ -96,6 +100,13 @@ def run_test(self):
96100 self .spendable_outputs = []
97101
98102 # Create a new block
103+ b_dup_cb = self .next_block ('dup_cb' )
104+ b_dup_cb .vtx [0 ].vin [0 ].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
105+ b_dup_cb .vtx [0 ].rehash ()
106+ duplicate_tx = b_dup_cb .vtx [0 ]
107+ b_dup_cb = self .update_block ('dup_cb' , [])
108+ self .send_blocks ([b_dup_cb ])
109+
99110 b0 = self .next_block (0 )
100111 self .save_spendable_output ()
101112 self .send_blocks ([b0 ])
@@ -750,7 +761,7 @@ def run_test(self):
750761
751762 # Test a few invalid tx types
752763 #
753- # -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17 )
764+ # -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 ()
754765 # \-> ??? (17)
755766 #
756767
@@ -776,35 +787,59 @@ def run_test(self):
776787
777788 # reset to good chain
778789 self .move_tip (57 )
779- b60 = self .next_block (60 , spend = out [ 17 ] )
790+ b60 = self .next_block (60 )
780791 self .send_blocks ([b60 ], True )
781792 self .save_spendable_output ()
782793
783- # Test BIP30
794+ # Test BIP30 (reject duplicate)
784795 #
785- # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17 )
786- # \-> b61 (18 )
796+ # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 ()
797+ # \-> b61 ()
787798 #
788799 # Blocks are not allowed to contain a transaction whose id matches that of an earlier,
789800 # not-fully-spent transaction in the same chain. To test, make identical coinbases;
790801 # the second one should be rejected.
791802 #
792803 self .log .info ("Reject a block with a transaction with a duplicate hash of a previous transaction (BIP30)" )
793804 self .move_tip (60 )
794- b61 = self .next_block (61 , spend = out [ 18 ] )
795- b61 .vtx [0 ].vin [0 ].scriptSig = b60 . vtx [ 0 ]. vin [ 0 ]. scriptSig # Equalize the coinbases
805+ b61 = self .next_block (61 )
806+ b61 .vtx [0 ].vin [0 ].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
796807 b61 .vtx [0 ].rehash ()
797808 b61 = self .update_block (61 , [])
798- assert_equal (b60 . vtx [ 0 ] .serialize (), b61 .vtx [0 ].serialize ())
809+ assert_equal (duplicate_tx .serialize (), b61 .vtx [0 ].serialize ())
799810 self .send_blocks ([b61 ], success = False , reject_reason = 'bad-txns-BIP30' , reconnect = True )
800811
812+ # Test BIP30 (allow duplicate if spent)
813+ #
814+ # -> b57 (16) -> b60 ()
815+ # \-> b_spend_dup_cb (b_dup_cb) -> b_dup_2 ()
816+ #
817+ self .move_tip (57 )
818+ b_spend_dup_cb = self .next_block ('spend_dup_cb' )
819+ tx = CTransaction ()
820+ tx .vin .append (CTxIn (COutPoint (duplicate_tx .sha256 , 0 )))
821+ tx .vout .append (CTxOut (0 , CScript ([OP_TRUE ])))
822+ self .sign_tx (tx , duplicate_tx )
823+ tx .rehash ()
824+ b_spend_dup_cb = self .update_block ('spend_dup_cb' , [tx ])
825+
826+ b_dup_2 = self .next_block ('dup_2' )
827+ b_dup_2 .vtx [0 ].vin [0 ].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
828+ b_dup_2 .vtx [0 ].rehash ()
829+ b_dup_2 = self .update_block ('dup_2' , [])
830+ assert_equal (duplicate_tx .serialize (), b_dup_2 .vtx [0 ].serialize ())
831+ assert_equal (self .nodes [0 ].gettxout (txid = duplicate_tx .hash , n = 0 )['confirmations' ], 119 )
832+ self .send_blocks ([b_spend_dup_cb , b_dup_2 ], success = True )
833+ # The duplicate has less confirmations
834+ assert_equal (self .nodes [0 ].gettxout (txid = duplicate_tx .hash , n = 0 )['confirmations' ], 1 )
835+
801836 # Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests)
802837 #
803- # -> b39 (11 ) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17 )
804- # \-> b62 (18)
838+ # -> b_spend_dup_cb (b_dup_cb ) -> b_dup_2 ( )
839+ # \-> b62 (18)
805840 #
806841 self .log .info ("Reject a block with a transaction with a nonfinal locktime" )
807- self .move_tip (60 )
842+ self .move_tip ('dup_2' )
808843 b62 = self .next_block (62 )
809844 tx = CTransaction ()
810845 tx .nLockTime = 0xffffffff # this locktime is non-final
@@ -817,11 +852,11 @@ def run_test(self):
817852
818853 # Test a non-final coinbase is also rejected
819854 #
820- # -> b39 (11 ) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17 )
821- # \-> b63 (-)
855+ # -> b_spend_dup_cb (b_dup_cb ) -> b_dup_2 ( )
856+ # \-> b63 (-)
822857 #
823858 self .log .info ("Reject a block with a coinbase transaction with a nonfinal locktime" )
824- self .move_tip (60 )
859+ self .move_tip ('dup_2' )
825860 b63 = self .next_block (63 )
826861 b63 .vtx [0 ].nLockTime = 0xffffffff
827862 b63 .vtx [0 ].vin [0 ].nSequence = 0xDEADBEEF
@@ -837,14 +872,14 @@ def run_test(self):
837872 # What matters is that the receiving node should not reject the bloated block, and then reject the canonical
838873 # block on the basis that it's the same as an already-rejected block (which would be a consensus failure.)
839874 #
840- # -> b39 (11 ) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17 ) -> b64 (18)
841- # \
842- # b64a (18)
875+ # -> b_spend_dup_cb (b_dup_cb ) -> b_dup_2 ( ) -> b64 (18)
876+ # \
877+ # b64a (18)
843878 # b64a is a bloated block (non-canonical varint)
844879 # b64 is a good block (same as b64 but w/ canonical varint)
845880 #
846881 self .log .info ("Accept a valid block even if a bloated version of the block has previously been sent" )
847- self .move_tip (60 )
882+ self .move_tip ('dup_2' )
848883 regular_block = self .next_block ("64a" , spend = out [18 ])
849884
850885 # make it a "broken_block," with non-canonical serialization
@@ -870,7 +905,7 @@ def run_test(self):
870905 node .disconnect_p2ps ()
871906 self .reconnect_p2p ()
872907
873- self .move_tip (60 )
908+ self .move_tip ('dup_2' )
874909 b64 = CBlock (b64a )
875910 b64 .vtx = copy .deepcopy (b64a .vtx )
876911 assert_equal (b64 .hash , b64a .hash )
@@ -882,7 +917,7 @@ def run_test(self):
882917
883918 # Spend an output created in the block itself
884919 #
885- # -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17 ) -> b64 (18) -> b65 (19)
920+ # -> b_dup_2 ( ) -> b64 (18) -> b65 (19)
886921 #
887922 self .log .info ("Accept a block with a transaction spending an output created in the same block" )
888923 self .move_tip (64 )
@@ -895,8 +930,8 @@ def run_test(self):
895930
896931 # Attempt to spend an output created later in the same block
897932 #
898- # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
899- # \-> b66 (20)
933+ # -> b64 (18) -> b65 (19)
934+ # \-> b66 (20)
900935 self .log .info ("Reject a block with a transaction spending an output created later in the same block" )
901936 self .move_tip (65 )
902937 b66 = self .next_block (66 )
@@ -907,8 +942,8 @@ def run_test(self):
907942
908943 # Attempt to double-spend a transaction created in a block
909944 #
910- # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
911- # \-> b67 (20)
945+ # -> b64 (18) -> b65 (19)
946+ # \-> b67 (20)
912947 #
913948 #
914949 self .log .info ("Reject a block with a transaction double spending a transaction created in the same block" )
@@ -922,8 +957,8 @@ def run_test(self):
922957
923958 # More tests of block subsidy
924959 #
925- # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
926- # \-> b68 (20)
960+ # -> b64 (18) -> b65 (19) -> b69 (20)
961+ # \-> b68 (20)
927962 #
928963 # b68 - coinbase with an extra 10 satoshis,
929964 # creates a tx that has 9 satoshis from out[20] go to fees
@@ -949,8 +984,8 @@ def run_test(self):
949984
950985 # Test spending the outpoint of a non-existent transaction
951986 #
952- # -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
953- # \-> b70 (21)
987+ # -> b65 (19) -> b69 (20)
988+ # \-> b70 (21)
954989 #
955990 self .log .info ("Reject a block containing a transaction spending from a non-existent input" )
956991 self .move_tip (69 )
@@ -965,8 +1000,8 @@ def run_test(self):
9651000
9661001 # Test accepting an invalid block which has the same hash as a valid one (via merkle tree tricks)
9671002 #
968- # -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21)
969- # \-> b71 (21)
1003+ # -> b65 (19) -> b69 (20) -> b72 (21)
1004+ # \-> b71 (21)
9701005 #
9711006 # b72 is a good block.
9721007 # b71 is a copy of 72, but re-adds one of its transactions. However, it has the same hash as b72.
@@ -994,8 +1029,8 @@ def run_test(self):
9941029
9951030 # Test some invalid scripts and MAX_BLOCK_SIGOPS
9961031 #
997- # -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21)
998- # \-> b** (22)
1032+ # -> b69 (20) -> b72 (21)
1033+ # \-> b** (22)
9991034 #
10001035
10011036 # b73 - tx with excessive sigops that are placed after an excessively large script element.
0 commit comments