Example #1
0
 def test_message(self):
     outs = construct_outputs(OUTPUTS + MESSAGES)
     assert outs[2].amount == hex_to_bytes(OUTPUT_BLOCK_MESSAGES[136:152])
     assert outs[2].script_pubkey == hex_to_bytes(
         OUTPUT_BLOCK_MESSAGES[154:168])
     assert outs[3].amount == hex_to_bytes(OUTPUT_BLOCK_MESSAGES[168:184])
     assert outs[3].script_pubkey == hex_to_bytes(
         OUTPUT_BLOCK_MESSAGES[186:])
Example #2
0
def create_new_transaction(private_key, unspents, outputs):

    version = VERSION_1
    lock_time = LOCK_TIME
    timestamp = int(time.time()).to_bytes(4, byteorder='little')
    outputs = construct_outputs(outputs)

    # Optimize for speed, not memory, by pre-computing values.
    inputs = []
    for unspent in unspents:
        script_sig = b''  # empty scriptSig for new unsigned transaction.
        txid = hex_to_bytes(unspent.txid)[::-1]
        txindex = unspent.txindex.to_bytes(4, byteorder='little')
        amount = int(unspent.amount).to_bytes(8, byteorder='little')
        inputs.append(
            TxIn(script_sig,
                 txid,
                 txindex,
                 amount=amount,
                 segwit_input=unspent.segwit))

    tx_unsigned = TxObj(version=version,
                        timestamp=timestamp,
                        TxIn=inputs,
                        TxOut=outputs,
                        locktime=lock_time)

    tx = sign_tx(private_key, tx_unsigned, unspents=unspents)
    return tx
Example #3
0
async def create_unsigned_transaction(source_address: str, outputs_dict: Dict[str, Decimal],
                                      fee_kb: int) -> Tuple[TxObj, List[Unspent]]:
    all_utxos = await get_unspent(source_address)
    confirmed_utxos = [u for u in all_utxos if u.confirmations >= settings.min_confirmations]

    if not confirmed_utxos:
        raise InsufficientFunds('No confirmed UTXOs were found')

    outputs = [(addr, int(amount * SATOSHI_MULTIPLIER)) for addr, amount in outputs_dict.items()]
    inputs, change_amount = select_unspents(source_address, confirmed_utxos, outputs, fee_kb)

    if change_amount > DUST_THRESHOLD:
        outputs.append((source_address, change_amount))

    version = VERSION_2
    lock_time = LOCK_TIME
    raw_outputs = construct_outputs(outputs)
    raw_inputs = []

    for unspent in inputs:
        script_sig = b''
        txid = hex_to_bytes(unspent.txid)[::-1]
        txindex = unspent.txindex.to_bytes(4, byteorder='little')
        amount = int(unspent.amount).to_bytes(8, byteorder='little')
        raw_inputs.append(TxIn(script_sig, txid, txindex, amount=amount))

    tx_unsigned = TxObj(version, raw_inputs, raw_outputs, lock_time)
    return tx_unsigned, inputs
Example #4
0
def multisig_to_redeemscript(public_keys, m):

    if m > 16:
        raise ValueError(
            'More than the allowed maximum of 16 public keys cannot be used.')

    redeemscript = int_to_unknown_bytes(m + 80)

    for key in public_keys:
        key_byte = hex_to_bytes(key)
        length = len(key_byte)

        if length not in (33, 65):
            raise ValueError(
                'At least one of the provided public keys is of invalid length {}.'
                .format(length))

        redeemscript += script_push(length) + key_byte

    redeemscript += int_to_unknown_bytes(
        len(public_keys) + 80
    ) + b'\xae'  # Only works for n = len(public_keys) < 17. OK due to P2SH script-length limitation.

    if len(redeemscript) > 520:
        raise ValueError(
            'The redeemScript exceeds the allowed 520-byte limitation with the number of public keys.'
        )

    return redeemscript
Example #5
0
 def test_get_signatures_1(self):
     script = hex_to_bytes(
         '0047304402200b526cf17f86891a62f4bd27745494005682d650c27dda87'
         '7f35b0161c38bc9002204674a0be6275ce948812c200251802d15eaa1953'
         '3d864d64b83b992c10b3ecf201'
         '483045022100a57ba5464a03343bd5ebf21ce0d3d49b84710c62a421b7d5'
         'b86de75ca10d8c7602206395d6a552fc0dbb31d3c0b1db34fa4a14cc29d6'
         '60c8c68172c7e513cb6a0ac901'
         '475221021816325d19fd34fd87a039e83e35fc9de3c9de64a501a6684b9b'
         'f9946364fbb721037d696886864509ed63044d8f1bcd53b8def1247bd2bbe'
         '056ff81b23e8c09280f52ae')
     sigs = get_signatures_from_script(script)
     assert len(sigs) == 2
     assert sigs[0][:4] == hex_to_bytes('30440220')
     assert sigs[0][-4:] == hex_to_bytes('b3ecf201')
     assert sigs[1][:4] == hex_to_bytes('30450221')
     assert sigs[1][-4:] == hex_to_bytes('6a0ac901')
Example #6
0
def create_p2pkh_transaction(private_key, unspents, outputs):

    public_key = private_key.public_key
    public_key_len = len(public_key).to_bytes(1, byteorder='little')

    version = VERSION_1
    lock_time = LOCK_TIME
    sequence = SEQUENCE
    hash_type = HASH_TYPE
    input_count = int_to_unknown_bytes(len(unspents), byteorder='little')
    output_count = int_to_unknown_bytes(len(outputs), byteorder='little')
    output_block = construct_output_block(outputs)

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

        inputs.append(TxIn(script, script_len, txid, txindex))

    for i, txin in enumerate(inputs):

        hashed = sha256(version + input_count +
                        b''.join(ti.txid + ti.txindex + OP_0 + sequence
                                 for ti in islice(inputs, i)) + txin.txid +
                        txin.txindex + txin.script_len + txin.script +
                        sequence +
                        b''.join(ti.txid + ti.txindex + OP_0 + sequence
                                 for ti in islice(inputs, i + 1, None)) +
                        output_count + output_block + lock_time + hash_type)

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

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

        txin.script = script_sig
        txin.script_len = int_to_unknown_bytes(len(script_sig),
                                               byteorder='little')

    return bytes_to_hex(version + input_count + construct_input_block(inputs) +
                        output_count + output_block + lock_time)
