示例#1
0
def transaction_digest(tx_ins: list, tx_outs: list, lock_time: bytes = LOCK_TIME, sighash: int = SIGHASH_ALL) -> list:
    """Returns the digest of unsigned transaction according to SIGHASH"""
    # BIP-143 https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
    #  1. nVersion of the transaction (4-byte little endian)
    #  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)
    #  8. hashOutputs (32-byte hash)
    #  9. nLocktime of the transaction (4-byte little endian)
    # 10. sighash type of the signature (4-byte little endian)
    if sighash == SIGHASH_ALL:
        hash_prevouts = double_sha256(b''.join([tx_in.txid + tx_in.index for tx_in in tx_ins]))
        hash_sequence = double_sha256(b''.join([tx_in.sequence for tx_in in tx_ins]))
        hash_outputs = double_sha256(serialize_outputs(tx_outs))
        digests = []
        for tx_in in tx_ins:
            digests.append(
                VERSION +
                hash_prevouts + hash_sequence +
                tx_in.txid + tx_in.index + tx_in.locking_script_len + tx_in.locking_script + tx_in.satoshi + tx_in.sequence +
                hash_outputs +
                lock_time +
                sighash.to_bytes(4, byteorder='little')
            )
        return digests
    raise ValueError(f'Unsupported SIGHASH value {sighash}')
def create_p2pkh_transaction(utxosets, outputs, custom_pushdata=False):

    version = VERSION_1
    lock_time = LOCK_TIME
    # sequence = SEQUENCE
    hash_type = HASH_TYPE
    unspents = [Unspent.from_dict(utxo) for utxo in utxosets]
    input_count = int_to_varint(len(unspents))
    output_count = int_to_varint(len(outputs))

    output_block = construct_output_block(outputs,
                                          custom_pushdata=custom_pushdata)

    # Optimize for speed, not memory, by pre-computing values.
    inputs = []
    for unspent in unspents:
        txid = hex_to_bytes(unspent.txid)[::-1]
        txindex = unspent.txindex.to_bytes(4, byteorder='little')
        amount = unspent.amount.to_bytes(8, byteorder='little')

        inputs.append(TxIn('', 0, txid, txindex, amount))

    hashPrevouts = double_sha256(b''.join([i.txid + i.txindex
                                           for i in inputs]))
    hashSequence = double_sha256(b''.join([SEQUENCE for i in inputs]))
    hashOutputs = double_sha256(output_block)

    # scriptCode_len is part of the script.
    for i, txin in enumerate(inputs):
        private_key = bsv(wif=utxosets[i]['PrivateKey'])
        public_key = bytes.fromhex(private_key.public_key)
        public_key_len = len(public_key).to_bytes(1, byteorder='little')

        scriptCode = (OP_DUP + OP_HASH160 + OP_PUSH_20 +
                      address_to_public_key_hash(private_key.address) +
                      OP_EQUALVERIFY + OP_CHECKSIG)
        scriptCode_len = int_to_varint(len(scriptCode))
        to_be_hashed = (version + hashPrevouts + hashSequence + txin.txid +
                        txin.txindex + scriptCode_len + scriptCode +
                        txin.amount + SEQUENCE + hashOutputs + lock_time +
                        hash_type)
        hashed = sha256(to_be_hashed)  # BIP-143: Used for Bitcoin SV

        # signature = private_key.sign(hashed) + b'\x01'
        signature = private_key.sign(hashed) + b'\x41'

        script_sig = (len(signature).to_bytes(1, byteorder='little') +
                      signature + public_key_len + public_key)

        inputs[i].script = script_sig
        inputs[i].script_len = int_to_varint(len(script_sig))

    return bytes_to_hex(version + input_count + construct_input_block(inputs) +
                        output_count + output_block + lock_time)
示例#3
0
def b58c_encode(data, version=b'\x00'):
    """Converts bytes data into a base 58 check string.

    WTF is Base 58 Check encoding? See here:
        https://en.bitcoin.it/wiki/Base58Check_encoding

    """
    data = version + data
    data_without_zeros = data.lstrip(b'\x00')
    nb_zeros = len(data) - len(data_without_zeros)

    double_hash = double_sha256(data)
    data = data + double_hash[0:4]
    number = bytes_to_int(data)

    b58 = int_to_base(number, B58)
    return (b'1' * nb_zeros) + b58
