Exemplo n.º 1
0
    def doit(num_ins, num_outs, master_xpub, subpath="0/%d", fee=10000):
        psbt = BasicPSBT()
        txn = Tx(2, [], [])

        # we have a key; use it to provide "plausible" value inputs
        from pycoin.key.BIP32Node import BIP32Node
        mk = BIP32Node.from_wallet_key(master_xpub)
        xfp = mk.fingerprint()

        psbt.inputs = [BasicPSBTInput(idx=i) for i in range(num_ins)]
        psbt.outputs = [BasicPSBTOutput(idx=i) for i in range(num_outs)]

        for i in range(num_ins):
            # make a fake txn to supply each of the inputs
            # - each input is 1BTC

            # addr where the fake money will be stored.
            subkey = mk.subkey_for_path(subpath % i)
            sec = subkey.sec()
            assert len(sec) == 33, "expect compressed"
            assert subpath[0:2] == '0/'

            psbt.inputs[i].bip32_paths[sec] = xfp + pack('<II', 0, i)

            # UTXO that provides the funding for to-be-signed txn
            supply = Tx(2, [TxIn(pack('4Q', 0xdead, 0xbeef, 0, 0), 73)], [])

            scr = bytes([0x76, 0xa9, 0x14]) + subkey.hash160() + bytes(
                [0x88, 0xac])
            supply.txs_out.append(TxOut(1E8, scr))

            with BytesIO() as fd:
                supply.stream(fd)
                psbt.inputs[i].utxo = fd.getvalue()

            if 0:
                with BytesIO() as fd:
                    supply.stream(fd, include_witness_data=True)
                    psbt.inputs[i].witness_utxo = fd.getvalue()

            spendable = TxIn(supply.hash(), 0)
            txn.txs_in.append(spendable)

        for i in range(num_outs):
            # random P2PKH
            scr = bytes([0x76, 0xa9, 0x14]) + pack(
                'I', i + 1) + bytes(16) + bytes([0x88, 0xac])
            h = TxOut(round(((1E8 * num_ins) - fee) / num_outs, 4), scr)
            txn.txs_out.append(h)

        with BytesIO() as b:
            txn.stream(b)
            psbt.txn = b.getvalue()

        rv = BytesIO()
        psbt.serialize(rv)
        assert rv.tell() <= MAX_TXN_LEN, 'too fat'

        return rv.getvalue()
Exemplo n.º 2
0
def sign_tx(tx, utxo_list, is_test):
    secret_exponents = [
        utxo.address_rec.rawPrivKey for utxo in utxo_list if utxo.address_rec
    ]
    solver = SecretExponentSolver(secret_exponents)
    txins = tx.txs_in[:]
    hash_type = SIGHASH_ALL
    for txin_idx in xrange(len(txins)):
        blank_txin = txins[txin_idx]
        utxo = None
        for utxo_candidate in utxo_list:
            if utxo_candidate.get_txhash() == blank_txin.previous_hash \
                    and utxo_candidate.outindex == blank_txin.previous_index:
                utxo = utxo_candidate
                break
        if not (utxo and utxo.address_rec):
            continue
        txout_script = utxo.script.decode('hex')
        signature_hash = tx.signature_hash(txout_script,
                                           txin_idx,
                                           hash_type=hash_type)
        txin_script = solver(txout_script, signature_hash, hash_type)
        txins[txin_idx] = TxIn(blank_txin.previous_hash,
                               blank_txin.previous_index, txin_script,
                               blank_txin.sequence)
        if not verify_script(
                txin_script, txout_script, signature_hash,
                hash_type=hash_type):
            raise Exception("invalid script")
    tx.txs_in = txins
Exemplo n.º 3
0
    def doit(num_ins, num_outs, fat=0):
        psbt = BasicPSBT()
        txn = Tx(2, [], [])

        for i in range(num_ins):
            h = TxIn(pack('4Q', 0, 0, 0, i), i)
            txn.txs_in.append(h)

        for i in range(num_outs):
            # random P2PKH
            scr = bytes([0x76, 0xa9, 0x14]) + pack(
                'I', i + 1) + bytes(16) + bytes([0x88, 0xac])
            h = TxOut((1E6 * i) if i else 1E8, scr)
            txn.txs_out.append(h)

        with BytesIO() as b:
            txn.stream(b)
            psbt.txn = b.getvalue()

        psbt.inputs = [BasicPSBTInput(idx=i) for i in range(num_ins)]
        psbt.outputs = [BasicPSBTOutput(idx=i) for i in range(num_outs)]

        if fat:
            for i in range(num_ins):
                psbt.inputs[i].utxo = os.urandom(fat)

        rv = BytesIO()
        psbt.serialize(rv)
        assert rv.tell() <= MAX_TXN_LEN, 'too fat'

        return rv.getvalue()