Example #7
0
 def test_valid_address(self):
     """Test whether valid addresses decode to the correct output."""
     for (address, hexscript) in VALID_ADDRESS:
         witver, witprog = segwit_addr.decode(address)
         assert witver is not None
         scriptpubkey = segwit_scriptpubkey(witver, witprog)
         assert scriptpubkey == hex_to_bytes(hexscript)
         hrp = address[:2].lower()
         addr = segwit_addr.encode(hrp, witver, witprog)
         assert address.lower() == addr
Example #8
0
 def test_get_signatures_2(self):
     script = hex_to_bytes(
           '0047304402200b526cf17f86891a62f4bd27745494005682d650c27dda87'
           '7f35b0161c38bc9002204674a0be6275ce948812c200251802d15eaa1953'
           '3d864d64b83b992c10b3ecf201'
           '00'
           '695221021816325d19fd34fd87a039e83e35fc9de3c9de64a501a6684b9b'
           'f9946364fbb721037d696886864509ed63044d8f1bcd53b8def1247bd2bb'
           'e056ff81b23e8c09280f21033dc7fb58b701fc0af63ee3a8b72ebbeed04a'
           '1c006b50007f32ec6a33a56213f853ae0400483045022100f686296df668'
           '17198feead5fa24f3f04cb7e6780187e73fc8c531254fd002c13022044ef'
           'e2ea00f31de395376d83cb122bd708116d151bdf2de61107d77447b475c6'
           '0100695221021816325d19fd34fd87a039e83e35fc9de3c9de64a501a668'
           '4b9bf9946364fbb721037d696886864509ed63044d8f1bcd53b8def1247b'
           'd2bbe056ff81b23e8c09280f21033dc7fb58b701fc0af63ee3a8b72ebbee'
           'd04a1c006b50007f32ec6a33a56213f853ae')
     sigs = get_signatures_from_script(script)
     assert len(sigs) == 1
     assert sigs[0][:4] == hex_to_bytes('30440220')
     assert sigs[0][-4:] == hex_to_bytes('b3ecf201')
Example #9
0
def deserialize(txhex):
    if isinstance(txhex, str) and re.match('^[0-9a-fA-F]*$', txhex):
        #return deserialize(binascii.unhexlify(txhex))
        return deserialize(hex_to_bytes(txhex))

    pos = [0]

    def read_as_int(bytez):
        pos[0] += bytez
        return int(bytes_to_hex(txhex[pos[0] - bytez:pos[0]][::-1]), base=16)

    def read_var_int():
        pos[0] += 1

        val = int(bytes_to_hex(txhex[pos[0] - 1:pos[0]]), base=16)
        if val < 253:
            return val
        return read_as_int(pow(2, val - 252))

    def read_bytes(bytez):
        pos[0] += bytez
        return txhex[pos[0] - bytez:pos[0]]

    def read_var_string():
        size = read_var_int()
        return read_bytes(size)

    version = read_as_int(4).to_bytes(4, byteorder='little')

    ins = read_var_int()
    inputs = []
    for _ in range(ins):
        txid = read_bytes(32)
        txindex = read_as_int(4).to_bytes(4, byteorder='little')
        script = read_var_string()
        sequence = read_as_int(4).to_bytes(4, byteorder='little')
        inputs.append(TxIn(script, txid, txindex, sequence))

    outs = read_var_int()
    outputs = []
    for _ in range(outs):
        value = read_as_int(8).to_bytes(8, byteorder='little')
        script = read_var_string()
        outputs.append(TxOut(value, script))

    locktime = read_as_int(4).to_bytes(4, byteorder='little')

    txobj = TxObj(version, inputs, outputs, locktime)

    return txobj
Example #10
0
def hex_to_wif(private_key, version='main', compressed=False):

    if version == 'test':
        prefix = TEST_PRIVATE_KEY
    else:
        prefix = MAIN_PRIVATE_KEY

    if compressed:
        suffix = PRIVATE_KEY_COMPRESSED_PUBKEY
    else:
        suffix = b''

    if not isinstance(private_key, bytes):
        private_key = hex_to_bytes(private_key)

    private_key = prefix + private_key + suffix

    return b58encode_check(private_key)
Example #11
0
def create_new_transaction(private_key, unspents, outputs):

    version = VERSION_1
    lock_time = LOCK_TIME
    outputs = construct_outputs(outputs)

    # Optimize for speed, not memory, by pre-computing values.
    inputs = []
    for unspent in unspents:
        script = b''  # empty scriptSig for new unsigned transaction.
        txid = hex_to_bytes(unspent.txid)[::-1]
        txindex = unspent.txindex.to_bytes(4, byteorder='little')

        inputs.append(TxIn(script, txid, txindex))

    tx_unsigned = TxObj(version, inputs, outputs, lock_time)

    tx = sign_legacy_tx(private_key, tx_unsigned)
    return tx
