diff --git a/07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md b/07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md index 8eadaa4..9f22177 100644 --- a/07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md +++ b/07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md @@ -12,14 +12,17 @@ Following are three examples, using PSBTs for: multi-sigs, pooling money, and jo Assume you've created a new multi-sig, just like you did in [ยง6.3](06_3_Sending_an_Automated_Multisig.md). ``` -$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["'$address3'","$address4"]''' +$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["'$pubkey1'","'$pubkey2'"]''' { - "address": "tb1q92a46jww0e6ne066nlagekhczkl3qa84czl5jk5nm78t2yf0vk4qte328m", - "redeemScript": "5221033055ec2da9bbb34c2acb343692bfbecdef8fab8d114f0036eba01baec3888aa02103f52980d322acaf084bcef3216f3d84bfb672d1db26ce2861de3ec047bede140d52ae", - "descriptor": "wsh(multi(2,[d6043800/0'/0'/23']033055ec2da9bbb34c2acb343692bfbecdef8fab8d114f0036eba01baec3888aa0,[ff1bf3b1]03f52980d322acaf084bcef3216f3d84bfb672d1db26ce2861de3ec047bede140d))#njkklz9u" + "address": "tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0", + "redeemScript": "5221038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e2103789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd063652ae", + "descriptor": "wsh(multi(2,[d6043800/0'/0'/26']038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e,[be686772]03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636))#07zyayfk" } -bitcoin-cli -named importaddress address="tb1q92a46jww0e6ne066nlagekhczkl3qa84czl5jk5nm78t2yf0vk4qte328m" rescan="false" + +machine1$ bitcoin-cli -named importaddress address="tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0" rescan=false +machine2$ bitcoin-cli -named importaddress address="tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0" rescan=false ``` +[[NEED TO FINISH REDOING THIS EXAMPLE]] And, you've got some money in it: ``` $ bitcoin-cli listunspent @@ -335,8 +338,172 @@ Obviously, there wasn't a big improvement in using this method over multiply sig ## Use a PSBT to Pool Money +Multisig, like the one used in the previous example, are often used to receive payments for collaborative work, whether it be royalties for a book or payments made to a company. In that situation, the above example works great: the two participants receive their money, then they split it up. But what about the converse case, where two (or more) participants want to set up a joint venture, and they need to seed it with money? + +The traditional answer is to create a multisig, then to have the participants individually send their funds to it. The problem is that the first payer has to depend on the good faith of the second, and that doesn't depend on the strength of Bitcoin, which is its _trustlessness_. Fortunately, with the advent of PSBTs, we can now make trustless payments that pool funds. + +> :book: ***What does trustless mean?*** Trustless means that no participant has to trust any other participant. They instead expect the software protocols to ensure that everything is enacted fairly, as they would expect. Bitcoin is a trustless protocol because you don't need anyone else to act in good faith; the system manages it. Similarly, PSBTs allow for the trustless creation of transactions that pool or split funds. + +The following example shows two users who each have 0.010 BTC that they want to pool to the multisig address `tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0`, created above. + +``` +machine1% bitcoin-cli listunspent +[ + { + "txid": "2536855bc8588e87206600cc980c30e8a65cf7f81002a34d6c37535e38a5b9db", + "vout": 0, + "address": "tb1qfg5y4fx979xkv4ezatc5eevufc8vh45553n4ut", + "label": "", + "scriptPubKey": "00144a284aa4c5f14d665722eaf14ce59c4e0ecbd694", + "amount": 0.01000000, + "confirmations": 2, + "spendable": true, + "solvable": true, + "desc": "wpkh([d6043800/0'/0'/25']02bea222cf9ea1f49b392103058cc7c8741d76a553fe627c1c43fc3ef4404c9d54)#4hnkg9ml", + "safe": true + } +] +machine2% bitcoin-cli listunspent +[ + { + "txid": "d7c7c24aeb1a61cdab81be6aefbf6c6a27562079629ffd9da4729bb82d93e4fe", + "vout": 0, + "address": "tb1qfqyyw6xrghm5kcrpkus3kl2l6dz4tpwrvn5ujs", + "label": "", + "scriptPubKey": "001448084768c345f74b6061b7211b7d5fd3455585c3", + "amount": 0.01000000, + "confirmations": 5363, + "spendable": true, + "solvable": true, + "desc": "wpkh([d3ed8825/0'/0'/0']03ff6b94c119582a63dbae4fb530efab0ed5635f7c3b2cf171264ca0af3ecef33a)#gtmd2e2k", + "safe": true + } +] +``` +They just set up variables to use this transactions: +``` +machine1$ utxo_txid_1=2536855bc8588e87206600cc980c30e8a65cf7f81002a34d6c37535e38a5b9db +machine1$ utxo_vout_1=0 +machine1$ utxo_txid_2=d7c7c24aeb1a61cdab81be6aefbf6c6a27562079629ffd9da4729bb82d93e4fe +machine1$ utxo_vout_2=0 +machine1$ multisig=tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0 + +``` +And create a PSBT: +``` +machine1$ psbt=$(bitcoin-cli -named createpsbt inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$multisig'": 0.019998 }''') +``` +Here's what it looks like: +``` +machine1$ bitcoin-cli decodepsbt $psbt +{ + "tx": { + "txid": "53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5", + "hash": "53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5", + "version": 2, + "size": 135, + "vsize": 135, + "weight": 540, + "locktime": 0, + "vin": [ + { + "txid": "2536855bc8588e87206600cc980c30e8a65cf7f81002a34d6c37535e38a5b9db", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + }, + { + "txid": "d7c7c24aeb1a61cdab81be6aefbf6c6a27562079629ffd9da4729bb82d93e4fe", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.01999800, + "n": 0, + "scriptPubKey": { + "asm": "0 224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074", + "hex": "0020224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074", + "reqSigs": 1, + "type": "witness_v0_scripthash", + "addresses": [ + "tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0" + ] + } + } + ] + }, + "unknown": { + }, + "inputs": [ + { + }, + { + } + ], + "outputs": [ + { + } + ] +} +``` +It doesn't matter that the transactions are owned by two different people, that their full information appears on two different machines. It'll work exactly the same as a multisig: once all of the controlling parties have signed, then the transaction can be finalized. + +Here's the process, this time passing the partially signed PSBT from one user to another rather than having to combine things at the end. +``` +machine1$ bitcoin-cli walletprocesspsbt $psbt +{ + "psbt": "cHNidP8BAIcCAAAAAtu5pTheUzdsTaMCEPj3XKboMAyYzABmIIeOWMhbhTYlAAAAAAD//////uSTLbibcqSd/Z9ieSBWJ2psv+9qvoGrzWEa60rCx9cAAAAAAP////8BuIMeAAAAAAAiACAiTLUDp/eDV5m5wi7gw8fZPQkDVuMOcAFcPrv6UVowdAAAAAAAAQEfQEIPAAAAAAAWABRKKEqkxfFNZlci6vFM5ZxODsvWlAEIawJHMEQCIGAiKIAWRXiw68o3pw61/cVNP7n2oH73S654XXgQ4kjHAiBtTBqmaF1iIzYGXrG4DadH8y6mTuCRVFDiPl+TLQDBJwEhAr6iIs+eofSbOSEDBYzHyHQddqVT/mJ8HEP8PvRATJ1UAAABAUdSIQONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDiEDeJ9UNCNnDhaWZ/9+Hy2iqX3xsJEicuFC1YJFGs69BjZSriICA3ifVDQjZw4Wlmf/fh8toql98bCRInLhQtWCRRrOvQY2BL5oZ3IiAgONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDhDWBDgAAAAAgAAAAIAaAACAAA==", + "complete": false +} + +machine2$ psbt_p="cHNidP8BAIcCAAAAAtu5pTheUzdsTaMCEPj3XKboMAyYzABmIIeOWMhbhTYlAAAAAAD//////uSTLbibcqSd/Z9ieSBWJ2psv+9qvoGrzWEa60rCx9cAAAAAAP////8BuIMeAAAAAAAiACAiTLUDp/eDV5m5wi7gw8fZPQkDVuMOcAFcPrv6UVowdAAAAAAAAQEfQEIPAAAAAAAWABRKKEqkxfFNZlci6vFM5ZxODsvWlAEIawJHMEQCIGAiKIAWRXiw68o3pw61/cVNP7n2oH73S654XXgQ4kjHAiBtTBqmaF1iIzYGXrG4DadH8y6mTuCRVFDiPl+TLQDBJwEhAr6iIs+eofSbOSEDBYzHyHQddqVT/mJ8HEP8PvRATJ1UAAABAUdSIQONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDiEDeJ9UNCNnDhaWZ/9+Hy2iqX3xsJEicuFC1YJFGs69BjZSriICA3ifVDQjZw4Wlmf/fh8toql98bCRInLhQtWCRRrOvQY2BL5oZ3IiAgONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDhDWBDgAAAAAgAAAAIAaAACAAA==" +machine2$ psbt_f=$(bitcoin-cli walletprocesspsbt $psbt_p | jq -r '.psbt') +machine2$ bitcoin-cli analyzepsbt $psbt_f +{ + "inputs": [ + { + "has_utxo": true, + "is_final": true, + "next": "extractor" + }, + { + "has_utxo": true, + "is_final": true, + "next": "extractor" + } + ], + "estimated_vsize": 189, + "estimated_feerate": 0.00001058, + "fee": 0.00000200, + "next": "extractor" +} +machine2$ psbt_hex=$(bitcoin-cli finalizepsbt $psbt_f | jq -r '.hex') +machine2$ bitcoin-cli -named sendrawtransaction hexstring=$psbt_hex +53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5 +``` +We've used a PSBT to trustlessly gather money into a multisig! + ## Use a PSBT to CoinJoin +CoinJoin is another Bitcoin application that requires trustlessness. Here, you have a variety of parties who don't necessarily know each other joining money and getting it back. + +The methodology for managing it with PSBTs is exactly the same as you've seen in the above examples, as the following pseudo-code demonstrates: +``` +$ psbt=$(bitcoin-cli -named createpsbt inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' }, { "txid": "'$utxo_txid_3'", "vout": '$utxo_vout_3' } ]''' outputs='''{ "'$split1'": 1.7,"'$split2'": 0.93,"'$split3'": 1.4 }''') +``` +Each user puts in their own UTXO, and each one receives a corresponding output. + +The best way to manage a CoinJoin is to send out the base PSBT to all the parties (who could be numerous), and then have them each sign the PSBT and send back to a single party who will combine, finalize, and send. + ## Summary: Using a Partially Signed Bitcoin Transaction > :fire: ***What's the power of a PSBT?***