Exemplo n.º 4
0
 def test_multisig_one_at_a_time(self):
     M = 3
     N = 3
     keys = [
         Key(secret_exponent=i, generator=secp256k1_generator)
         for i in range(1, N + 2)
     ]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     script = script_for_multisig(m=M,
                                  sec_keys=[key.sec() for key in keys[:N]])
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(),
                              [keys[-1].address()])
     ids = [
         "403e5bfc59e097bb197bf77a692d158dd3a4f7affb4a1fa41072dafe7bec7058",
         "5931d9995e83721243dca24772d7012afcd4378996a8b953c458175f15a544db",
         "9bb4421088190bbbb5b42a9eaa9baed7ec7574a407c25f71992ba56ca43d9c44",
         "03a1dc2a63f93a5cf5a7cb668658eb3fc2eda88c06dc287b85ba3e6aff751771"
     ]
     for i in range(1, N + 1):
         self.assertEqual(tx2.bad_signature_count(), 1)
         self.assertEqual(tx2.id(), ids[i - 1])
         hash160_lookup = build_hash160_lookup(
             [keys[i - 1].secret_exponent()], [secp256k1_generator])
         tx2.sign(hash160_lookup=hash160_lookup)
         self.assertEqual(tx2.id(), ids[i])
         t1 = sorted(who_signed_tx(tx2, 0, UI))
         t2 = sorted(((key.address(), SIGHASH_ALL) for key in keys[:i]))
         self.assertEqual(t1, t2)
     self.assertEqual(tx2.bad_signature_count(), 0)
Exemplo n.º 5
0
def construct_standard_tx(composed_tx_spec, is_test):
    txouts = []
    STANDARD_SCRIPT_OUT = "OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG"
    for txout in composed_tx_spec.get_txouts():
        hash160 = bitcoin_address_to_hash160_sec(txout.target_addr, is_test)
        script_text = STANDARD_SCRIPT_OUT % b2h(hash160)
        script_bin = tools.compile(script_text)
        txouts.append(TxOut(txout.value, script_bin))
    txins = []
    for cts_txin in composed_tx_spec.get_txins():
        txin = TxIn(cts_txin.get_txhash(), cts_txin.prevout.n)
        if cts_txin.nSequence:
            print cts_txin.nSequence
            txin.sequence = cts_txin.nSequence
        txins.append(txin)
    version = 1
    lock_time = 0
    return Tx(version, txins, txouts, lock_time)
Exemplo n.º 6
0
def construct_standard_tx(composed_tx_spec, is_test):
    txouts = []
    STANDARD_SCRIPT_OUT = "OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG"
    for txout in composed_tx_spec.get_txouts():
        hash160 = bitcoin_address_to_hash160_sec(txout.target_addr, is_test)
        script_text = STANDARD_SCRIPT_OUT % b2h(hash160)
        script_bin = tools.compile(script_text)
        txouts.append(TxOut(txout.value, script_bin))
    txins = []
    for cts_txin in composed_tx_spec.get_txins():
        txin = TxIn(cts_txin.get_txhash(), cts_txin.prevout.n)
        if cts_txin.nSequence:
            print cts_txin.nSequence
            txin.sequence = cts_txin.nSequence
        txins.append(txin)
    version = 1
    lock_time = 0
    return Tx(version, txins, txouts, lock_time)
Exemplo n.º 7
0
def find_txins(service, addresses, amount):
    spendables = retrieve_utxos(service, addresses)
    txins = []
    total = 0
    for spendable in spendables:
        total += spendable.coin_value
        txins.append(TxIn(spendable.tx_hash, spendable.tx_out_index))
        if total >= amount:
            return txins, total
    return txins, total
