2016-03-19 20:58:06 +01:00
#!/usr/bin/env python3
2024-08-27 10:27:40 +02:00
# Copyright (c) 2015-present The Bitcoin Core developers
2016-03-19 20:58:06 +01:00
# Distributed under the MIT software license, see the accompanying
2015-04-28 12:39:47 -04:00
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-01-17 18:34:40 -05:00
""" Utilities for manipulating blocks and transactions. """
2015-04-28 12:39:47 -04:00
2016-01-12 19:44:01 +00:00
import struct
import time
2020-05-27 10:05:34 -07:00
import unittest
2017-09-14 11:41:30 -04:00
from . address import (
2025-04-17 09:19:21 +02:00
# address_to_scriptpubkey,
2017-09-14 11:41:30 -04:00
key_to_p2sh_p2wpkh ,
key_to_p2wpkh ,
script_to_p2sh_p2wsh ,
script_to_p2wsh ,
)
2018-04-20 14:10:12 -04:00
from . messages import (
CBlock ,
COIN ,
COutPoint ,
CTransaction ,
CTxIn ,
CTxInWitness ,
CTxOut ,
2019-03-20 11:22:45 +00:00
CTxOutValue ,
2022-01-11 02:08:01 +01:00
SEQUENCE_FINAL ,
2018-04-20 14:10:12 -04:00
hash256 ,
ser_uint256 ,
2021-06-15 23:02:28 +02:00
tx_from_hex ,
2025-01-03 10:54:45 +01:00
uint256_from_compact ,
2018-04-20 14:10:12 -04:00
uint256_from_str ,
2018-12-11 10:58:56 -05:00
CProof ,
2024-05-03 10:30:50 +01:00
WITNESS_SCALE_FACTOR ,
2018-04-20 14:10:12 -04:00
)
2017-09-14 11:41:30 -04:00
from . script import (
CScript ,
2018-10-12 14:47:35 -04:00
CScriptNum ,
2019-07-09 11:58:43 -04:00
CScriptOp ,
2025-01-08 19:03:30 +01:00
OP_0 ,
2017-09-14 11:41:30 -04:00
OP_RETURN ,
OP_TRUE ,
2021-06-28 20:45:04 +02:00
)
from . script_util import (
2021-09-28 13:37:46 +02:00
key_to_p2pk_script ,
2021-06-28 20:45:04 +02:00
key_to_p2wpkh_script ,
2021-10-18 22:25:04 +02:00
keys_to_multisig_script ,
2021-06-28 20:45:04 +02:00
script_to_p2wsh_script ,
2017-09-14 11:41:30 -04:00
)
from . util import assert_equal
2015-04-28 12:39:47 -04:00
2018-10-08 04:56:39 -04:00
MAX_BLOCK_SIGOPS = 20000
2020-09-13 22:20:17 -07:00
MAX_BLOCK_SIGOPS_WEIGHT = MAX_BLOCK_SIGOPS * WITNESS_SCALE_FACTOR
2024-02-29 12:43:52 +01:00
MAX_STANDARD_TX_WEIGHT = 400000
2018-10-08 04:56:39 -04:00
2019-02-11 11:59:34 -05:00
# Genesis block time (regtest)
TIME_GENESIS_BLOCK = 1296688602
2021-11-30 16:03:55 +01:00
MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60
2021-05-17 16:38:02 +02:00
# Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
COINBASE_MATURITY = 100
2018-04-20 14:16:57 -04:00
# From BIP141
WITNESS_COMMITMENT_HEADER = b " \xaa \x21 \xa9 \xed "
2016-01-12 19:44:01 +00:00
NORMAL_GBT_REQUEST_PARAMS = { " rules " : [ " segwit " ] }
2019-07-03 16:14:55 +02:00
VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4
2022-11-27 11:03:04 +01:00
MIN_BLOCKS_TO_KEEP = 288
2019-02-11 11:59:34 -05:00
2018-10-12 14:47:35 -04:00
# Assumes a BIP34 valid commitment exists
def get_coinbase_height ( coinbase ) :
2020-11-09 21:20:12 +00:00
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 )
2018-10-12 14:47:35 -04:00
2024-12-31 14:48:40 +01:00
REGTEST_RETARGET_PERIOD = 150
2025-01-08 13:13:08 +01:00
REGTEST_N_BITS = 0x207fffff # difficulty retargeting is disabled in REGTEST chainparams"
2025-01-03 10:54:45 +01:00
REGTEST_TARGET = 0x7fffff0000000000000000000000000000000000000000000000000000000000
assert_equal ( uint256_from_compact ( REGTEST_N_BITS ) , REGTEST_TARGET )
2025-01-08 13:13:08 +01:00
2024-12-31 14:48:40 +01:00
DIFF_1_N_BITS = 0x1d00ffff
DIFF_1_TARGET = 0x00000000ffff0000000000000000000000000000000000000000000000000000
assert_equal ( uint256_from_compact ( DIFF_1_N_BITS ) , DIFF_1_TARGET )
DIFF_4_N_BITS = 0x1c3fffc0
DIFF_4_TARGET = int ( DIFF_1_TARGET / 4 )
assert_equal ( uint256_from_compact ( DIFF_4_N_BITS ) , DIFF_4_TARGET )
2025-01-08 13:13:08 +01:00
def nbits_str ( nbits ) :
return f " { nbits : 08x } "
2016-01-12 19:44:01 +00:00
2025-01-03 10:54:45 +01:00
def target_str ( target ) :
return f " { target : 064x } "
2016-01-12 19:44:01 +00:00
def create_block ( hashprev = None , coinbase = None , ntime = None , * , version = None , tmpl = None , txlist = None ) :
2018-04-20 14:16:57 -04:00
""" Create a block (with regtest difficulty). """
2015-04-28 12:39:47 -04:00
block = CBlock ( )
2016-01-12 19:44:01 +00:00
if tmpl is None :
tmpl = { }
2019-07-03 16:14:55 +02:00
block . nVersion = version or tmpl . get ( ' version ' ) or VERSIONBITS_LAST_OLD_BLOCK_VERSION
2016-01-12 19:44:01 +00:00
block . nTime = ntime or tmpl . get ( ' curtime ' ) or int ( time . time ( ) + 600 )
block . hashPrevBlock = hashprev or int ( tmpl [ ' previousblockhash ' ] , 0x10 )
2025-04-17 09:19:21 +02:00
if tmpl and tmpl . get ( ' bits ' ) is not None :
2021-08-04 19:59:06 +01:00
block . nBits = struct . unpack ( ' >I ' , bytes . fromhex ( tmpl [ ' bits ' ] ) ) [ 0 ]
2015-04-28 12:39:47 -04:00
else :
2025-01-08 13:13:08 +01:00
block . nBits = REGTEST_N_BITS
2016-01-12 19:44:01 +00:00
if coinbase is None :
coinbase = create_coinbase ( height = tmpl [ ' height ' ] )
2015-04-28 12:39:47 -04:00
block . vtx . append ( coinbase )
2018-12-11 10:58:56 -05:00
block . proof = CProof ( bytearray . fromhex ( ' 51 ' ) , bytearray . fromhex ( ' ' ) )
2020-12-01 05:14:13 +00:00
block . block_height = get_coinbase_height ( coinbase )
2016-01-12 19:44:01 +00:00
if txlist :
for tx in txlist :
if not hasattr ( tx , ' calc_sha256 ' ) :
2021-06-15 23:02:28 +02:00
tx = tx_from_hex ( tx )
2016-01-12 19:44:01 +00:00
block . vtx . append ( tx )
2015-04-28 12:39:47 -04:00
block . hashMerkleRoot = block . calc_merkle_root ( )
block . calc_sha256 ( )
return block
2017-04-17 09:23:44 -07:00
def get_witness_script ( witness_root , witness_nonce ) :
2018-04-20 14:10:12 -04:00
witness_commitment = uint256_from_str ( hash256 ( ser_uint256 ( witness_root ) + ser_uint256 ( witness_nonce ) ) )
2017-04-17 09:23:44 -07:00
output_data = WITNESS_COMMITMENT_HEADER + ser_uint256 ( witness_commitment )
return CScript ( [ OP_RETURN , output_data ] )
2016-04-08 21:02:24 -04:00
def add_witness_commitment ( block , nonce = 0 ) :
2018-04-20 14:16:57 -04:00
""" Add a witness commitment to the block ' s coinbase transaction.
According to BIP141 , blocks with witness rules active must commit to the
hash of all in - block transactions including witness . """
2016-04-08 21:02:24 -04:00
# First calculate the merkle root of the block's
# transactions, with witnesses.
witness_nonce = nonce
2019-03-20 11:22:45 +00:00
# ELEMENTS: add empty txout to end of coinbase tx
block . vtx [ 0 ] . vout . append ( CTxOut ( ) )
# block.vtx[0].vout[-1].nAsset.setNull() # TODO find out why this breaks stuff
# unless you directly put back in a valid .vchCommitment
witness_root_hex = block . calc_witness_merkle_root ( )
2023-04-03 19:31:50 +00:00
witness_root = uint256_from_str ( bytes . fromhex ( witness_root_hex ) [ : : - 1 ] )
2016-04-08 21:02:24 -04:00
# witness_nonce should go to coinbase witness.
2016-07-06 19:46:46 -04:00
block . vtx [ 0 ] . wit . vtxinwit = [ CTxInWitness ( ) ]
2016-04-08 21:02:24 -04:00
block . vtx [ 0 ] . wit . vtxinwit [ 0 ] . scriptWitness . stack = [ ser_uint256 ( witness_nonce ) ]
# witness commitment is the last OP_RETURN output in coinbase
2019-03-20 11:22:45 +00:00
block . vtx [ 0 ] . vout [ - 1 ] = CTxOut ( 0 , get_witness_script ( witness_root , witness_nonce ) )
2016-04-08 21:02:24 -04:00
block . vtx [ 0 ] . rehash ( )
block . hashMerkleRoot = block . calc_merkle_root ( )
block . rehash ( )
2019-07-09 11:58:43 -04:00
def script_BIP34_coinbase_height ( height ) :
if height < = 16 :
res = CScriptOp . encode_op_n ( height )
2025-01-08 19:03:30 +01:00
# Append dummy to increase scriptSig size to 2 (see bad-cb-length consensus rule)
return CScript ( [ res , OP_0 ] )
2019-07-09 11:58:43 -04:00
return CScript ( [ CScriptNum ( height ) ] )
2015-04-28 12:39:47 -04:00
2026-07-07 14:24:24 +01:00
def create_coinbase ( height , pubkey = None , * , script_pubkey = None , extra_output_script = None , fees = 0 , nValue = 50 , retarget_period = REGTEST_RETARGET_PERIOD ) : # noqa: unused - used by mining_mainnet.py currently disabled
2020-09-13 22:20:17 -07:00
""" Create a coinbase transaction.
2018-04-20 14:16:57 -04:00
If pubkey is passed in , the coinbase output will be a P2PK output ;
2020-09-13 22:20:17 -07:00
otherwise an anyone - can - spend output .
If extra_output_script is given , make a 0 - value output to that
script . This is useful to pad block weight / sigops as needed . """
2015-04-28 12:39:47 -04:00
coinbase = CTransaction ( )
2022-01-11 02:08:01 +01:00
coinbase . vin . append ( CTxIn ( COutPoint ( 0 , 0xffffffff ) , script_BIP34_coinbase_height ( height ) , SEQUENCE_FINAL ) )
2015-04-28 12:39:47 -04:00
coinbaseoutput = CTxOut ( )
2021-07-04 19:51:38 +00:00
value = nValue * COIN
2020-08-22 18:51:45 +02:00
if nValue == 50 :
halvings = int ( height / 150 ) # regtest
2021-07-04 19:51:38 +00:00
value >> = halvings
value + = fees
2019-03-20 11:22:45 +00:00
coinbaseoutput . nValue = CTxOutValue ( value )
2020-09-13 22:20:17 -07:00
if pubkey is not None :
2021-09-28 13:37:46 +02:00
coinbaseoutput . scriptPubKey = key_to_p2pk_script ( pubkey )
2022-10-02 18:21:41 +02:00
elif script_pubkey is not None :
coinbaseoutput . scriptPubKey = script_pubkey
2015-08-05 17:47:34 -04:00
else :
coinbaseoutput . scriptPubKey = CScript ( [ OP_TRUE ] )
2018-04-20 14:10:12 -04:00
coinbase . vout = [ coinbaseoutput ]
2020-09-13 22:20:17 -07:00
if extra_output_script is not None :
coinbaseoutput2 = CTxOut ( )
2020-12-01 02:54:57 +00:00
coinbaseoutput2 . nValue = CTxOutValue ( 0 )
2020-09-13 22:20:17 -07:00
coinbaseoutput2 . scriptPubKey = extra_output_script
coinbase . vout . append ( coinbaseoutput2 )
2015-04-28 12:39:47 -04:00
coinbase . calc_sha256 ( )
return coinbase
2026-03-11 00:30:13 +00:00
def create_tx_with_script ( prevtx , n , script_sig = b " " , * , amount , fee = 0 , output_script = None ) :
2018-07-30 10:16:40 +02:00
""" Return one-input, one-output transaction object
spending the prevtx ' s n-th output with the given amount.
2018-04-20 14:16:57 -04:00
2018-08-14 09:27:30 +02:00
Can optionally pass scriptPubKey and scriptSig , default is anyone - can - spend output .
2018-07-30 10:16:40 +02:00
"""
2024-07-31 10:13:10 +02:00
if output_script is None :
output_script = CScript ( )
2015-04-28 12:39:47 -04:00
tx = CTransaction ( )
2019-02-19 17:43:44 -05:00
assert n < len ( prevtx . vout )
2022-01-11 02:08:01 +01:00
tx . vin . append ( CTxIn ( COutPoint ( prevtx . sha256 , n ) , script_sig , SEQUENCE_FINAL ) )
2024-07-31 10:13:10 +02:00
tx . vout . append ( CTxOut ( amount , output_script ) )
2019-03-20 11:22:45 +00:00
if fee > 0 :
tx . vout . append ( CTxOut ( fee ) )
2015-04-28 12:39:47 -04:00
tx . calc_sha256 ( )
return tx
2016-06-02 14:42:09 -04:00
2018-04-20 14:10:12 -04:00
def get_legacy_sigopcount_block ( block , accurate = True ) :
2016-06-02 14:42:09 -04:00
count = 0
for tx in block . vtx :
2018-04-20 14:10:12 -04:00
count + = get_legacy_sigopcount_tx ( tx , accurate )
2016-06-02 14:42:09 -04:00
return count
2018-04-20 14:10:12 -04:00
def get_legacy_sigopcount_tx ( tx , accurate = True ) :
2016-06-02 14:42:09 -04:00
count = 0
for i in tx . vout :
2019-03-20 11:22:45 +00:00
count + = CScript ( i . scriptPubKey ) . GetSigOpCount ( accurate )
2016-06-02 14:42:09 -04:00
for j in tx . vin :
# scriptSig might be of type bytes, so convert to CScript for the moment
2018-04-20 14:10:12 -04:00
count + = CScript ( j . scriptSig ) . GetSigOpCount ( accurate )
2016-06-02 14:42:09 -04:00
return count
2017-09-14 11:41:30 -04:00
def witness_script ( use_p2wsh , pubkey ) :
2018-10-09 22:18:34 +09:00
""" Create a scriptPubKey for a pay-to-witness TxOut.
2018-04-20 14:16:57 -04:00
This is either a P2WPKH output for the given pubkey , or a P2WSH output of a
1 - of - 1 multisig for the given pubkey . Returns the hex encoding of the
scriptPubKey . """
2018-04-20 14:10:12 -04:00
if not use_p2wsh :
2017-09-14 11:41:30 -04:00
# P2WPKH instead
2021-06-28 20:45:04 +02:00
pkscript = key_to_p2wpkh_script ( pubkey )
2017-09-14 11:41:30 -04:00
else :
# 1-of-1 multisig
2021-10-18 22:25:04 +02:00
witness_script = keys_to_multisig_script ( [ pubkey ] )
2021-07-11 15:51:48 +02:00
pkscript = script_to_p2wsh_script ( witness_script )
2019-02-18 10:35:48 -05:00
return pkscript . hex ( )
2017-09-14 11:41:30 -04:00
def create_witness_tx ( node , use_p2wsh , utxo , pubkey , encode_p2sh , amount ) :
2018-04-20 14:16:57 -04:00
""" Return a transaction (in hex) that spends the given utxo to a segwit output.
Optionally wrap the segwit output using P2SH . """
2017-09-14 11:41:30 -04:00
if use_p2wsh :
2021-10-18 22:25:04 +02:00
program = keys_to_multisig_script ( [ pubkey ] )
2017-09-14 11:41:30 -04:00
addr = script_to_p2sh_p2wsh ( program ) if encode_p2sh else script_to_p2wsh ( program )
else :
addr = key_to_p2sh_p2wpkh ( pubkey ) if encode_p2sh else key_to_p2wpkh ( pubkey )
if not encode_p2sh :
2018-02-09 11:12:27 -05:00
assert_equal ( node . getaddressinfo ( addr ) [ ' scriptPubKey ' ] , witness_script ( use_p2wsh , pubkey ) )
2019-02-27 15:06:47 +00:00
if " amount " not in utxo :
utxo [ " amount " ] = node . gettxout ( utxo [ " txid " ] , utxo [ " vout " ] ) [ " value " ]
2021-04-21 14:55:38 -04:00
return node . createrawtransaction ( [ utxo ] , [ { addr : amount } , { " fee " : utxo [ " amount " ] - amount } ] )
2017-09-14 11:41:30 -04:00
def send_to_witness ( use_p2wsh , node , utxo , pubkey , encode_p2sh , amount , sign = True , insert_redeem_script = " " ) :
2018-04-20 14:16:57 -04:00
""" Create a transaction spending a given utxo to a segwit output.
The output corresponds to the given pubkey : use_p2wsh determines whether to
use P2WPKH or P2WSH ; encode_p2sh determines whether to wrap in P2SH .
sign = True will have the given node sign the transaction .
insert_redeem_script will be added to the scriptSig , if given . """
2017-09-14 11:41:30 -04:00
tx_to_witness = create_witness_tx ( node , use_p2wsh , utxo , pubkey , encode_p2sh , amount )
if ( sign ) :
2017-09-05 16:49:18 -07:00
signed = node . signrawtransactionwithwallet ( tx_to_witness )
2019-02-19 17:43:44 -05:00
assert " errors " not in signed or len ( [ " errors " ] ) == 0
2017-09-14 11:41:30 -04:00
return node . sendrawtransaction ( signed [ " hex " ] )
else :
if ( insert_redeem_script ) :
2021-06-15 23:02:28 +02:00
tx = tx_from_hex ( tx_to_witness )
2021-07-31 21:23:16 +02:00
tx . vin [ 0 ] . scriptSig + = CScript ( [ bytes . fromhex ( insert_redeem_script ) ] )
2021-06-16 00:32:18 +02:00
tx_to_witness = tx . serialize ( ) . hex ( )
2017-09-14 11:41:30 -04:00
return node . sendrawtransaction ( tx_to_witness )
2020-05-27 10:05:34 -07:00
class TestFrameworkBlockTools ( unittest . TestCase ) :
def test_create_coinbase ( self ) :
height = 20
coinbase_tx = create_coinbase ( height = height )
assert_equal ( CScriptNum . decode ( coinbase_tx . vin [ 0 ] . scriptSig ) , height )