What is a correct way to compose a transaction from UTXO?

297 views
Skip to first unread message

Sergey Aldoukhov

unread,
Feb 12, 2015, 8:02:40 PM2/12/15
to bitc...@googlegroups.com
I'd like to use BitcoinJ to create a temporary wallet, add a transaction constructed from an utxo (let's assume 1 utxo for simplicity) and use sendCoinsOffline to obtain the signed transaction. So the code should look like:

Transaction unspent = utxoToTransaction(hash, outputIndex, script, value, address);
wallet.addWalletTransaction(new WalletTransaction(WalletTransaction.Pool.UNSPENT, unspent));
Wallet.SendRequest request = Wallet.SendRequest.to(sendToAddress, sendAmount);
Transaction send = wallet.sendCoinsOffline(request);

But, I can't quite understand how utxoToTransaction function should look like. If I add utxo information to the transaction as an input (txn.addInput(hash, outputIndex, script);) then the transaction has a different hash from the utxo and cannot be used as input for my transaction.
 


devrandom

unread,
Feb 12, 2015, 11:26:14 PM2/12/15
to bitc...@googlegroups.com
On 2015-02-12 05:02 PM, Sergey Aldoukhov wrote:
> I'd like to use BitcoinJ to create a temporary wallet, add a transaction
> constructed from an utxo (let's assume 1 utxo for simplicity) and use
> sendCoinsOffline to obtain the signed transaction. So the code should
> look like:
>
> Transaction unspent = utxoToTransaction(hash, outputIndex, script,
> value, address);
> wallet.addWalletTransaction(new
> WalletTransaction(WalletTransaction.Pool.UNSPENT, unspent));

No need for this, sendCoinsOffline already adds the tx.

> Wallet.SendRequest request = Wallet.SendRequest.to(sendToAddress,
> sendAmount);
> Transaction send = wallet.sendCoinsOffline(request);
>
> But, I can't quite understand how utxoToTransaction function should look
> like. If I add utxo information to the transaction as an input
> (txn.addInput(hash, outputIndex, script);) then the transaction has a

This looks correct. script should be empty (e.g. new Script()).

> different hash from the utxo and cannot be used as input for my transaction.

Not sure what you mean by that. Could you give an example?

>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "bitcoinj" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to bitcoinj+u...@googlegroups.com
> <mailto:bitcoinj+u...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout.

--
devrandom / Miron

Sergey Aldoukhov

unread,
Feb 13, 2015, 2:19:54 AM2/13/15
to bitc...@googlegroups.com
I think I didn't state the problem clear enough. My wallet is not connected to the blockchain, so no transactions whatsoever exist in it. Now, I have a UTXO sent to my address: 

{"transaction_hash":"0801c93078c926050707bc94622ebe5a2cd2e5ef6dc385f3c1856fcde01d456b","output_index":1,"value":10000,"addresses":["mgex8y7ExdTdAfLxDovKyY4aru6QEyCrDd"],"script":"OP_DUP OP_HASH160 0c7b529d3625ebbb237efadbfbae5f75f13f0f4e OP_EQUALVERIFY OP_CHECKSIG","script_hex":"76a9140c7b529d3625ebbb237efadbfbae5f75f13f0f4e88ac","script_type":"pubkeyhash","required_signatures":1,"spent":false,"confirmations":6412}

I want to create a transaction from this utxo, and place it into the wallet, so when I create a send request for the amount lesser than one on the above utxo, the subsequent sendCoinsOffline will find the utxo, connect it as an input to the new transaction, calculate change and fee and sign the transaction. I will broadcast the transaction via other channels than bitcoinj.

If the wallet is online, I would already have this transaction with the above output. But, if I want to "emulate" receiving the transaction from the blockchain, I need to create a transaction:
Transaction unspent = new Transaction(params)
(This transaction must have the hash same as on the utxo. It will serve as source of input for my sendCoinsOffline, and if has it's own hash, the result will not be accepted by the network, because the transaction does not exist for real)
and add the above utxo as an output on this transaction. But, I can't find a way to pass hash, index and script, which are needed to unlock the transaction, to unspent.addOutput. I can add this info to input of a new transaction, but this is not what I want (it won't be picked by bitcoinj for spending).

Maybe I'm trying to follow a wrong path and just need to manually construct/connect transaction? My thinking was that the above approach would let me to reuse wallet logic of connecting things together, picking the change address and calculating the fee.

Andreas Schildbach

unread,
Feb 13, 2015, 3:29:04 AM2/13/15
to bitc...@googlegroups.com
I have code for this in Bitcoin Wallet. It's used by the "Swipe paper
wallet" feature. It's in RequestWalletBalanceTask.java, plus
SweepWalletFragment.java.
> <http://Wallet.SendRequest.to>(sendToAddress,
> > sendAmount);
> > Transaction send = wallet.sendCoinsOffline(request);
> >
> > But, I can't quite understand how utxoToTransaction function
> should look
> > like. If I add utxo information to the transaction as an input
> > (txn.addInput(hash, outputIndex, script);) then the transaction has a
>
> This looks correct. script should be empty (e.g. new Script()).
>
> > different hash from the utxo and cannot be used as input for my
> transaction.
>
> Not sure what you mean by that. Could you give an example?
>
> >
> >
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "bitcoinj" group.
> > To unsubscribe from this group and stop receiving emails from it,
> send
> > an email to bitcoinj+u...@googlegroups.com
> > <mailto:bitcoinj+u...@googlegroups.com>.
> > For more options, visit https://groups.google.com/d/optout
> <https://groups.google.com/d/optout>.
>
> --
> devrandom / Miron

