Example #1
0
def test_read_opcode():
    assert read_opcode(get_stream(get_bytes([b"\x08", b"1" * 8
                                             ]))) == (b"\x08", b"1" * 8)
    assert read_opcode(
        get_stream(get_bytes([OP_PUSHDATA1, b"\x4c",
                              b"1" * 76]))) == (OP_PUSHDATA1, b"1" * 76)
    assert read_opcode(get_stream(get_bytes([OP_PUSHDATA2, pack('<H' ,256), b"1" * 256]))) == \
           (OP_PUSHDATA2, b"1" * 256)
    p = b"1" * 65537
    l = OP_PUSHDATA4 + pack('<L', 65537) + p
    assert read_opcode(get_stream(l)) == (OP_PUSHDATA4, p)
Example #2
0
def test_op_push_data():
    assert op_push_data("") == b"\x00"
    assert op_push_data(b"1234567890") == b'\n1234567890'
    assert op_push_data(b"1" * 75) == b'K' + b"1" * 75
    assert op_push_data(b"1" * 76) != b'\x4c' + b"1" * 76
    assert op_push_data(b"1" * 76) == get_bytes(
        [OP_PUSHDATA1, b"\x4c", b"1" * 76])
    assert op_push_data(b"1" * 256) == get_bytes(
        [OP_PUSHDATA2, pack('<H', 256), b"1" * 256])
    p = b"1" * 65537
    l = op_push_data(p) == OP_PUSHDATA4 + pack('<L', 65537) + p
    assert l
Example #3
0
def public_key_recovery(signature,
                        messsage,
                        rec_id,
                        compressed=True,
                        hex=True):
    signature = get_bytes(signature)
    messsage = get_bytes(messsage)
    pub = __secp256k1_ecdsa_recover__(signature, messsage, rec_id, compressed)
    if isinstance(pub, int):
        if pub == 0:
            return None
        else:
            raise RuntimeError("signature recovery error %s" % pub)
    return pub.hex() if hex else pub
Example #4
0
def parse_signature(sig):
    """
    Check is valid signature encoded in DER format

    :param sig:  signature in bytes or HEX encoded string.
    :return:  boolean.
    """
    # Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
    # * total-length: 1-byte length descriptor of everything that follows,
    #   excluding the sighash byte.
    # * R-length: 1-byte length descriptor of the R value that follows.
    # * R: arbitrary-length big-endian encoded R value. It must use the shortest
    #   possible encoding for a positive integers (which means no null bytes at
    #   the start, except a single one when the next byte has its highest bit set).
    # * S-length: 1-byte length descriptor of the S value that follows.
    # * S: arbitrary-length big-endian encoded S value. The same rules apply.
    # * sighash: 1-byte value indicating what data is hashed (not part of the DER
    #   signature)
    sig = get_bytes(sig)
    if not is_valid_signature_encoding(sig):
        raise ValueError("invalid signature")
    len_r = sig[3]
    r = sig[5:4 + len_r]
    s = sig[len_r + 6:-1]
    return r, s
Example #5
0
def verify_signature(sig, pub_key, msg, encoding="hex"):
    """
    Verify signature for message and given public key

    :param sig: signature in bytes or HEX encoded string.
    :param pub_key:  public key in bytes or HEX encoded string.
    :param msg:  message in bytes or HEX encoded string.
    :return: boolean.
    """
    sig = get_bytes(sig)
    pub_key = get_bytes(pub_key)
    msg = get_bytes(msg, encoding=encoding)
    r = __secp256k1_ecdsa_verify__(sig, pub_key, msg)
    if r == 1:
        return True
    return False
