Beispiel #1
0
 def serialize(self, segwit=True, hex=True):
     """
     Get serialized transaction 
     
     :param bool segwit: (optional) flag for segwit representation of serialized transaction, by 
                         default True.
     :param bool hex: (optional) if set to True return HEX encoded string, by default True.
     :return str,bytes: serialized transaction in HEX or bytes.
      """
     chunks = []
     append = chunks.append
     append(pack('<L', self["version"]))
     if segwit and self["segwit"]:
         append(b"\x00\x01")
     append(int_to_var_int(len(self["vIn"])))
     for i in self["vIn"]:
         if isinstance(self["vIn"][i]['txId'], bytes):
             append(self["vIn"][i]['txId'])
         else:
             append(s2rh(self["vIn"][i]['txId']))
         append(pack('<L', self["vIn"][i]['vOut']))
         if isinstance(self["vIn"][i]['scriptSig'], bytes):
             append(int_to_var_int(len(self["vIn"][i]['scriptSig'])))
             append(self["vIn"][i]['scriptSig'])
         else:
             append(int_to_var_int(int(len(self["vIn"][i]['scriptSig']) / 2)))
             append(bytes_from_hex(self["vIn"][i]['scriptSig']))
         append(pack('<L', self["vIn"][i]['sequence']))
     append(int_to_var_int(len(self["vOut"])))
     for i in self["vOut"]:
         append(pack('<Q', self["vOut"][i]['value']))
         if isinstance(self["vOut"][i]['scriptPubKey'], bytes):
             append(int_to_var_int(len(self["vOut"][i]['scriptPubKey'])))
             append(self["vOut"][i]['scriptPubKey'])
         else:
             append(int_to_var_int(int(len(self["vOut"][i]['scriptPubKey']) / 2)))
             append(bytes_from_hex(self["vOut"][i]['scriptPubKey']))
     if segwit and self["segwit"]:
         for i in self["vIn"]:
             append(int_to_var_int(len(self["vIn"][i]['txInWitness'])))
             for w in self["vIn"][i]['txInWitness']:
                 if isinstance(w, bytes):
                     append(int_to_var_int(len(w)))
                     append(w)
                 else:
                     append(int_to_var_int(int(len(w) / 2)))
                     append(bytes_from_hex(w))
     append(pack('<L', self['lockTime']))
     tx = b''.join(chunks)
     return tx if not hex else tx.hex()
Beispiel #2
0
def encode_huffman(elements):
    if elements:
        map_freq = dict()
        for value in elements:
            try:
                map_freq[value] += 1
            except:
                map_freq[value] = 1
        bitstr = bitarray()
        nfreq, code_table = huffman_freq_normalize(map_freq)
        codes = huffman_code(huffman_tree(nfreq))
        bitstr.encode(codes, elements)

        code_table_string = int_to_var_int(len(code_table))
        for code in code_table:
            code_table_string += int_to_var_int(code)
        h = bitstr.tobytes()
        delta_bit_length = 8 * len(h) - bitstr.length()
        return b"".join((code_table_string, int_to_var_int(len(h)),
                         int_to_var_int(delta_bit_length), h))
    return b""
Beispiel #3
0
 def __sign_p2wsh_multisig(self, n, private_key, public_key, script_pub_key, redeem_script, sighash_type, amount):
     script_code = int_to_var_int(len(redeem_script)) + redeem_script
     sighash = self.sig_hash_segwit(n, amount, script_pub_key=script_code, sighash_type=sighash_type)
     sighash = bytes.fromhex(sighash) if isinstance(sighash, str) else sighash
     sig = [sign_message(sighash, p, 0) + bytes([sighash_type]) for p in private_key]
     self["vIn"][n]['signatures'] = [s if self["format"] == "raw" else s.hex() for s in sig]
     if "txInWitness" not in self["vIn"][n]:
         self["vIn"][n]["txInWitness"] = []
     witness = self.__get_multisig_script_sig__(self["vIn"][n]["txInWitness"],
                                                public_key, sig, script_code, redeem_script, n, amount)
     if self["format"] == "raw":
         self["vIn"][n]['txInWitness'] = list(witness)
     else:
         self["vIn"][n]["txInWitness"] = list([w.hex() for w in witness])
     return b""