Example #12
0
def deserialize(tx):
    if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx):
        return deserialize(hex_to_bytes(tx))

    segwit_tx = TxObj.is_segwit(tx)

    version, tx = read_bytes(tx, 4)
    timestamp, tx = read_bytes(tx, 4)

    if segwit_tx:
        _, tx = read_bytes(tx, 1)  # ``marker`` is nulled
        _, tx = read_bytes(tx, 1)  # ``flag`` is nulled

    ins, tx = read_var_int(tx)
    inputs = []
    for i in range(ins):
        txid, tx = read_bytes(tx, 32)
        txindex, tx = read_bytes(tx, 4)
        script_sig, tx = read_var_string(tx)
        sequence, tx = read_bytes(tx, 4)
        inputs.append(TxIn(script_sig, txid, txindex, sequence=sequence))

    outs, tx = read_var_int(tx)
    outputs = []
    for _ in range(outs):
        amount, tx = read_bytes(tx, 8)
        script_pubkey, tx = read_var_string(tx)
        outputs.append(TxOut(amount, script_pubkey))

    if segwit_tx:
        for i in range(ins):
            wnum, tx = read_var_int(tx)
            witness = int_to_varint(wnum)
            for _ in range(wnum):
                w, tx = read_segwit_string(tx)
                witness += w
            inputs[i].witness = witness

    locktime, _ = read_bytes(tx, 4)

    txobj = TxObj(version, timestamp, inputs, outputs, locktime)

    return txobj
Example #13
0
 def is_segwit(cls, tx):
     if isinstance(tx, cls):
         tx = bytes(tx)
     elif not isinstance(tx, bytes):
         tx = hex_to_bytes(tx)
     return tx[4:6] == MARKER + FLAG
Example #14
0
 def test_no_message(self):
     outs = construct_outputs(OUTPUTS)
     assert outs[0].amount == hex_to_bytes(OUTPUT_BLOCK[:16])
     assert outs[0].script_pubkey == hex_to_bytes(OUTPUT_BLOCK[18:68])
     assert outs[1].amount == hex_to_bytes(OUTPUT_BLOCK[68:84])
     assert outs[1].script_pubkey == hex_to_bytes(OUTPUT_BLOCK[86:])
Example #15
0
def sanitize_tx_data(unspents,
                     outputs,
                     fee,
                     leftover,
                     combine=True,
                     message=None,
                     compressed=True):
    """
    sanitize_tx_data()

    fee is in satoshis per byte.
    """

    outputs = outputs.copy()

    for i, output in enumerate(outputs):
        dest, amount, currency = output
        outputs[i] = (dest, currency_to_satoshi_cached(amount, currency))

    if not unspents:
        raise ValueError('Transactions must have at least one unspent.')

    messages = []
    if message:
        if type(message) == int:
            messages.append((int_to_unknown_bytes(message), 0))
        else:
            messages.append((hex_to_bytes(message), 0))

    # Include return address in output count.
    num_outputs = len(outputs) + len(messages) + 1
    sum_outputs = sum(out[1] for out in outputs)

    total_in = 0

    if combine:
        # calculated_fee is in total satoshis.
        calculated_fee = estimate_tx_fee(len(unspents), num_outputs, fee,
                                         compressed)
        total_out = sum_outputs + calculated_fee
        unspents = unspents.copy()
        total_in += sum(unspent.amount for unspent in unspents)

    else:
        unspents = sorted(unspents, key=lambda x: x.amount)

        index = 0

        for index, unspent in enumerate(unspents):
            total_in += unspent.amount
            calculated_fee = estimate_tx_fee(len(unspents[:index + 1]),
                                             num_outputs, fee, compressed)
            total_out = sum_outputs + calculated_fee

            if total_in >= total_out:
                break

        unspents[:] = unspents[:index + 1]

    remaining = total_in - total_out

    if remaining > 0:
        outputs.append((leftover, remaining))
    elif remaining < 0:
        raise InsufficientFunds('Balance {} is less than {} (including '
                                'fee).'.format(total_in, total_out))

    outputs.extend(messages)

    return unspents, outputs
Example #16
0
 def test_segwit_deserialize(self):
     txobj = deserialize(SEGWIT_TX_1)
     assert txobj.version == hex_to_bytes(SEGWIT_TX_1[:8])
     assert len(txobj.TxIn) == 2
     assert txobj.TxIn[0].txid == hex_to_bytes(SEGWIT_TX_1[14:78])
     assert txobj.TxIn[0].txindex == hex_to_bytes(SEGWIT_TX_1[78:86])
     assert txobj.TxIn[0].script_sig_len == hex_to_bytes(SEGWIT_TX_1[86:88])
     assert txobj.TxIn[0].script_sig == hex_to_bytes(SEGWIT_TX_1[88:300])
     assert txobj.TxIn[0].sequence == hex_to_bytes(SEGWIT_TX_1[300:308])
     assert txobj.TxIn[0].witness == hex_to_bytes(SEGWIT_TX_1[564:566])
     assert txobj.TxIn[1].txid == hex_to_bytes(SEGWIT_TX_1[308:372])
     assert txobj.TxIn[1].txindex == hex_to_bytes(SEGWIT_TX_1[372:380])
     assert txobj.TxIn[1].script_sig_len == hex_to_bytes(SEGWIT_TX_1[380:382])
     assert txobj.TxIn[1].script_sig == hex_to_bytes(SEGWIT_TX_1[382:428])
     assert txobj.TxIn[1].sequence == hex_to_bytes(SEGWIT_TX_1[428:436])
     assert txobj.TxIn[1].witness == hex_to_bytes(SEGWIT_TX_1[566:780])
     assert len(txobj.TxOut) == 2
     assert txobj.TxOut[0].amount == hex_to_bytes(SEGWIT_TX_1[438:454])
     assert txobj.TxOut[0].script_pubkey_len == hex_to_bytes(SEGWIT_TX_1[454:456])
     assert txobj.TxOut[0].script_pubkey == hex_to_bytes(SEGWIT_TX_1[456:500])
     assert txobj.TxOut[1].amount == hex_to_bytes(SEGWIT_TX_1[500:516])
     assert txobj.TxOut[1].script_pubkey_len == hex_to_bytes(SEGWIT_TX_1[516:518])
     assert txobj.TxOut[1].script_pubkey == hex_to_bytes(SEGWIT_TX_1[518:564])
     assert txobj.locktime == hex_to_bytes(SEGWIT_TX_1[780:])