Exemplo n.º 8
0
def spend_sh_fund(tx_ins, wif_keys, tx_outs):
    """
    spend script hash fund
    the key point of an input comes from multisig address is that,
    its sign script is combined with several individual signs
    :param tx_ins: list with tuple(tx_id, idx, balance, address, redeem_script)
    :param wif_keys: private keys in wif format,
        technical should be the same order with the pubkey in redeem script,
        but pycoin has inner control, so here order is not mandatory
    :param tx_outs: balance, receiver_address
    :return: raw hex and tx id
    """
    _txs_in = []
    _un_spent = []
    for tx_id, idx, balance, address, _ in tx_ins:
        # must h2b_rev NOT h2b
        tx_id_b = h2b_rev(tx_id)
        _txs_in.append(TxIn(tx_id_b, idx))

        _un_spent.append(
            Spendable(
                balance,
                script_obj_from_address(address, netcodes=[NET_CODE]).script(),
                tx_id_b, idx))

    _txs_out = []
    for balance, receiver_address in tx_outs:
        _txs_out.append(
            TxOut(
                balance,
                script_obj_from_address(receiver_address,
                                        netcodes=[NET_CODE]).script()))

    version, lock_time = 1, 0
    tx = Tx(version, _txs_in, _txs_out, lock_time)
    tx.set_unspents(_un_spent)

    # construct hash160_lookup[hash160] = (secret_exponent, public_pair, compressed) for each individual key
    hash160_lookup = build_hash160_lookup(
        [Key.from_text(wif_key).secret_exponent() for wif_key in wif_keys])

    for i in range(0, len(tx_ins)):
        # you can add some conditions that if the input script is not p2sh type, not provide p2sh_lookup,
        # so that all kinds of inputs can work together
        p2sh_lookup = build_p2sh_lookup([binascii.unhexlify(tx_ins[i][-1])])
        tx.sign_tx_in(hash160_lookup,
                      i,
                      tx.unspents[i].script,
                      hash_type=SIGHASH_ALL,
                      p2sh_lookup=p2sh_lookup)

    return tx.as_hex(), tx.id()
Exemplo n.º 9
0
 def multisig_M_of_N(self, M, N, unsigned_id, signed_id):
     keys = [Key(secret_exponent=i) for i in range(1, N+2)]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script()
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()])
     self.assertEqual(tx2.id(), unsigned_id)
     self.assertEqual(tx2.bad_signature_count(), 1)
     hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys)
     tx2.sign(hash160_lookup=hash160_lookup)
     self.assertEqual(tx2.id(), signed_id)
     self.assertEqual(tx2.bad_signature_count(), 0)
     self.assertEqual(sorted(who_signed.who_signed_tx(tx2, 0)),
                      sorted(((key.address(), SIGHASH_ALL) for key in keys[:M])))
Exemplo n.º 10
0
def standard_tx(coins_from, coins_to):
    txs_in = []
    unspents = []
    for h, idx, tx_out in coins_from:
        txs_in.append(TxIn(h, idx))
        unspents.append(tx_out)

    txs_out = []
    for coin_value, address in coins_to:
        txs_out.append(TxOut(coin_value, script_for_address(address)))

    version, lock_time = 1, 0
    tx = Tx(version, txs_in, txs_out, lock_time)
    tx.set_unspents(unspents)
    return tx
Exemplo n.º 11
0
 def test_sign_pay_to_script_multisig(self):
     M, N = 3, 3
     keys = [Key(secret_exponent=i) for i in range(1, N+2)]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     underlying_script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script()
     address = address_for_pay_to_script(underlying_script)
     self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q")
     script = standard_tx_out_script(address)
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address])
     hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[:N])
     p2sh_lookup = build_p2sh_lookup([underlying_script])
     tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)
     self.assertEqual(tx2.bad_signature_count(), 0)
     self.assertRaises(who_signed.NoAddressesForScriptTypeError, who_signed.who_signed_tx, tx2, 0)