Beispiel #4
0
    def multisig(cls, n, m, public_key_list, testnet=False, witness_version=0):
        """
        The class method for creating a multisig address.

        :param n: count of required signatures (max 15).
        :param m: count of total addresses of participants (max 15).
        :param list address_list: addresses list, allowed types:
                       
                             - bytes or HEX encoded private key
                             - private key in WIF format
                             - PrivateKey instance,
                             - bytes or HEX encoded public key
                             - PublicKey instance
                             
                             
        """
        if n > 15 or m > 15 or n > m or n < 1 or m < 1:
            raise TypeError("invalid n of m maximum 15 of 15 multisig allowed")
        if len(public_key_list) != m:
            raise TypeError("invalid address list count")
        script = bytes([0x50 + n])
        for a in list(public_key_list):
            if isinstance(a, str):
                try:
                    a = bytes.fromhex(a)
                except:
                    if is_wif_valid(a):
                        a = private_to_public_key(a, hex=False)
                    pass
            if isinstance(a, Address):
                a = a.public_key.key
            elif isinstance(a, PublicKey):
                a = a.key
            elif isinstance(a, PrivateKey):
                a = private_to_public_key(a.key)
            if not isinstance(a, bytes):
                raise TypeError("invalid public key list element")
            if len(a) == 32:
                a = private_to_public_key(a)
            if len(a) != 33:
                raise TypeError("invalid public key list element size")
            script += b"%s%s" % (int_to_var_int(len(a)), a)
        script += b"%s%s" % (bytes([0x50 + m]), OP_CHECKMULTISIG)
        return cls(script, testnet=testnet, witness_version=witness_version)
Beispiel #5
0
    def sig_hash_segwit(self, n, amount, script_pub_key=None, sighash_type=SIGHASH_ALL, preimage=False):
        try:
            self["vIn"][n]
        except:
            raise Exception("sig_hash error, input not exist")

        # check script_pub_key for input
        if script_pub_key is not None:
            script_code = script_pub_key
        else:
            if  "scriptPubKey" not in self["vIn"][n]:
                raise Exception("sig_hash error, scriptPubKey required")
            script_code = self["vIn"][n]["scriptPubKey"]
        if isinstance(script_code, str):
            script_code = bytes.fromhex(script_code)
        if not isinstance(script_code,bytes):
            raise Exception("sig_hash error, script_code type error")

        # remove opcode separators
        pm = bytearray()
        # 1. nVersion of the transaction (4-byte little endian)
        pm += pack('<L', self["version"])
        # 2. hashPrevouts (32-byte hash)
        # 3. hashSequence (32-byte hash)
        # 4. outpoint (32-byte hash + 4-byte little endian)
        # 5. scriptCode of the input (serialized as scripts inside CTxOuts)
        # 6. value of the output spent by this input (8-byte little endian)
        # 7. nSequence of the input (4-byte little endian)
        hp = bytearray()  # hash of out points
        hs = bytearray()  # hash of sequences
        for i in self["vIn"]:
            tx_id = self["vIn"][i]["txId"]
            if type(tx_id) == str:
                tx_id = s2rh(tx_id)
            if not (sighash_type & SIGHASH_ANYONECANPAY):
                hp += b"%s%s" % (tx_id, pack('<L', self["vIn"][i]["vOut"]))
                if (sighash_type & 31) != SIGHASH_SINGLE and (sighash_type & 31) != SIGHASH_NONE:
                    hs += pack('<L', self["vIn"][i]["sequence"])
            if i == n:
                outpoint = b"%s%s" % (tx_id, pack('<L', self["vIn"][i]["vOut"]))
                n_sequence = pack('<L', self["vIn"][i]["sequence"])
        hash_prevouts = double_sha256(hp) if hp else b'\x00' * 32
        hash_sequence = double_sha256(hs) if hs else b'\x00' * 32
        value = amount.to_bytes(8, 'little')
        # 8. hashOutputs (32-byte hash)
        ho = bytearray()
        for o in self["vOut"]:
            script_pub_key = self["vOut"][o]["scriptPubKey"]
            if type(self["vOut"][o]["scriptPubKey"]) == str:
                script_pub_key = bytes_from_hex(script_pub_key)
            if (sighash_type & 31) != SIGHASH_SINGLE and (sighash_type & 31) != SIGHASH_NONE:
                ho += b"%s%s%s" % (self["vOut"][o]["value"].to_bytes(8, 'little'),
                                 int_to_var_int(len(script_pub_key)),
                                 script_pub_key)
            elif (sighash_type & 31) == SIGHASH_SINGLE and n < len(self["vOut"]):
                if o == n:
                    ho += b"%s%s%s" % (self["vOut"][o]["value"].to_bytes(8, 'little'),
                                       int_to_var_int(len(script_pub_key)),
                                       script_pub_key)
        hash_outputs = double_sha256(ho) if ho else b'\x00' * 32
        pm += b"%s%s%s%s%s%s%s%s%s" % (hash_prevouts, hash_sequence, outpoint,
                                       script_code, value, n_sequence, hash_outputs,
                                       pack('<L', self["lockTime"]),
                                       pack('<L', sighash_type))
        if not preimage:
            pm = double_sha256(pm)
        return pm if self["format"] == "raw" else pm.hex()
