10

Using, e.g., the Bitcoin Core command line, how could I spend bitcoins from multiple wallets in a single transaction?

This comment says:

instead of sending the transaction to the network, you send it to the next person who will add their inputs and outputs and sign them as well, and so on. The last person would then broadcast the transaction on the network.

I assume I use createrawtransaction and signrawtransaction somehow, but how exactly do I actually do this?

cf. Mastering Bitcoin (1st ed.), §"Using Bitcoin Core’s JSON-RPC API from the Command Line", §§"Creating, Signing, and Submitting Transactions Based on Unspent Outputs"

  • ...Or spend bitcoins from multiple wallets in a single transaction with any tool. – zylstra Jan 31 '18 at 8:38
  • 1
    @zylstra thanks. I've generalized my question. – Geremia Jan 31 '18 at 16:00
3

There are currently three different ways to do this: raw transactions, PSBT in 0.17, and PSBT in 0.18. I recommend that you use PSBT in 0.18 as it is the least hassle, but I will describe all three here for you.


Traditionally, you would do this with createrawtransaction, fundrawtransaction, and signrawtransactionwithkey/signrawtransactionwithwallet. One person would have to know all of the inputs that were being used in the transaction or have all of those stored in their wallet (i.e. they have imported everyone else's public keys and/or redeemScripts into their wallet) and then they can use createrawtransaction or fundrawtransaction to create the raw transaction.

createrawtransaction just takes inputs and outputs that are specified by the user and gives the resulting transaction as is (so you need to be careful about fees and change). fundrawtransaction can choose the inputs to use for you using your wallet and it will handle fees and change outputs itself. However fundrawtransaction needs to know all of the information necessary to construct the final transaction (except for the private key, it can just use a dummy signature) in order to correctly estimate the transaction fees, which is why you need to import the public keys and scripts into your wallet.

Once you have the raw transaction, you then send it to each of the other people involved in the transaction. They then sign it using signrawtransactionwithwallet (if the keys and scripts are in their wallet) or signrawtransactionwithkey (if their keys and scripts are not in their wallet). Most people will use signrawtransactionwithwallet. They then send the result back to you where you have to combine all of the signed transactions into the final transaction using combinerawtransaction. Then you can broadcast it with sendrawtransaction.

Instead of sending the transactions out to everyone to sign at the same time, you could send to one person who signs, who then sends to the next person and so on. This would not require combinerawtransaction. The last person would sign and then use sendrawtransaction to broadcast.

This process is kind of bulky and requires that one person knows some (or all) of the information for the inputs being used (except for the private keys).


Since Bitcoin Core 0.17, you can use the various *psbt RPCs to achieve the same thing. With 0.17, the flow is fairly similar to the the raw transaction flow described earlier. You would have to have all of the information for creating the final transaction in your wallet (except for private keys) so that fee estimation can be properly done for coin selection, or you need to know which inputs to use. Either way, you use walletcreatefundedpsbt and specify the inputs you want and the outputs you want. Bitcoin Core will then automatically choose additional inputs if there is not enough to cover the output amount and create a change output for you. Because it needs to also conver transaction fees, it needs to have the same information that you need for fundrawtransaction to be able to estimate fees for the inputs it chooses.

Then you would send the transaction to everyone else who would add their signatures (and other metadata) using walletprocesspsbt. You can also do walletprocesspsbt first before sending the transaction to everyone so that various metadata needed for signing (like the UTXO that is being spent for each input) is added beforehand. Once signed, everyone would send the transaction back to you and you combine them together using combinepsbts Then you create the final transaction for broadcast using finalizepsbt and send the result using sendrawtransaction.

Of course using PSBTs you can do the same thing described above where each person sends the transaction to the next person to be signed instead of sending back to you to be combined.

Again, this process is kind of bulky and requires that one person knows some (or all) of information for the inputs being used (except for the private keys). But it is slightly less likely to result in an error than the raw transaction method. PSBTs also allows you to use other non-Bitcoin Core wallets that support PSBT, and you can use this method with wallets which are not connected to the internet or otherwise do not have the blockchain or the UTXOs that are being spent in the transaction.


However, Bitcoin Core 0.18 actually makes this whole process a lot easier. Bitcoin Core 0.18 introduces a couple of new *psbt RPCs which make it so that one person does not need to know all of the inputs being used and all of the information for each input. The only caveat is that this method assumes that each person has their own outputs that they want to create instead of multiple people pooling together their Bitcoin to make one large output.

With 0.18, everyone would create their own PSBT using walletcreatefundedpsbt. They specify any of their own inputs that they want to use and all of their outputs. Any change outputs will be added, and additional inputs from the wallet will be added to cover the output amount and transaction fee if not enough were specified by the user. Since every user does this with their own wallet, no one person needs to know anything about what the other users have in their wallets.

Then each person would send the PSBT to a designated coordinator who uses joinpsbts to join every PSBT into one large PSBT. This PSBT will have all of the inputs and outputs that each person wants to spend and create. So instead of having many individual PSBTs with their own inputs and outputs, there is now one large PSBT with everyone's inputs and outputs.

This PSBT is then sent back to each person who uses walletprocesspsbt to update the PSBT and add their input information to the PSBT and signs it. Even if a user has an airgapped setup where their private keys are somewhere that does not have access to the blockchain, they can update the PSBT from an online watching only wallet and send the PSBT to the offline machine to be signed.

Once everyone has signed the PSBT, it is sent back to the coordinator who uses combinepsbt to combine all of the signatures and input information into the same PSBT, then creates the final network transaction using finalizepsbt and broadcasts it using sendrawtransaction.

Again, this can be done serially like the other methods described earlier and thus omit the need for combinepsbt.

-2

That's techinally not possible. Not yet. And I don't think it will ever be possible unless you are the developer of this system. Butcoin and other crypto currency a tunnel visioned when it comes to transactions. Better Watch out.

  • This is incorrect. At a purely technical level, you could absolutely create an unsigned transaction, and sign the relevant inputs using keys from each wallet. To my knowledge, Bitcoin Core does not provide a easy method to do that, so it may require chaining multiple rpc calls – Raghav Sood Nov 27 '18 at 14:05
-3

I haven't checked the Bitcoin-core command when it comes to Withdraw all balances from all wallets in a single transaction - But I do know is the structure and the flow of it, I assume it's the same (THIS IS NOT THE ANSWER, THIS IS ONLY A LOGICAL FLOW) :

/api/v2/withdraw_from_addresses/?api_key=API KEY&from_addresses=ADDRESS1,ADDRESS2,...&to_addresses=ADDRESS1,ADDRESS2,...&amounts=AMOUNT1,AMOUNT2,...&pin=SECRET PIN

Code is from block.io

Not the answer you're looking for? Browse other questions tagged or ask your own question.