Skip to content

Spending from cold storage, P2SH or other exotic inputs with CoinJoin

chris-belcher edited this page Oct 8, 2015 · 2 revisions

create-unsigned-tx.py is a bot that creates CoinJoin transactions that spend from user-given input UTXOs (Unspent Transaction Outputs). The script returns a partially-signed transaction which the user has to sign and broadcast themselves using other tools.

Example uses are for spending from cold storage where the private key must not be on an internet-connected machine, or for spending from a p2sh multisig address where multiple people must sign the transaction. The script obtains transaction inputs and signatures from makers. Note that makers are under no obligation not to double-spend their inputs until they see a complete transaction broadcast on the bitcoin network. If those makers get another coinjoin deal, they may use the same UTXOs. Therefore a user of create-unsigned-tx.py must be quick in signing and broadcasting their transaction.

Warning: Directly manipulating ECDSA private keys and bitcoin raw transaction is dangerous and can result in losing money. See discussion here and here. This script is for advanced users only. Always carefully check transactions before signing and broadcasting them.

Testnet is used for all examples here. It's highly recommended to get comfortable with them before trying this with real bitcoins. Read python create-unsigned-tx.py --help for a detailed view of the options and ordering of arguments. Many options are similar to ones used in sendpayment.py

Authentication UTXO

In the JoinMarket protocol, communication is encrypted and authenticated between taker and maker. One of the pay-to-pubkey-hash inputs is used to authenticate the encrypted channel. The UTXO doesn't have to be worth much bitcoin but it and it's private key must be there. Note that the private key is prompted for on stdin to stop it appearing in .bash_history or ps.

Example: Spending from Cold Storage

For the auth UTXO we will use 0531dec28f2436787bb9c638779f8a46ffcb20fcc9360664a6353b57cbf7a2ad:2 which is on the address myLumLZykEuvNhL4WP4HJ5wkGZLRc55wih and has a corresponding private key cPWeLjzahLWtx7Bq1ro7f5b2sikU7H3eJAFueGrWczanq4urg1Wr.

We want to spend from the UTXO d056b6160f7181f61f3d3f85a187432b1cd4ba3f1bb32e24d414e0b659227a47:1 from cold storage. We'll be sending 1btc to mrooPrd91PauYzeW8ekLfEX9zdFwa8UBzk with change going back to cold storage in mnGeND9aE14sdaSGu2XauHqwu3C5x52HDh. These UTXOs can be found using a web API or the listunspent command on many popular wallets like Bitcoin Core or Electrum.

Run the JoinMarket script.

$ python create-unsigned-tx.py -N 1 0531dec28f2436787bb9c638779f8a46ffcb20fcc9360664a6353b57cbf7a2ad:2 100000000 mrooPrd91PauYzeW8ekLfEX9zdFwa8UBzk mnGeND9aE14sdaSGu2XauHqwu3C5x52HDh d056b6160f7181f61f3d3f85a187432b1cd4ba3f1bb32e24d414e0b659227a47:1

Input the private key of the auth UTXO when prompted.

input private key for myLumLZykEuvNhL4WP4HJ5wkGZLRc55wih :cPWeLjzahLWtx7Bq1ro7f5b2sikU7H3eJAFueGrWczanq4urg1Wr

Allow the bot to connect to the marketplace and create the coinjoin deal. Finally we see

[2015/10/03 19:14:23] timeout thread woken by notify(), makers responded in time

unsigned tx =

0100000003ada2f7cb573b35a6640636c9fc20cbff468a9f7738c6b97b7836248fc2de3105040000006a473044022034516f89b849b97eb0ea373cc61563c193df77e2a8f1ceca6b83627cb41a71020220788495dc320076e6891ebd8b7ec27930f6f3ec71c24d369bf1eefb5e66877c46012102505afd8cf9f31b6fdd60d686a270a3fd1e2a9e5f266714184ac6c4e9d2f5db29ffffffffada2f7cb573b35a6640636c9fc20cbff468a9f7738c6b97b7836248fc2de3105020000006b483045022100fbd4235492e70ca10902046bdc98272d244d48010c2d603345cc0cca035bf775022062b8d5e979c34e71410351e202d8930d6d23b700ee0565dc68cc7099807792a8012102b6857d182cdf24ccd6d4e90590d846ec4fe8a4de3a1708b8c2c6d28f28c22465ffffffff477a2259b6e014d4242eb31b3fbad41c2b4387a1853f3d1ff681710f16b656d00100000000ffffffff0400e1f505000000001976a9147bd90691aa0c77ad65ca7258a4564ca02b9b9e4288ac00e1f505000000001976a9148796d5545d1141d44fa89b527f37112dc320719a88acd7cad802000000001976a9144a141758a37c5e39f97caef7becf5169fea27cd188ac3ac3a900000000001976a9140def9bc5fbcf0e103cc669f538ae73377f80e30688ac00000000