Exemplo n.º 12
0
def tether_tx(tx_ins, private_key, send_amount, receiver):
    """
    simple usdt transaction
    here assume utxo comes from the sender and is used for mine fee
    bitcoin change will be sent back to sender address

    of course different address's utxo can be used for mine fee,
    but should be aware sender is determined by the first input in the tx
    bitcoin change can also be sent back to different address,
    but should be aware receiver is indicated by the last output address that is not the sender

    for full customization, use btc sample p2pkh_tx
    :param tx_ins: utxo from the sender
    :param private_key: private key of the same sender
    :param send_amount: (display amount) * (10 ** 8)
    :param receiver: address to receive usdt
    """
    _txs_in = []
    _un_spent = []
    total_bal = 0

    for tx_id, idx, balance, address in tx_ins:
        total_bal += balance

        # must h2b_rev NOT h2b
        tx_id_b = h2b_rev(tx_id)
        _txs_in.append(TxIn(tx_id_b, idx))

        _un_spent.append(Spendable(balance, standard_tx_out_script(address), tx_id_b, idx))

    txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins), 3) * recommend_satoshi_per_byte()

    _txs_out = [TxOut(total_bal - txn_fee - 546, standard_tx_out_script(tx_ins[0][3])),
                TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))),
                TxOut(546, standard_tx_out_script(receiver))]

    version, lock_time = 1, 0
    tx = Tx(version, _txs_in, _txs_out, lock_time)
    tx.set_unspents(_un_spent)

    solver = build_hash160_lookup([int(private_key, 16)] * len(tx_ins))
    signed_tx = tx.sign(solver, hash_type=SIGHASH_ALL)

    return signed_tx.as_hex(), signed_tx.id()
Exemplo n.º 13
0
    def get_raw_unsigned(self, fee_satoshi):
        """Return raw transaction ready for signing

        May return a transaction with amount=0 if the input amount is not enough to cover fees
        """
        txout = self.tx.txs_out[self.vout]
        amount_satoshi = txout.coin_value

        if fee_satoshi >= amount_satoshi:
            logging.warning('Insufficient funds to cover fee')
            logging.warning('txout has value of {}, fee = {}'.format(
                amount_satoshi, fee_satoshi))

        # Calculate adjusted amount = input amount - fee
        adjusted_amount_satoshi = max(0, amount_satoshi - fee_satoshi)
        logging.debug('tx amount = amount - fee = {} - {} = {}'.format(
            amount_satoshi, fee_satoshi, adjusted_amount_satoshi))
        assert adjusted_amount_satoshi >= 0
        adjusted_amount_btc = decimal.Decimal(
            adjusted_amount_satoshi) / satoshi_per_btc

        logging.debug("Create tx: {} sat -> {}".format(adjusted_amount_satoshi,
                                                       self.dest_address))
        logging.info("Input tx id = {}, vout={}".format(
            self.tx.id().encode("ascii"), self.vout))
        txin = TxIn(self.tx.hash(),
                    self.vout,
                    sequence=MAX_BIP125_RBF_SEQUENCE)
        scriptPubKey = pycoin.ui.script_obj_from_address(self.dest_address)
        txout = TxOut(adjusted_amount_satoshi, scriptPubKey.script())

        # Set nlocktime to the current blockheight to discourage 'fee sniping', as per the core
        # wallet implementation
        nlocktime = util.get_current_blockcount() or 0

        version = 1
        tx = Tx(version, [
            txin,
        ], [
            txout,
        ], nlocktime)
        return tx.as_hex()
Exemplo n.º 14
0
 def test_multisig_one_at_a_time(self):
     M = 3
     N = 3
     keys = [Key(secret_exponent=i) for i in range(1, N+2)]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script()
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()])
     ids = ["403e5bfc59e097bb197bf77a692d158dd3a4f7affb4a1fa41072dafe7bec7058",
            "5931d9995e83721243dca24772d7012afcd4378996a8b953c458175f15a544db",
            "9bb4421088190bbbb5b42a9eaa9baed7ec7574a407c25f71992ba56ca43d9c44",
            "03a1dc2a63f93a5cf5a7cb668658eb3fc2eda88c06dc287b85ba3e6aff751771"]
     for i in range(1, N+1):
         self.assertEqual(tx2.bad_signature_count(), 1)
         self.assertEqual(tx2.id(), ids[i-1])
         hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[i-1:i])
         tx2.sign(hash160_lookup=hash160_lookup)
         self.assertEqual(tx2.id(), ids[i])
         self.assertEqual(sorted(who_signed.who_signed_tx(tx2, 0)),
                          sorted(((key.address(), SIGHASH_ALL) for key in keys[:i])))
     self.assertEqual(tx2.bad_signature_count(), 0)