Example #6
0
def public_key_to_address(pubkey,
                          testnet=False,
                          p2sh_p2wpkh=False,
                          witness_version=0):
    """
    Get address from public key/script hash. In case PUBKEY, P2PKH, P2PKH public key/script hash is SHA256+RIPEMD160,
    P2WSH script hash is SHA256.

    :param pubkey: public key HEX or bytes string format.
    :param testnet: (optional) flag for testnet network, by default is False.
    :param p2sh_p2wpkh: (optional) flag for P2WPKH inside P2SH address, by default is False.
    :param witness_version: (optional) witness program version, by default is 0, for legacy
                            address format use None.
    :return: address in base58 or bech32 format.
    """
    pubkey = get_bytes(pubkey, encoding='hex')
    if p2sh_p2wpkh:
        if len(pubkey) != 33:
            raise ValueError("public key invalid")
        h = hash160(b'\x00\x14%s' % hash160(pubkey))
        witness_version = None
    else:
        if witness_version is not None:
            if len(pubkey) != 33:
                raise ValueError("public key invalid")
        h = hash160(pubkey)
    return hash_to_address(h,
                           testnet=testnet,
                           script_hash=p2sh_p2wpkh,
                           witness_version=witness_version)
Example #7
0
def hash_to_script(address_hash, script_type, hex=False):
    """
    Get public key script from hash.

    :param address: h in base58 or bech32 format.
    :param hex:  (optional) If set to True return key in HEX format, by default is True.
    :return: public key script in HEX or bytes string.
    """
    address_hash = get_bytes(address_hash)
    if isinstance(script_type, str):
        try:
            script_type = SCRIPT_TYPES[script_type]
        except:
            script_type = ""

    if script_type == 1:
        s = [OP_HASH160, b'\x14', address_hash, OP_EQUAL]
    elif script_type == 0:
        s = [
            OP_DUP, OP_HASH160, b'\x14', address_hash, OP_EQUALVERIFY,
            OP_CHECKSIG
        ]
    elif script_type in (5, 6):
        s = [OP_0, bytes([len(address_hash)]), address_hash]
    else:
        raise ValueError("address type invalid")
    s = b''.join(s)
    return s.hex() if hex else s
Example #8
0
def sign_message(msg, private_key, hex=True):
    """
        Sign message

        :param msg:  message to sign  bytes or HEX encoded string.
        :param private_key:  private key (bytes, hex encoded string or WIF format)
        :param hex:  (optional) If set to True return key in HEX format, by default is True.
        :return:  DER encoded signature in bytes or HEX encoded string.
        """
    msg = get_bytes(msg)

    if isinstance(private_key, bytearray):
        private_key = bytes(private_key)
    if isinstance(private_key, str):
        try:
            private_key = bytes_from_hex(private_key)
        except:
            if is_wif_valid(private_key):
                private_key = wif_to_private_key(private_key, hex=False)
    if not isinstance(private_key, bytes):
        raise TypeError(
            "private key must be a bytes, hex encoded string or in WIF format")

    signature = __secp256k1_ecdsa_sign__(msg, private_key)
    return signature.hex() if hex else signature