[2015/10/03 19:14:23] created unsigned tx, ending

That transaction hex string can be transfered to cold storage and signed in the usual way. After broadcasting the result is http://tbtc.blockr.io/tx/info/e5ec00488acee87927290d1fde9ac959d8ea0f2228ef581ec93ca3bf172a157f

Example: Spending from a 2-of-3 Multisig Address.

It is worth understanding non-coinjoin multisig transactions first, read TwoOfThree.sh

A 2-of-3 multisig address is created from the public keys 03fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a56, 03764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2 and 0245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d344. The corresponding private keys of the first two are cRgXFhZU1Nq6bBotwahUt6jqNzovsDyviRyZoVXkRqHCg1cH8QRF and cPzhgGZHZBVsS9mi5c9tqB1EhZmz7Jcz566XTugSF3BDvKHHhhx6. We use the Bitcoin Core RPC console.

createmultisig 2 '["03fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a56", "03764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2", "0245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d344"]'

{
"address" : "2MwShYED1vTnMFvADW5W5be3XsBDutnmyP2",
"redeemScript" : "522103fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a562103764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2210245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d34453ae"
}

We send 0.1btc to the address 2MwShYED1vTnMFvADW5W5be3XsBDutnmyP2 with a normal bitcoin wallet. The resulting UTXO is f7ac52d7b0fb19f8622205d2238b917e1519bd36af20b05e18fde4a319f33053:1. We use f062fec8fbc50025762d112d3f4bd9981a88a94baea9cb6c4a60e978b404083a:0 as the auth_utxo for the JoinMarket protocol.

We run the JoinMarket script with amount = 0 to sweep the entire amount into the coinjoin address mjeYBCV8ZNmx5fkDe5f9z4fnroV3FCXgBt without any remaining change.

python create-unsigned-tx.py -N 1 f062fec8fbc50025762d112d3f4bd9981a88a94baea9cb6c4a60e978b404083a:0 0 mjeYBCV8ZNmx5fkDe5f9z4fnroV3FCXgBt any-string-here f7ac52d7b0fb19f8622205d2238b917e1519bd36af20b05e18fde4a319f33053:1

The resulting unsigned transaction hex string is:

01000000035330f319a3e4fd185eb020af36bd19157e918b23d2052262f819fbb0d752acf70100000000ffffffff3a0804b478e9604a6ccba9ae4ba9881a98d94b3f2d112d762500c5fbc8fe62f0000000006b483045022100d28cddb67a942d118a1b1a85d670989ad7d6255210d4a504e0a24e5ae215566102207ff694b62f2c284a5aa38ea667e95d28b114318dad430b8c7872e7997499e9a50121037a2f98d23387b9cfafb6b311e9f222bb76466335334d8769fe647be57f036e11fffffffff2b72aa082e43e54bcc600d9653a82d979ae3231ac0722800d39b4febafd6ced000000006a47304402206523a8173d3cc05ddebe075425a8a19ad9097419a03693e6e5c8d4b738376b62022077ddf61f62b916d10caeeb150e39cc90417656e0e3801e09ed515208f59c8f9f01210223def164e930529eb9962eb3377fe3666e56755dbc05ed45ee36f9411e22414fffffffff03140be700000000001976a91412eef8dde4c5e4b6ea8e1499bc74d338b6772cd288acbe62c108000000001976a9143e95f4785e3f9ad6246b579d9db4f704726f595388ac140be700000000001976a9142d4fb2ae8c4d0994cf7c027db68fabae121fcdaa88ac00000000

We use Bitcoin Core RPC calls to sign the multisig input. Note that the scriptPubKey of the multisig address is a9142e0c13b238506bc58d1e62dfe89d0c4eb7f6ecff87. It is simply the decoded bitcoin address, it can be found by using the gettxout RPC call, or the address_to_script method from pybitcointools.

