From 56b878fd9401cd2a36b631edaa28f2f60def4fab Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Thu, 29 Dec 2022 18:51:59 +0000 Subject: [PATCH 1/3] Add notes on transaction signing Add notes on transaction signing with Dogecoin 1.21 experimental. --- ...g_notes_dogecoin_core_1_21_experimental.md | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 docs/signing_notes_dogecoin_core_1_21_experimental.md diff --git a/docs/signing_notes_dogecoin_core_1_21_experimental.md b/docs/signing_notes_dogecoin_core_1_21_experimental.md new file mode 100644 index 0000000..6f164c1 --- /dev/null +++ b/docs/signing_notes_dogecoin_core_1_21_experimental.md @@ -0,0 +1,158 @@ +# Signing Notes + +Writing up my notes on the transaction creation and signing process so they're +readily available to refer to later, and because they may be useful to others. + +All of this is tested on an experimental branch of Dogecoin 1.21; the theory is +generally applicable but other tools will have different interfaces. + +## Pre-requisites + +In order to sign the output transaction, the PSBT needs to include the details +of the input transaction(s). As nodes do not track transactions unless they're +relevant to an address the node is watching, the address the transaction is to +needs to be watched. + +This only needs to be done once, as the transaction creator can add these to +the PSBT and then circulate the expanded PSBT. + +If this is done before the address receives any funds, you can avoid rescanning, +but as the address now exists the node needs to rescan the blockchain, which +takes around an hour. + +I ran the following to add the address: + +```shell +$ dogecoin-cli importaddress 9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5 "corefunds" true +``` + +The following will then return a non-empty list: + +```shell +$ dogecoin-cli listunspent 1 9999999 "[\"9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5\"]" +``` + +## Creating the transaction + +Creating the transaction involves defining its inputs, and the amounts to send. +This generates a very bare PSBT which isn't very useful until it's processed +by a node with a wallet. + +The following consumes input #1 (the second) of transaction +`169a73cf972fbc1ff9d480474e5de7db03d63c243f4b57d25cdd09ba56ff2738`, which was +10 Dogecoins, and sends 9.9 Doge back to `9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5`. +The remaining 0.1 Doge is burnt as a (high) transaction fee. + +```shell +dogecoin-cli "[{\"txid\":\"169a73cf972fbc1ff9d480474e5de7db03d63c243f4b57d25cdd09ba56ff2738\",\"vout\":1}]" "[{\"9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5\":9.9}]" +``` + +This creates the following PSBT, which you'll see as inputs to later examples: + +``` +cHNidP8BAFMCAAAAATgn/1a6Cd1c0ldLPyQ81gPb511OR4DU+R+8L5fPc5oWAQAAAAD/////AYAzAjsAAAAAF6kUP5EutQN3mspXxZVmYkhcTKkTMK2HAAAAAAAAAA== +``` + +I can decode the resulting PSBT to check its contents: + +```shell +$ dogecoin-cli decodepsbt cHNidP8BAFMCAAAAATgn/1a6Cd1c0ldLPyQ81gPb511OR4DU+R+8L5fPc5oWAQAAAAD/////AYAzAjsAAAAAF6kUP5EutQN3mspXxZVmYkhcTKkTMK2HAAAAAAAAAA== +``` + +## Wallet Processing the Transaction + +The next step is to add the required details to the PSBT can be signed. + +``` +$ dogecoin-cli -datadir=/data/dogecoin walletprocesspsbt cHNidP8BAFMCAAAAATgn/1a6Cd1c0ldLPyQ81gPb511OR4DU+R+8L5fPc5oWAQAAAAD/////AYAzAjsAAAAAF6kUP5EutQN3mspXxZVmYkhcTKkTMK2HAAAAAAAAAA== +``` + +If this has worked correctly, decoding the resulting PSBT should show it +includes the transaction inputs (i.e. pipe it to `| jq .inputs`). + +If this is done on a wallet with an available signing key, by default +it will add a signature to the PSBT too. The process I follow involves +a node which does not have the key, and then moving the PSBT to an isolated +machine for signing. + +## Signing the Transaction + +Signing the transaction is identical to wallet processing, except performed +on a node with one of the signing keys present. It will then update the +PSBT with the signature from that signing key. + +Before signing, it's important to `decodepsbt` the PSBT to check what is +being signed. This produces an output such as that below (note this is +trimmed to focus on just the "tx" and "fee"): + +``` +$ dogecoin-cli decodepsbt +{ + "tx": { + "txid": "e80a06fb189acef79e98ffd86ceea78ff7504e434f4aea0a86c50373327ddd98", + "hash": "e80a06fb189acef79e98ffd86ceea78ff7504e434f4aea0a86c50373327ddd98", + "version": 2, + "size": 83, + "vsize": 83, + "weight": 332, + "locktime": 0, + "vin": [ + { + "txid": "169a73cf972fbc1ff9d480474e5de7db03d63c243f4b57d25cdd09ba56ff2738", + "vout": 1, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 9.90000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 3f912eb503779aca57c5956662485c4ca91330ad OP_EQUAL", + "hex": "a9143f912eb503779aca57c5956662485c4ca91330ad87", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5" + ] + } + } + ] + }, + ... + "fee": 0.10000000 +} +``` + +The "tx" is the transaction being built. Within it, "vin" is the inputs (what +is being spent) and "vout" is the outputs. Here you can see it has a single +output of 9.9 Dogecoins being sent to `9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5`. +The fee is then calculated based on the total input value, minus the total +output value, and in this case is 0.1 Dogecoins. + +## Finalizing the Transaction + +Once you have enough signatures, you can assemble the transaction. Note +"can" doesn not mean "should" - getting a signature from every signer +is definitely preferable. That said, conventionally only sufficient +signatures to meet the threshold are relayed, so the other signatures +should be kept for audit purposes elsewhere. + +Depending how the signing has happened, if each person has passed the +PSBT along to the next in turn, you should be able to call `finalizepsbt` +directly. Alternatively, if they were signed independently then the +signatures need assembling, `combinepsbt` can put the PSBTs together +and return the assembled set ready to pass to `finalizepsbt`. + +`finalizepsbt` returns a fully signed transaction, but does not relay it. +Before relaying, it's a good idea to `decoderawtransaction` the transaction +to verify it is correct. + +## Relaying the Transaction + +Once the finalized transaction is verified, it can be relayed with +`sendrawtransaction`, which will relay it to the P2P network for mining. From 81fc980a92f1326377b9ebd677bfe19dc15657e9 Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Thu, 29 Dec 2022 22:16:17 +0000 Subject: [PATCH 2/3] Add links to commands --- ...ning_notes_dogecoin_core_1_21_experimental.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/signing_notes_dogecoin_core_1_21_experimental.md b/docs/signing_notes_dogecoin_core_1_21_experimental.md index 6f164c1..b379ff2 100644 --- a/docs/signing_notes_dogecoin_core_1_21_experimental.md +++ b/docs/signing_notes_dogecoin_core_1_21_experimental.md @@ -44,7 +44,7 @@ The following consumes input #1 (the second) of transaction The remaining 0.1 Doge is burnt as a (high) transaction fee. ```shell -dogecoin-cli "[{\"txid\":\"169a73cf972fbc1ff9d480474e5de7db03d63c243f4b57d25cdd09ba56ff2738\",\"vout\":1}]" "[{\"9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5\":9.9}]" +dogecoin-cli createpsbt "[{\"txid\":\"169a73cf972fbc1ff9d480474e5de7db03d63c243f4b57d25cdd09ba56ff2738\",\"vout\":1}]" "[{\"9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5\":9.9}]" ``` This creates the following PSBT, which you'll see as inputs to later examples: @@ -143,14 +143,16 @@ signatures to meet the threshold are relayed, so the other signatures should be kept for audit purposes elsewhere. Depending how the signing has happened, if each person has passed the -PSBT along to the next in turn, you should be able to call `finalizepsbt` +PSBT along to the next in turn, you should be able to call +[finalizepsbt](https://bitcoincore.org/en/doc/0.17.0/rpc/rawtransactions/finalizepsbt/) directly. Alternatively, if they were signed independently then the -signatures need assembling, `combinepsbt` can put the PSBTs together -and return the assembled set ready to pass to `finalizepsbt`. +signatures need assembling, [combinepsbt](https://bitcoincore.org/en/doc/0.17.0/rpc/rawtransactions/combinepsbt/) +can put the PSBTs together and return the assembled set ready to pass in to +finalizepsbt. -`finalizepsbt` returns a fully signed transaction, but does not relay it. -Before relaying, it's a good idea to `decoderawtransaction` the transaction -to verify it is correct. +finalizepsbt returns a fully signed transaction, but does not relay it. +Before relaying, it's a good idea to [decoderawtransaction](https://bitcoincore.org/en/doc/0.17.0/rpc/rawtransactions/decoderawtransaction/) +the transaction to verify it is correct. ## Relaying the Transaction From 975f564ac3518ccafad6297d6d19b28f1f4b3d3a Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Thu, 29 Dec 2022 22:20:40 +0000 Subject: [PATCH 3/3] General cleanup --- ...g_notes_dogecoin_core_1_21_experimental.md | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/signing_notes_dogecoin_core_1_21_experimental.md b/docs/signing_notes_dogecoin_core_1_21_experimental.md index b379ff2..c10e270 100644 --- a/docs/signing_notes_dogecoin_core_1_21_experimental.md +++ b/docs/signing_notes_dogecoin_core_1_21_experimental.md @@ -38,10 +38,13 @@ Creating the transaction involves defining its inputs, and the amounts to send. This generates a very bare PSBT which isn't very useful until it's processed by a node with a wallet. -The following consumes input #1 (the second) of transaction +The following uses the [createpsbt](https://bitcoincore.org/en/doc/0.17.0/rpc/rawtransactions/createpsbt/) +command to generate a new transaction which consumes input #1 (the second) of +transaction `169a73cf972fbc1ff9d480474e5de7db03d63c243f4b57d25cdd09ba56ff2738`, which was -10 Dogecoins, and sends 9.9 Doge back to `9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5`. -The remaining 0.1 Doge is burnt as a (high) transaction fee. +10 Dogecoins, and sends 9.9 Dogecoins back to +`9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5`. The remaining 0.1 Dogecoins are burnt +as a (somewhat high) transaction fee. ```shell dogecoin-cli createpsbt "[{\"txid\":\"169a73cf972fbc1ff9d480474e5de7db03d63c243f4b57d25cdd09ba56ff2738\",\"vout\":1}]" "[{\"9xEP9voiNLw7Y7DS87M8QRqKM43r6r5KM5\":9.9}]" @@ -53,7 +56,8 @@ This creates the following PSBT, which you'll see as inputs to later examples: cHNidP8BAFMCAAAAATgn/1a6Cd1c0ldLPyQ81gPb511OR4DU+R+8L5fPc5oWAQAAAAD/////AYAzAjsAAAAAF6kUP5EutQN3mspXxZVmYkhcTKkTMK2HAAAAAAAAAA== ``` -I can decode the resulting PSBT to check its contents: +You can decode the resulting PSBT to check its contents, we'll discuss +this in detail later. ```shell $ dogecoin-cli decodepsbt cHNidP8BAFMCAAAAATgn/1a6Cd1c0ldLPyQ81gPb511OR4DU+R+8L5fPc5oWAQAAAAD/////AYAzAjsAAAAAF6kUP5EutQN3mspXxZVmYkhcTKkTMK2HAAAAAAAAAA== @@ -61,14 +65,15 @@ $ dogecoin-cli decodepsbt cHNidP8BAFMCAAAAATgn/1a6Cd1c0ldLPyQ81gPb511OR4DU+R+8L5 ## Wallet Processing the Transaction -The next step is to add the required details to the PSBT can be signed. +The next step is to add the required details to the PSBT can be signed. For +this we'll use [walletprocesspsbt](https://bitcoincore.org/en/doc/0.17.0/rpc/wallet/walletprocesspsbt/), as below: ``` -$ dogecoin-cli -datadir=/data/dogecoin walletprocesspsbt cHNidP8BAFMCAAAAATgn/1a6Cd1c0ldLPyQ81gPb511OR4DU+R+8L5fPc5oWAQAAAAD/////AYAzAjsAAAAAF6kUP5EutQN3mspXxZVmYkhcTKkTMK2HAAAAAAAAAA== +$ dogecoin-cli walletprocesspsbt cHNidP8BAFMCAAAAATgn/1a6Cd1c0ldLPyQ81gPb511OR4DU+R+8L5fPc5oWAQAAAAD/////AYAzAjsAAAAAF6kUP5EutQN3mspXxZVmYkhcTKkTMK2HAAAAAAAAAA== ``` -If this has worked correctly, decoding the resulting PSBT should show it -includes the transaction inputs (i.e. pipe it to `| jq .inputs`). +If the wallet has the address watched correctly, decoding the resulting PSBT +will show it includes the transaction inputs (i.e. pipe it to `| jq .inputs`). If this is done on a wallet with an available signing key, by default it will add a signature to the PSBT too. The process I follow involves @@ -137,7 +142,7 @@ output value, and in this case is 0.1 Dogecoins. ## Finalizing the Transaction Once you have enough signatures, you can assemble the transaction. Note -"can" doesn not mean "should" - getting a signature from every signer +"can" does not mean "should" - getting a signature from every signer is definitely preferable. That said, conventionally only sufficient signatures to meet the threshold are relayed, so the other signatures should be kept for audit purposes elsewhere.