Example #17
0
def create_sweep_transaction(private_keys,
                             destination_address,
                             amount=None,
                             currency='satoshi',
                             fee=None,
                             leftover=None,
                             message=None,
                             compressed=True):

    private_key_map = {}
    unspents = []
    for key in private_keys:
        utxos = key.get_unspents()
        unspents += utxos
        for utx in utxos:
            private_key_map[utx.txid] = key

    version = VERSION_1
    lock_time = LOCK_TIME
    sequence = SEQUENCE
    hash_type = HASH_TYPE
    input_count = int_to_unknown_bytes(len(unspents), byteorder='little')

    # Construct the outputs, taking the fee into account
    sum_of_unspents = sum([int(x.amount) for x in unspents])
    amount = amount or sum_of_unspents
    outputs = [(destination_address, sum_of_unspents, currency)]

    unspents, outputs = sanitize_tx_data(unspents,
                                         outputs,
                                         fee or get_fee_cached(),
                                         leftover or private_keys[0].address,
                                         combine=True,
                                         message=message,
                                         compressed=compressed,
                                         sweep=True)

    output_count = int_to_unknown_bytes(len(outputs), byteorder='little')
    output_block = construct_output_block(outputs)

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

        inputs.append(TxIn(script, script_len, txid, txindex))

    for i, txin in enumerate(inputs):

        hashed = sha256(version + input_count +
                        b''.join(ti.txid + ti.txindex + OP_0 + sequence
                                 for ti in islice(inputs, i)) + txin.txid +
                        txin.txindex + txin.script_len + txin.script +
                        sequence +
                        b''.join(ti.txid + ti.txindex + OP_0 + sequence
                                 for ti in islice(inputs, i + 1, None)) +
                        output_count + output_block + lock_time + hash_type)

        private_key = private_key_map[unspents[i].txid]
        signature = private_key.sign(hashed) + b'\x01'
        public_key = private_key.public_key
        public_key_len = len(public_key).to_bytes(1, byteorder='little')

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

        txin.script = script_sig
        txin.script_len = int_to_unknown_bytes(len(script_sig),
                                               byteorder='little')

    return bytes_to_hex(version + input_count + construct_input_block(inputs) +
                        output_count + output_block + lock_time)
Example #18
0
def serialize_txid(txid: str) -> bytes:
    """Serializes txid to bytes"""

    return hex_to_bytes(txid)[::-1]
Example #19
0
 def test_legacy_deserialize(self):
     txobj = deserialize(FINAL_TX_1)
     assert txobj.version == hex_to_bytes(FINAL_TX_1[:8])
     assert len(txobj.TxIn) == 1
     assert txobj.TxIn[0].txid == hex_to_bytes(FINAL_TX_1[10:74])
     assert txobj.TxIn[0].txindex == hex_to_bytes(FINAL_TX_1[74:82])
     assert txobj.TxIn[0].script_sig_len == hex_to_bytes(FINAL_TX_1[82:84])
     assert txobj.TxIn[0].script_sig == hex_to_bytes(FINAL_TX_1[84:360])
     assert txobj.TxIn[0].witness == b''
     assert txobj.TxIn[0].sequence == hex_to_bytes(FINAL_TX_1[360:368])
     assert len(txobj.TxOut) == 2
     assert txobj.TxOut[0].amount == hex_to_bytes(FINAL_TX_1[370:386])
     assert txobj.TxOut[0].script_pubkey_len == hex_to_bytes(FINAL_TX_1[386:388])
     assert txobj.TxOut[0].script_pubkey == hex_to_bytes(FINAL_TX_1[388:438])
     assert txobj.TxOut[1].amount == hex_to_bytes(FINAL_TX_1[438:454])
     assert txobj.TxOut[1].script_pubkey_len == hex_to_bytes(FINAL_TX_1[454:456])
     assert txobj.TxOut[1].script_pubkey == hex_to_bytes(FINAL_TX_1[456:506])
     assert txobj.locktime == hex_to_bytes(FINAL_TX_1[506:])
Example #20
0
def test_hex_to_bytes():
    assert hex_to_bytes(HEX) == BYTES_BIG
    assert hex_to_bytes(ODD_HEX) == ODD_HEX_BYTES
Example #21
0
def calc_txid(tx_hex):
    return bytes_to_hex(double_sha256(hex_to_bytes(tx_hex))[::-1])
