diff --git a/test/functional/README.md b/test/functional/README.md index 8d5407c11f..0c4c03e9a8 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -118,9 +118,6 @@ Utilities for manipulating transaction scripts (originally from python-bitcoinli #### [test_framework/key.py](test_framework/key.py) Test-only secp256k1 elliptic curve implementation -#### [test_framework/bignum.py](test_framework/bignum.py) -Helpers for script.py - #### [test_framework/blocktools.py](test_framework/blocktools.py) Helper functions for creating blocks and transactions. diff --git a/test/functional/test_framework/bignum.py b/test/functional/test_framework/bignum.py deleted file mode 100644 index db5ccd62c2..0000000000 --- a/test/functional/test_framework/bignum.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 -# -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Big number routines. - -This file is copied from python-bitcoinlib. -""" - -import struct - - -# generic big endian MPI format - -def bn_bytes(v, have_ext=False): - ext = 0 - if have_ext: - ext = 1 - return ((v.bit_length()+7)//8) + ext - -def bn2bin(v): - s = bytearray() - i = bn_bytes(v) - while i > 0: - s.append((v >> ((i-1) * 8)) & 0xff) - i -= 1 - return s - -def bn2mpi(v): - have_ext = False - if v.bit_length() > 0: - have_ext = (v.bit_length() & 0x07) == 0 - - neg = False - if v < 0: - neg = True - v = -v - - s = struct.pack(b">I", bn_bytes(v, have_ext)) - ext = bytearray() - if have_ext: - ext.append(0) - v_bin = bn2bin(v) - if neg: - if have_ext: - ext[0] |= 0x80 - else: - v_bin[0] |= 0x80 - return s + ext + v_bin - -# bitcoin-specific little endian format, with implicit size -def mpi2vch(s): - r = s[4:] # strip size - r = r[::-1] # reverse string, converting BE->LE - return r - -def bn2vch(v): - return bytes(mpi2vch(bn2mpi(v))) diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index 943b404deb..2b95f9a99a 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -6,20 +6,56 @@ This file is modified from python-bitcoinlib. """ - import hashlib import struct -from .bignum import bn2vch -from .messages import CTransaction, CTxOut, sha256, hash256 +from .messages import ( + CTransaction, + CTxOut, + hash256, + sha256, +) MAX_SCRIPT_ELEMENT_SIZE = 520 - OPCODE_NAMES = {} def hash160(s): return hashlib.new('ripemd160', sha256(s)).digest() +def bn2vch(v): + """Convert number to bitcoin-specific little endian format.""" + # The top bit is used to indicate the sign of the number. If there + # isn't a spare bit in the bit length, add an extension byte. + have_ext = False + ext = bytearray() + if v.bit_length() > 0: + have_ext = (v.bit_length() & 0x07) == 0 + ext.append(0) + + # Is the number negative? + neg = False + if v < 0: + neg = True + v = -v + + # Convert the int to bytes + v_bin = bytearray() + bytes_len = (v.bit_length() + 7) // 8 + for i in range(bytes_len, 0, -1): + v_bin.append((v >> ((i - 1) * 8)) & 0xff) + + # Add the sign bit if necessary + if neg: + if have_ext: + ext[0] |= 0x80 + else: + v_bin[0] |= 0x80 + + v_bytes = ext + v_bin + # Reverse bytes ordering for LE + v_bytes.reverse() + + return bytes(v_bytes) _opcode_instances = [] class CScriptOp(int): @@ -30,13 +66,13 @@ class CScriptOp(int): def encode_op_pushdata(d): """Encode a PUSHDATA op, returning bytes""" if len(d) < 0x4c: - return b'' + bytes([len(d)]) + d # OP_PUSHDATA + return b'' + bytes([len(d)]) + d # OP_PUSHDATA elif len(d) <= 0xff: - return b'\x4c' + bytes([len(d)]) + d # OP_PUSHDATA1 + return b'\x4c' + bytes([len(d)]) + d # OP_PUSHDATA1 elif len(d) <= 0xffff: - return b'\x4d' + struct.pack(b'= 0x80: # Mask for all but the highest result bit - num_mask = (2**(len(value)*8) - 1) >> 1 + num_mask = (2**(len(value) * 8) - 1) >> 1 result &= num_mask result *= -1 return result @@ -494,21 +530,20 @@ class CScript(bytes): pushdata_type = 'PUSHDATA2' if i + 1 >= len(self): raise CScriptInvalidError('PUSHDATA2: missing data length') - datasize = self[i] + (self[i+1] << 8) + datasize = self[i] + (self[i + 1] << 8) i += 2 elif opcode == OP_PUSHDATA4: pushdata_type = 'PUSHDATA4' if i + 3 >= len(self): raise CScriptInvalidError('PUSHDATA4: missing data length') - datasize = self[i] + (self[i+1] << 8) + (self[i+2] << 16) + (self[i+3] << 24) + datasize = self[i] + (self[i + 1] << 8) + (self[i + 2] << 16) + (self[i + 3] << 24) i += 4 else: - assert False # shouldn't happen + assert False # shouldn't happen - - data = bytes(self[i:i+datasize]) + data = bytes(self[i:i + datasize]) # Check for truncation if len(data) < datasize: