Пример #1
0
def decompress_script(compressed_script, script_type):
    """ Takes CScript as stored in leveldb and returns it in uncompressed form
    (de)compression scheme is defined in bitcoin/src/compressor.cpp

    :param compressed_script: raw script bytes hexlified (data in decode_utxo)
    :type compressed_script: str
    :param script_type: first byte of script data (out_type in decode_utxo)
    :type script_type: int
    :return: the decompressed CScript
    :rtype: str
    """

    if script_type == 0:
        if len(compressed_script) != 40:
            raise Exception("Compressed script has wrong size")
        script = OutputScript.P2PKH(compressed_script, hash160=True)

    elif script_type == 1:
        if len(compressed_script) != 40:
            raise Exception("Compressed script has wrong size")
        script = OutputScript.P2SH(compressed_script)

    elif script_type in [2, 3]:
        if len(compressed_script) != 66:
            raise Exception("Compressed script has wrong size")
        script = OutputScript.P2PK(compressed_script)

    elif script_type in [4, 5]:
        if len(compressed_script) != 66:
            raise Exception("Compressed script has wrong size")
        prefix = format(script_type - 2, '02')
        script = OutputScript.P2PK(
            get_uncompressed_pk(prefix + compressed_script[2:]))

    else:
        assert len(compressed_script) / 2 == script_type - NSPECIALSCRIPTS
        script = OutputScript.from_hex(compressed_script)

    return script.content
Пример #2
0
def decompress_script(compressed_script, script_type):
    """ Takes CScript as stored in leveldb and returns it in uncompressed form
    (de)compression scheme is defined in bitcoin/src/compressor.cpp

    :param compressed_script: raw script bytes hexlified (data in decode_utxo)
    :type compressed_script: str
    :param script_type: first byte of script data (out_type in decode_utxo)
    :type script_type: int
    :return: the decompressed CScript
    :rtype: str
    """

    if script_type == 0:
        if len(compressed_script) != 40:
            raise Exception("Compressed script has wrong size")
        script = OutputScript.P2PKH(compressed_script)

    elif script_type == 1:
        if len(compressed_script) != 40:
            raise Exception("Compressed script has wrong size")
        script = OutputScript.P2SH(compressed_script)

    elif script_type in [2, 3]:
        if len(compressed_script) != 66:
            raise Exception("Compressed script has wrong size")
        script = OutputScript.P2PK(compressed_script)

    elif script_type in [4, 5]:
        # pfx = chr(int(script_bytes[:2], 16) - 2)
        # script = OutputScript.P2PK(hexlify(pfx) + script_bytes[2:])
        # ToDO: Create P2PK script using decompressed PK (decompress_pk needs to be implemented).
        pass

    else:
        assert len(compressed_script) == script_type - (NSPECIALSCRIPTS * 2)
        script = OutputScript.from_hex(compressed_script)

    return script.serialize()