Example #22
0
def sign_tx(private_key, tx, *, unspents):
    """Signs inputs in provided transaction object for which unspents
    are provided and can be signed by the private key.

    :param private_key: Private key
    :type private_key: ``PrivateKey`` or ``MultiSig``
    :param tx: Transaction object
    :type tx: ``TxObj``
    :param unspents: For inputs to be signed their corresponding Unspent objects
                     must be provided.
    :returns: The signed transaction as hex.
    :rtype: ``str``
    """

    # input_dict contains those unspents that can be signed by private_key,
    # providing additional information for segwit-inputs (the amount to spend)
    input_dict = {}
    try:
        for unspent in unspents:
            if not private_key.can_sign_unspent(unspent):
                continue
            tx_input = hex_to_bytes(unspent.txid)[::-1] + \
                unspent.txindex.to_bytes(4, byteorder='little')
            input_dict[tx_input] = unspent.to_dict()
    except TypeError:
        raise ValueError('Please provide as unspents at least all inputs to '
                         'be signed with the function call.')

    # Determine input indices to sign from input_dict (allows for transaction batching)
    sign_inputs = [j for j, i in enumerate(tx.TxIn) if i.txid+i.txindex in input_dict]

    segwit_tx = TxObj.is_segwit(tx)

    version = tx.version
    lock_time = tx.locktime
    hash_type = HASH_TYPE

    input_count = int_to_varint(len(tx.TxIn))
    output_count = int_to_varint(len(tx.TxOut))

    output_block = b''.join([bytes(o) for o in tx.TxOut])

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

    for i in sign_inputs:

        tx_input = tx.TxIn[i].txid + tx.TxIn[i].txindex
        segwit_input = input_dict[tx_input]['segwit']
        tx.TxIn[i].segwit_input = segwit_input

        public_key = private_key.public_key
        public_key_push = script_push(len(public_key))

        script_code = private_key.scriptcode
        script_code_len = int_to_varint(len(script_code))

        if not segwit_input:
            hashed = sha256(
                version +
                input_count +
                b''.join(ti.txid + ti.txindex + OP_0 + ti.sequence
                         for ti in islice(tx.TxIn, i)) +
                tx.TxIn[i].txid +
                tx.TxIn[i].txindex +
                script_code_len +
                script_code +
                tx.TxIn[i].sequence +
                b''.join(ti.txid + ti.txindex + OP_0 + ti.sequence
                         for ti in islice(tx.TxIn, i + 1, None)) +
                output_count +
                output_block +
                lock_time +
                hash_type
                )

            input_script_field = tx.TxIn[i].script_sig

        elif segwit_input:
            try:
                tx.TxIn[i].amount = input_dict[tx_input]['amount']\
                                    .to_bytes(8, byteorder='little')
            except Attributerror:
                raise ValueError(
                    'Cannot sign a segwit input when the input\'s amount is '
                    'unknown. Maybe no network connection or the input is '
                    'already spent? Then please provide all inputs to sign as '
                    '`Unspent` objects to the function call.')

            hashed = sha256(  # BIP-143: Used for Segwit
                version +
                hashPrevouts +
                hashSequence +
                tx.TxIn[i].txid +
                tx.TxIn[i].txindex +
                script_code_len +
                script_code +
                tx.TxIn[i].amount +
                tx.TxIn[i].sequence +
                hashOutputs +
                lock_time +
                hash_type
                )

            input_script_field = tx.TxIn[i].witness

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

        # ------------------------------------------------------------------
        if (private_key.instance == 'MultiSig' or
                private_key.instance == 'MultiSigTestnet'):
            # P2(W)SH input

            script_blob = b''
            sigs = {}
            # Initial number of witness items (OP_0 + one signature + redeemscript).
            witness_count = 3
            if input_script_field:
                sig_list = get_signatures_from_script(input_script_field)
                # Bitcoin Core convention: Every missing signature is denoted
                # by 0x00. Only used for already partially-signed scriptSigs:
                script_blob += b'\x00' * (private_key.m - len(sig_list)-1)
                # Total number of witness items when partially or fully signed:
                witness_count = private_key.m + 2
                # For a partially signed input make a dictionary containing
                # all the provided signatures with public-keys as keys:
                for sig in sig_list:
                    for pub in private_key.public_keys:
                        if verify_sig(sig[:-1], hashed, hex_to_bytes(pub)):
                            # If we already found a valid signature for pubkey
                            # we just overwrite it and don't care.
                            sigs[pub] = sig
                if len(sigs) == private_key.m:
                    raise TypeError('Transaction is already signed with '
                                    'sufficiently needed signatures.')
                elif len(sigs) > private_key.m:
                    raise TypeError('Transaction already contains {} '
                                    'signatures, but only {} needed.').format(
                                        len(sigs), private_key.m)

            sigs[bytes_to_hex(public_key)] = signature

            witness = b''
            # Sort ingthe signatures according to the public-key list:
            for pub in private_key.public_keys:
                if pub in sigs:
                    sig = sigs[pub]
                    length = int_to_varint(len(sig)) if segwit_input else \
                        script_push(len(sig))
                    witness += length + sig

            script_sig = b'\x22' + private_key.segwit_scriptcode

            witness = (int_to_varint(witness_count) if segwit_input else b'') \
                + b'\x00' + witness + script_blob
            witness += (int_to_varint(len(private_key.redeemscript)) if
                segwit_input else script_push(len(private_key.redeemscript))) \
                + private_key.redeemscript

            script_sig = script_sig if segwit_input else witness
            witness = witness if segwit_input else b'\x00' if segwit_tx else b''

        # ------------------------------------------------------------------
        else:
            # P2(W)PKH input

            script_sig = b'\x16' + private_key.segwit_scriptcode

            witness = (
                      (b'\x02' if segwit_input else b'') +  # witness counter
                      len(signature).to_bytes(1, byteorder='little') +
                      signature +
                      public_key_push +
                      public_key
                     )

            script_sig = script_sig if segwit_input else witness
            witness = witness if segwit_input else b'\x00' if segwit_tx else b''

        # Providing the signature(s) to the input
        tx.TxIn[i].script_sig = script_sig
        tx.TxIn[i].script_sig_len = int_to_varint(len(script_sig))
        tx.TxIn[i].witness = witness

    return tx.to_hex()
 def test_message(self):
     assert construct_output_block(OUTPUTS + MESSAGES) == hex_to_bytes(
         OUTPUT_BLOCK_MESSAGES)