示例#4
0
    # Verify the ECDSA signature of a signed transaction
    # 4674da699de44c9c5d182870207ba89e5ccf395e5101dab6b0900bbf2f3b16cb
    #
    tx_inputs = inputs[0:1]
    tx_outputs = [TxOut(address='1JDZRGf5fPjGTpqLNwjHFFZnagcZbwDsxw', satoshi=800)]
    tx_digest = transaction_digest(tx_inputs, tx_outputs)[0]
    serialized_sig = unhexlify('304402207e2c6eb8c4b20e251a71c580373a2836e209c50726e5f8b0f4f59f8af00eee1a022019ae1690e2eb4455add6ca5b86695d65d3261d914bc1d7abb40b188c7f46c9a5')
    sig = deserialize_signature(serialized_sig)
    print(verify_signature(pub_key, tx_digest, sig))
    #
    # Sign an unsigned transaction then broadcast
    # c04bbd007ad3987f9b2ea8534175b5e436e43d64471bf32139b5851adf9f477e
    #
    serialized_pub_key = serialize_public_key(pub_key)
    tx_inputs = inputs[1:]
    tx_outputs = [TxOut(address='18CgRLx9hFZqDZv75J5kED7ANnDriwvpi1', satoshi=1700)]
    tx_digests = transaction_digest(tx_inputs, tx_outputs)
    for i in range(len(tx_digests)):
        tx_digest = tx_digests[i]
        sig = sign(priv_key, tx_digest)
        serialized_sig = serialize_signature(sig)
        # unlocking_script = LEN + der + sighash + LEN + public_key
        tx_inputs[i].unlocking_script = bytes([len(serialized_sig) + 1]) + serialized_sig + bytes([SIGHASH_ALL, len(serialized_pub_key)]) + serialized_pub_key
        print(hexlify(tx_inputs[i].unlocking_script))
        tx_inputs[i].unlocking_script_len = int_to_varint(len(tx_inputs[i].unlocking_script))
        print(hexlify(tx_inputs[i].unlocking_script_len))
    raw = serialize_transaction(tx_inputs, tx_outputs)
    print(hexlify(raw))
    tx_id = double_sha256(raw)[::-1]
    print(hexlify(tx_id))
def calc_txid(tx_hex):
    return bytes_to_hex(double_sha256(hex_to_bytes(tx_hex))[::-1])
def generate_sighash_single_rawtx(utxosets, changeaddress, authrized_amount):
    unspents = [Unspent.from_dict(utxo) for utxo in utxosets]
    version = VERSION_1
    lock_time = LOCK_TIME
    #sequence = SEQUENCE

    input_count = int_to_varint(len(unspents))

    inputs = []
    total_input_amount = 0
    for unspent in unspents:
        txid = hex_to_bytes(unspent.txid)[::-1]
        txindex = unspent.txindex.to_bytes(4, byteorder='little')
        amount = unspent.amount.to_bytes(8, byteorder='little')
        inputs.append(TxIn('', 0, txid, txindex, amount))
        total_input_amount += unspent.amount  #satoshi

    output_count = int_to_varint(1)
    output_block = b''
    output_script = (OP_DUP + OP_HASH160 + OP_PUSH_20 +
                     address_to_public_key_hash(changeaddress) +
                     OP_EQUALVERIFY + OP_CHECKSIG)
    output_block += (total_input_amount - authrized_amount).to_bytes(
        8, byteorder='little')  #satoshi
    output_block += int_to_varint(len(output_script))
    output_block += output_script

    hashPrevouts = double_sha256(b''.join([i.txid + i.txindex
                                           for i in inputs]))
    hashSequence = bytes.fromhex(
        '0000000000000000000000000000000000000000000000000000000000000000')
    # scriptCode_len is part of the script.
    for i, txin in enumerate(inputs):
        if i == 0:
            hashOutputs = double_sha256(output_block)
            hash_type = 0x43.to_bytes(4, byteorder='little')  #sighash single
        else:
            hashOutputs = bytes.fromhex(
                '0000000000000000000000000000000000000000000000000000000000000000'
            )
            hash_type = 0x42.to_bytes(4, byteorder='little')  #sighash none

        private_key = bsv(utxosets[i]['PrivateKey'])
        public_key = bytes.fromhex(private_key.public_key)
        public_key_len = len(public_key).to_bytes(1, byteorder='little')
        scriptCode = (OP_DUP + OP_HASH160 + OP_PUSH_20 +
                      address_to_public_key_hash(private_key.address) +
                      OP_EQUALVERIFY + OP_CHECKSIG)
        scriptCode_len = int_to_varint(len(scriptCode))
        to_be_hashed = (version + hashPrevouts + hashSequence + txin.txid +
                        txin.txindex + scriptCode_len + scriptCode +
                        txin.amount + SEQUENCE + hashOutputs + lock_time +
                        hash_type)
        hashed = sha256(to_be_hashed)  # BIP-143: Used for Bitcoin SV

        # signature = private_key.sign(hashed) + b'\x01'   sighash ALL  ; single b'\x03' ,NONE b'\x02'
        if i == 0:
            signature = private_key.sign(hashed) + b'\x43'
        else:
            signature = private_key.sign(hashed) + b'\x42'

        script_sig = (len(signature).to_bytes(1, byteorder='little') +
                      signature + public_key_len + public_key)

        inputs[i].script = script_sig
        inputs[i].script_len = int_to_varint(len(script_sig))

    return {
        "version": bytes_to_hex(version),
        "input": bytes_to_hex(input_count + construct_input_block(inputs)),
        "output": bytes_to_hex(output_block),
        "lock_time": bytes_to_hex(lock_time)
    }
示例#7
0
def hash_to_int(message: bytes) -> int:
    """Calculate the bitcoin double-sha256 hash of the message, return as an integer"""
    h = double_sha256(message)
    return int.from_bytes(h, byteorder='big')