Beispiel #6
0
    def sig_hash(self, n, script_pub_key=None, sighash_type=SIGHASH_ALL, preimage=False):
        try:
            self["vIn"][n]
        except:
            raise Exception("sig_hash error, input not exist")

        # check script_pub_key for input
        if script_pub_key is not None:
            script_code = script_pub_key
        else:
            if  "scriptPubKey" not in self["vIn"][n]:
                raise Exception("sig_hash error, scriptPubKey required")
            script_code = self["vIn"][n]["scriptPubKey"]
        if isinstance(script_code, str):
            script_code = bytes.fromhex(script_code)
        if not isinstance(script_code,bytes):
            raise Exception("sig_hash error, script_code type error")

        # remove opcode separators
        if ((sighash_type & 31) == SIGHASH_SINGLE) and (n >= (len(self["vOut"]))):
            if self["format"] == "raw":
                return  b'\x01%s' % (b'\x00' * 31)
            return rh2s(b'\x01%s' % (b'\x00' * 31))

        script_code = delete_from_script(script_code, BYTE_OPCODE["OP_CODESEPARATOR"])
        pm = bytearray()
        pm += b"%s%s" % (pack('<L', self["version"]),
                         b'\x01' if sighash_type & SIGHASH_ANYONECANPAY else int_to_var_int(len(self["vIn"])))
        for i in self["vIn"]:
            # skip all other inputs for SIGHASH_ANYONECANPAY case
            if (sighash_type & SIGHASH_ANYONECANPAY) and (n != i):
                continue
            sequence = self["vIn"][i]["sequence"]
            if ((sighash_type & 31) == SIGHASH_SINGLE or (sighash_type & 31) == SIGHASH_NONE) and (n != i):
                sequence = 0
            tx_id = self["vIn"][i]["txId"]
            if isinstance(tx_id, str):
                tx_id = s2rh(tx_id)

            if n == i:
                pm += b"%s%s%s%s%s" % (tx_id, pack('<L', self["vIn"][i]["vOut"]),
                                       int_to_var_int(len(script_code)),
                                       script_code, pack('<L', sequence))
            else:
                pm += b'%s%s\x00%s' % (tx_id,
                                       pack('<L', self["vIn"][i]["vOut"]),
                                       pack('<L', sequence))
        if (sighash_type & 31) == SIGHASH_NONE:
            pm += b'\x00'
        else:
            if (sighash_type & 31) == SIGHASH_SINGLE:
                pm += int_to_var_int(n + 1)
            else:
                pm += int_to_var_int(len(self["vOut"]))

        if (sighash_type & 31) != SIGHASH_NONE:
            for i in self["vOut"]:
                script_pub_key = self["vOut"][i]["scriptPubKey"]
                if isinstance(self["vOut"][i]["scriptPubKey"], str):
                    script_pub_key = bytes_from_hex(script_pub_key)
                if i > n and (sighash_type & 31) == SIGHASH_SINGLE:
                    continue
                if (sighash_type & 31) == SIGHASH_SINGLE and (n != i):
                    pm += b"%s%s" % (b'\xff' * 8, b'\x00')
                else:
                    pm += b"%s%s%s" % (self["vOut"][i]["value"].to_bytes(8, 'little'),
                                       int_to_var_int(len(script_pub_key)),
                                       script_pub_key)
        pm += b"%s%s" % (self["lockTime"].to_bytes(4, 'little'), pack(b"<i", sighash_type))
        if not preimage:
            pm = double_sha256(pm)
        return pm if self["format"] == "raw" else rh2s(pm)
Beispiel #7
0
def bitcoin_message(msg):
    if isinstance(msg, str):
        msg = msg.encode()
    print(b"\x18Bitcoin Signed Message:\n" + int_to_var_int(len(msg)) + msg)
    return double_sha256(b"\x18Bitcoin Signed Message:\n" +
                         int_to_var_int(len(msg)) + msg)