Пример #3
0
    def build_from_io(cls,
                      prev_tx_id,
                      prev_out_index,
                      value,
                      outputs,
                      fees=None,
                      network='test'):
        """ Builds a transaction from a collection of inputs and outputs, such as previous transactions references and
        output references (either public keys, Bitcoin addresses, list of public keys (for multisig transactions), etc).
        This builder leaves the transaction ready to sign, so its the one to be used in most cases
        (Standard transactions).
        outputs format:
        P2PKH -> Bitcoin address, or list of Bitcoin addresses.
        e.g: output = btc_addr or output = [btc_addr0, btc_addr1, ...]
        P2PK -> Serialized Public key, or list of serialized pubic keys. (use keys.serialize_pk)
        e.g: output = pk or output = [pk0, pk1, ...]
        P2MS -> List of int (m) and public keys, or list of lists of int (m_i) and public keys. m represent the m-of-n
        number of public keys needed to redeem the transaction.
        e.g: output = [n, pk0, pk1, ...] or output = [[n_0, pk0_0, pk0_1, ...], [n_1, pk1_0, pk1_1, ...], ...]
        P2SH -> script hash (hash160 str hex) or list of hash 160s.
        e.g: output = da1745e9b549bd0bfa1a569971c77eba30cd5a4b or output = [da1745e9b549bd0bfa1a569971c77eba30cd5a4b,
        ...]
        :param prev_tx_id: Previous transaction id.
        :type prev_tx_id: either str or list of str
        :param prev_out_index: Previous output index. Together with prev_tx_id represent the UTXOs the current
        transaction is aiming to redeem.
        :type prev_out_index: either str or list of str
        :param value: Value in Satoshis to be spent.
        :type value: either int or list of int
        :param outputs: Information to build the output of the transaction.
        :type outputs: See above outputs format.
        :param fees: Fees that will be applied to the transaction. If set, fees will be subtracted from the last output.
        :type fees: int
        :param network: Network into which the transaction will be published (either mainnet or testnet).
        :type network: str
        :return: Transaction build with the input and output provided data.
        :rtype: TX
        """

        ins = []
        outs = []

        # Normalize all parameters
        if isinstance(prev_tx_id, str):
            prev_tx_id = [prev_tx_id]
        if isinstance(prev_out_index, int):
            prev_out_index = [prev_out_index]
        if isinstance(value, int):
            value = [value]
        if isinstance(outputs, str) or (isinstance(outputs, list)
                                        and isinstance(outputs[0], int)):
            outputs = [outputs]

        # If fees have been set, subtract them from the final value. Otherwise, assume they have been already
        # subtracted when specifying the amounts.
        if fees:
            value[-1] -= fees

        if len(prev_tx_id) != len(prev_out_index):
            raise Exception(
                "Previous transaction id and index number of elements must match. "
                + str(len(prev_tx_id)) + "!= " + str(len(prev_out_index)))
        elif len(value) != len(outputs):
            raise Exception(
                "Each output must have set a Satoshi amount. Use 0 if no value is going to be transferred."
            )

        for o in outputs:
            # Multisig outputs are passes ad an integer m representing the m-of-n transaction, amb m public keys.
            if isinstance(o, list) and o[0] in range(1, 15):
                pks = [is_public_key(pk) for pk in o[1:]]
                if all(pks):
                    oscript = OutputScript.P2MS(o[0], len(o) - 1, o[1:])
                else:
                    raise Exception("Bad output")
            elif is_public_key(o):
                oscript = OutputScript.P2PK(o)
            elif is_btc_addr(o, network):
                oscript = OutputScript.P2PKH(o)
            elif is_script(o):
                oscript = OutputScript.P2SH(o)
            else:
                raise Exception("Bad output")

            outs.append(deepcopy(oscript))

        for i in range(len(prev_tx_id)):
            # Temporarily set IS content to 0, since data will be signed afterwards.
            iscript = InputScript()
            ins.append(iscript)

        # Once all inputs and outputs has been formatted as scripts, we could construct the transaction with the proper
        # builder.
        tx = cls.build_from_scripts(prev_tx_id, prev_out_index, value, ins,
                                    outs)

        return tx
Пример #4
0
from bitcoin_tools.wallet import hash_160

pk = "04a01f076082a713a82b47ace012934052bcf3359c964f1963d00def84a34e7b0345efeefe037f4b0a4e160cc40a7fac052523da88398630c07ef3c54b47aa6046"
signature = "3045022100df7b7e5cda14ddf91290e02ea10786e03eb11ee36ec02dd862fe9a326bbcb7fd02203f5b4496b667e6e281cc654a2da9e4f08660c620a1051337fa8965f727eb191901"
btc_addr = "mgwpBW3g4diqasfxzWDgSi5fBrsFKmNdva"
data = ["OP_0", signature]
script = "OP_1 <" + pk + "> <" + pk + "> OP_2 OP_CHECKMULTISIG"
script_hash = b2a_hex(hash_160(Script.serialize(script)))

sigs = [signature]
pks = [pk, pk]


print ("OUTPUT SCRIPTS")

o = OutputScript.P2PK(pk)
print o.type, o.content

o = OutputScript.P2PKH(btc_addr)
print o.type, o.content

o = OutputScript.P2MS(1, 2, pks)
print o.type, o.content

o = OutputScript.P2SH(script_hash)
print o.type, o.content

print ("\nINPUT SCRIPTS")

i = InputScript().P2PK(signature)
print i.type, i.content