Signing with the first private key:

 signrawtransaction '01000000035330f319a3e4fd185eb020af36bd19157e918b23d2052262f819fbb0d752acf70100000000ffffffff3a0804b478e9604a6ccba9ae4ba9881a98d94b3f2d112d762500c5fbc8fe62f0000000006b483045022100d28cddb67a942d118a1b1a85d670989ad7d6255210d4a504e0a24e5ae215566102207ff694b62f2c284a5aa38ea667e95d28b114318dad430b8c7872e7997499e9a50121037a2f98d23387b9cfafb6b311e9f222bb76466335334d8769fe647be57f036e11fffffffff2b72aa082e43e54bcc600d9653a82d979ae3231ac0722800d39b4febafd6ced000000006a47304402206523a8173d3cc05ddebe075425a8a19ad9097419a03693e6e5c8d4b738376b62022077ddf61f62b916d10caeeb150e39cc90417656e0e3801e09ed515208f59c8f9f01210223def164e930529eb9962eb3377fe3666e56755dbc05ed45ee36f9411e22414fffffffff03140be700000000001976a91412eef8dde4c5e4b6ea8e1499bc74d338b6772cd288acbe62c108000000001976a9143e95f4785e3f9ad6246b579d9db4f704726f595388ac140be700000000001976a9142d4fb2ae8c4d0994cf7c027db68fabae121fcdaa88ac00000000' '[{"txid":"f7ac52d7b0fb19f8622205d2238b917e1519bd36af20b05e18fde4a319f33053","vout":1,"scriptPubKey":"a9142e0c13b238506bc58d1e62dfe89d0c4eb7f6ecff87","redeemScript":"522103fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a562103764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2210245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d34453ae"}]' '["cRgXFhZU1Nq6bBotwahUt6jqNzovsDyviRyZoVXkRqHCg1cH8QRF"]'

{
"hex" : "01000000035330f319a3e4fd185eb020af36bd19157e918b23d2052262f819fbb0d752acf701000000b400473044022001d80b53c7dff703353c082a8507eae5a9779741ba17727a954b2a755af09bf402203a5df57af08f30bd9fbbbebb40fe74434538c494c98fccd63ddbd788d480550f014c69522103fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a562103764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2210245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d34453aeffffffff3a0804b478e9604a6ccba9ae4ba9881a98d94b3f2d112d762500c5fbc8fe62f0000000006b483045022100d28cddb67a942d118a1b1a85d670989ad7d6255210d4a504e0a24e5ae215566102207ff694b62f2c284a5aa38ea667e95d28b114318dad430b8c7872e7997499e9a50121037a2f98d23387b9cfafb6b311e9f222bb76466335334d8769fe647be57f036e11fffffffff2b72aa082e43e54bcc600d9653a82d979ae3231ac0722800d39b4febafd6ced000000006a47304402206523a8173d3cc05ddebe075425a8a19ad9097419a03693e6e5c8d4b738376b62022077ddf61f62b916d10caeeb150e39cc90417656e0e3801e09ed515208f59c8f9f01210223def164e930529eb9962eb3377fe3666e56755dbc05ed45ee36f9411e22414fffffffff03140be700000000001976a91412eef8dde4c5e4b6ea8e1499bc74d338b6772cd288acbe62c108000000001976a9143e95f4785e3f9ad6246b579d9db4f704726f595388ac140be700000000001976a9142d4fb2ae8c4d0994cf7c027db68fabae121fcdaa88ac00000000",
"complete" : false
}

Signing with the second private key

 signrawtransaction '01000000035330f319a3e4fd185eb020af36bd19157e918b23d2052262f819fbb0d752acf701000000b400473044022001d80b53c7dff703353c082a8507eae5a9779741ba17727a954b2a755af09bf402203a5df57af08f30bd9fbbbebb40fe74434538c494c98fccd63ddbd788d480550f014c69522103fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a562103764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2210245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d34453aeffffffff3a0804b478e9604a6ccba9ae4ba9881a98d94b3f2d112d762500c5fbc8fe62f0000000006b483045022100d28cddb67a942d118a1b1a85d670989ad7d6255210d4a504e0a24e5ae215566102207ff694b62f2c284a5aa38ea667e95d28b114318dad430b8c7872e7997499e9a50121037a2f98d23387b9cfafb6b311e9f222bb76466335334d8769fe647be57f036e11fffffffff2b72aa082e43e54bcc600d9653a82d979ae3231ac0722800d39b4febafd6ced000000006a47304402206523a8173d3cc05ddebe075425a8a19ad9097419a03693e6e5c8d4b738376b62022077ddf61f62b916d10caeeb150e39cc90417656e0e3801e09ed515208f59c8f9f01210223def164e930529eb9962eb3377fe3666e56755dbc05ed45ee36f9411e22414fffffffff03140be700000000001976a91412eef8dde4c5e4b6ea8e1499bc74d338b6772cd288acbe62c108000000001976a9143e95f4785e3f9ad6246b579d9db4f704726f595388ac140be700000000001976a9142d4fb2ae8c4d0994cf7c027db68fabae121fcdaa88ac00000000' '[{"txid":"f7ac52d7b0fb19f8622205d2238b917e1519bd36af20b05e18fde4a319f33053","vout":1,"scriptPubKey":"a9142e0c13b238506bc58d1e62dfe89d0c4eb7f6ecff87","redeemScript":"522103fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a562103764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2210245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d34453ae"}]' '["cPzhgGZHZBVsS9mi5c9tqB1EhZmz7Jcz566XTugSF3BDvKHHhhx6"]'