Beispiel #8
0
def encode_dhcs(elements, min_bits_threshold=20):
    # Delta-Hoffman coded set
    data_sequence = bitarray()
    data_sequence_append = data_sequence.append

    deltas_bits = deque()
    deltas_bits_map_freq = dict()
    last = 0

    for value in sorted(elements):
        delta = value - last

        bits = delta.bit_length()
        if bits < min_bits_threshold:
            bits = min_bits_threshold

        deltas_bits.append(bits)

        try:
            deltas_bits_map_freq[bits] += 1
        except:
            deltas_bits_map_freq[bits] = 1

        while bits > 0:
            data_sequence_append(delta & (1 << (bits - 1)))
            bits -= 1
        last = value

    # huffman encode round 1
    # encode bits length sequence to byte string
    codes_round_1 = huffman_code(huffman_tree(deltas_bits_map_freq))
    r = bitarray()
    r.encode(codes_round_1, deltas_bits)
    bits_sequence = r.tobytes()
    bits_sequnce_len_round_1 = r.length()

    # huffman encode round 2
    # encode byte string
    deltas_bits = deque()
    deltas_bits_map_freq = dict()
    for i in bits_sequence:
        b = i >> 4
        c = i & 0b1111
        deltas_bits.append(b)
        try:
            deltas_bits_map_freq[b] += 1
        except:
            deltas_bits_map_freq[b] = 1

        deltas_bits.append(c)
        try:
            deltas_bits_map_freq[c] += 1
        except:
            deltas_bits_map_freq[c] = 1

    codes_round_2 = huffman_code(huffman_tree(deltas_bits_map_freq))
    r = bitarray()
    r.encode(codes_round_2, deltas_bits)
    bits_sequnce_len_round_2 = r.length()
    bits_sequence = r.tobytes()

    code_table_1 = int_to_var_int(len(codes_round_1))
    for code in codes_round_1:
        code_table_1 += int_to_var_int(code)
        code_table_1 += int_to_var_int(codes_round_1[code].length())
        code_table_1 += b"".join(
            [bytes([i]) for i in codes_round_1[code].tolist()])

    code_table_2 = int_to_var_int(len(codes_round_2))
    for code in codes_round_2:
        code_table_2 += int_to_var_int(code)
        code_table_2 += int_to_var_int(codes_round_2[code].length())
        code_table_2 += b"".join(
            [bytes([i]) for i in codes_round_2[code].tolist()])

    d_filter_len = data_sequence.length()
    d_filter_string = data_sequence.tobytes()

    return b"".join(
        (code_table_1, code_table_2, int_to_var_int(bits_sequnce_len_round_1),
         int_to_var_int(bits_sequnce_len_round_2), bits_sequence,
         int_to_var_int(d_filter_len), d_filter_string))
Beispiel #9
0
def encode_gcs(elements, P=None, sort=True, deltas=True):
    gcs_filter = bitarray()
    gcs_filter_append = gcs_filter.append

    if len(elements) == 0:
        return b""

    if sort:
        elements = sorted(elements)
    if P is None:
        if deltas:
            last = 0

            if len(elements) < 2:
                d_max = elements[0]
            else:
                d_max = 0
                new_elements = deque()
                for value in elements:
                    d = value - last
                    new_elements.append(d)
                    if last and d_max < d:
                        d_max = d
                    last = value

                deltas = False
                elements = new_elements
        else:
            d_max = max(elements)
        if not sort:
            mc = sorted(elements)[len(elements) // 2]  # median high
        else:
            mc = elements[len(elements) // 2]  # median high
        d_max = d_max if d_max > 1 else 2
        mc = mc if mc > 1 else 2

        P = (floor(log2((mc / 1.497137))) + floor(log2(
            (d_max / 1.497137)))) >> 1

        if P < 1:
            P = 1

    last = 0
    for value in elements:
        if deltas:
            e = value - last
            last = value
        else:
            e = value
        q, r = e >> P, e & ((1 << P) - 1)

        while q:
            gcs_filter_append(True)
            q -= 1

        gcs_filter_append(False)

        c = P - 1
        while c >= 0:
            gcs_filter_append(bool(r & (1 << c)))
            c -= 1

    return int_to_var_int(
        len(elements)) + int_to_var_int(P) + gcs_filter.tobytes()