Example #24
0
def sign_tx(private_key, tx, *, unspents):
    """Signs inputs in provided transaction object for which unspents
    are provided and can be signed by the private key.

    :param private_key: Private key
    :type private_key: ``PrivateKey`` or ``MultiSig``
    :param tx: Transaction object
    :type tx: ``TxObj``
    :param unspents: For inputs to be signed their corresponding Unspent objects
                     must be provided.
    :type unspents: ``list`` of :class:`~bit.network.meta.Unspent`
    :returns: The signed transaction as hex.
    :rtype: ``str``
    """

    # input_dict contains those unspents that can be signed by private_key,
    # providing additional information for segwit-inputs (the amount to spend)
    input_dict = {}
    try:
        for unspent in unspents:
            if not private_key.can_sign_unspent(unspent):
                continue
            tx_input = hex_to_bytes(
                unspent.txid)[::-1] + unspent.txindex.to_bytes(
                    4, byteorder='little')
            input_dict[tx_input] = unspent.to_dict()
    except TypeError:
        raise TypeError(
            'Please provide as unspents at least all inputs to be signed with the function call in a list.'
        )

    # Determine input indices to sign from input_dict (allows for transaction batching)
    sign_inputs = [
        j for j, i in enumerate(tx.TxIn) if i.txid + i.txindex in input_dict
    ]

    segwit_tx = TxObj.is_segwit(tx)
    public_key = private_key.public_key
    public_key_push = script_push(len(public_key))
    hash_type = HASH_TYPE

    # Make input parameters for preimage calculation
    inputs_parameters = []

    # The TxObj in `tx` will below be modified to contain the scriptCodes used
    # for the transaction structure to be signed

    # `input_script_field` copies the scriptSigs for partially signed
    # transactions to later extract signatures from it:
    input_script_field = [tx.TxIn[i].script_sig for i in range(len(tx.TxIn))]

    for i in sign_inputs:
        # Create transaction object for preimage calculation
        tx_input = tx.TxIn[i].txid + tx.TxIn[i].txindex
        segwit_input = input_dict[tx_input]['segwit']
        tx.TxIn[i].segwit_input = segwit_input

        script_code = private_key.scriptcode
        script_code_len = int_to_varint(len(script_code))

        # Use scriptCode for preimage calculation of transaction object:
        tx.TxIn[i].script_sig = script_code
        tx.TxIn[i].script_sig_len = script_code_len

        if segwit_input:
            try:
                tx.TxIn[i].script_sig += input_dict[tx_input][
                    'amount'].to_bytes(8, byteorder='little')

                # For partially signed Segwit transactions the signatures must
                # be extracted from the witnessScript field:
                input_script_field[i] = tx.TxIn[i].witness
            except AttributeError:
                raise ValueError(
                    'Cannot sign a segwit input when the input\'s amount is '
                    'unknown. Maybe no network connection or the input is '
                    'already spent? Then please provide all inputs to sign as '
                    '`Unspent` objects to the function call.')

        inputs_parameters.append([i, hash_type, segwit_input])
    preimages = calculate_preimages(tx, inputs_parameters)

    # Calculate signature scripts:
    for hash, (i, _, segwit_input) in zip(preimages, inputs_parameters):
        signature = private_key.sign(hash) + b'\x01'

        # ------------------------------------------------------------------
        if private_key.instance == 'MultiSig' or private_key.instance == 'MultiSigTestnet':
            # P2(W)SH input

            script_blob = b''
            sigs = {}
            # Initial number of witness items (OP_0 + one signature + redeemscript).
            witness_count = 3
            if input_script_field[i]:
                sig_list = get_signatures_from_script(input_script_field[i])
                # Bitcoin Core convention: Every missing signature is denoted
                # by 0x00. Only used for already partially-signed scriptSigs:
                script_blob += b'\x00' * (private_key.m - len(sig_list) - 1)
                # Total number of witness items when partially or fully signed:
                witness_count = private_key.m + 2
                # For a partially signed input make a dictionary containing
                # all the provided signatures with public-keys as keys:
                for sig in sig_list:
                    for pub in private_key.public_keys:
                        if verify_sig(sig[:-1], hash, pub):
                            # If we already found a valid signature for pubkey
                            # we just overwrite it and don't care.
                            sigs[pub] = sig
                if len(sigs) >= private_key.m:
                    raise ValueError(
                        'Transaction is already signed with sufficiently needed signatures.'
                    )

            sigs[public_key] = signature

            witness = b''
            # Sort ingthe signatures according to the public-key list:
            for pub in private_key.public_keys:
                if pub in sigs:
                    sig = sigs[pub]
                    length = int_to_varint(
                        len(sig)) if segwit_input else script_push(len(sig))
                    witness += length + sig

            script_sig = b'\x22' + private_key.segwit_scriptcode

            witness = (int_to_varint(witness_count) if segwit_input else
                       b'') + b'\x00' + witness + script_blob
            witness += (int_to_varint(len(
                private_key.redeemscript)) if segwit_input else script_push(
                    len(private_key.redeemscript))) + private_key.redeemscript

            script_sig = script_sig if segwit_input else witness
            witness = witness if segwit_input else b'\x00' if segwit_tx else b''

        # ------------------------------------------------------------------
        else:
            # P2(W)PKH input

            script_sig = b'\x16' + private_key.segwit_scriptcode

            witness = ((b'\x02' if segwit_input else b'') +
                       len(signature).to_bytes(
                           1, byteorder='little')  # witness counter
                       + signature + public_key_push + public_key)

            script_sig = script_sig if segwit_input else witness
            witness = witness if segwit_input else b'\x00' if segwit_tx else b''

        # Providing the signature(s) to the input
        tx.TxIn[i].script_sig = script_sig
        tx.TxIn[i].script_sig_len = int_to_varint(len(script_sig))
        tx.TxIn[i].witness = witness

    return tx.to_hex()