Exemplo n.º 15
0
 def test_sign_pay_to_script_multisig(self):
     M, N = 3, 3
     keys = [
         Key(secret_exponent=i, generator=secp256k1_generator)
         for i in range(1, N + 2)
     ]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     underlying_script = script_for_multisig(
         m=M, sec_keys=[key.sec() for key in keys[:N]])
     address = address_for_p2s(underlying_script)
     self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q")
     script = script_for_address(address)
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address])
     hash160_lookup = build_hash160_lookup(
         (key.secret_exponent() for key in keys[:N]), [secp256k1_generator])
     p2sh_lookup = build_p2sh_lookup([underlying_script])
     tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)
     self.assertEqual(tx2.bad_signature_count(), 0)
     self.assertEqual(
         sorted(who_signed_tx(tx2, 0, UI)),
         sorted(((key.address(), SIGHASH_ALL) for key in keys[:M])))
Exemplo n.º 16
0
def spend_pkh_fund(tx_ins, in_keys, tx_outs):
    """
    p2pkh address send to p2pkh p2sh transaction
    :param tx_ins: list with tuple(tx_id, idx, balance, address)
    :param in_keys: list of private keys in hex format corresponding to each input
    :param tx_outs: balance, receiver_address
    :return: raw hex and tx id
    """
    _txs_in = []
    _un_spent = []
    for tx_id, idx, balance, address in tx_ins:
        # must h2b_rev NOT h2b
        tx_id_b = h2b_rev(tx_id)
        _txs_in.append(TxIn(tx_id_b, idx))

        _un_spent.append(
            Spendable(
                balance,
                script_obj_from_address(address, netcodes=[NET_CODE]).script(),
                tx_id_b, idx))

    _txs_out = []
    for balance, receiver_address in tx_outs:
        _txs_out.append(
            TxOut(
                balance,
                script_obj_from_address(receiver_address,
                                        netcodes=[NET_CODE]).script()))

    version, lock_time = 1, 0
    tx = Tx(version, _txs_in, _txs_out, lock_time)
    tx.set_unspents(_un_spent)

    solver = build_hash160_lookup([int(pri_hex, 16) for pri_hex in in_keys])
    tx.sign(solver, hash_type=SIGHASH_ALL)

    return tx.as_hex(), tx.id()
