示例#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)
示例#2
0
def decode_gcs(h):
    stream = get_stream(h)
    L = var_int_to_int(read_var_int(stream))
    P = var_int_to_int(read_var_int(stream))
    s = deque()
    s_append = s.append
    last = 0
    gcs_filter = bitarray(endian='big')
    gcs_filter.frombytes(stream.read())

    f = 0
    for i in range(L):
        q = 0
        r = 0

        while gcs_filter[f]:
            q += 1
            f += 1
        f += 1
        c = P - 1

        while c >= 0:
            r = r << 1
            if gcs_filter[f]:
                r += 1
            f += 1
            c -= 1
        delta = (q << P) + r
        last += delta
        s_append(last)
    return s
示例#3
0
def get_multisig_public_keys(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)
    return pub_keys
示例#4
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
示例#5
0
 def __get_multisig_script_sig__(self,  script_sig,
                                 keys, signatures,
                                 script_code,
                                 redeem_script,
                                 n, amount=None):
     sig_map = {keys[i]:signatures[i] for i in range(len(keys))}
     pub_keys = get_multisig_public_keys(redeem_script)
     p2wsh = True if isinstance(script_sig, list) else False
     if not p2wsh:
         s = get_stream(script_sig)
         o, d = read_opcode(s)
         while o:
             o, d = read_opcode(s)
             if d and is_valid_signature_encoding(d):
                 for i in range(4):
                     sighash = self.sig_hash(n, script_pub_key=script_code, sighash_type=d[-1])
                     sighash = s2rh(sighash) if isinstance(sighash, str) else sighash
                     pk = public_key_recovery(d[:-1], sighash, i, hex=0)
                     if pk in pub_keys:
                         sig_map[pk] = d
                         break
         # recreate script sig
         r = [OP_0]
         for k in pub_keys:
             try:
                 r.append(op_push_data(sig_map[k]))
             except:
                 pass
         r += [op_push_data(redeem_script)]
     else:
         for w in script_sig:
             if isinstance(w, str):
                 w = bytes.fromhex(w)
             if w and is_valid_signature_encoding(w):
                 d = w[:-1]
                 for i in range(4):
                     sighash = self.sig_hash_segwit(n, amount,
                                                    script_pub_key=script_code,
                                                    sighash_type=w[-1])
                     pk = public_key_recovery(d, sighash, i, hex=0)
                     if pk in pub_keys:
                         sig_map[pk] = w
                         break
         r = [b""]
         for k in pub_keys:
             try:
                 r.append(sig_map[k])
             except:
                 pass
         r += [redeem_script]
     return r
示例#6
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
示例#7
0
def decode_huffman(h):
    if h:
        stream = get_stream(h)
        c = var_int_to_int(read_var_int(stream))
        freq = dict()
        for i in range(c):
            key = var_int_to_int(read_var_int(stream))
            freq[key] = i + 1
        codes = huffman_code(huffman_tree(freq))

        l = var_int_to_int(read_var_int(stream))
        delta_bit_length = var_int_to_int(read_var_int(stream))
        d = bitarray()
        d.frombytes(stream.read(l))
        while d.length() > (l * 8 - delta_bit_length):
            d.pop()
        return d.decode(codes)
    return []
示例#8
0
 def __get_bare_multisig_script_sig__(self,  script_sig, script_pub_key,
                                      keys, signatures, n):
     sig_map = {keys[i]:signatures[i] for i in range(len(keys))}
     pub_keys = get_multisig_public_keys(script_pub_key)
     s = get_stream(script_sig)
     o, d = read_opcode(s)
     while o:
         o, d = read_opcode(s)
         if d and is_valid_signature_encoding(d):
             for i in range(4):
                 sighash = self.sig_hash(n, script_pub_key=script_pub_key, sighash_type=d[-1])
                 sighash = s2rh(sighash) if isinstance(sighash, str) else sighash
                 pk = public_key_recovery(d[:-1], sighash, i, hex=0)
                 if pk in pub_keys:
                     sig_map[pk] = d
                     break
     # recreate script sig
     r = [OP_0]
     for k in pub_keys:
         try:
             r.append(op_push_data(sig_map[k]))
         except:
             pass
     return r
示例#9
0
def decode_dhcs(h):
    # Delta-Hoffman coded set
    stream = get_stream(h)

    # read code_table_1
    c = var_int_to_int(read_var_int(stream))
    code_table_1 = dict()
    for i in range(c):
        key = var_int_to_int(read_var_int(stream))
        l = var_int_to_int(read_var_int(stream))
        code = bitarray([bool(k) for k in stream.read(l)])
        code_table_1[key] = code

    # read code_table_2
    c = var_int_to_int(read_var_int(stream))
    code_table_2 = dict()
    for i in range(c):
        key = var_int_to_int(read_var_int(stream))
        l = var_int_to_int(read_var_int(stream))
        code = bitarray([bool(k) for k in stream.read(l)])
        code_table_2[key] = code

    # read compressed deltas
    deltas_bits_len_1 = var_int_to_int(read_var_int(stream))
    deltas_bits_len_2 = var_int_to_int(read_var_int(stream))
    deltas_byte_len = deltas_bits_len_2 // 8 + int(bool(deltas_bits_len_2 % 8))

    r = stream.read(deltas_byte_len)
    deltas = bitarray()
    deltas.frombytes(r)

    while deltas.length() > deltas_bits_len_2:
        deltas.pop()

    # Huffman decode round 1
    r = deltas.decode(code_table_2)
    deltas_string = bytearray()
    for i in range(int(len(r) / 2)):
        deltas_string += bytes([(r[i * 2] << 4) + r[i * 2 + 1]])

    # Huffman decode round 2
    r = bitarray()
    r.frombytes(bytes(deltas_string))

    while r.length() > deltas_bits_len_1:
        r.pop()

    deltas_bits = r.decode(code_table_1)

    d_filter_bit_len = var_int_to_int(read_var_int(stream))
    d_filter_byte_len = d_filter_bit_len // 8 + int(bool(d_filter_bit_len % 8))
    r = stream.read(d_filter_byte_len)

    d_filter = bitarray()
    d_filter.frombytes(r)

    while d_filter.length() > d_filter_bit_len:
        d_filter.pop()

    f = 0
    f_max = d_filter.length()
    decoded_set = set()
    last = 0

    for bits in deltas_bits:
        d = 0
        while bits > 0 and f < f_max:
            bits -= 1
            d = d << 1
            if d_filter[f]:
                d += 1
            f += 1
        last += d
        decoded_set.add(last)

    return decoded_set