Example #25
0
def sign_tx(
    private_key,
    tx,
    j=-1
):  # Future-TODO: add sw_dict to allow override of segwit input dictionary?
    # j is the input to be signed and can be a single index, a list of indices, or denote all inputs (-1)

    if not isinstance(tx, TxObj):
        # Add sw_dict containing unspent segwit txid:txindex and amount to deserialize tx:
        sw_dict = {}
        unspents = private_key.unspents
        for u in unspents:
            if u.segwit:
                tx_input = u.txid + ':' + str(u.txindex)
                sw_dict[tx_input] = u.amount
        tx = deserialize(tx, sw_dict, private_key.sw_scriptcode)

    version = tx.version
    marker = b'\x00'
    flag = b'\x01'
    lock_time = tx.locktime
    hash_type = HASH_TYPE

    input_count = int_to_varint(tx.input_count)
    output_count = int_to_varint(tx.output_count)

    output_block = b''
    for i in range(tx.output_count):
        output_block += tx.TxOut[i].value
        output_block += tx.TxOut[i].script_len
        output_block += tx.TxOut[i].script

    hashPrevouts = double_sha256(b''.join(
        [i.txid + i.txindex for i in tx.TxIn]))
    hashSequence = double_sha256(b''.join([i.sequence for i in tx.TxIn]))
    hashOutputs = double_sha256(b''.join([bytes(o) for o in tx.TxOut]))

    if j < 0:  # Sign all inputs
        j = range(len(tx.TxIn))
    elif not isinstance(j, list):  # Sign a single input
        j = [j]

    segwit = False  # Global check if at least one input is segwit

    for i in j:
        # Check if input is segwit or non-segwit:
        sw = tx.TxIn[i].segwit
        segwit = segwit or sw  # Global check if at least one input is segwit => Transaction must be of segwit-format

        public_key = private_key.public_key
        public_key_len = script_push(len(public_key))

        scriptCode = private_key.scriptcode
        scriptCode_len = int_to_varint(len(scriptCode))

        if sw == False:
            hashed = sha256(version + input_count +
                            b''.join(ti.txid + ti.txindex + OP_0 + ti.sequence
                                     for ti in islice(tx.TxIn, i)) +
                            tx.TxIn[i].txid + tx.TxIn[i].txindex +
                            scriptCode_len + scriptCode + tx.TxIn[i].sequence +
                            b''.join(ti.txid + ti.txindex + OP_0 + ti.sequence
                                     for ti in islice(tx.TxIn, i + 1, None)) +
                            output_count + output_block + lock_time +
                            hash_type)

            input_script_field = tx.TxIn[i].script

        else:
            hashed = sha256(  # BIP-143: Used for Segwit
                version + hashPrevouts + hashSequence + tx.TxIn[i].txid +
                tx.TxIn[i].txindex + scriptCode_len + scriptCode +
                tx.TxIn[i].amount + tx.TxIn[i].sequence + hashOutputs +
                lock_time + hash_type)

            input_script_field = tx.TxIn[i].witness

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

        # ------------------------------------------------------------------
        if private_key.instance == 'MultiSig' or private_key.instance == 'MultiSigTestnet':
            # P2(W)SH input

            script_blob = b''
            sigs = {}
            if input_script_field:  # If tx is already partially signed: Make a dictionary of the provided signatures with public-keys as key-values
                sig_list = get_signatures_from_script(input_script_field)
                if len(sig_list) > private_key.m:
                    raise TypeError(
                        'Transaction is already signed with {} of {} needed signatures.'
                    ).format(len(sig_list), private_key.m)
                for sig in sig_list:
                    for pub in private_key.public_keys:
                        if verify_sig(sig[:-1], hashed, hex_to_bytes(pub)):
                            sigs[pub] = sig
                script_blob += b'\x00' * (
                    private_key.m - len(sig_list) - 1
                )  # Bitcoin Core convention: Every missing signature is denoted by 0x00. Only used for already partially-signed scriptSigs.

            sigs[bytes_to_hex(public_key)] = signature

            witness = b''
            witness_count = 2  # count number of witness items (OP_0 + each signature + redeemscript).
            for pub in private_key.public_keys:  # Sort the signatures according to the public-key list:
                if pub in sigs:
                    sig = sigs[pub]
                    length = int_to_varint(
                        len(sig)) if sw == True else script_push(len(sig))
                    witness += length + sig
                    witness_count += 1

            script_sig = b'\x22' + private_key.sw_scriptcode

            witness = (witness_count.to_bytes(1, byteorder='little') if sw
                       == True else b'') + b'\x00' + witness + script_blob
            witness += (int_to_varint(len(
                private_key.redeemscript)) if sw == True else script_push(
                    len(private_key.redeemscript))) + private_key.redeemscript

            script_sig = witness if sw == False else script_sig
            witness = b'\x00' if sw == False else witness

        # ------------------------------------------------------------------
        else:
            # P2(W)PKH input

            script_sig = b'\x16' + private_key.sw_scriptcode

            witness = ((b'\x02' if sw == True else b'') +  # witness counter
                       len(signature).to_bytes(1, byteorder='little') +
                       signature + public_key_len + public_key)

            script_sig = witness if sw == False else script_sig
            witness = b'\x00' if sw == False else witness

        tx.TxIn[i].script = script_sig
        tx.TxIn[i].script_len = int_to_varint(len(script_sig))
        tx.TxIn[i].witness = witness

    return bytes_to_hex(
        version + (marker if segwit == True else b'') +
        (flag if segwit == True else b'') + input_count +
        construct_input_block(tx.TxIn) + output_count + output_block +
        (construct_witness_block(tx.TxIn) if segwit == True else b'') +
        lock_time)