Example #9
0
def create_master_xprivate_key(seed, testnet=False, base58=None, hex=None):
    """
    Create extended private key from seed

    :param str,bytes key: seed HEX or bytes string. 
    :param boolean base58: (optional) return result as base58 encoded string, by default True.
    :param boolean hex: (optional) return result as HEX encoded string, by default False.
                        In case True base58 flag value will be ignored.
    :return: extended private key  in base58, HEX or bytes string format.
    """
    seed = get_bytes(seed)
    i = hmac_sha512(b"Bitcoin seed", seed)
    m, c = i[:32], i[32:]
    m_int = int.from_bytes(m, byteorder="big")

    if m_int <= 0 or m_int > ECDSA_SEC256K1_ORDER:  # pragma: no cover
        return None
    prefix = TESTNET_XPRIVATE_KEY_PREFIX if testnet else MAINNET_XPRIVATE_KEY_PREFIX
    key = b''.join(
        [prefix, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00', c, b'\x00', m])
    if base58 is None and hex is None:
        base58 = True
    if base58:
        key = b"".join([key, double_sha256(key)[:4]])
        return encode_base58(key)
    else:
        if hex is None:
            hex = False
        return key if not hex else key.hex()
Example #10
0
def delete_from_script(script, sub_script):
    """
    Decode OP_CODE or subscript from script.

    :param script: target script in bytes or HEX encoded string.
    :param sub_script:  sub_script which is necessary to remove from target script in bytes or HEX encoded string.
    :return: script in bytes or HEX encoded string corresponding to the format of target script.
    """
    s_hex = isinstance(script, str)
    script = get_bytes(script)
    sub_script = get_bytes(sub_script)
    stream = get_stream(script)
    if not sub_script:
        return script.hex() if s_hex else script
    r = b''
    offset = 0
    skip_until = 0
    o, d = read_opcode(stream)
    while o:
        if script[offset:offset + len(sub_script)] == sub_script:
            skip_until = offset + len(sub_script)
            r += d[len(sub_script) - 1:] if d is not None else b""
        if offset >= skip_until:
            r += o
            if d is not None:
                if o == OP_PUSHDATA1:
                    r += bytes([len(d)])
                elif o == OP_PUSHDATA2:
                    r += pack('<H', len(d))
                elif o == OP_PUSHDATA4:
                    r += pack('<L', len(d))
                r += d

        offset += 1
        if d is not None:
            offset += len(d)
            if o == OP_PUSHDATA1:
                offset += 1
            elif o == OP_PUSHDATA2:
                offset += 2
            elif o == OP_PUSHDATA4:
                offset += 4

        o, d = read_opcode(stream)
    return r.hex() if s_hex else r
Example #11
0
def encode_base58(b, checksum=False):
    """Encode bytes to a base58-encoded string"""
    # Convert big-endian bytes to integer
    if not b:
        return ''
    b = get_bytes(b)
    if checksum:
        return __encode_base58__(b"%s%s" % (b, double_sha256(b)[:4]))
    return __encode_base58__(b)
Example #12
0
def op_push_data(data):
    data = get_bytes(data)
    if len(data) <= 0x4b:
        return b''.join([bytes([len(data)]), data])
    elif len(data) <= 0xff:
        return b''.join([OP_PUSHDATA1, bytes([len(data)]), data])
    elif len(data) <= 0xffff:
        return b''.join([OP_PUSHDATA2, pack('<H', len(data)), data])
    else:
        return b''.join([OP_PUSHDATA4, pack('<L', len(data)), data])
Example #13
0
def get_multisig_public_keys(script, hex=False):
    script = get_bytes(script)
    pub_keys = []
    s = get_stream(script)
    o, d = read_opcode(s)
    while o:
        o, d = read_opcode(s)
        if d:
            pub_keys.append(d.hex() if hex else d)
    return pub_keys
Example #14
0
def murmurhash3(seed, h, encoding = None):
    """
    Calculate murmurhash3 from byte string

    :param h: byte string or HEX encoded string
    :param seed: seed randomization vector integer
    :return: hash as integer
    """

    h = get_bytes(h, encoding=encoding)
    return __murmurhash3__(seed, h)
Example #15
0
def siphash(h, v_0=0, v_1=0, encoding = None):
    """
    Calculate siphash from byte string

    :param h: byte string or HEX encoded string
    :param v_0: randomization  vector 0  64 bit integer
    :param v_1:  randomization  vector 1  64 bit integer
    :return: hash as 64 bit integer
    """
    h = get_bytes(h, encoding=encoding)
    return __siphash__(v_0, v_1, h)
Example #16
0
def hash_to_address(address_hash,
                    testnet=False,
                    script_hash=False,
                    witness_version=0):
    """
    Get address from public key/script hash. In case PUBKEY, P2PKH, P2PKH public key/script hash is SHA256+RIPEMD160,
    P2WSH script hash is SHA256.


    :param address_hash: public key hash or script hash in HEX or bytes string format.
    :param testnet: (optional) flag for testnet network, by default is False.
    :param script_hash: (optional) flag for script hash (P2SH address), by default is False.
    :param witness_version: (optional) witness program version, by default is 0, for legacy
                            address format use None.
    :return: address in base58 or bech32 format.
    """
    address_hash = get_bytes(address_hash, encoding='hex')

    if not script_hash:
        if witness_version is None:
            if len(address_hash) != 20:
                raise ValueError("address hash length incorrect")
            if testnet:
                prefix = TESTNET_ADDRESS_BYTE_PREFIX
            else:
                prefix = MAINNET_ADDRESS_BYTE_PREFIX
            address_hash = b"%s%s" % (prefix, address_hash)
            address_hash += double_sha256(address_hash)[:4]
            return encode_base58(address_hash)
        else:
            if len(address_hash) not in (20, 32):
                raise ValueError("address hash length incorrect")

    if witness_version is None:
        if testnet:
            prefix = TESTNET_SCRIPT_ADDRESS_BYTE_PREFIX
        else:
            prefix = MAINNET_SCRIPT_ADDRESS_BYTE_PREFIX
        address_hash = b"%s%s" % (prefix, address_hash)
        address_hash += double_sha256(address_hash)[:4]
        return encode_base58(address_hash)

    if testnet:
        prefix = TESTNET_SEGWIT_ADDRESS_BYTE_PREFIX
        hrp = TESTNET_SEGWIT_ADDRESS_PREFIX
    else:
        prefix = MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX
        hrp = MAINNET_SEGWIT_ADDRESS_PREFIX

    address_hash = b"%s%s" % (witness_version.to_bytes(
        1, "big"), rebase_8_to_5(address_hash))
    checksum = bech32_polymod(b"%s%s%s" % (prefix, address_hash, b"\x00" * 6))
    checksum = rebase_8_to_5(checksum.to_bytes(5, "big"))[2:]
    return "%s1%s" % (hrp, rebase_5_to_32(address_hash + checksum).decode())
Example #17
0
def script_to_hash(script, witness=False, hex=True):
    """
    Encode script to hash HASH160 or SHA256 in dependency of the witness.

    :param script: script in bytes or HEX encoded string.
    :param witness:  (optional) If set to True return SHA256 hash for P2WSH, by default is False.
    :param hex:  (optional) If set to True return key in HEX format, by default is True.
    :param sub_script:  sub_script which is necessary to remove from target script in bytes or HEX encoded string.
    :return: script in bytes or HEX encoded string corresponding to the format of target script.
    """
    script = get_bytes(script)
    return sha256(script, hex) if witness else hash160(script, hex)
Example #18
0
def entropy_to_mnemonic(entropy,
                        language='english',
                        word_list_dir=None,
                        word_list=None,
                        data=None):
    """
    Convert entropy to mnemonic words string.

    :param str,bytes entropy: random entropy HEX encoded or bytes string.
    :param str language: (optional) uses word list language (chinese_simplified, chinese_traditional, english, french,
                         italian, japanese, korean, spanish), by default is english.
    :param str word_list_dir: (optional) path to a directory containing a list of words,
                              by default None (use BIP39 standard list)
    :param list word_list: (optional) already loaded word list, by default None    
    :return: mnemonic words string.
    """
    entropy = get_bytes(entropy)
    if len(entropy) not in [16, 20, 24, 28, 32]:
        raise ValueError(
            'entropy length should be one of the following: [16, 20, 24, 28, 32]'
        )
    if word_list is None:
        word_list = load_word_list(language, word_list_dir)
    elif not isinstance(word_list, list) or len(word_list) != 2048:
        raise TypeError("invalid word list type")

    i = int.from_bytes(entropy, byteorder="big")
    # append checksum
    b = math.ceil(len(entropy) * 8 / 32)
    if data is not None:
        if data > (2**b - 1):
            raise ValueError('embedded data bits too long')
        i = (i << b) | data
    else:
        i = (i << b) | (sha256(entropy)[0] >> (8 - b))

    return " ".join([
        word_list[i.__rshift__(((d - 1) * 11)) & 2047]
        for d in range(int((len(entropy) * 8 + 8) // 11), 0, -1)
    ])
Example #19
0
def hmac_sha512(key, data, hex=False, encoding=None):
    key = get_bytes(key, encoding=encoding)
    data = get_bytes(data, encoding=encoding)
    if hex:
        return hmac.new(key, data, hashlib_sha512).hexdigest()
    return hmac.new(key, data, hashlib_sha512).digest()
Example #20
0
def double_sha256(h, hex=False, encoding=None):
    h = get_bytes(h, encoding=encoding)
    return __double_sha256__(h).hex() if hex else __double_sha256__(h)
Example #21
0
def public_key_to_p2sh_p2wpkh_script(pubkey, hex=False):
    pubkey = get_bytes(pubkey)
    if len(pubkey) != 33:
        raise ValueError("public key len invalid")
    r = b'\x00\x14%s' % hash160(pubkey)
    return r.hex() if hex else r
Example #22
0
def decode_script(script, asm=False):
    """
    Decode script to ASM format or to human readable OPCODES string.

    :param script: script in bytes string or HEX encoded string format.
    :param asm:  (optional) If set to True decode to ASM format, by default set to False.
    :return: script in ASM format string or OPCODES string.
    """

    script = get_bytes(script)
    l = len(script)
    s = 0
    result = []
    append = result.append
    try:
        while l - s > 0:
            if script[s] < 0x4c and script[s]:
                if asm:
                    append("OP_PUSHBYTES[%s]" % script[s])
                    append(script[s + 1:s + 1 + script[s]].hex())
                else:
                    append('[%s]' % script[s])
                s += script[s] + 1
                continue

            if script[s] == OPCODE["OP_PUSHDATA1"]:
                if asm:
                    ld = script[s + 1]
                    append("OP_PUSHDATA1[%s]" % ld)
                    append(script[s + 2:s + 2 + ld].hex())
                else:
                    append(RAW_OPCODE[script[s]])
                    ld = script[s + 1]
                    append('[%s]' % ld)
                s += 1 + script[s + 1] + 1
            elif script[s] == OPCODE["OP_PUSHDATA2"]:
                if asm:
                    ld = unpack('<H', script[s + 1:s + 3])[0]
                    append("OP_PUSHDATA2[%s]" % ld)
                    append(script[s + 3:s + 3 + ld].hex())
                else:
                    ld = unpack('<H', script[s + 1:s + 3])[0]
                    append(RAW_OPCODE[script[s]])
                    append('[%s]' % ld)
                s += 2 + 1 + ld
            elif script[s] == OPCODE["OP_PUSHDATA4"]:
                if asm:
                    ld = unpack('<L', script[s + 1:s + 5])[0]
                    append("OP_PUSHDATA4[%s]" % ld)
                    append(script[s + 5:s + 5 + ld].hex())
                else:
                    ld = unpack('<L', script[s + 1:s + 5])[0]
                    append(RAW_OPCODE[script[s]])
                    append('[%s]' % ld)
                s += 5 + 1 + ld
            else:
                append(RAW_OPCODE[script[s]])
                s += 1
    except:
        append("[SCRIPT_DECODE_FAILED]")
    return ' '.join(result)
Example #23
0
def ripemd160(h, hex=False, encoding=None):
    h = get_bytes(h, encoding=encoding)
    a = hashlib_new('ripemd160')
    a.update(h)
    return a.hexdigest() if hex else a.digest()
Example #24
0
def test_delete_from_script():
    assert delete_from_script([OP_1, OP_2], []) == get_bytes([OP_1, OP_2])
    assert delete_from_script([OP_1, OP_2, OP_3],
                              [OP_2]) == get_bytes([OP_1, OP_3])
    assert delete_from_script([OP_3, OP_1, OP_3, OP_3, OP_4, OP_3],
                              [OP_3]) == get_bytes([OP_1, OP_4])
    assert delete_from_script([b"\x03", b"\x02\xff\x03"],
                              [b"\x03", b"\x02\xff\x03"]) == get_bytes([])
    assert delete_from_script(
        [b"\x03", b"\x02\xff\x03", b"\x03", b"\x02\xff\x03"],
        [b"\x03", b"\x02\xff\x03"]) == get_bytes([])
    assert delete_from_script(
        [b"\x03", b"\x02\xff\x03", b"\x03", b"\x02\xff\x03"],
        [b"\x02"]) == get_bytes(
            [b"\x03", b"\x02\xff\x03", b"\x03", b"\x02\xff\x03"])
    assert delete_from_script(
        [b"\x03", b"\x02\xff\x03", b"\x03", b"\x02\xff\x03"],
        [b"\xff"]) == get_bytes(
            [b"\x03", b"\x02\xff\x03", b"\x03", b"\x02\xff\x03"])

    assert delete_from_script(
        [b"\x03", b"\x02\xff\x03", b"\x03", b"\x02\xff\x03"],
        [b"\x03"]) == get_bytes([b"\x02\xff\x03", b"\x02\xff\x03"])
    assert delete_from_script([b"\x02", b"\xfe\xed", OP_1, OP_VERIFY],
                              [b"\xfe\xed", OP_1]) == \
           get_bytes([b"\x02", b"\xfe\xed", OP_1, OP_VERIFY])

    assert delete_from_script([b"\x02", b"\xfe\xed", OP_1, OP_VERIFY],
                              [b"\x02", b"\xfe\xed", OP_1]) == get_bytes(
                                  [OP_VERIFY])

    s = "0302ff030302ff03"
    d = "0302ff03"
    e = ""
    assert delete_from_script(s, d) == e

    s = "0302ff030302ff03"
    d = "02"
    assert delete_from_script(s, d) == s

    s = "0302ff030302ff03"
    d = "ff"
    assert delete_from_script(s, d) == s
    s = "0302ff030302ff03"
    d = "03"
    e = "02ff0302ff03"
    assert delete_from_script(s, d) == e

    s = "02feed5169"
    d = "feed51"
    e = s
    assert delete_from_script(s, d) == e

    s = "02feed5169"
    d = "02feed51"
    e = "69"
    assert delete_from_script(s, d) == e
    #
    s = "516902feed5169"
    d = "feed51"
    e = s
    assert delete_from_script(s, d) == e

    s = "516902feed5169"
    d = "02feed51"
    e = "516969"
    assert delete_from_script(s, d) == e

    s = BYTE_OPCODE["OP_0"] + BYTE_OPCODE["OP_0"] + BYTE_OPCODE["OP_1"]
    s += BYTE_OPCODE["OP_1"]
    d = BYTE_OPCODE["OP_0"] + BYTE_OPCODE["OP_1"]
    e = d
    assert delete_from_script(s, d) == e

    s = BYTE_OPCODE["OP_0"] + BYTE_OPCODE["OP_0"] + BYTE_OPCODE["OP_1"]
    s += BYTE_OPCODE["OP_0"] + BYTE_OPCODE["OP_1"] + BYTE_OPCODE["OP_1"]
    d = BYTE_OPCODE["OP_0"] + BYTE_OPCODE["OP_1"]
    e = d
    assert delete_from_script(s, d) == e

    s = "0003feed"
    d = "03feed"
    e = "00"
    assert delete_from_script(s, d) == e

    s = "0003feed"
    d = "00"
    e = "03feed"
    assert delete_from_script(s, d) == e
    assert delete_from_script([OP_PUSHDATA1, pack('<B', 20),b"12345678901234567890"], "00").hex() == \
           "4c143132333435363738393031323334353637383930"
    assert delete_from_script([OP_PUSHDATA2, pack('<H', 20),b"12345678901234567890"], "00").hex() == \
           "4d14003132333435363738393031323334353637383930"
    assert delete_from_script([OP_PUSHDATA4, pack('<L', 20),b"12345678901234567890"], "00").hex() == \
           "4e140000003132333435363738393031323334353637383930"
Example #25
0
def is_valid_signature_encoding(sig):
    """
    Check is valid signature encoded in DER format

    :param sig:  signature in bytes or HEX encoded string.
    :return:  boolean.  
    """
    # Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
    # * total-length: 1-byte length descriptor of everything that follows,
    #   excluding the sighash byte.
    # * R-length: 1-byte length descriptor of the R value that follows.
    # * R: arbitrary-length big-endian encoded R value. It must use the shortest
    #   possible encoding for a positive integers (which means no null bytes at
    #   the start, except a single one when the next byte has its highest bit set).
    # * S-length: 1-byte length descriptor of the S value that follows.
    # * S: arbitrary-length big-endian encoded S value. The same rules apply.
    # * sighash: 1-byte value indicating what data is hashed (not part of the DER
    #   signature)
    sig = get_bytes(sig)
    length = len(sig)
    # Minimum and maximum size constraints.
    if (length < 9) or (length > 73):
        return False
    # A signature is of type 0x30 (compound).
    if sig[0] != 0x30:
        return False
    # Make sure the length covers the entire signature.
    if sig[1] != (length - 3):
        return False
    # Extract the length of the R element.
    len_r = sig[3]
    # Zero-length integers are not allowed for R.
    if len_r == 0:
        return False
    # Make sure the length of the S element is still inside the signature.
    if (5 + len_r) >= length:
        return False

    # Extract the length of the S element.
    len_s = sig[5 + len_r]
    # Verify that the length of the signature matches the sum of the length
    # of the elements.
    # Zero-length integers are not allowed for S.
    if len_s == 0:
        return False

    if (len_r + len_s + 7) != length:
        return False
    # Check whether the R element is an integer.
    if sig[2] != 0x02:
        return False
    # Negative numbers are not allowed for R.
    if sig[4] & 0x80:
        return False
    # Null bytes at the start of R are not allowed, unless R would
    # otherwise be interpreted as a negative number.

    if (len_r > 1) and (sig[4] == 0x00) and (not sig[5] & 0x80):
        return False
    # Check whether the S element is an integer.
    if sig[len_r + 4] != 0x02:
        return False
    # Negative numbers are not allowed for S.
    if sig[len_r + 6] & 0x80:
        return False
    # Null bytes at the start of S are not allowed, unless S would otherwise be
    # interpreted as a negative number.
    if (len_s > 1) and (sig[len_r + 6]
                        == 0x00) and (not sig[len_r + 7] & 0x80):
        return False
    return True
Example #26
0
def public_key_to_pubkey_script(key, hex=True):
    key = get_bytes(key)
    s = b"%s%s%s" % (bytes([len(key)]), key, OP_CHECKSIG)
    return s.hex() if hex else s
Example #27
0
def hash160(h, hex=False, encoding=None):
    h = get_bytes(h, encoding=encoding)
    return ripemd160(sha256(h), True) if hex else ripemd160(sha256(h))
Example #28
0
def parse_script(script, segwit=True):
    """
    Parse script and return script type, script address and required signatures count.

    :param script: script in bytes string or HEX encoded string format.
    :param segwit:  (optional) If set to True recognize P2WPKH and P2WSH sripts, by default set to True.

    :return: dictionary:

            - nType - numeric script type
            - type  - script type
            - addressHash - address hash in case address recognized
            - script - script if no address recognized
            - reqSigs - required signatures count
    """
    if not script:
        return {
            "nType": 7,
            "type": "NON_STANDARD",
            "reqSigs": 0,
            "script": b""
        }
    script = get_bytes(script)
    l = len(script)
    if segwit:
        if l == 22 and script[0] == 0:
            return {
                "nType": 5,
                "type": "P2WPKH",
                "reqSigs": 1,
                "addressHash": script[2:]
            }
        if l == 34 and script[0] == 0:
            return {
                "nType": 6,
                "type": "P2WSH",
                "reqSigs": None,
                "addressHash": script[2:]
            }
    if l == 25 and \
       script[:2] == b"\x76\xa9" and \
       script[-2:] == b"\x88\xac":
        return {
            "nType": 0,
            "type": "P2PKH",
            "reqSigs": 1,
            "addressHash": script[3:-2]
        }
    if l == 23 and \
       script[0] == 169 and \
       script[-1] == 135:
        return {
            "nType": 1,
            "type": "P2SH",
            "reqSigs": None,
            "addressHash": script[2:-1]
        }
    if l == 67 and script[-1] == 172:
        return {
            "nType": 2,
            "type": "PUBKEY",
            "reqSigs": 1,
            "addressHash": hash160(script[1:-1])
        }
    if l == 35 and script[-1] == 172:
        return {
            "nType": 2,
            "type": "PUBKEY",
            "reqSigs": 1,
            "addressHash": hash160(script[1:-1])
        }
    if script[0] == OPCODE["OP_RETURN"]:
        if l == 1:
            return {"nType": 3, "type": "NULL_DATA", "reqSigs": 0, "data": b""}
        elif script[1] < OPCODE["OP_PUSHDATA1"]:
            if script[1] == l - 2:
                return {
                    "nType": 3,
                    "type": "NULL_DATA",
                    "reqSigs": 0,
                    "data": script[2:]
                }
        elif script[1] == OPCODE["OP_PUSHDATA1"]:
            if l > 2:
                if script[2] == l - 3 and script[2] <= 80:
                    return {
                        "nType": 3,
                        "type": "NULL_DATA",
                        "reqSigs": 0,
                        "data": script[3:]
                    }
        return {
            "nType": 8,
            "type": "NULL_DATA_NON_STANDARD",
            "reqSigs": 0,
            "script": script
        }
    if script[0] >= 81 and script[0] <= 96:
        if script[-1] == 174:
            if script[-2] >= 81 and script[-2] <= 96:
                if script[-2] >= script[0]:
                    c, s = 0, 1
                    while l - 2 - s > 0:
                        if script[s] < 0x4c:
                            s += script[s]
                            c += 1
                        else:
                            c = 0
                            break
                        s += 1
                    if c == script[-2] - 80:
                        return {
                            "nType": 4,
                            "type": "MULTISIG",
                            "reqSigs": script[0] - 80,
                            "pubKeys": c,
                            "script": script
                        }

    s, m, n, last, req_sigs = 0, 0, 0, 0, 0
    while l - s > 0:
        # OP_1 -> OP_16
        if script[s] >= 81 and script[s] <= 96:
            if not n:
                n = script[s] - 80
            elif not m:
                n, m = script[s] - 80, 0
            elif n > m:
                n, m = script[s] - 80, 0
            elif m == script[s] - 80:
                last = 0 if last else 2
        elif script[s] < 0x4c:
            s += script[s]
            m += 1
            if m > 16:
                n, m = 0, 0
        elif script[s] == OPCODE["OP_PUSHDATA1"]:
            try:
                s += 1 + script[s + 1]
            except:
                break
        elif script[s] == OPCODE["OP_PUSHDATA2"]:
            try:
                s += 2 + unpack('<H', script[s + 1:s + 3])[0]
            except:
                break
        elif script[s] == OPCODE["OP_PUSHDATA4"]:
            try:
                s += 4 + unpack('<L', script[s + 1:s + 5])[0]
            except:
                break
        else:
            if script[s] == OPCODE["OP_CHECKSIG"]:
                req_sigs += 1
            elif script[s] == OPCODE["OP_CHECKSIGVERIFY"]:
                req_sigs += 1
            elif script[s] in (OPCODE["OP_CHECKMULTISIG"],
                               OPCODE["OP_CHECKMULTISIGVERIFY"]):
                if last:
                    req_sigs += n
                else:
                    req_sigs += 20
            n, m = 0, 0
        if last:
            last -= 1
        s += 1
    return {
        "nType": 7,
        "type": "NON_STANDARD",
        "reqSigs": req_sigs,
        "script": script
    }