Update 6_1_Sending_a_Transaction_to_a_Multisig.md

This commit is contained in:
Shannon Appelcline 2017-05-10 16:08:57 -07:00 committed by GitHub
parent 7ef6ffd8a1
commit 7b5cf41519

View File

@ -156,7 +156,6 @@ You can see any transactions related to your funds if you import the new multisi
$ bitcoin-cli -named importaddress address=2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz $ bitcoin-cli -named importaddress address=2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz
``` ```
This can take a while, because it does a `rescan` to find all the related transactions. Afterward the funds should show up when you `listunspent` ... but they aren't necessarily easily spendable yet. This can take a while, because it does a `rescan` to find all the related transactions. Afterward the funds should show up when you `listunspent` ... but they aren't necessarily easily spendable yet.
``` ```
$ bitcoin-cli listunspent $ bitcoin-cli listunspent
[ [
@ -178,45 +177,60 @@ $ bitcoin-cli listunspent
When you're ready to spend your money received by a multisig address, you're going need to collect a _lot_ of data. Much more than you needed to when you spend a normal P2PKH UTXO. That's in part because the info on the multisig address isn't in your wallet, and in part because you're spending money that was send to a script address (P2SH), and that's a lot more demanding, as future chapters will explain. When you're ready to spend your money received by a multisig address, you're going need to collect a _lot_ of data. Much more than you needed to when you spend a normal P2PKH UTXO. That's in part because the info on the multisig address isn't in your wallet, and in part because you're spending money that was send to a script address (P2SH), and that's a lot more demanding, as future chapters will explain.
At this point, you can use that UTXO as the basis of a new transaction. Just grab the variables like usual: In total, you're going to need to collect four things: extended information about the UTXO; the redeemScript; a recipient address; and all the private keys involved. We'll collect the first two now, then save the private keys for the signing step.
```
user1@blockstream:~$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
user1@blockstream:~$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
user1@blockstream:~$ echo $utxo_txid #### Access the UTXO information
To start with, grab the `txid` and the `vout` for the transaction that you want to spend, as usual.
```
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
$ echo $utxo_txid
621be11aac439d6ec58be398058fc33c3e89cf45138a0e73e05b7001f9b6e328 621be11aac439d6ec58be398058fc33c3e89cf45138a0e73e05b7001f9b6e328
user1@blockstream:~$ echo $utxo_vout $ echo $utxo_vout
0 0
``` ```
However, you're going to need two more variable. However, you need to also access a third bit of information about the UTXO, its `scriptPubKey`, which is the script that locks the transaction. This is done with a simple `bitcoin-cli`/`jq` invocation that mirrors the previous information.
First, the `scriptPubKey`, which is available in your `listunspent` info
``` ```
$ utxo_spk=$(bitcoin-cli listunspent | jq -r '.[0] | .scriptPubKey') $ utxo_spk=$(bitcoin-cli listunspent | jq -r '.[0] | .scriptPubKey')
``` ```
[[why?]]
Second, the `redeemScript` that you hopefully saved away: #### Record the Redeem Script
Hopefully, you saved the `redeemScript`. Now you should record it in a variable.
``` ```
$ redeem_script="52210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852ae" $ redeem_script="52210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852ae"
``` ```
Third, you need the private keys that you signed with. You'll probably need to get them one at a time, on the individual machines. So starting with `machine1`, we reveal that private key, not saving it into a variable as usual, because we don't want to leave any footprint on the system with such delicate information: #### Decide Your Recipient
```
machine1$ bitcoin-cli -named dumpprivkey address=$address1 We're just going to send the money back to ourself. This is useful because it frees the funds up from the multisig and convert them into a normal P2PKH transaction that can be confirmed by a single private key:
cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw
```
We're just going to send the money back to ourself, but in the process, we'll free it up from the multisig, and convert it into a normal P2PKH transaction that can be confirmed by a single private key:
``` ```
$ recipient=$(bitcoin-cli getrawchangeaddress) $ recipient=$(bitcoin-cli getrawchangeaddress)
``` ```
### Create Your Transaction ### Create Your Transaction
You can now create your transaction, including new `inputs` variables for the `scriptPubKey` and the `redeemScript`: You can now create your transaction, including new `inputs` variables for the `scriptPubKey` and the `redeemScript`:
``` ```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' outputs='''{ "'$recipient'": 1.299}''') $ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' outputs='''{ "'$recipient'": 1.299}''')
``` ```
Things get more complex when you sign, because you have to (1) tell `signrawtransaction` about all the inputs of the transaction your using; and (2) include your private key. The first is simply a copy of the `inputs` JSON array, reclassified as `prevtxs`, while the second is the private key from the first user that you dumped:
### Sign Your Transaction
You're now ready to sign your transaction. This is a multi-step process because you'll need to do it on multiple machines, each of which will contribute their own private keys.
#### Dump Your Local Private Keys
Because this transaction isn't making full use of your wallet, you're going to need to directly access your private key. Start on `machine1` where you should get information on any of that user's keys that were involved in the multisig:
```
machine1$ bitcoin-cli -named dumpprivkey address=$address1
cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw
```
> **WARNING:** Directly accessing your private keys is subpar behavior, and should be done with extreme care if you're using real money. At the least, don't save the information into a variable that could be accessed from your machine. Removing your shell's history is another great step.
#### Make Your First Signature
You can now make your first signature with the `signrawtransaction` command, except you're going to have to add two variables: `prevtxs` should be a list of all the `inputs` from your raw transaction; while `privkeys` should be a list of all the private keys you dumped on this machine.
``` ```
machine1$ bitcoin-cli -named signrawtransaction hexstring=$rawtxhex prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw"]' machine1$ bitcoin-cli -named signrawtransaction hexstring=$rawtxhex prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw"]'
{ {
@ -233,20 +247,18 @@ machine1$ bitcoin-cli -named signrawtransaction hexstring=$rawtxhex prevtxs='''[
] ]
} }
``` ```
That produces scary errors and says that it's not `complete`. Nonetheless, the transaction has been partially signed by the first user. You'll note there's now information in the `scriptSig` variable and the hex code is larger. That produces scary errors and says that it's not `complete`. That's all correct. The transaction has been partially signed but is not done because it needs more signatures. Note in particular your `hex` has gotten longer, demonstrating that it's partially signed.
#### Sign The Transaction Again ### Sign Your Transaction Again
Here's the final trick: the other person (or people) that are part of the multisig also need to sign the transaction. They do this by running the same signing command with you but (1) with the output hex (`bitcoin-cli -named signrawtransaction hexstring=$rawtxhex prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw"]' | jq -r '. | .hex'`) and (2) with their own private key. Now you can pass the transaction on to be signed again by anyone else required for the mutisig. They do this by running the same signing command that you did but (1) with the longer `hex` that you output (`bitcoin-cli -named signrawtransaction hexstring=$rawtxhex prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw"]' | jq -r '. | .hex'`) and (2) with their own private key.
So, you'd send the complete info to the next signer, including (1) the `prevtxs`; and (2) the new `hex`. They would then dump their own private key on their own machine:
They'd then dump their own private key on their own machine:
``` ```
$ bitcoin-cli -named dumpprivkey address=$address2 $ bitcoin-cli -named dumpprivkey address=$address2
cTi1Muvj24vG159R8orFjtqsPygCxhu8mJt2GLDQv7bNBGYoav4B cTi1Muvj24vG159R8orFjtqsPygCxhu8mJt2GLDQv7bNBGYoav4B
``` ```
And sign the new hex: And sign the new `hex` using all the same `prevtxs` values as you:
``` ```
$ bitcoin-cli -named signrawtransaction hexstring=020000000128e3b6f901705be0730e8a1345cf893e3cc38f0598e38bc56e9d43ac1ae11b62000000009200483045022100a9fe6ed0dbe14c0c4c7c89cee0aef2770f0b2bdcd6b3e8d71fe91e91c4bb765e02200cfba27a59b584a0cc8e70fb4438be94da417ee77eff28deb70449e012b6d6fa014752210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852aeffffffff01e01dbe07000000001976a914cd1b2ba4fa8ae3e62bc4fc6be467a63228ceeedf88ac00000000 prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cTi1Muvj24vG159R8orFjtqsPygCxhu8mJt2GLDQv7bNBGYoav4B"]' $ bitcoin-cli -named signrawtransaction hexstring=020000000128e3b6f901705be0730e8a1345cf893e3cc38f0598e38bc56e9d43ac1ae11b62000000009200483045022100a9fe6ed0dbe14c0c4c7c89cee0aef2770f0b2bdcd6b3e8d71fe91e91c4bb765e02200cfba27a59b584a0cc8e70fb4438be94da417ee77eff28deb70449e012b6d6fa014752210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852aeffffffff01e01dbe07000000001976a914cd1b2ba4fa8ae3e62bc4fc6be467a63228ceeedf88ac00000000 prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cTi1Muvj24vG159R8orFjtqsPygCxhu8mJt2GLDQv7bNBGYoav4B"]'
{ {
@ -254,14 +266,58 @@ $ bitcoin-cli -named signrawtransaction hexstring=020000000128e3b6f901705be0730e
"complete": true "complete": true
} }
``` ```
You'll note that it now says signature is complete, which means that you should just fall back on the standard JQ methodology: You'll note that this now says signature is complete, which means that you should just fall back on the standard JQ methodology to save your `hexstring` and then to send it:
``` ```
$ signedtx = $(bitcoin-cli -named signrawtransaction hexstring=020000000128e3b6f901705be0730e8a1345cf893e3cc38f0598e38bc56e9d43ac1ae11b62000000009200483045022100a9fe6ed0dbe14c0c4c7c89cee0aef2770f0b2bdcd6b3e8d71fe91e91c4bb765e02200cfba27a59b584a0cc8e70fb4438be94da417ee77eff28deb70449e012b6d6fa014752210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852aeffffffff01e01dbe07000000001976a914cd1b2ba4fa8ae3e62bc4fc6be467a63228ceeedf88ac00000000 prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cTi1Muvj24vG159R8orFjtqsPygCxhu8mJt2GLDQv7bNBGYoav4B"]' | jq -r '.hex')^C $ signedtx = $(bitcoin-cli -named signrawtransaction hexstring=020000000128e3b6f901705be0730e8a1345cf893e3cc38f0598e38bc56e9d43ac1ae11b62000000009200483045022100a9fe6ed0dbe14c0c4c7c89cee0aef2770f0b2bdcd6b3e8d71fe91e91c4bb765e02200cfba27a59b584a0cc8e70fb4438be94da417ee77eff28deb70449e012b6d6fa014752210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852aeffffffff01e01dbe07000000001976a914cd1b2ba4fa8ae3e62bc4fc6be467a63228ceeedf88ac00000000 prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cTi1Muvj24vG159R8orFjtqsPygCxhu8mJt2GLDQv7bNBGYoav4B"]' | jq -r '.hex')
user1@blockstream2:~$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx user1@blockstream2:~$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
99d2b5717fed8875a1ed3b2827dd60ae3089f9caa7c7c23d47635f6f5b397c04 99d2b5717fed8875a1ed3b2827dd60ae3089f9caa7c7c23d47635f6f5b397c04
``` ```
Whew! That took some work, but the transaction was successfully used! Whew! That took some work, but the transaction was successfully used!
## Optional: Make Multisigs Easier
The above showed the standard technique for creating multisigs and spending funds received through them. It was a worthwhile exercise for understanding a bit more about how they work, and how you'd be manipulating them at a relatively low level. However, Bitcoin core has made multisigs a little bit easier in new releases.
The following describes a slightly different way to create multisigs using the `addmultisigaddress` command, which then allows easier spending of the money. It's probably not what you'd want to do if you were writing multisig wallet programs, but if you were just trying to retrieving some funds by hand, it might save you some hair-pulling.
### Create Multisigs Everywhere
You start off creating addresses and retrieving public keys as usual for each user who will be part of the multisig:
```
machine1$ address3=$(bitcoin-cli getnewaddress)
machine1$ echo $address3
mkMkhbUzcSPdEHUoRQkBKHe8otP1SzWWeb
machine1$ bitcoin-cli -named validateaddress address=$address3 | jq -r '. | .pubkey'
02e7356952f4bb1daf475c04b95a2f7e0d9a12cf5b5c48a25b2303783d91849ba4
machine2$ address4=$(bitcoin-cli getnewaddress)
$ echo $address4
mkyeUBPDoeyFrfLE4V5oAQfee99pT2W1E3
$ bitcoin-cli -named validateaddress address=$address4 | jq -r '. | .pubkey'
030186d2b55de166389aefe209f508ce1fbd79966d9ac417adef74b7c1b5e07776
```
But now you're going to create the multisig on _each machine that contributes signatures_ using a new command, `addmultisigaddress`. The difference between this and `createmultisig` is that it saves some of the information into your wallet, making it a lot easier to spend the money afterward.
```
machine1$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["'$address3'","030186d2b55de166389aefe209f508ce1fbd79966d9ac417adef74b7c1b5e07776"]'''
2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8
machine2$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["02e7356952f4bb1daf475c04b95a2f7e0d9a12cf5b5c48a25b2303783d91849ba4","'$address4'"]'''
2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8
```
As we noted earlier, it doesn't matter whether you use addresses or public keys: you'll get the same multisig address. However, you must use the same order. Thus, it's best for the members of the multisig to check amongst themselves to make sure they all got the same result.
The members of the multisig will still need to run `importaddress` to watch for funds received on the multisig address:
```
machine1$ bitcoin-cli -named importaddress address=2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8
machine2$ bitcoin-cli -named importaddress address=2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8
```
### Respend Your Funds
There are no changes to sending or receiving funds. The use of `addmultisigaddress` is simply a technical issue on your sides as the recipient: a bit of bookkeeping to make life easier for you.
## Summary: Sending a Transaction with a Multisig ## Summary: Sending a Transaction with a Multisig
_What is the power of multisignatures?_ _What is the power of multisignatures?_