Example #26
0
def deserialize(txhex, sw_dict={}, sw_scriptcode=None):
    # sw_dict is a dictionary containing segwit-inputs' txid concatenated with txindex using ":" mapping to information of the amount the input contains.
    # E.g.: sw_dict = {'txid:txindex': amount, ...}
    if isinstance(txhex, str) and re.match('^[0-9a-fA-F]*$', txhex):
        return deserialize(hex_to_bytes(txhex), sw_dict, sw_scriptcode)

    if txhex[
            4:
            6] == b'\x00\x01':  # ``marker|flag'' == 0001 if segwit-transaction
        segwit = True
    else:
        segwit = False

    pos = [0]

    def read_as_int(bytez):
        pos[0] += bytez
        return int(bytes_to_hex(txhex[pos[0] - bytez:pos[0]][::-1]), base=16)

    def read_var_int():
        pos[0] += 1

        val = int(bytes_to_hex(txhex[pos[0] - 1:pos[0]]), base=16)
        if val < 253:
            return val
        return read_as_int(pow(2, val - 252))

    def read_bytes(bytez):
        pos[0] += bytez
        return txhex[pos[0] - bytez:pos[0]]

    def read_var_string():
        size = read_var_int()
        return read_bytes(size)

    def read_segwit_string():
        size = read_var_int()
        return int_to_varint(size) + read_bytes(size)

    version = read_as_int(4).to_bytes(4, byteorder='little')

    if segwit:
        _ = read_as_int(1).to_bytes(1,
                                    byteorder='little')  # ``marker`` is read
        _ = read_as_int(1).to_bytes(1, byteorder='little')  # ``flag`` is read

    ins = read_var_int()
    inputs = []
    for i in range(ins):
        txid = read_bytes(32)
        txindex = read_as_int(4).to_bytes(4, byteorder='little')
        script = read_var_string()
        sequence = read_as_int(4).to_bytes(4, byteorder='little')
        # Check if input is segwit:
        tx_input = bytes_to_hex(txid) + ':' + bytes_to_hex(txindex)
        sw = True if (
            sw_scriptcode == script[1:] or tx_input in sw_dict
        ) else False  # Partially-signed segwit-multisig input or input provided in sw_dict.
        amount = sw_dict[
            tx_input] if tx_input in sw_dict else 0  # Read ``amount`` from sw_dict if it is provided.
        inputs.append(TxIn(script, txid, txindex, b'', amount, sequence, sw))

    outs = read_var_int()
    outputs = []
    for _ in range(outs):
        value = read_as_int(8).to_bytes(8, byteorder='little')
        script = read_var_string()
        outputs.append(TxOut(value, script))

    if segwit:
        for i in range(ins):
            wnum = read_var_int()
            witness = int_to_varint(wnum)
            for _ in range(wnum):
                witness += read_segwit_string()
            inputs[i].witness = witness

    locktime = read_as_int(4).to_bytes(4, byteorder='little')

    txobj = TxObj(version, inputs, outputs, locktime)

    return txobj
 def test_no_message(self):
     assert construct_output_block(OUTPUTS) == hex_to_bytes(OUTPUT_BLOCK)
Example #28
0
def test_int(intk, debug=False, do_endian=True, do_ops=True):
    if do_ops:
        test_with_prime21e_ops(intk)
    if do_endian:
        n = int(intk)
        n2 = int.from_bytes(n.to_bytes((n.bit_length() + 7) // 8, 'big')
                            or b'\0',
                            byteorder='little')
        #print(n, '->', n2)
        test_int(n2, do_endian=False, do_ops=False)
        # concat PRIME21E
        n3 = str(intk) + str(PRIME21E)
        n4 = str(PRIME21E) + str(intk)
        test_int(n3, do_endian=False, do_ops=False)
        test_int(n4, do_endian=False, do_ops=False)
        #test_int(struct.pack('>L', int(intk)))

    if int(intk) == 0 or int(
            intk
    ) > 115792089237316195423570985008687907852837564279074904382605163141518161494337:
        return 'invalid size'
    try:
        sha_hex = to_hex(intk)
        sha_key = right_pad_zed(sha_hex)
        #print(len(sha_key), sha_hex, '->', sha_key)
        sha_key_compressed = Key.from_hex(sha_key)
        sha_key_uncompressed = uncompressed_key(sha_key_compressed)
        priv_key_compressed = Key.from_int(int(intk))
        priv_key_uncompressed = uncompressed_key(priv_key_compressed)
        #priv_key_compressed2 = compressed_key(int(intk))
        priv_key_compressed2 = compressed_key(priv_key_compressed)  #int(intk))
        priv_key_compressed3 = Key.from_int(int(intk) & PRIME21E)
        priv_key_c2 = Key.from_bytes(
            b58decode(
                b58encode(utils.hex_to_bytes(utils.int_to_hex(int(intk))))))
        priv_key_uc2 = uncompressed_key(priv_key_c2)
    except Exception as err:
        print("ERROR: test_int:", err, 'intk:', intk)
        traceback.print_exc(file=sys.stdout)
        return False
    """Debug:
    print('addrc:{} addru:{} wifc:{} wifu:{}'.format(
        priv_key_compressed.address,
        priv_key_uncompressed.address,
        priv_key_compressed.to_wif(),
        priv_key_uncompressed.to_wif(),

    ))
    """
    if debug:
        print(
            intk,
            priv_key_compressed.address,
            priv_key_uncompressed.address,
            bytes_to_hex(priv_key_compressed.public_key),
            bytes_to_hex(priv_key_uncompressed.public_key),
        )
    if test_key(sha_key_compressed):
        return True
    if test_key(sha_key_uncompressed):
        return True
    if test_key(priv_key_compressed3):
        return True
    if test_key(priv_key_compressed):
        return True
    if test_key(priv_key_compressed2):
        return True
    if test_key(priv_key_uncompressed):
        return True
    if test_key(priv_key_uc2):
        return True
    if test_key(priv_key_c2):
        return True
    return False
def test_construct_input_block():
    assert construct_input_block(INPUTS) == hex_to_bytes(INPUT_BLOCK)
Example #30
0
 def is_segwit(cls, tx):
     if isinstance(tx, cls):
         return tx.marker + tx.flag == MARKER + FLAG
     elif not isinstance(tx, bytes):
         tx = hex_to_bytes(tx)
     return tx[4:6] == MARKER + FLAG