{
"hex" : "01000000035330f319a3e4fd185eb020af36bd19157e918b23d2052262f819fbb0d752acf701000000fc00473044022001d80b53c7dff703353c082a8507eae5a9779741ba17727a954b2a755af09bf402203a5df57af08f30bd9fbbbebb40fe74434538c494c98fccd63ddbd788d480550f01473044022043a98ae2197e38432218597ea9fd8c7201bc98b12eeeed1dabf37e1432e854820220030c7a4b56834f4016cb54b6e009b2e4846b8f9605b7ea4ed0fd7fca44008180014c69522103fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a562103764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2210245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d34453aeffffffff3a0804b478e9604a6ccba9ae4ba9881a98d94b3f2d112d762500c5fbc8fe62f0000000006b483045022100d28cddb67a942d118a1b1a85d670989ad7d6255210d4a504e0a24e5ae215566102207ff694b62f2c284a5aa38ea667e95d28b114318dad430b8c7872e7997499e9a50121037a2f98d23387b9cfafb6b311e9f222bb76466335334d8769fe647be57f036e11fffffffff2b72aa082e43e54bcc600d9653a82d979ae3231ac0722800d39b4febafd6ced000000006a47304402206523a8173d3cc05ddebe075425a8a19ad9097419a03693e6e5c8d4b738376b62022077ddf61f62b916d10caeeb150e39cc90417656e0e3801e09ed515208f59c8f9f01210223def164e930529eb9962eb3377fe3666e56755dbc05ed45ee36f9411e22414fffffffff03140be700000000001976a91412eef8dde4c5e4b6ea8e1499bc74d338b6772cd288acbe62c108000000001976a9143e95f4785e3f9ad6246b579d9db4f704726f595388ac140be700000000001976a9142d4fb2ae8c4d0994cf7c027db68fabae121fcdaa88ac00000000",
"complete" : true
}

The transaction is fully-signed, note the "complete": true. We now broadcast it.

sendrawtransaction 01000000035330f319a3e4fd185eb020af36bd19157e918b23d2052262f819fbb0d752acf701000000fc00473044022001d80b53c7dff703353c082a8507eae5a9779741ba17727a954b2a755af09bf402203a5df57af08f30bd9fbbbebb40fe74434538c494c98fccd63ddbd788d480550f01473044022043a98ae2197e38432218597ea9fd8c7201bc98b12eeeed1dabf37e1432e854820220030c7a4b56834f4016cb54b6e009b2e4846b8f9605b7ea4ed0fd7fca44008180014c69522103fade4e24512a85baf101e3c089d4c53f8c1ef75dbc5e78c6bb8af6c0444e2a562103764d38ce619fb3bdc6af99a9adab7e2602beee0a49ba72af32cc5d754bca49b2210245c2e341f758044c0ae46287d41e2d45489188f126bfdd469c73395cde18d34453aeffffffff3a0804b478e9604a6ccba9ae4ba9881a98d94b3f2d112d762500c5fbc8fe62f0000000006b483045022100d28cddb67a942d118a1b1a85d670989ad7d6255210d4a504e0a24e5ae215566102207ff694b62f2c284a5aa38ea667e95d28b114318dad430b8c7872e7997499e9a50121037a2f98d23387b9cfafb6b311e9f222bb76466335334d8769fe647be57f036e11fffffffff2b72aa082e43e54bcc600d9653a82d979ae3231ac0722800d39b4febafd6ced000000006a47304402206523a8173d3cc05ddebe075425a8a19ad9097419a03693e6e5c8d4b738376b62022077ddf61f62b916d10caeeb150e39cc90417656e0e3801e09ed515208f59c8f9f01210223def164e930529eb9962eb3377fe3666e56755dbc05ed45ee36f9411e22414fffffffff03140be700000000001976a91412eef8dde4c5e4b6ea8e1499bc74d338b6772cd288acbe62c108000000001976a9143e95f4785e3f9ad6246b579d9db4f704726f595388ac140be700000000001976a9142d4fb2ae8c4d0994cf7c027db68fabae121fcdaa88ac00000000

d056b6160f7181f61f3d3f85a187432b1cd4ba3f1bb32e24d414e0b659227a47

The confirmed transaction: http://tbtc.blockr.io/tx/info/d056b6160f7181f61f3d3f85a187432b1cd4ba3f1bb32e24d414e0b659227a47