Mike Hearn

unread,
Feb 13, 2015, 6:31:12 AM2/13/15
to bitc...@googlegroups.com
Maybe I'm trying to follow a wrong path and just need to manually construct/connect transaction? My thinking was that the above approach would let me to reuse wallet logic of connecting things together, picking the change address and calculating the fee.

You can build a transaction manually that isn't quite finished, and let the wallet finish it off. Make the tx with the input for the output you want to spend manually, using the Transaction.addInput() API, then add an output for what you want to pay, and then you should be able to use Wallet.SendRequest.forTx(tx) to build a send request that the wallet will complete with change/fees.
Message has been deleted

Sergey Aldoukhov

unread,
Feb 13, 2015, 5:58:01 PM2/13/15
to bitc...@googlegroups.com
Thanks Andreas, worked beautifully. Here is the snippet for anyone who is too lazy to visit bitcoin-wallet:

            List<UTXO> utxos = jsonToUTXOs(unspents.getJSONArray("data")); // sorted by txn hash / outputIndex
            FakeTransaction unspent = null;
            for (UTXO utxo: utxos) {

                if (unspent == null || !unspent.hash.equals(utxo.hash)) {
                    unspent = new FakeTransaction(params, utxo.hash);
                    unspent.getConfidence().setConfidenceType(TransactionConfidence.ConfidenceType.BUILDING);
                    wallet.addWalletTransaction(new WalletTransaction(WalletTransaction.Pool.UNSPENT, unspent));
                }

                // catch up on index
                while (unspent.getOutputs().size() < utxo.outputIndex)
                    unspent.addOutput(new TransactionOutput(params, unspent, Coin.NEGATIVE_SATOSHI, new byte[] {}));

                // add the real output
                unspent.addOutput(new TransactionOutput(params, unspent, utxo.value, utxo.scriptBytes));
            }
            Transaction tx = wallet.sendCoinsOffline(request);


    private static class FakeTransaction extends Transaction
    {
        private final Sha256Hash hash;

        public FakeTransaction(final NetworkParameters params, final Sha256Hash hash)
        {
            super(params);
            this.hash = hash;
        }

        @Override
        public Sha256Hash getHash()
        {
            return hash;
        }
    }
- show quoted text -
Reply all
Reply to author
Forward
0 new messages