mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-15 12:51:00 +02:00
Merge 62117f9f36 into merged_master (Bitcoin PR #16363)
This commit is contained in:
commit
d576fc5aeb
2 changed files with 81 additions and 50 deletions
|
|
@ -73,6 +73,10 @@ class CBrokenBlock(CBlock):
|
|||
def normal_serialize(self):
|
||||
return super().serialize()
|
||||
|
||||
|
||||
DUPLICATE_COINBASE_SCRIPT_SIG = b'\x01\x78' # Valid for block at height 120
|
||||
|
||||
|
||||
class FullBlockTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
|
|
@ -95,6 +99,13 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
self.spendable_outputs = []
|
||||
|
||||
# Create a new block
|
||||
b_dup_cb = self.next_block('dup_cb')
|
||||
b_dup_cb.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
|
||||
b_dup_cb.vtx[0].rehash()
|
||||
duplicate_tx = b_dup_cb.vtx[0]
|
||||
b_dup_cb = self.update_block('dup_cb', [])
|
||||
self.send_blocks([b_dup_cb])
|
||||
|
||||
b0 = self.next_block(0)
|
||||
self.save_spendable_output()
|
||||
self.send_blocks([b0])
|
||||
|
|
@ -767,7 +778,7 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# Test a few invalid tx types
|
||||
#
|
||||
# -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
|
||||
# -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 ()
|
||||
# \-> ??? (17)
|
||||
#
|
||||
|
||||
|
|
@ -793,14 +804,14 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# reset to good chain
|
||||
self.move_tip(57)
|
||||
b60 = self.next_block(60, spend=out[17])
|
||||
b60 = self.next_block(60)
|
||||
self.send_blocks([b60], True)
|
||||
self.save_spendable_output()
|
||||
|
||||
# Test BIP30
|
||||
# Test BIP30 (reject duplicate)
|
||||
#
|
||||
# -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
|
||||
# \-> b61 (18)
|
||||
# -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 ()
|
||||
# \-> b61 ()
|
||||
#
|
||||
# Blocks are not allowed to contain a transaction whose id matches that of an earlier,
|
||||
# not-fully-spent transaction in the same chain. To test, make identical coinbases;
|
||||
|
|
@ -808,20 +819,44 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
#
|
||||
self.log.info("Reject a block with a transaction with a duplicate hash of a previous transaction (BIP30)")
|
||||
self.move_tip(60)
|
||||
b61 = self.next_block(61, spend=out[18])
|
||||
b61.vtx[0].vin[0].scriptSig = b60.vtx[0].vin[0].scriptSig # Equalize the coinbases
|
||||
b61 = self.next_block(61)
|
||||
b61.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
|
||||
b61.vtx[0].rehash()
|
||||
b61 = self.update_block(61, [])
|
||||
assert_equal(b60.vtx[0].serialize(), b61.vtx[0].serialize())
|
||||
assert_equal(duplicate_tx.serialize(), b61.vtx[0].serialize())
|
||||
self.send_blocks([b61], success=False, reject_reason='bad-txns-BIP30', reconnect=True)
|
||||
|
||||
# Test BIP30 (allow duplicate if spent)
|
||||
#
|
||||
# -> b57 (16) -> b60 ()
|
||||
# \-> b_spend_dup_cb (b_dup_cb) -> b_dup_2 ()
|
||||
#
|
||||
self.move_tip(57)
|
||||
b_spend_dup_cb = self.next_block('spend_dup_cb')
|
||||
tx = CTransaction()
|
||||
tx.vin.append(CTxIn(COutPoint(duplicate_tx.sha256, 0)))
|
||||
tx.vout.append(CTxOut(duplicate_tx.vout[0].nValue, CScript([OP_TRUE])))
|
||||
self.sign_tx(tx, duplicate_tx)
|
||||
tx.rehash()
|
||||
b_spend_dup_cb = self.update_block('spend_dup_cb', [tx])
|
||||
|
||||
b_dup_2 = self.next_block('dup_2')
|
||||
b_dup_2.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG
|
||||
b_dup_2.vtx[0].rehash()
|
||||
b_dup_2 = self.update_block('dup_2', [])
|
||||
assert_equal(duplicate_tx.serialize(), b_dup_2.vtx[0].serialize())
|
||||
assert_equal(self.nodes[0].gettxout(txid=duplicate_tx.hash, n=0)['confirmations'], 119)
|
||||
self.send_blocks([b_spend_dup_cb, b_dup_2], success=True)
|
||||
# The duplicate has less confirmations
|
||||
assert_equal(self.nodes[0].gettxout(txid=duplicate_tx.hash, n=0)['confirmations'], 1)
|
||||
|
||||
# Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests)
|
||||
#
|
||||
# -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
|
||||
# \-> b62 (18)
|
||||
# -> b_spend_dup_cb (b_dup_cb) -> b_dup_2 ()
|
||||
# \-> b62 (18)
|
||||
#
|
||||
self.log.info("Reject a block with a transaction with a nonfinal locktime")
|
||||
self.move_tip(60)
|
||||
self.move_tip('dup_2')
|
||||
b62 = self.next_block(62)
|
||||
tx = CTransaction()
|
||||
tx.nLockTime = 0xffffffff # this locktime is non-final
|
||||
|
|
@ -834,11 +869,11 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# Test a non-final coinbase is also rejected
|
||||
#
|
||||
# -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
|
||||
# \-> b63 (-)
|
||||
# -> b_spend_dup_cb (b_dup_cb) -> b_dup_2 ()
|
||||
# \-> b63 (-)
|
||||
#
|
||||
self.log.info("Reject a block with a coinbase transaction with a nonfinal locktime")
|
||||
self.move_tip(60)
|
||||
self.move_tip('dup_2')
|
||||
b63 = self.next_block(63)
|
||||
b63.vtx[0].nLockTime = 0xffffffff
|
||||
b63.vtx[0].vin[0].nSequence = 0xDEADBEEF
|
||||
|
|
@ -854,14 +889,14 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
# What matters is that the receiving node should not reject the bloated block, and then reject the canonical
|
||||
# block on the basis that it's the same as an already-rejected block (which would be a consensus failure.)
|
||||
#
|
||||
# -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18)
|
||||
# \
|
||||
# b64a (18)
|
||||
# -> b_spend_dup_cb (b_dup_cb) -> b_dup_2 () -> b64 (18)
|
||||
# \
|
||||
# b64a (18)
|
||||
# b64a is a bloated block (non-canonical varint)
|
||||
# b64 is a good block (same as b64 but w/ canonical varint)
|
||||
#
|
||||
self.log.info("Accept a valid block even if a bloated version of the block has previously been sent")
|
||||
self.move_tip(60)
|
||||
self.move_tip('dup_2')
|
||||
regular_block = self.next_block("64a", spend=out[18])
|
||||
|
||||
# make it a "broken_block," with non-canonical serialization
|
||||
|
|
@ -889,7 +924,7 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
node.disconnect_p2ps()
|
||||
self.reconnect_p2p()
|
||||
|
||||
self.move_tip(60)
|
||||
self.move_tip('dup_2')
|
||||
b64 = CBlock(b64a)
|
||||
b64.vtx = copy.deepcopy(b64a.vtx)
|
||||
assert_equal(b64.hash, b64a.hash)
|
||||
|
|
@ -901,7 +936,7 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# Spend an output created in the block itself
|
||||
#
|
||||
# -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
|
||||
# -> b_dup_2 () -> b64 (18) -> b65 (19)
|
||||
#
|
||||
self.log.info("Accept a block with a transaction spending an output created in the same block")
|
||||
self.move_tip(64)
|
||||
|
|
@ -915,8 +950,8 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# Attempt to spend an output created later in the same block
|
||||
#
|
||||
# -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
|
||||
# \-> b66 (20)
|
||||
# -> b64 (18) -> b65 (19)
|
||||
# \-> b66 (20)
|
||||
self.log.info("Reject a block with a transaction spending an output created later in the same block")
|
||||
self.move_tip(65)
|
||||
b66 = self.next_block(66)
|
||||
|
|
@ -927,8 +962,8 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# Attempt to double-spend a transaction created in a block
|
||||
#
|
||||
# -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
|
||||
# \-> b67 (20)
|
||||
# -> b64 (18) -> b65 (19)
|
||||
# \-> b67 (20)
|
||||
#
|
||||
#
|
||||
self.log.info("Reject a block with a transaction double spending a transaction created in the same block")
|
||||
|
|
@ -942,8 +977,8 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# More tests of block subsidy
|
||||
#
|
||||
# -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
|
||||
# \-> b68 (20)
|
||||
# -> b64 (18) -> b65 (19) -> b69 (20)
|
||||
# \-> b68 (20)
|
||||
#
|
||||
# b68 - coinbase with an extra 10 satoshis,
|
||||
# creates a tx that has 9 satoshis from out[20] go to fees
|
||||
|
|
@ -969,8 +1004,8 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# Test spending the outpoint of a non-existent transaction
|
||||
#
|
||||
# -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
|
||||
# \-> b70 (21)
|
||||
# -> b65 (19) -> b69 (20)
|
||||
# \-> b70 (21)
|
||||
#
|
||||
self.log.info("Reject a block containing a transaction spending from a non-existent input")
|
||||
self.move_tip(69)
|
||||
|
|
@ -985,8 +1020,8 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# Test accepting an invalid block which has the same hash as a valid one (via merkle tree tricks)
|
||||
#
|
||||
# -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21)
|
||||
# \-> b71 (21)
|
||||
# -> b65 (19) -> b69 (20) -> b72 (21)
|
||||
# \-> b71 (21)
|
||||
#
|
||||
# b72 is a good block.
|
||||
# b71 is a copy of 72, but re-adds one of its transactions. However, it has the same hash as b72.
|
||||
|
|
@ -1014,8 +1049,8 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
|
||||
# Test some invalid scripts and MAX_BLOCK_SIGOPS
|
||||
#
|
||||
# -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21)
|
||||
# \-> b** (22)
|
||||
# -> b69 (20) -> b72 (21)
|
||||
# \-> b** (22)
|
||||
#
|
||||
|
||||
# b73 - tx with excessive sigops that are placed after an excessively large script element.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ from .messages import (
|
|||
ToHex,
|
||||
hash256,
|
||||
hex_str_to_bytes,
|
||||
ser_string,
|
||||
ser_uint256,
|
||||
sha256,
|
||||
uint256_from_str,
|
||||
|
|
@ -32,6 +31,7 @@ from .messages import (
|
|||
from .script import (
|
||||
CScript,
|
||||
CScriptNum,
|
||||
CScriptOp,
|
||||
OP_0,
|
||||
OP_1,
|
||||
OP_CHECKMULTISIG,
|
||||
|
|
@ -53,7 +53,10 @@ WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
|
|||
|
||||
# Assumes a BIP34 valid commitment exists
|
||||
def get_coinbase_height(coinbase):
|
||||
return CScriptNum.decode(coinbase.vin[0].scriptSig)
|
||||
if CScriptOp.is_small_int(coinbase.vin[0].scriptSig[0]):
|
||||
return CScriptOp.decode_op_n(coinbase.vin[0].scriptSig[0])
|
||||
else:
|
||||
return CScriptNum.decode(coinbase.vin[0].scriptSig)
|
||||
|
||||
def create_block(hashprev, coinbase, ntime=None, *, version=1):
|
||||
"""Create a block (with regtest difficulty)."""
|
||||
|
|
@ -104,20 +107,14 @@ def add_witness_commitment(block, nonce=0):
|
|||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.rehash()
|
||||
|
||||
def serialize_script_num(value):
|
||||
r = bytearray(0)
|
||||
if value == 0:
|
||||
return r
|
||||
neg = value < 0
|
||||
absvalue = -value if neg else value
|
||||
while (absvalue):
|
||||
r.append(int(absvalue & 0xff))
|
||||
absvalue >>= 8
|
||||
if r[-1] & 0x80:
|
||||
r.append(0x80 if neg else 0)
|
||||
elif neg:
|
||||
r[-1] |= 0x80
|
||||
return r
|
||||
|
||||
def script_BIP34_coinbase_height(height):
|
||||
if height <= 16:
|
||||
res = CScriptOp.encode_op_n(height)
|
||||
# Append dummy to increase scriptSig size above 2 (see bad-cb-length consensus rule)
|
||||
return CScript([res, OP_1])
|
||||
return CScript([CScriptNum(height)])
|
||||
|
||||
|
||||
def create_coinbase(height, pubkey=None):
|
||||
"""Create a coinbase transaction, assuming no miner fees.
|
||||
|
|
@ -125,8 +122,7 @@ def create_coinbase(height, pubkey=None):
|
|||
If pubkey is passed in, the coinbase output will be a P2PK output;
|
||||
otherwise an anyone-can-spend output."""
|
||||
coinbase = CTransaction()
|
||||
coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff),
|
||||
ser_string(serialize_script_num(height)), 0xffffffff))
|
||||
coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff), script_BIP34_coinbase_height(height), 0xffffffff))
|
||||
coinbaseoutput = CTxOut()
|
||||
value = 50 * COIN
|
||||
halvings = int(height / 150) # regtest
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue