electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

bitcoin.py (23572B)


      1 # -*- coding: utf-8 -*-
      2 #
      3 # Electrum - lightweight Bitcoin client
      4 # Copyright (C) 2011 thomasv@gitorious
      5 #
      6 # Permission is hereby granted, free of charge, to any person
      7 # obtaining a copy of this software and associated documentation files
      8 # (the "Software"), to deal in the Software without restriction,
      9 # including without limitation the rights to use, copy, modify, merge,
     10 # publish, distribute, sublicense, and/or sell copies of the Software,
     11 # and to permit persons to whom the Software is furnished to do so,
     12 # subject to the following conditions:
     13 #
     14 # The above copyright notice and this permission notice shall be
     15 # included in all copies or substantial portions of the Software.
     16 #
     17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     21 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     22 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     23 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     24 # SOFTWARE.
     25 
     26 import hashlib
     27 from typing import List, Tuple, TYPE_CHECKING, Optional, Union, Sequence
     28 import enum
     29 from enum import IntEnum, Enum
     30 
     31 from .util import bfh, bh2u, BitcoinException, assert_bytes, to_bytes, inv_dict, is_hex_str
     32 from . import version
     33 from . import segwit_addr
     34 from . import constants
     35 from . import ecc
     36 from .crypto import sha256d, sha256, hash_160, hmac_oneshot
     37 
     38 if TYPE_CHECKING:
     39     from .network import Network
     40 
     41 
     42 ################################## transactions
     43 
     44 COINBASE_MATURITY = 100
     45 COIN = 100000000
     46 TOTAL_COIN_SUPPLY_LIMIT_IN_BTC = 21000000
     47 
     48 NLOCKTIME_MIN = 0
     49 NLOCKTIME_BLOCKHEIGHT_MAX = 500_000_000 - 1
     50 NLOCKTIME_MAX = 2 ** 32 - 1
     51 
     52 # supported types of transaction outputs
     53 # TODO kill these with fire
     54 TYPE_ADDRESS = 0
     55 TYPE_PUBKEY  = 1
     56 TYPE_SCRIPT  = 2
     57 
     58 
     59 class opcodes(IntEnum):
     60     # push value
     61     OP_0 = 0x00
     62     OP_FALSE = OP_0
     63     OP_PUSHDATA1 = 0x4c
     64     OP_PUSHDATA2 = 0x4d
     65     OP_PUSHDATA4 = 0x4e
     66     OP_1NEGATE = 0x4f
     67     OP_RESERVED = 0x50
     68     OP_1 = 0x51
     69     OP_TRUE = OP_1
     70     OP_2 = 0x52
     71     OP_3 = 0x53
     72     OP_4 = 0x54
     73     OP_5 = 0x55
     74     OP_6 = 0x56
     75     OP_7 = 0x57
     76     OP_8 = 0x58
     77     OP_9 = 0x59
     78     OP_10 = 0x5a
     79     OP_11 = 0x5b
     80     OP_12 = 0x5c
     81     OP_13 = 0x5d
     82     OP_14 = 0x5e
     83     OP_15 = 0x5f
     84     OP_16 = 0x60
     85 
     86     # control
     87     OP_NOP = 0x61
     88     OP_VER = 0x62
     89     OP_IF = 0x63
     90     OP_NOTIF = 0x64
     91     OP_VERIF = 0x65
     92     OP_VERNOTIF = 0x66
     93     OP_ELSE = 0x67
     94     OP_ENDIF = 0x68
     95     OP_VERIFY = 0x69
     96     OP_RETURN = 0x6a
     97 
     98     # stack ops
     99     OP_TOALTSTACK = 0x6b
    100     OP_FROMALTSTACK = 0x6c
    101     OP_2DROP = 0x6d
    102     OP_2DUP = 0x6e
    103     OP_3DUP = 0x6f
    104     OP_2OVER = 0x70
    105     OP_2ROT = 0x71
    106     OP_2SWAP = 0x72
    107     OP_IFDUP = 0x73
    108     OP_DEPTH = 0x74
    109     OP_DROP = 0x75
    110     OP_DUP = 0x76
    111     OP_NIP = 0x77
    112     OP_OVER = 0x78
    113     OP_PICK = 0x79
    114     OP_ROLL = 0x7a
    115     OP_ROT = 0x7b
    116     OP_SWAP = 0x7c
    117     OP_TUCK = 0x7d
    118 
    119     # splice ops
    120     OP_CAT = 0x7e
    121     OP_SUBSTR = 0x7f
    122     OP_LEFT = 0x80
    123     OP_RIGHT = 0x81
    124     OP_SIZE = 0x82
    125 
    126     # bit logic
    127     OP_INVERT = 0x83
    128     OP_AND = 0x84
    129     OP_OR = 0x85
    130     OP_XOR = 0x86
    131     OP_EQUAL = 0x87
    132     OP_EQUALVERIFY = 0x88
    133     OP_RESERVED1 = 0x89
    134     OP_RESERVED2 = 0x8a
    135 
    136     # numeric
    137     OP_1ADD = 0x8b
    138     OP_1SUB = 0x8c
    139     OP_2MUL = 0x8d
    140     OP_2DIV = 0x8e
    141     OP_NEGATE = 0x8f
    142     OP_ABS = 0x90
    143     OP_NOT = 0x91
    144     OP_0NOTEQUAL = 0x92
    145 
    146     OP_ADD = 0x93
    147     OP_SUB = 0x94
    148     OP_MUL = 0x95
    149     OP_DIV = 0x96
    150     OP_MOD = 0x97
    151     OP_LSHIFT = 0x98
    152     OP_RSHIFT = 0x99
    153 
    154     OP_BOOLAND = 0x9a
    155     OP_BOOLOR = 0x9b
    156     OP_NUMEQUAL = 0x9c
    157     OP_NUMEQUALVERIFY = 0x9d
    158     OP_NUMNOTEQUAL = 0x9e
    159     OP_LESSTHAN = 0x9f
    160     OP_GREATERTHAN = 0xa0
    161     OP_LESSTHANOREQUAL = 0xa1
    162     OP_GREATERTHANOREQUAL = 0xa2
    163     OP_MIN = 0xa3
    164     OP_MAX = 0xa4
    165 
    166     OP_WITHIN = 0xa5
    167 
    168     # crypto
    169     OP_RIPEMD160 = 0xa6
    170     OP_SHA1 = 0xa7
    171     OP_SHA256 = 0xa8
    172     OP_HASH160 = 0xa9
    173     OP_HASH256 = 0xaa
    174     OP_CODESEPARATOR = 0xab
    175     OP_CHECKSIG = 0xac
    176     OP_CHECKSIGVERIFY = 0xad
    177     OP_CHECKMULTISIG = 0xae
    178     OP_CHECKMULTISIGVERIFY = 0xaf
    179 
    180     # expansion
    181     OP_NOP1 = 0xb0
    182     OP_CHECKLOCKTIMEVERIFY = 0xb1
    183     OP_NOP2 = OP_CHECKLOCKTIMEVERIFY
    184     OP_CHECKSEQUENCEVERIFY = 0xb2
    185     OP_NOP3 = OP_CHECKSEQUENCEVERIFY
    186     OP_NOP4 = 0xb3
    187     OP_NOP5 = 0xb4
    188     OP_NOP6 = 0xb5
    189     OP_NOP7 = 0xb6
    190     OP_NOP8 = 0xb7
    191     OP_NOP9 = 0xb8
    192     OP_NOP10 = 0xb9
    193 
    194     OP_INVALIDOPCODE = 0xff
    195 
    196     def hex(self) -> str:
    197         return bytes([self]).hex()
    198 
    199 
    200 def rev_hex(s: str) -> str:
    201     return bh2u(bfh(s)[::-1])
    202 
    203 
    204 def int_to_hex(i: int, length: int=1) -> str:
    205     """Converts int to little-endian hex string.
    206     `length` is the number of bytes available
    207     """
    208     if not isinstance(i, int):
    209         raise TypeError('{} instead of int'.format(i))
    210     range_size = pow(256, length)
    211     if i < -(range_size//2) or i >= range_size:
    212         raise OverflowError('cannot convert int {} to hex ({} bytes)'.format(i, length))
    213     if i < 0:
    214         # two's complement
    215         i = range_size + i
    216     s = hex(i)[2:].rstrip('L')
    217     s = "0"*(2*length - len(s)) + s
    218     return rev_hex(s)
    219 
    220 def script_num_to_hex(i: int) -> str:
    221     """See CScriptNum in Bitcoin Core.
    222     Encodes an integer as hex, to be used in script.
    223 
    224     ported from https://github.com/bitcoin/bitcoin/blob/8cbc5c4be4be22aca228074f087a374a7ec38be8/src/script/script.h#L326
    225     """
    226     if i == 0:
    227         return ''
    228 
    229     result = bytearray()
    230     neg = i < 0
    231     absvalue = abs(i)
    232     while absvalue > 0:
    233         result.append(absvalue & 0xff)
    234         absvalue >>= 8
    235 
    236     if result[-1] & 0x80:
    237         result.append(0x80 if neg else 0x00)
    238     elif neg:
    239         result[-1] |= 0x80
    240 
    241     return bh2u(result)
    242 
    243 
    244 def var_int(i: int) -> str:
    245     # https://en.bitcoin.it/wiki/Protocol_specification#Variable_length_integer
    246     # https://github.com/bitcoin/bitcoin/blob/efe1ee0d8d7f82150789f1f6840f139289628a2b/src/serialize.h#L247
    247     # "CompactSize"
    248     assert i >= 0, i
    249     if i<0xfd:
    250         return int_to_hex(i)
    251     elif i<=0xffff:
    252         return "fd"+int_to_hex(i,2)
    253     elif i<=0xffffffff:
    254         return "fe"+int_to_hex(i,4)
    255     else:
    256         return "ff"+int_to_hex(i,8)
    257 
    258 
    259 def witness_push(item: str) -> str:
    260     """Returns data in the form it should be present in the witness.
    261     hex -> hex
    262     """
    263     return var_int(len(item) // 2) + item
    264 
    265 
    266 def _op_push(i: int) -> str:
    267     if i < opcodes.OP_PUSHDATA1:
    268         return int_to_hex(i)
    269     elif i <= 0xff:
    270         return opcodes.OP_PUSHDATA1.hex() + int_to_hex(i, 1)
    271     elif i <= 0xffff:
    272         return opcodes.OP_PUSHDATA2.hex() + int_to_hex(i, 2)
    273     else:
    274         return opcodes.OP_PUSHDATA4.hex() + int_to_hex(i, 4)
    275 
    276 
    277 def push_script(data: str) -> str:
    278     """Returns pushed data to the script, automatically
    279     choosing canonical opcodes depending on the length of the data.
    280     hex -> hex
    281 
    282     ported from https://github.com/btcsuite/btcd/blob/fdc2bc867bda6b351191b5872d2da8270df00d13/txscript/scriptbuilder.go#L128
    283     """
    284     data = bfh(data)
    285     data_len = len(data)
    286 
    287     # "small integer" opcodes
    288     if data_len == 0 or data_len == 1 and data[0] == 0:
    289         return opcodes.OP_0.hex()
    290     elif data_len == 1 and data[0] <= 16:
    291         return bh2u(bytes([opcodes.OP_1 - 1 + data[0]]))
    292     elif data_len == 1 and data[0] == 0x81:
    293         return opcodes.OP_1NEGATE.hex()
    294 
    295     return _op_push(data_len) + bh2u(data)
    296 
    297 
    298 def add_number_to_script(i: int) -> bytes:
    299     return bfh(push_script(script_num_to_hex(i)))
    300 
    301 
    302 def construct_witness(items: Sequence[Union[str, int, bytes]]) -> str:
    303     """Constructs a witness from the given stack items."""
    304     witness = var_int(len(items))
    305     for item in items:
    306         if type(item) is int:
    307             item = script_num_to_hex(item)
    308         elif isinstance(item, (bytes, bytearray)):
    309             item = bh2u(item)
    310         else:
    311             assert is_hex_str(item)
    312         witness += witness_push(item)
    313     return witness
    314 
    315 
    316 def construct_script(items: Sequence[Union[str, int, bytes, opcodes]]) -> str:
    317     """Constructs bitcoin script from given items."""
    318     script = ''
    319     for item in items:
    320         if isinstance(item, opcodes):
    321             script += item.hex()
    322         elif type(item) is int:
    323             script += add_number_to_script(item).hex()
    324         elif isinstance(item, (bytes, bytearray)):
    325             script += push_script(item.hex())
    326         elif isinstance(item, str):
    327             assert is_hex_str(item)
    328             script += push_script(item)
    329         else:
    330             raise Exception(f'unexpected item for script: {item!r}')
    331     return script
    332 
    333 
    334 def relayfee(network: 'Network' = None) -> int:
    335     """Returns feerate in sat/kbyte."""
    336     from .simple_config import FEERATE_DEFAULT_RELAY, FEERATE_MAX_RELAY
    337     if network and network.relay_fee is not None:
    338         fee = network.relay_fee
    339     else:
    340         fee = FEERATE_DEFAULT_RELAY
    341     # sanity safeguards, as network.relay_fee is coming from a server:
    342     fee = min(fee, FEERATE_MAX_RELAY)
    343     fee = max(fee, FEERATE_DEFAULT_RELAY)
    344     return fee
    345 
    346 
    347 # see https://github.com/bitcoin/bitcoin/blob/a62f0ed64f8bbbdfe6467ac5ce92ef5b5222d1bd/src/policy/policy.cpp#L14
    348 DUST_LIMIT_DEFAULT_SAT_LEGACY = 546
    349 DUST_LIMIT_DEFAULT_SAT_SEGWIT = 294
    350 
    351 
    352 def dust_threshold(network: 'Network' = None) -> int:
    353     """Returns the dust limit in satoshis."""
    354     # Change <= dust threshold is added to the tx fee
    355     dust_lim = 182 * 3 * relayfee(network)  # in msat
    356     # convert to sat, but round up:
    357     return (dust_lim // 1000) + (dust_lim % 1000 > 0)
    358 
    359 
    360 def hash_encode(x: bytes) -> str:
    361     return bh2u(x[::-1])
    362 
    363 
    364 def hash_decode(x: str) -> bytes:
    365     return bfh(x)[::-1]
    366 
    367 
    368 ############ functions from pywallet #####################
    369 
    370 def hash160_to_b58_address(h160: bytes, addrtype: int) -> str:
    371     s = bytes([addrtype]) + h160
    372     s = s + sha256d(s)[0:4]
    373     return base_encode(s, base=58)
    374 
    375 
    376 def b58_address_to_hash160(addr: str) -> Tuple[int, bytes]:
    377     addr = to_bytes(addr, 'ascii')
    378     _bytes = DecodeBase58Check(addr)
    379     if len(_bytes) != 21:
    380         raise Exception(f'expected 21 payload bytes in base58 address. got: {len(_bytes)}')
    381     return _bytes[0], _bytes[1:21]
    382 
    383 
    384 def hash160_to_p2pkh(h160: bytes, *, net=None) -> str:
    385     if net is None: net = constants.net
    386     return hash160_to_b58_address(h160, net.ADDRTYPE_P2PKH)
    387 
    388 def hash160_to_p2sh(h160: bytes, *, net=None) -> str:
    389     if net is None: net = constants.net
    390     return hash160_to_b58_address(h160, net.ADDRTYPE_P2SH)
    391 
    392 def public_key_to_p2pkh(public_key: bytes, *, net=None) -> str:
    393     if net is None: net = constants.net
    394     return hash160_to_p2pkh(hash_160(public_key), net=net)
    395 
    396 def hash_to_segwit_addr(h: bytes, witver: int, *, net=None) -> str:
    397     if net is None: net = constants.net
    398     return segwit_addr.encode(net.SEGWIT_HRP, witver, h)
    399 
    400 def public_key_to_p2wpkh(public_key: bytes, *, net=None) -> str:
    401     if net is None: net = constants.net
    402     return hash_to_segwit_addr(hash_160(public_key), witver=0, net=net)
    403 
    404 def script_to_p2wsh(script: str, *, net=None) -> str:
    405     if net is None: net = constants.net
    406     return hash_to_segwit_addr(sha256(bfh(script)), witver=0, net=net)
    407 
    408 def p2wpkh_nested_script(pubkey: str) -> str:
    409     pkh = hash_160(bfh(pubkey))
    410     return construct_script([0, pkh])
    411 
    412 def p2wsh_nested_script(witness_script: str) -> str:
    413     wsh = sha256(bfh(witness_script))
    414     return construct_script([0, wsh])
    415 
    416 def pubkey_to_address(txin_type: str, pubkey: str, *, net=None) -> str:
    417     if net is None: net = constants.net
    418     if txin_type == 'p2pkh':
    419         return public_key_to_p2pkh(bfh(pubkey), net=net)
    420     elif txin_type == 'p2wpkh':
    421         return public_key_to_p2wpkh(bfh(pubkey), net=net)
    422     elif txin_type == 'p2wpkh-p2sh':
    423         scriptSig = p2wpkh_nested_script(pubkey)
    424         return hash160_to_p2sh(hash_160(bfh(scriptSig)), net=net)
    425     else:
    426         raise NotImplementedError(txin_type)
    427 
    428 
    429 # TODO this method is confusingly named
    430 def redeem_script_to_address(txin_type: str, scriptcode: str, *, net=None) -> str:
    431     if net is None: net = constants.net
    432     if txin_type == 'p2sh':
    433         # given scriptcode is a redeem_script
    434         return hash160_to_p2sh(hash_160(bfh(scriptcode)), net=net)
    435     elif txin_type == 'p2wsh':
    436         # given scriptcode is a witness_script
    437         return script_to_p2wsh(scriptcode, net=net)
    438     elif txin_type == 'p2wsh-p2sh':
    439         # given scriptcode is a witness_script
    440         redeem_script = p2wsh_nested_script(scriptcode)
    441         return hash160_to_p2sh(hash_160(bfh(redeem_script)), net=net)
    442     else:
    443         raise NotImplementedError(txin_type)
    444 
    445 
    446 def script_to_address(script: str, *, net=None) -> str:
    447     from .transaction import get_address_from_output_script
    448     return get_address_from_output_script(bfh(script), net=net)
    449 
    450 
    451 def address_to_script(addr: str, *, net=None) -> str:
    452     if net is None: net = constants.net
    453     if not is_address(addr, net=net):
    454         raise BitcoinException(f"invalid bitcoin address: {addr}")
    455     witver, witprog = segwit_addr.decode(net.SEGWIT_HRP, addr)
    456     if witprog is not None:
    457         if not (0 <= witver <= 16):
    458             raise BitcoinException(f'impossible witness version: {witver}')
    459         return construct_script([witver, bytes(witprog)])
    460     addrtype, hash_160_ = b58_address_to_hash160(addr)
    461     if addrtype == net.ADDRTYPE_P2PKH:
    462         script = pubkeyhash_to_p2pkh_script(bh2u(hash_160_))
    463     elif addrtype == net.ADDRTYPE_P2SH:
    464         script = construct_script([opcodes.OP_HASH160, hash_160_, opcodes.OP_EQUAL])
    465     else:
    466         raise BitcoinException(f'unknown address type: {addrtype}')
    467     return script
    468 
    469 
    470 class OnchainOutputType(Enum):
    471     """Opaque types of scriptPubKeys.
    472     In case of p2sh, p2wsh and similar, no knowledge of redeem script, etc.
    473     """
    474     P2PKH = enum.auto()
    475     P2SH = enum.auto()
    476     WITVER0_P2WPKH = enum.auto()
    477     WITVER0_P2WSH = enum.auto()
    478 
    479 
    480 def address_to_hash(addr: str, *, net=None) -> Tuple[OnchainOutputType, bytes]:
    481     """Return (type, pubkey hash / witness program) for an address."""
    482     if net is None: net = constants.net
    483     if not is_address(addr, net=net):
    484         raise BitcoinException(f"invalid bitcoin address: {addr}")
    485     witver, witprog = segwit_addr.decode(net.SEGWIT_HRP, addr)
    486     if witprog is not None:
    487         if witver != 0:
    488             raise BitcoinException(f"not implemented handling for witver={witver}")
    489         if len(witprog) == 20:
    490             return OnchainOutputType.WITVER0_P2WPKH, bytes(witprog)
    491         elif len(witprog) == 32:
    492             return OnchainOutputType.WITVER0_P2WSH, bytes(witprog)
    493         else:
    494             raise BitcoinException(f"unexpected length for segwit witver=0 witprog: len={len(witprog)}")
    495     addrtype, hash_160_ = b58_address_to_hash160(addr)
    496     if addrtype == net.ADDRTYPE_P2PKH:
    497         return OnchainOutputType.P2PKH, hash_160_
    498     elif addrtype == net.ADDRTYPE_P2SH:
    499         return OnchainOutputType.P2SH, hash_160_
    500     raise BitcoinException(f"unknown address type: {addrtype}")
    501 
    502 
    503 def address_to_scripthash(addr: str) -> str:
    504     script = address_to_script(addr)
    505     return script_to_scripthash(script)
    506 
    507 def script_to_scripthash(script: str) -> str:
    508     h = sha256(bfh(script))[0:32]
    509     return bh2u(bytes(reversed(h)))
    510 
    511 def public_key_to_p2pk_script(pubkey: str) -> str:
    512     return construct_script([pubkey, opcodes.OP_CHECKSIG])
    513 
    514 def pubkeyhash_to_p2pkh_script(pubkey_hash160: str) -> str:
    515     return construct_script([
    516         opcodes.OP_DUP,
    517         opcodes.OP_HASH160,
    518         pubkey_hash160,
    519         opcodes.OP_EQUALVERIFY,
    520         opcodes.OP_CHECKSIG
    521     ])
    522 
    523 
    524 __b58chars = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
    525 assert len(__b58chars) == 58
    526 
    527 __b43chars = b'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$*+-./:'
    528 assert len(__b43chars) == 43
    529 
    530 
    531 class BaseDecodeError(BitcoinException): pass
    532 
    533 
    534 def base_encode(v: bytes, *, base: int) -> str:
    535     """ encode v, which is a string of bytes, to base58."""
    536     assert_bytes(v)
    537     if base not in (58, 43):
    538         raise ValueError('not supported base: {}'.format(base))
    539     chars = __b58chars
    540     if base == 43:
    541         chars = __b43chars
    542     long_value = 0
    543     power_of_base = 1
    544     for c in v[::-1]:
    545         # naive but slow variant:   long_value += (256**i) * c
    546         long_value += power_of_base * c
    547         power_of_base <<= 8
    548     result = bytearray()
    549     while long_value >= base:
    550         div, mod = divmod(long_value, base)
    551         result.append(chars[mod])
    552         long_value = div
    553     result.append(chars[long_value])
    554     # Bitcoin does a little leading-zero-compression:
    555     # leading 0-bytes in the input become leading-1s
    556     nPad = 0
    557     for c in v:
    558         if c == 0x00:
    559             nPad += 1
    560         else:
    561             break
    562     result.extend([chars[0]] * nPad)
    563     result.reverse()
    564     return result.decode('ascii')
    565 
    566 
    567 def base_decode(v: Union[bytes, str], *, base: int, length: int = None) -> Optional[bytes]:
    568     """ decode v into a string of len bytes."""
    569     # assert_bytes(v)
    570     v = to_bytes(v, 'ascii')
    571     if base not in (58, 43):
    572         raise ValueError('not supported base: {}'.format(base))
    573     chars = __b58chars
    574     if base == 43:
    575         chars = __b43chars
    576     long_value = 0
    577     power_of_base = 1
    578     for c in v[::-1]:
    579         digit = chars.find(bytes([c]))
    580         if digit == -1:
    581             raise BaseDecodeError('Forbidden character {} for base {}'.format(c, base))
    582         # naive but slow variant:   long_value += digit * (base**i)
    583         long_value += digit * power_of_base
    584         power_of_base *= base
    585     result = bytearray()
    586     while long_value >= 256:
    587         div, mod = divmod(long_value, 256)
    588         result.append(mod)
    589         long_value = div
    590     result.append(long_value)
    591     nPad = 0
    592     for c in v:
    593         if c == chars[0]:
    594             nPad += 1
    595         else:
    596             break
    597     result.extend(b'\x00' * nPad)
    598     if length is not None and len(result) != length:
    599         return None
    600     result.reverse()
    601     return bytes(result)
    602 
    603 
    604 class InvalidChecksum(BaseDecodeError):
    605     pass
    606 
    607 
    608 def EncodeBase58Check(vchIn: bytes) -> str:
    609     hash = sha256d(vchIn)
    610     return base_encode(vchIn + hash[0:4], base=58)
    611 
    612 
    613 def DecodeBase58Check(psz: Union[bytes, str]) -> bytes:
    614     vchRet = base_decode(psz, base=58)
    615     payload = vchRet[0:-4]
    616     csum_found = vchRet[-4:]
    617     csum_calculated = sha256d(payload)[0:4]
    618     if csum_calculated != csum_found:
    619         raise InvalidChecksum(f'calculated {bh2u(csum_calculated)}, found {bh2u(csum_found)}')
    620     else:
    621         return payload
    622 
    623 
    624 # backwards compat
    625 # extended WIF for segwit (used in 3.0.x; but still used internally)
    626 # the keys in this dict should be a superset of what Imported Wallets can import
    627 WIF_SCRIPT_TYPES = {
    628     'p2pkh':0,
    629     'p2wpkh':1,
    630     'p2wpkh-p2sh':2,
    631     'p2sh':5,
    632     'p2wsh':6,
    633     'p2wsh-p2sh':7
    634 }
    635 WIF_SCRIPT_TYPES_INV = inv_dict(WIF_SCRIPT_TYPES)
    636 
    637 
    638 def is_segwit_script_type(txin_type: str) -> bool:
    639     return txin_type in ('p2wpkh', 'p2wpkh-p2sh', 'p2wsh', 'p2wsh-p2sh')
    640 
    641 
    642 def serialize_privkey(secret: bytes, compressed: bool, txin_type: str, *,
    643                       internal_use: bool = False) -> str:
    644     # we only export secrets inside curve range
    645     secret = ecc.ECPrivkey.normalize_secret_bytes(secret)
    646     if internal_use:
    647         prefix = bytes([(WIF_SCRIPT_TYPES[txin_type] + constants.net.WIF_PREFIX) & 255])
    648     else:
    649         prefix = bytes([constants.net.WIF_PREFIX])
    650     suffix = b'\01' if compressed else b''
    651     vchIn = prefix + secret + suffix
    652     base58_wif = EncodeBase58Check(vchIn)
    653     if internal_use:
    654         return base58_wif
    655     else:
    656         return '{}:{}'.format(txin_type, base58_wif)
    657 
    658 
    659 def deserialize_privkey(key: str) -> Tuple[str, bytes, bool]:
    660     if is_minikey(key):
    661         return 'p2pkh', minikey_to_private_key(key), False
    662 
    663     txin_type = None
    664     if ':' in key:
    665         txin_type, key = key.split(sep=':', maxsplit=1)
    666         if txin_type not in WIF_SCRIPT_TYPES:
    667             raise BitcoinException('unknown script type: {}'.format(txin_type))
    668     try:
    669         vch = DecodeBase58Check(key)
    670     except Exception as e:
    671         neutered_privkey = str(key)[:3] + '..' + str(key)[-2:]
    672         raise BaseDecodeError(f"cannot deserialize privkey {neutered_privkey}") from e
    673 
    674     if txin_type is None:
    675         # keys exported in version 3.0.x encoded script type in first byte
    676         prefix_value = vch[0] - constants.net.WIF_PREFIX
    677         try:
    678             txin_type = WIF_SCRIPT_TYPES_INV[prefix_value]
    679         except KeyError as e:
    680             raise BitcoinException('invalid prefix ({}) for WIF key (1)'.format(vch[0])) from None
    681     else:
    682         # all other keys must have a fixed first byte
    683         if vch[0] != constants.net.WIF_PREFIX:
    684             raise BitcoinException('invalid prefix ({}) for WIF key (2)'.format(vch[0]))
    685 
    686     if len(vch) not in [33, 34]:
    687         raise BitcoinException('invalid vch len for WIF key: {}'.format(len(vch)))
    688     compressed = False
    689     if len(vch) == 34:
    690         if vch[33] == 0x01:
    691             compressed = True
    692         else:
    693             raise BitcoinException(f'invalid WIF key. length suggests compressed pubkey, '
    694                                    f'but last byte is {vch[33]} != 0x01')
    695 
    696     if is_segwit_script_type(txin_type) and not compressed:
    697         raise BitcoinException('only compressed public keys can be used in segwit scripts')
    698 
    699     secret_bytes = vch[1:33]
    700     # we accept secrets outside curve range; cast into range here:
    701     secret_bytes = ecc.ECPrivkey.normalize_secret_bytes(secret_bytes)
    702     return txin_type, secret_bytes, compressed
    703 
    704 
    705 def is_compressed_privkey(sec: str) -> bool:
    706     return deserialize_privkey(sec)[2]
    707 
    708 
    709 def address_from_private_key(sec: str) -> str:
    710     txin_type, privkey, compressed = deserialize_privkey(sec)
    711     public_key = ecc.ECPrivkey(privkey).get_public_key_hex(compressed=compressed)
    712     return pubkey_to_address(txin_type, public_key)
    713 
    714 def is_segwit_address(addr: str, *, net=None) -> bool:
    715     if net is None: net = constants.net
    716     try:
    717         witver, witprog = segwit_addr.decode(net.SEGWIT_HRP, addr)
    718     except Exception as e:
    719         return False
    720     return witprog is not None
    721 
    722 def is_b58_address(addr: str, *, net=None) -> bool:
    723     if net is None: net = constants.net
    724     try:
    725         # test length, checksum, encoding:
    726         addrtype, h = b58_address_to_hash160(addr)
    727     except Exception as e:
    728         return False
    729     if addrtype not in [net.ADDRTYPE_P2PKH, net.ADDRTYPE_P2SH]:
    730         return False
    731     return True
    732 
    733 def is_address(addr: str, *, net=None) -> bool:
    734     if net is None: net = constants.net
    735     return is_segwit_address(addr, net=net) \
    736            or is_b58_address(addr, net=net)
    737 
    738 
    739 def is_private_key(key: str, *, raise_on_error=False) -> bool:
    740     try:
    741         deserialize_privkey(key)
    742         return True
    743     except BaseException as e:
    744         if raise_on_error:
    745             raise
    746         return False
    747 
    748 
    749 ########### end pywallet functions #######################
    750 
    751 def is_minikey(text: str) -> bool:
    752     # Minikeys are typically 22 or 30 characters, but this routine
    753     # permits any length of 20 or more provided the minikey is valid.
    754     # A valid minikey must begin with an 'S', be in base58, and when
    755     # suffixed with '?' have its SHA256 hash begin with a zero byte.
    756     # They are widely used in Casascius physical bitcoins.
    757     return (len(text) >= 20 and text[0] == 'S'
    758             and all(ord(c) in __b58chars for c in text)
    759             and sha256(text + '?')[0] == 0x00)
    760 
    761 def minikey_to_private_key(text: str) -> bytes:
    762     return sha256(text)