Exemplo n.º 17
0
def fake_txn(num_ins,
             num_outs,
             master_xpub=None,
             subpath="0/%d",
             fee=10000,
             outvals=None,
             segwit_in=False,
             outstyles=['p2pkh'],
             is_testnet=False,
             change_style='p2pkh',
             partial=False,
             change_outputs=[]):

    # make various size txn's ... completely fake and pointless values
    # - but has UTXO's to match needs
    # - input total = num_inputs * 1BTC
    from pycoin.tx.Tx import Tx
    from pycoin.tx.TxIn import TxIn
    from pycoin.tx.TxOut import TxOut
    from pycoin.serialize import h2b_rev
    from struct import pack

    psbt = BasicPSBT()
    txn = Tx(2, [], [])

    # we have a key; use it to provide "plausible" value inputs
    mk = BIP32Node.from_wallet_key(master_xpub)
    xfp = mk.fingerprint()

    psbt.inputs = [BasicPSBTInput(idx=i) for i in range(num_ins)]
    psbt.outputs = [BasicPSBTOutput(idx=i) for i in range(num_outs)]

    outputs = []

    for i in range(num_ins):
        # make a fake txn to supply each of the inputs
        # - each input is 1BTC

        # addr where the fake money will be stored.
        subkey = mk.subkey_for_path(subpath % i)
        sec = subkey.sec()
        assert len(sec) == 33, "expect compressed"
        assert subpath[0:2] == '0/'

        if partial and (i == 0):
            psbt.inputs[i].bip32_paths[sec] = b'Nope' + pack('<II', 0, i)
        else:
            psbt.inputs[i].bip32_paths[sec] = xfp + pack('<II', 0, i)

        # UTXO that provides the funding for to-be-signed txn
        supply = Tx(2, [TxIn(pack('4Q', 0xdead, 0xbeef, 0, 0), 73)], [])

        scr = bytes([0x76, 0xa9, 0x14]) + subkey.hash160() + bytes(
            [0x88, 0xac])

        supply.txs_out.append(TxOut(1E8, scr))

        with BytesIO() as fd:
            if not segwit_in:
                supply.stream(fd)
                psbt.inputs[i].utxo = fd.getvalue()
            else:
                supply.txs_out[-1].stream(fd)
                psbt.inputs[i].witness_utxo = fd.getvalue()

        spendable = TxIn(supply.hash(), 0)
        txn.txs_in.append(spendable)

    for i in range(num_outs):
        is_change = False

        # random P2PKH
        if not outstyles:
            style = ADDR_STYLES[i % len(ADDR_STYLES)]
        else:
            style = outstyles[i % len(outstyles)]

        if i in change_outputs:
            scr, act_scr, isw, pubkey, sp = make_change_addr(mk, change_style)
            psbt.outputs[i].bip32_paths[pubkey] = sp
            is_change = True
        else:
            scr = act_scr = fake_dest_addr(style)
            isw = ('w' in style)

        assert scr
        act_scr = act_scr or scr

        if isw:
            psbt.outputs[i].witness_script = scr
        elif style.endswith('sh'):
            psbt.outputs[i].redeem_script = scr

        if not outvals:
            h = TxOut(round(((1E8 * num_ins) - fee) / num_outs, 4), act_scr)
        else:
            h = TxOut(outvals[i], act_scr)

        outputs.append(
            (Decimal(h.coin_value) / Decimal(1E8), act_scr, is_change))

        txn.txs_out.append(h)

    with BytesIO() as b:
        txn.stream(b)
        psbt.txn = b.getvalue()

    rv = BytesIO()
    psbt.serialize(rv)

    return rv.getvalue(), [(n, render_address(s, is_testnet), ic)
                           for n, s, ic in outputs]
Exemplo n.º 18
0
def txin(txhash, index):
    txhash = txid(txhash)
    index = positive_integer(index)
    return TxIn(txhash, index)
Exemplo n.º 19
0
    def doit(num_ins,
             num_outs,
             master_xpub,
             subpath="0/%d",
             fee=10000,
             outvals=None,
             segwit_in=False,
             outstyles=['p2pkh'],
             change_outputs=[]):
        psbt = BasicPSBT()
        txn = Tx(2, [], [])

        # we have a key; use it to provide "plausible" value inputs
        mk = BIP32Node.from_wallet_key(master_xpub)
        xfp = mk.fingerprint()

        psbt.inputs = [BasicPSBTInput(idx=i) for i in range(num_ins)]
        psbt.outputs = [BasicPSBTOutput(idx=i) for i in range(num_outs)]

        for i in range(num_ins):
            # make a fake txn to supply each of the inputs
            # - each input is 1BTC

            # addr where the fake money will be stored.
            subkey = mk.subkey_for_path(subpath % i)
            sec = subkey.sec()
            assert len(sec) == 33, "expect compressed"
            assert subpath[0:2] == '0/'

            psbt.inputs[i].bip32_paths[sec] = xfp + pack('<II', 0, i)

            # UTXO that provides the funding for to-be-signed txn
            supply = Tx(2, [TxIn(pack('4Q', 0xdead, 0xbeef, 0, 0), 73)], [])

            scr = bytes([0x76, 0xa9, 0x14]) + subkey.hash160() + bytes(
                [0x88, 0xac])

            supply.txs_out.append(TxOut(1E8, scr))

            with BytesIO() as fd:
                if not segwit_in:
                    supply.stream(fd)
                    psbt.inputs[i].utxo = fd.getvalue()
                else:
                    supply.txs_out[-1].stream(fd)
                    psbt.inputs[i].witness_utxo = fd.getvalue()

            spendable = TxIn(supply.hash(), 0)
            txn.txs_in.append(spendable)

        for i in range(num_outs):
            # random P2PKH
            if not outstyles:
                style = ADDR_STYLES[i % len(ADDR_STYLES)]
            else:
                style = outstyles[i % len(outstyles)]

            if i in change_outputs:
                scr, act_scr, isw, pubkey, sp = make_change_addr(mk, style)
                psbt.outputs[i].bip32_paths[pubkey] = sp
            else:
                scr = act_scr = fake_dest_addr(style)
                isw = ('w' in style)
                #if style.endswith('sh'):

            assert scr
            act_scr = act_scr or scr

            if isw:
                psbt.outputs[i].witness_script = scr
            elif style.endswith('sh'):
                psbt.outputs[i].redeem_script = scr

            if not outvals:
                h = TxOut(round(((1E8 * num_ins) - fee) / num_outs, 4),
                          act_scr)
            else:
                h = TxOut(outvals[i], act_scr)

            txn.txs_out.append(h)

        with BytesIO() as b:
            txn.stream(b)
            psbt.txn = b.getvalue()

        rv = BytesIO()
        psbt.serialize(rv)
        assert rv.tell() <= MAX_TXN_LEN, 'too fat'

        return rv.getvalue()
