/ test / functional / test_framework / script_util.py
script_util.py
  1  #!/usr/bin/env python3
  2  # Copyright (c) 2019-2022 The Bitcoin Core developers
  3  # Distributed under the MIT software license, see the accompanying
  4  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5  """Useful Script constants and utils."""
  6  from test_framework.script import (
  7      CScript,
  8      CScriptOp,
  9      OP_0,
 10      OP_CHECKMULTISIG,
 11      OP_CHECKSIG,
 12      OP_DUP,
 13      OP_EQUAL,
 14      OP_EQUALVERIFY,
 15      OP_HASH160,
 16      OP_RETURN,
 17      hash160,
 18      sha256,
 19  )
 20  
 21  # To prevent a "tx-size-small" policy rule error, a transaction has to have a
 22  # non-witness size of at least 65 bytes (MIN_STANDARD_TX_NONWITNESS_SIZE in
 23  # src/policy/policy.h). Considering a Tx with the smallest possible single
 24  # input (blank, empty scriptSig), and with an output omitting the scriptPubKey,
 25  # we get to a minimum size of 60 bytes:
 26  #
 27  # Tx Skeleton: 4 [Version] + 1 [InCount] + 1 [OutCount] + 4 [LockTime] = 10 bytes
 28  # Blank Input: 32 [PrevTxHash] + 4 [Index] + 1 [scriptSigLen] + 4 [SeqNo] = 41 bytes
 29  # Output:      8 [Amount] + 1 [scriptPubKeyLen] = 9 bytes
 30  #
 31  # Hence, the scriptPubKey of the single output has to have a size of at
 32  # least 5 bytes.
 33  MIN_STANDARD_TX_NONWITNESS_SIZE = 65
 34  MIN_PADDING = MIN_STANDARD_TX_NONWITNESS_SIZE - 10 - 41 - 9
 35  assert MIN_PADDING == 5
 36  
 37  # This script cannot be spent, allowing dust output values under
 38  # standardness checks
 39  DUMMY_MIN_OP_RETURN_SCRIPT = CScript([OP_RETURN] + ([OP_0] * (MIN_PADDING - 1)))
 40  assert len(DUMMY_MIN_OP_RETURN_SCRIPT) == MIN_PADDING
 41  
 42  def key_to_p2pk_script(key):
 43      key = check_key(key)
 44      return CScript([key, OP_CHECKSIG])
 45  
 46  
 47  def keys_to_multisig_script(keys, *, k=None):
 48      n = len(keys)
 49      if k is None:  # n-of-n multisig by default
 50          k = n
 51      assert k <= n
 52      op_k = CScriptOp.encode_op_n(k)
 53      op_n = CScriptOp.encode_op_n(n)
 54      checked_keys = [check_key(key) for key in keys]
 55      return CScript([op_k] + checked_keys + [op_n, OP_CHECKMULTISIG])
 56  
 57  
 58  def keyhash_to_p2pkh_script(hash):
 59      assert len(hash) == 20
 60      return CScript([OP_DUP, OP_HASH160, hash, OP_EQUALVERIFY, OP_CHECKSIG])
 61  
 62  
 63  def scripthash_to_p2sh_script(hash):
 64      assert len(hash) == 20
 65      return CScript([OP_HASH160, hash, OP_EQUAL])
 66  
 67  
 68  def key_to_p2pkh_script(key):
 69      key = check_key(key)
 70      return keyhash_to_p2pkh_script(hash160(key))
 71  
 72  
 73  def script_to_p2sh_script(script):
 74      script = check_script(script)
 75      return scripthash_to_p2sh_script(hash160(script))
 76  
 77  
 78  def key_to_p2sh_p2wpkh_script(key):
 79      key = check_key(key)
 80      p2shscript = CScript([OP_0, hash160(key)])
 81      return script_to_p2sh_script(p2shscript)
 82  
 83  
 84  def program_to_witness_script(version, program):
 85      if isinstance(program, str):
 86          program = bytes.fromhex(program)
 87      assert 0 <= version <= 16
 88      assert 2 <= len(program) <= 40
 89      assert version > 0 or len(program) in [20, 32]
 90      return CScript([version, program])
 91  
 92  
 93  def script_to_p2wsh_script(script):
 94      script = check_script(script)
 95      return program_to_witness_script(0, sha256(script))
 96  
 97  
 98  def key_to_p2wpkh_script(key):
 99      key = check_key(key)
100      return program_to_witness_script(0, hash160(key))
101  
102  
103  def script_to_p2sh_p2wsh_script(script):
104      script = check_script(script)
105      p2shscript = CScript([OP_0, sha256(script)])
106      return script_to_p2sh_script(p2shscript)
107  
108  
109  def output_key_to_p2tr_script(key):
110      assert len(key) == 32
111      return program_to_witness_script(1, key)
112  
113  
114  def check_key(key):
115      if isinstance(key, str):
116          key = bytes.fromhex(key)  # Assuming this is hex string
117      if isinstance(key, bytes) and (len(key) == 33 or len(key) == 65):
118          return key
119      assert False
120  
121  
122  def check_script(script):
123      if isinstance(script, str):
124          script = bytes.fromhex(script)  # Assuming this is hex string
125      if isinstance(script, bytes) or isinstance(script, CScript):
126          return script
127      assert False