Exemplo n.º 20
0
    def doit(num_ins, num_outs, M, keys, fee=10000,
                outvals=None, segwit_in=False, outstyles=['p2pkh'], change_outputs=[],
                incl_xpubs=False):
        psbt = BasicPSBT()
        txn = Tx(2,[],[])

        if incl_xpubs:
            # add global header with XPUB's
            # - assumes BIP45
            for xfp, m, sk in keys:
                kk = pack('<II', xfp, 45|0x80000000)
                psbt.xpubs.append( (sk.serialize(as_private=False), kk) )

        psbt.inputs = [BasicPSBTInput(idx=i) for i in range(num_ins)]
        psbt.outputs = [BasicPSBTOutput(idx=i) for i in range(num_outs)]

        for i in range(num_ins):
            # make a fake txn to supply each of the inputs
            # - each input is 1BTC

            # addr where the fake money will be stored.
            addr, scriptPubKey, script, details = make_ms_address(M, keys, idx=i)

            # lots of supporting details needed for p2sh inputs
            if segwit_in:
                psbt.inputs[i].witness_script = script
            else:
                psbt.inputs[i].redeem_script = script

            for pubkey, xfp_path in details:
                psbt.inputs[i].bip32_paths[pubkey] = b''.join(pack('<I', j) for j in xfp_path)

            # UTXO that provides the funding for to-be-signed txn
            supply = Tx(2,[TxIn(pack('4Q', 0xdead, 0xbeef, 0, 0), 73)],[])

            supply.txs_out.append(TxOut(1E8, scriptPubKey))

            with BytesIO() as fd:
                if not segwit_in:
                    supply.stream(fd)
                    psbt.inputs[i].utxo = fd.getvalue()
                else:
                    supply.txs_out[-1].stream(fd)
                    psbt.inputs[i].witness_utxo = fd.getvalue()

            spendable = TxIn(supply.hash(), 0)
            txn.txs_in.append(spendable)


        for i in range(num_outs):
            # random P2PKH
            if not outstyles:
                style = ADDR_STYLES[i % len(ADDR_STYLES)]
            else:
                style = outstyles[i % len(outstyles)]

            if i in change_outputs:
                addr, scriptPubKey, scr, details = \
                    make_ms_address(M, keys, idx=i, addr_fmt=unmap_addr_fmt[style])

                for pubkey, xfp_path in details:
                    psbt.outputs[i].bip32_paths[pubkey] = b''.join(pack('<I', j) for j in xfp_path)

                if 'w' in style:
                    psbt.outputs[i].witness_script = scr
                    if style.endswith('p2sh'):
                        psbt.outputs[i].redeem_script = b'\0\x20' + sha256(scr).digest()
                elif style.endswith('sh'):
                    psbt.outputs[i].redeem_script = scr
            else:
                scr = fake_dest_addr(style)

            assert scr

            if not outvals:
                h = TxOut(round(((1E8*num_ins)-fee) / num_outs, 4), scriptPubKey)
            else:
                h = TxOut(outvals[i], scriptPubKey)

            txn.txs_out.append(h)

        with BytesIO() as b:
            txn.stream(b)
            psbt.txn = b.getvalue()

        rv = BytesIO()
        psbt.serialize(rv)
        assert rv.tell() <= MAX_TXN_LEN, 'too fat'

        return rv.getvalue()