mirror of
https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
synced 2026-04-12 16:12:55 +00:00
Compare commits
11 Commits
d177b8dc68
...
ca6b408c59
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca6b408c59 | ||
|
|
e0f7527210 | ||
|
|
177114e42a | ||
|
|
5b19abd229 | ||
|
|
9d17db393c | ||
|
|
893ca0547a | ||
|
|
1b5509688f | ||
|
|
4dc54ba900 | ||
|
|
4af31394cc | ||
|
|
553e570f95 | ||
|
|
f98fc83ee9 |
@ -34,6 +34,8 @@ The addresseses commonly in use for new Bitcoin addresses today are:
|
||||
* **✅ P2WSH (Pay to Witness Script Hash).** P2WSH is a SegWit address that can be unlocked by a script (rather than one or more private keys doing so). Scripts are described in [Chapter 11](11_0_Introducing_Bitcoin_Scripts.md) (and afterward). P2WSH deprecates P2SH.
|
||||
* **✅ P2TR.** Taproot is the newest Bitcoin address type, but it was soft forked back in 2021, so it should have wide acceptance at this point. It's considered to be SegWit v1. Due to its use of Schnorr signatures, it can produce smaller transactions for multisigs, has privacy advantages, and can also combine singular signatures with scripts. It hasn't been widely adopted yet. We'll examing Taproot transcations starting in [Chapter 9](09_0_Expanding_Bitcoin_Transactions_with_Schnorr.md).
|
||||
|
||||
Other addresses such as [P2MR](https://github.com/bitcoin/bips/blob/master/bip-0360.mediawiki), which proposes a quantum-resistant address, may appear in the future.
|
||||
|
||||
The following two address types are not in wide use, but still hold large amounts of old funds:
|
||||
|
||||
* **❌ P2PKH (Pay to Public Key Hash).** The P2PKH address was the predominent address type prior to the introduction of SegWit, which replaced it with P2WKH. Most new addresses are now created with P2WPKH, since their transactions are cheaper, but many older P2PKH addresses still hold funds, since it was in use for roughly a decade.
|
||||
|
||||
@ -26,3 +26,4 @@ Supporting objectives include the ability to:
|
||||
* [Section Four: Sending Coins with Raw Transactions](04_4_Sending_Coins_with_a_Raw_Transaction.md)
|
||||
* [Interlude: Using Curl](04_4__Interlude_Using_Curl.md)
|
||||
* [Section Five: Sending Coins with Automated Raw Transactions](04_5_Sending_Coins_with_Automated_Raw_Transactions.md)
|
||||
* [Section Six: Sending Coins to Other Addresses](04_6_Sending_Coins_to_Other_Addresses.md)
|
||||
|
||||
@ -1,93 +1,95 @@
|
||||
TODO:
|
||||
* Freezing coins
|
||||
|
||||
# 4.4: Sending Coins with Raw Transactions
|
||||
|
||||
As noted at the start of this chapter, the `bitcoin-cli` interface offers three major ways to send coins. [§4.1](04_1_Sending_Coins_The_Easy_Way.md) talked about sending them the first way, using the `sendtoaddress` command. Since then, we've been building details on how to send coins a second way, with raw transactions. [§4.2](04_2_Creating_a_Raw_Transaction.md) taught how to create a raw transaction, an [Interlude](04_2__Interlude_Using_JQ.md) explained JQ, and [§4.3](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md) demonstrated named arguments.
|
||||
|
||||
We can now put those together and actually send funds using a raw transaction.
|
||||
We can now put those together and actually send funds using a raw transaction (or more precisely, we can send funds in a way that actually represents a real transaction, rather than sending complete UTXOs, as was did in the previous two sections).
|
||||
|
||||
## Create a Change Address
|
||||
|
||||
Our sample raw transaction in section §4.2 was very simplistic: we sent the entirety of a UTXO to a new address. More frequently, you'll want to send someone an amount of money that doesn't match a UTXO. But, you'll recall that the excess money from a UTXO that's not sent to your recipient just becomes a transaction fee. So, how do you send someone just part of a UTXO, while keeping the rest for yourself?
|
||||
Our sample raw transactions in §4.2 and §4.3 were very simplistic: we sent the entirety of a UTXO to a new address. In real-life, you'll want to send someone an amount of money that doesn't match a UTXO. But, you'll recall that the excess money from a UTXO that's not sent to your recipient just becomes a transaction fee. So, how do you send someone just part of a UTXO, while keeping the rest for yourself?
|
||||
|
||||
The solution is to _send_ the rest of the funds to a second address, a change address that you've created in your wallet specifically to receive them:
|
||||
```
|
||||
$ changeaddress=$(bitcoin-cli getrawchangeaddress legacy)
|
||||
$ changeaddress=$(bitcoin-cli getrawchangeaddress)
|
||||
$ echo $changeaddress
|
||||
mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h
|
||||
tb1qjrs9jr572nfyg5un8f2rzjdngml0mvskxlyd09
|
||||
```
|
||||
Note that this uses a new function: `getrawchangeaddress`. It's largely the same as `getnewaddress` but is optimized for use as a change address in a raw transaction, so it doesn't do things like make entries in your address book. We again selected the `legacy` address, instead of going with the default of `bech32`, simply for consistency. This is a situation where it would have been entirely safe to generate a default Bech32 address, just by using `bitcoin-cli getrawchangeaddress`, because it would being sent and received by you on your Bitcoin Core node which fully supports this. But, hobgoblins; we'll shift this over to Bech32 as well in [§4.6](04_6_Creating_a_Segwit_Transaction.md).
|
||||
|
||||
You now have an additional address inside your wallet, so that you can receive change from a UTXO! In order to use it, you'll need to create a raw transaction with two outputs.
|
||||
Note that this uses a new function: `getrawchangeaddress`. It's largely the same as `getnewaddress` but is optimized for use as a change address in a raw transaction, so it doesn't do things like make entries in your address book. You now have an additional address inside your wallet, so that you can receive change from a UTXO! In order to use it, you'll need to create a raw transaction with two outputs.
|
||||
|
||||
## Pick Sufficient UTXOs
|
||||
|
||||
Our sample raw transaction was simple in another way: it assumed that there was enough money in a single UTXO to cover the transaction. Often this will be the case, but sometimes you'll want to create transactions that spends more money than you have in a single UTXO. To do so, you must create a raw transaction with two (or more) inputs.
|
||||
Our sample raw transactions of the previous two sections were simple in another way: they assumed that there was enough money in a single UTXO to cover the transaction. Often this will be the case, but sometimes you'll want to create transactions that spends more money than you have in a single UTXO. To do so, you must create a raw transaction with two (or more) inputs.
|
||||
|
||||
## Write a Real Raw Transaction
|
||||
|
||||
To summarize: creating a real raw transaction to send coins will sometimes require multiple inputs and will almost always require multiple outputs, one of which is a change address. We'll be creating that sort of more realistic transaction here, in a new example that shows a real-life example of sending funds via Bitcoin's second methodology, raw transactions.
|
||||
|
||||
We're going to use our 0th and 2nd UTXOs:
|
||||
We've got three UTXOs in our wallet.
|
||||
```
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
[
|
||||
{
|
||||
"txid": "0619fecf6b2668fab1308fbd7b291ac210932602a6ac6b8cc11c7ae22c43701e",
|
||||
"vout": 1,
|
||||
"address": "mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
|
||||
"txid": "3c31ad2dec55a1c4b82e1c3615c71e68bc492dc81cbe2e9c12deba2064b0186f",
|
||||
"vout": 49,
|
||||
"address": "tb1qukwva953qreduzm3mgnjwh5ymxupa4jrrkj8ym",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a914ad1ed1c5971b2308f89c1362d4705d020a40e8e788ac",
|
||||
"amount": 0.00899999,
|
||||
"scriptPubKey": "0014e59cce969100f2de0b71da27275e84d9b81ed643",
|
||||
"amount": 0.00300147,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/4']03eae28c93035f95a620dd96e1822f2a96e0357263fa1f87606a5254d5b9e6698f)#wwnfx2sp",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/8]028f44c673718437fe9b22957e5551b3a186a2d7435b9f477f965ace21f852195f)#nzce84pw",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"txid": "8a0d9ab73d81a1ce043d1ede0e737136e6d3352d3e0bc9590f9e8bbd91036dc2",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"address": "tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022000,
|
||||
"confirmations": 15,
|
||||
"scriptPubKey": "0014f1ad72d46aa89d5e622e42bbbb75064eebd9d101",
|
||||
"amount": 0.00099000,
|
||||
"confirmations": 7,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/5]027650c44c6f71d50a173f3f18858490cf26d2661a1d9929deba9aca57c76d1e5b)#7ss7jfnn",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
},
|
||||
},
|
||||
{
|
||||
"txid": "0df23a9dba49e822bbc558f15516f33021a64a5c2e48962cec541e0bcc79854d",
|
||||
"txid": "615813d052e48b9761afed8732b78ff67f3ee26390de9e1274418629bd80e45c",
|
||||
"vout": 0,
|
||||
"address": "mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
|
||||
"address": "tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a914ad1ed1c5971b2308f89c1362d4705d020a40e8e788ac",
|
||||
"amount": 0.00100000,
|
||||
"confirmations": 1,
|
||||
"scriptPubKey": "0014f1ad72d46aa89d5e622e42bbbb75064eebd9d101",
|
||||
"amount": 0.01895000,
|
||||
"confirmations": 2,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/4']03eae28c93035f95a620dd96e1822f2a96e0357263fa1f87606a5254d5b9e6698f)#wwnfx2sp",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/5]027650c44c6f71d50a173f3f18858490cf26d2661a1d9929deba9aca57c76d1e5b)#7ss7jfnn",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
In our example, we're going to send .009 BTC, which is (barely) larger than either of our UTXOs. This requires combining them, then using our change address to retrieve the unspent funds.
|
||||
We're going to be spending the 0th and the 2nd so that we can sum up .02 BTC.
|
||||
|
||||
### Set Up Your Variables
|
||||
|
||||
We already have `$changeaddress` and `$recipient` variables from previous examples:
|
||||
```
|
||||
$ echo $changeaddress
|
||||
mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h
|
||||
tb1qjrs9jr572nfyg5un8f2rzjdngml0mvskxlyd09
|
||||
$ recipient=$(bitcoin-cli getnewaddress)
|
||||
$ echo $recipient
|
||||
n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi
|
||||
tb1qdu69s5f9nw8x88lvsc8nt5d7gy9rgtnef0upfu
|
||||
```
|
||||
We also need to record the txid and vout for each of our two UTXOs. Having identified the UTXOs that we want to spend, we can use our JQ techniques to make sure accessing them is error free:
|
||||
We also need to record the txid and vout for each of our two UTXOs. Having identified the UTXOs that we want to spend by hand, we can use our JQ techniques to make sure accessing them is error free:
|
||||
```
|
||||
$ utxo_txid_1=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
|
||||
$ utxo_vout_1=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
|
||||
@ -101,14 +103,14 @@ Writing the actual raw transaction is surprisingly simple. All you need to do is
|
||||
|
||||
Here's the example. Note the multiple inputs after the `inputs` arg and the multiple outputs after the `outputs` arg.
|
||||
```
|
||||
$ rawtxhex2=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$recipient'": 0.009, "'$changeaddress'": 0.0009 }''')
|
||||
$ rawtxhex2=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$recipient'": 0.02, "'$changeaddress'": 0.00194 }''')
|
||||
```
|
||||
We were _very_ careful figuring out our money math. These two UTXOs contain 0.00999999 BTC. After sending 0.009 BTC, we'll have .00099999 BTC left. We chose .00009999 BTC the transaction fee. To accommodate that fee, we set our change to .0009 BTC. If we'd messed up our math and instead set our change to .00009 BTC, that additional BTC would be lost to the miners! If we'd forgot to make change at all, then the whole excess would have disappeared. So, again, _be careful_.
|
||||
We were _very_ careful figuring out our money math. These two UTXOs contain 0.02195147 BTC. After sending 0.02 BTC, we'll have 0.00195147 BTC left. We chose 0.00001147 BTC the transaction fee. To accommodate that fee, we set our change to .00194 BTC. If we'd messed up our math and instead set our change to .000195 BTC, that additional BTC would be lost to the miners! If we'd forgot to make change at all, then the whole excess would have disappeared. So, again, _be careful_.
|
||||
|
||||
Fortunately, we can triple-check with the `btctxfee` alias from the JQ Interlude:
|
||||
```
|
||||
$ ./txfee-calc.sh $rawtxhex2
|
||||
.00009999
|
||||
.00001150
|
||||
```
|
||||
|
||||
### Finish It Up
|
||||
@ -117,64 +119,89 @@ You can now sign, seal, and deliver your transaction, and it's yours (and the fa
|
||||
```
|
||||
$ signedtx2=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex2 | jq -r '.hex')
|
||||
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx2
|
||||
e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d
|
||||
80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465
|
||||
```
|
||||
|
||||
### Wait
|
||||
|
||||
As usual, your money will be in flux for a while: the change will be unavailable until the transaction actually gets confirmed and a new UTXO is given to you.
|
||||
|
||||
But, in 10 minutes or less (probably), you'll have your remaining money back and fully spendable again. For now, we're still waiting:
|
||||
But, in 10 minutes or less (probably), you'll have your remaining money back and fully spendable again. For now, we're still waiting, and so can only see that one UTXO that we didn't spend:
|
||||
```
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"txid": "8a0d9ab73d81a1ce043d1ede0e737136e6d3352d3e0bc9590f9e8bbd91036dc2",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"address": "tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022000,
|
||||
"confirmations": 15,
|
||||
"scriptPubKey": "0014f1ad72d46aa89d5e622e42bbbb75064eebd9d101",
|
||||
"amount": 0.00099000,
|
||||
"confirmations": 8,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/5]027650c44c6f71d50a173f3f18858490cf26d2661a1d9929deba9aca57c76d1e5b)#7ss7jfnn",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
```
|
||||
And the change will eventuall arrive:
|
||||
But eventually the change will arrive (and for that matter, the spent funds too, since we sent them to another of our addresses this time):
|
||||
```
|
||||
[
|
||||
{
|
||||
"txid": "e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d",
|
||||
"txid": "80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465",
|
||||
"vout": 1,
|
||||
"address": "mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
|
||||
"scriptPubKey": "76a91432db726320e4ad170c9c1ee83cd4d8a243c3435988ac",
|
||||
"amount": 0.00090000,
|
||||
"address": "tb1qjrs9jr572nfyg5un8f2rzjdngml0mvskxlyd09",
|
||||
"scriptPubKey": "001490e0590e9e54d24453933a543149b346fefdb216",
|
||||
"amount": 0.00194000,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/1'/2']02881697d252d8bf181d08c58de1f02aec088cd2d468fc5fd888c6e39909f7fabf)#p6k7dptk",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/1/3]0347d61d5a0d09bf411b059a8ee97225e3430171b303a71ec40c5f414029cd84db)#gl740gxy",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/1/*)#eeegkjmk"
|
||||
],
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"txid": "80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"address": "tb1qdu69s5f9nw8x88lvsc8nt5d7gy9rgtnef0upfu",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022000,
|
||||
"confirmations": 16,
|
||||
"scriptPubKey": "00146f345851259b8e639fec860f35d1be410a342e79",
|
||||
"amount": 0.02000000,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/11]03d9cbd48a1238cc2c7371fd0c7169995106db6dec9fb287e4490c08cbd2b35cf1)#n3vc09ew",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "8a0d9ab73d81a1ce043d1ede0e737136e6d3352d3e0bc9590f9e8bbd91036dc2",
|
||||
"vout": 0,
|
||||
"address": "tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl",
|
||||
"label": "",
|
||||
"scriptPubKey": "0014f1ad72d46aa89d5e622e42bbbb75064eebd9d101",
|
||||
"amount": 0.00099000,
|
||||
"confirmations": 9,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/5]027650c44c6f71d50a173f3f18858490cf26d2661a1d9929deba9aca57c76d1e5b)#7ss7jfnn",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
This also might be a good time to revisit a blockchain explorer, so that you can see more intuitively how the inputs, outputs, and transaction fee are all laid out: [e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d](https://live.blockcypher.com/btc-testnet/tx/e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d/).
|
||||
This also might be a good time to revisit a blockchain explorer, so that you can see more intuitively how the inputs, outputs, and transaction fee are all laid out: [80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465](https://mempool.space/signet/tx/80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465).
|
||||
|
||||
## Summary: Sending Coins with Raw Transactions
|
||||
|
||||
@ -182,7 +209,7 @@ To send coins with raw transactions, you need to create a raw transaction with o
|
||||
|
||||
> :fire: ***What is the power of sending coins with raw transactions?***
|
||||
|
||||
> _The advantages._ It gives you the best control. If your goal is to write a more intricate Bitcoin script or program, you'll probably use raw transactions so that you know exactly what's going on. This is also the _safest_ situation to use raw transactions, because you can programmatically ensure that you don't make mistakes.
|
||||
> _The advantages._ It gives you the best control. If your goal is to write a more intricate Bitcoin script or program, you'll probably use raw transactions so that you know exactly what's going on. That is also the _safest_ situation in which to use raw transactions, because you can programmatically ensure that you don't make mistakes.
|
||||
|
||||
> _The disadvantages._ It's easy to lose money. There are no warnings, no safeguards, and no programmatic backstops unless you write them. It's also arcane. The formatting is obnoxious, even using the easy-to-use `bitcoin-cli` interface, and you have to do a lot of lookup and calculation by hand.
|
||||
|
||||
@ -190,5 +217,5 @@ To send coins with raw transactions, you need to create a raw transaction with o
|
||||
|
||||
See another alternative way to input commands with [Interlude: Using Curl](04_4__Interlude_Using_Curl.md).
|
||||
|
||||
Or, you prefer to skip what's frankly a digression, learn one more way to "Send Bitcoin Transactions" with [§4.5 Sending Coins with Automated Raw Transactions](04_5_Sending_Coins_with_Automated_Raw_Transactions.md).
|
||||
Or, if you prefer to skip what's frankly a digression, learn a final way to "Send Bitcoin Transactions" with [§4.5 Sending Coins with Automated Raw Transactions](04_5_Sending_Coins_with_Automated_Raw_Transactions.md).
|
||||
|
||||
|
||||
@ -18,23 +18,37 @@ $ bitcoin-cli help getmininginfo
|
||||
getmininginfo
|
||||
|
||||
Returns a json object containing mining-related information.
|
||||
|
||||
Result:
|
||||
{ (json object)
|
||||
"blocks" : n, (numeric) The current block
|
||||
"currentblockweight" : n, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)
|
||||
"currentblocktx" : n, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)
|
||||
"difficulty" : n, (numeric) The current difficulty
|
||||
"networkhashps" : n, (numeric) The network hashes per second
|
||||
"pooledtx" : n, (numeric) The size of the mempool
|
||||
"chain" : "str", (string) current network name (main, test, regtest)
|
||||
"warnings" : "str" (string) any network and blockchain warnings
|
||||
{ (json object)
|
||||
"blocks" : n, (numeric) The current block
|
||||
"currentblockweight" : n, (numeric, optional) The block weight (including reserved weight for block header, txs count and coinbase tx) of the last assembled block (only present if a block was ever assembled)
|
||||
"currentblocktx" : n, (numeric, optional) The number of block transactions (excluding coinbase) of the last assembled block (only present if a block was ever assembled)
|
||||
"bits" : "hex", (string) The current nBits, compact representation of the block difficulty target
|
||||
"difficulty" : n, (numeric) The current difficulty
|
||||
"target" : "hex", (string) The current target
|
||||
"networkhashps" : n, (numeric) The network hashes per second
|
||||
"pooledtx" : n, (numeric) The size of the mempool
|
||||
"blockmintxfee" : n, (numeric) Minimum feerate of packages selected for block inclusion in BTC/kvB
|
||||
"chain" : "str", (string) current network name (main, test, testnet4, signet, regtest)
|
||||
"signet_challenge" : "hex", (string, optional) The block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)
|
||||
"next" : { (json object) The next block
|
||||
"height" : n, (numeric) The next height
|
||||
"bits" : "hex", (string) The next target nBits
|
||||
"difficulty" : n, (numeric) The next difficulty
|
||||
"target" : "hex" (string) The next target
|
||||
},
|
||||
"warnings" : [ (json array) any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)
|
||||
"str", (string) warning
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
Examples:
|
||||
> bitcoin-cli getmininginfo
|
||||
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
|
||||
> curl --user myusername --data-binary '{"jsonrpc": "2.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||
```
|
||||
And there's the `curl` command, at the end of the help screen! This somewhat lengthy command has four major parts: (1) a listing of your user name; (2) a `--data-binary` flag; (3) a JSON object that tells `bitcoind` what to do, including a JSON array of parameters; and (4) an HTTP header that includes the `bitcoind` URL.
|
||||
There's the `curl` command, at the end of the help screen! This somewhat lengthy command has four major parts: (1) a listing of your user name; (2) a `--data-binary` flag; (3) a JSON object that tells `bitcoind` what to do, including a JSON array of parameters; and (4) an HTTP header that includes the `bitcoind` URL.
|
||||
|
||||
When you are working with `curl`, most of these arguments to `curl` will stay the same from command to command; only the `method` and `params` entries in the JSON array will typically change. However, you need to know how to fill in your username and your URL address in order to make it work in the first place!
|
||||
|
||||
@ -53,16 +67,17 @@ par=1
|
||||
maxuploadtarget=137
|
||||
maxconnections=16
|
||||
rpcuser=StandUp
|
||||
rpcpassword=8eaf562eaf45c33c3328bc66008f2dd1
|
||||
rpcpassword=4b42b0447b08784cb41adedac54d7f26
|
||||
rpcallowip=127.0.0.1
|
||||
debug=tor
|
||||
prune=550
|
||||
signet=1
|
||||
mintxfee=0.001
|
||||
fallbackfee=0.0001
|
||||
mintxfee=0.0001
|
||||
txconfirmtarget=1
|
||||
[test]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=38332
|
||||
rpcport=18332
|
||||
[main]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=8332
|
||||
@ -70,9 +85,9 @@ rpcport=8332
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=18443
|
||||
```
|
||||
Our user name is `StandUp` and our password is `8eaf562eaf45c33c3328bc66008f2dd1`.
|
||||
Our user name is `StandUp` and our password is `4b42b0447b08784cb41adedac54d7f26`.
|
||||
|
||||
> **WARNING:** Clearly, it's not very secure to have this information in a plain text file. As of Bitcoin Core 0.12, you can instead omit the `rpcpassword` from your `bitcoin.conf` file, and have `bitcoind` generate a new cookie whenever it starts up. The downside of this is that it makes use of RPC commands by other applications, such as the ones detailed in this chapter, more difficult. So, we're going to stick with the plain `rpcuser` and `rpcpassword` information for now, but for production software, consider moving to cookies.
|
||||
> **WARNING:** Clearly, it's not very secure to have this information in a plain text file. You can instead omit the `rpcpassword` from your `bitcoin.conf` file, and have `bitcoind` generate a new cookie whenever it starts up. The downside of this is that it makes use of RPC commands by other applications, such as the ones detailed in this chapter, more difficult. So, we're going to stick with the plain `rpcuser` and `rpcpassword` information for now, but for production software, consider moving to cookies.
|
||||
|
||||
The secure way to RPC with `bitcoind` is as follows:
|
||||
```
|
||||
@ -81,13 +96,13 @@ Enter host password for user 'bitcoinrpc':
|
||||
```
|
||||
As noted, you will be prompted for your password.
|
||||
|
||||
> :link: **SIGNET vs MAINNET:** Testnet uses a URL with port 38332 and mainnet uses a URL with port 8332. Take a look in your `bitcoin.conf`, it's all laid out there.
|
||||
> 🔗 **SIGNET vs MAINNET:** Signet uses a URL with port 38332 and mainnet uses a URL with port 8332. Take a look in your `bitcoin.conf`, it's mostly laid out there.
|
||||
|
||||
The insecure way to do so is as follows:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/
|
||||
$ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/
|
||||
```
|
||||
> **WARNING:** Entering your password on the command line may put your password into the process table and/or save it into a history. This is even less recommended than putting it in a file, except for testing on signet (or testnet). If you want to do it anywhere else, make sure you know what you're doing!
|
||||
> ⚠️ **WARNING: Password Not Secure!** Entering your password on the command line may put your password into the process table and/or save it into a history. This is even less recommended than putting it in a file, except for testing on signet (or testnet). If you want to do it anywhere else, make sure you know what you're doing!
|
||||
|
||||
### Know Your Command & Parameters
|
||||
|
||||
@ -110,34 +125,41 @@ Here's what some parameter arrays will look like:
|
||||
|
||||
You can now send your first `curl` command by accessing the `getmininginfo` RPC:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/
|
||||
{"result":{"blocks":1772428,"difficulty":10178811.40698772,"networkhashps":91963587385939.06,"pooledtx":61,"chain":"test","warnings":"Warning: unknown new rules activated (versionbit 28)"},"error":null,"id":"curltest"}
|
||||
$ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/
|
||||
{"result":{"blocks":293320,"bits":"1d150eea","difficulty":0.0474865840527392,"target":"000000150eea0000000000000000000000000000000000000000000000000000","networkhashps":301893.0621307249,"pooledtx":80,"blockmintxfee":0.00000001,"chain":"signet","next":{"height":293321,"bits":"1d150eea","difficulty":0.0474865840527392,"target":"000000150eea0000000000000000000000000000000000000000000000000000"},"signet_challenge":"512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae","warnings":[]},"error":null,"id":"curltest"}
|
||||
```
|
||||
|
||||
Note that we provided the method, `getmininginfo`, and the parameter, `[]`, but that everything else was the standard `curl` command line.
|
||||
|
||||
> **WARNING:** If you get a result like "Failed to connect to 127.0.0.1 port 8332: Connection refused", be sure that a line like `rpcallowip=127.0.0.1` is in your ~/.bitcoin/bitcoin.conf. If things still don't work, be sure that you're allowing access to port 38332 (or 8332) from localhost. Our standard setup from [Chapter Two: Creating a Bitcoin-Core VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md) should do all of this.
|
||||
> ⚠️ **WARNING: RPC May Not Allow.** If you get a result like "Failed to connect to 127.0.0.1 port 8332: Connection refused", be sure that a line like `rpcallowip=127.0.0.1` is in your ~/.bitcoin/bitcoin.conf. If things still don't work, be sure that you're allowing access to port 38332 (or 8332) from localhost. Our standard setup from [Chapter Two: Creating a Bitcoin-Core VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md) should do all of this.
|
||||
|
||||
The result is another JSON array, which is unfortunately ugly to read if you're using `curl` by hand. Fortunately, you can clean it up simply by piping it through `jq`:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.'
|
||||
% Total % Received % Xferd Average Speed Time Time Time Current
|
||||
Dload Upload Total Spent Left Speed
|
||||
100 295 100 218 100 77 72666 25666 --:--:-- --:--:-- --:--:-- 98333
|
||||
$ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
|
||||
{
|
||||
"result": {
|
||||
"blocks": 1772429,
|
||||
"difficulty": 10178811.40698772,
|
||||
"networkhashps": 90580030969896.44,
|
||||
"pooledtx": 4,
|
||||
"chain": "test",
|
||||
"warnings": "Warning: unknown new rules activated (versionbit 28)"
|
||||
"blocks": 293320,
|
||||
"bits": "1d150eea",
|
||||
"difficulty": 0.0474865840527392,
|
||||
"target": "000000150eea0000000000000000000000000000000000000000000000000000",
|
||||
"networkhashps": 301893.0621307249,
|
||||
"pooledtx": 88,
|
||||
"blockmintxfee": 1E-8,
|
||||
"chain": "signet",
|
||||
"next": {
|
||||
"height": 293321,
|
||||
"bits": "1d150eea",
|
||||
"difficulty": 0.0474865840527392,
|
||||
"target": "000000150eea0000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"signet_challenge": "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae",
|
||||
"warnings": []
|
||||
},
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
You'll see a bit of connectivity reporting as the data is downloaded, then when that data hits `jq`, everything will be output in a correctly indented form. (We'll be omitting the download information in future examples.)
|
||||
The '2>' throws out the connectivity reporting that `curl` reports, and then we send the rest to `jq`, which ensures that everything will be output in a correctly indented form.
|
||||
|
||||
## Manipulate Your Wallet
|
||||
|
||||
@ -147,25 +169,43 @@ Though you're accessing `bitcoind` directly, you'll still get access to wallet f
|
||||
|
||||
Use the `getaddressesbylabel` RPC to list all of your current addresses:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbylabel", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.'
|
||||
$ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbylabel", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
|
||||
{
|
||||
"result": {
|
||||
"mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE": {
|
||||
"tb1qxe0nn84xxw76jfc0s93g8kuefu2llglcvscy28": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff": {
|
||||
"tb1qxmx50fc06jt67nw6eqdcsm3rexgn6qvcet3rcm": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B": {
|
||||
"tb1q8lpqzydarurhsqttvw2qkf2qjxrwdv0kkej2ux": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d": {
|
||||
"tb1qdu69s5f9nw8x88lvsc8nt5d7gy9rgtnef0upfu": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6": {
|
||||
"tb1qsnm8mfafey9mlc3wj0qqspfmzdvhy0pnlmw9xm": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1qmtucvjtga68kgrvkl7q05x4t9lylxhku7kqdpr": {
|
||||
"tb1qnu24edevunfh8lk2a4x74ctn9jhslr83e4nsxx": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1qkvcgm83wv9np7re8w4w5ayg9tm2kxxpxk99h9p": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1qmwzvuavdvc6x0kmlrqncau4txhm5qrs7exjnv4": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1qukwva953qreduzm3mgnjwh5ymxupa4jrrkj8ym": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1qactkrm2yj2g73s966ptw7m56634zdv4acnhjhx": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1qlw280hk7cf7r97sm896s83wysat4vrqzpalm7e": {
|
||||
"purpose": "receive"
|
||||
}
|
||||
},
|
||||
@ -181,32 +221,54 @@ The result is a list of all the addresses that have been used by this wallet ...
|
||||
|
||||
Use the `listunspent` RPC to list the funds that you have available:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.'
|
||||
$ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
|
||||
{
|
||||
"result": [
|
||||
{
|
||||
"txid": "e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d",
|
||||
"txid": "80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465",
|
||||
"vout": 1,
|
||||
"address": "mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
|
||||
"scriptPubKey": "76a91432db726320e4ad170c9c1ee83cd4d8a243c3435988ac",
|
||||
"amount": 0.0009,
|
||||
"confirmations": 4,
|
||||
"address": "tb1qjrs9jr572nfyg5un8f2rzjdngml0mvskxlyd09",
|
||||
"scriptPubKey": "001490e0590e9e54d24453933a543149b346fefdb216",
|
||||
"amount": 0.00194000,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/1'/2']02881697d252d8bf181d08c58de1f02aec088cd2d468fc5fd888c6e39909f7fabf)#p6k7dptk",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/1/3]0347d61d5a0d09bf411b059a8ee97225e3430171b303a71ec40c5f414029cd84db)#gl740gxy",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/1/*)#eeegkjmk"
|
||||
],
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"txid": "80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"address": "tb1qdu69s5f9nw8x88lvsc8nt5d7gy9rgtnef0upfu",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022,
|
||||
"confirmations": 19,
|
||||
"scriptPubKey": "00146f345851259b8e639fec860f35d1be410a342e79",
|
||||
"amount": 0.02000000,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/11]03d9cbd48a1238cc2c7371fd0c7169995106db6dec9fb287e4490c08cbd2b35cf1)#n3vc09ew",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "8a0d9ab73d81a1ce043d1ede0e737136e6d3352d3e0bc9590f9e8bbd91036dc2",
|
||||
"vout": 0,
|
||||
"address": "tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl",
|
||||
"label": "",
|
||||
"scriptPubKey": "0014f1ad72d46aa89d5e622e42bbbb75064eebd9d101",
|
||||
"amount": 0.00099000,
|
||||
"confirmations": 9,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/5]027650c44c6f71d50a173f3f18858490cf26d2661a1d9929deba9aca57c76d1e5b)#7ss7jfnn",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
}
|
||||
],
|
||||
@ -218,25 +280,24 @@ This is almost exactly the same output that you receive when you type `bitcoin-c
|
||||
|
||||
### Create an Address
|
||||
|
||||
After you know where your funds are, the next step in crafting a transaction is to get a change address. By now you've probably got the hang of this, and you know that for simple RPC commands, all you need to do is adjust the `method` is the `curl` command:
|
||||
After you know where your funds are, the next step in crafting a transaction is to get a change address. By now you've probably got the hang of this, and you know that for simple RPC commands, all you need to do is adjust the `method` is the `curl` command. This example demonstrates the creation of an older "legacy" address, mainly so that we can demonstrate how an actual parameter works in the RPC interface.
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.'
|
||||
$ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
|
||||
{
|
||||
"result": "mrSqN37TPs89GcidSZTvXmMzjxoJZ6RKoz",
|
||||
"result": "n2cv88ogXyYSiGsVvRuAswetLnf7D7GRM5",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
|
||||
> **WARNING:** The parameters order is important when you are sending RPC commands using curl. There's only one argument for `getrawchangeaddress`, but consider its close cousin `getnewaddress`. That takes two arguments: first label, then type. If we sent that same `"params": ["legacy"]` instead of `"params": ["", "legacy"]`, we would get a `bech32` address with a label of `"legacy"` instead of a `legacy` address, so pay attention to the order!
|
||||
> ⚠️ **WARNING: Parameter Order Matters!** The parameters order is important when you are sending RPC commands using curl. There's only one argument for `getrawchangeaddress`, but consider its close cousin `getnewaddress`. That takes two arguments: first label, then type. If we sent that same `"params": ["legacy"]` instead of `"params": ["", "legacy"]`, we would get a `bech32` address with a label of `"legacy"` instead of a `legacy` address, so pay attention to the order!
|
||||
|
||||
At this point, we can even revert to our standard practice of saving results to variables with additional help from `jq`:
|
||||
```
|
||||
$ newaddress=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result')
|
||||
$ newaddress=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result')
|
||||
$ echo $newaddress
|
||||
mqdfnjgWr2r3sCCeuTDfe8fJ1CnycF2e6R
|
||||
tb1qmp3jd7s9s0vgnyxtjdf50qua90s825alqrpktv
|
||||
```
|
||||
No need to worry about the downloading info. It'll go to `STDERR` and be displayed on your screen, while the results go to `STDOUT` and are saved in your variable.
|
||||
|
||||
## Create a Transaction
|
||||
|
||||
@ -246,30 +307,30 @@ You're now ready to create a transaction with `curl`.
|
||||
|
||||
Just as with `bitcoin-cli`, in order to create a transaction by curling RPC commands, you should first save your variables. The only change here is that `curl` creates a JSON object that includes a `result` key-value, so you always need to pipe through the `.result` tag before you do anything else.
|
||||
|
||||
This example sets up our variables for using the 1.2985 BTC in funds listed in the first unspent transaction above:
|
||||
This example sets up our variables for using the 0.00194000 BTC in funds listed in the first unspent transaction above:
|
||||
```
|
||||
$ utxo_txid=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result | .[0] | .txid')
|
||||
$ utxo_vout=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result | .[0] | .vout')
|
||||
$ recipient=mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
|
||||
$ changeaddress=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result')
|
||||
$ utxo_txid=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result | .[0] | .txid')
|
||||
$ utxo_vout=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result | .[0] | .vout')
|
||||
$ recipient=tb1qg3lau83hm9e9tdvzr5k7aqtw3uv0dwkfct4xdn
|
||||
$ changeaddress=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result')
|
||||
|
||||
$ echo $utxo_txid
|
||||
e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d
|
||||
80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465
|
||||
$ echo $utxo_vout
|
||||
1
|
||||
$ echo $recipient
|
||||
mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
|
||||
tb1qg3lau83hm9e9tdvzr5k7aqtw3uv0dwkfct4xdn
|
||||
$ echo $changeaddress
|
||||
n2jf3MzeFpFGa7wq8rXKVnVuv5FoNSJZ1N
|
||||
tb1q79st28w04n57z6ht8zasfrdy9804qe9u5l4ahf
|
||||
```
|
||||
|
||||
### Create the Transaction
|
||||
|
||||
The transaction created with `curl` is very similar to the transaction created with `bitcoin-cli`, but with a few subtle differences:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.'
|
||||
$ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.001, "'$changeaddress'": 0.0009}'']}' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
|
||||
{
|
||||
"result": "02000000010d6acd0356db222ca3a7ee7fa1e3044316223ceec1f64b58aeb2e0de921007e70100000000ffffffff0230750000000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac50c30000000000001976a9147021efec134057043386decfaa6a6aa4ee5f19eb88ac00000000",
|
||||
"result": "02000000016524475f2cb9b7af59f86d25183d6dbe79b41b248a5a40c5e608ce79ca9f61800100000000fdffffff02a086010000000000160014447fde1e37d97255b5821d2dee816e8f18f6bac9905f010000000000160014f160b51dcface9e16aeb38bb048da429df5064bc00000000",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
@ -282,11 +343,11 @@ We've also varied up the quoting from how things worked in `bitcoin-cli`, to sta
|
||||
|
||||
However, there's one last thing of note in this example, and it can be _maddening_ if you miss it. When you executed a `createrawtransaction` command with `bitcoin-cli` the JSON array of inputs and the JSON object of outputs were each distinct parameters, so they were separated by a space. Now, because they're part of that `params` JSON array, they're separated by a comma (`,`). Miss that and you'll get a `parse error` without much additional information.
|
||||
|
||||
> **WARNING:** Ever having troubles debugging your `curl`? Add the argument `--trace-ascii /tmp/foo`. Full information on what's being sent to the server will be saved in `/tmp/foo` (or whatever file name you provide).
|
||||
> ⚠️ **WARNING: Loggin Ahead.** Ever having troubles debugging your `curl`? Add the argument `--trace-ascii /tmp/foo`. Full information on what's being sent to the server will be saved in `/tmp/foo` (or whatever file name you provide).
|
||||
|
||||
Having verified that things work, you probably want to save the hex code into a variable:
|
||||
```
|
||||
$ hexcode=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result')
|
||||
$ hexcode=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result')
|
||||
```
|
||||
|
||||
### Sign and Send
|
||||
@ -294,22 +355,25 @@ $ hexcode=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '
|
||||
Signing and sending your transaction using `curl` is an easy use of the `signrawtransactionwithwallet` and `sendrawtransaction` RPC:
|
||||
|
||||
```
|
||||
$ signedhex=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransactionwithwallet", "params": ["'$hexcode'"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result | .hex')
|
||||
$ signedhex=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransactionwithwallet", "params": ["'$hexcode'"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result | .hex')
|
||||
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["'$signedhex'"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.'
|
||||
$ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["'$signedhex'"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
|
||||
{
|
||||
"result": "eb84c5008038d760805d4d9644ace67849542864220cb2685a1ea2c64176b82d",
|
||||
"result": "d4ce7ab7db122373567addca4aa5a2866fc617b720db8147748b4108834144ff",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
|
||||
Whew! We're not going to do that again! (Using `bitcoin-cli` is complex enough!)
|
||||
|
||||
## Summary: Accessing Bitcoind with Curl
|
||||
|
||||
Having finished this section, you may feel that accessing `bitcoind` via `curl` is very much like accessing it through `bitcoin-cli` ... but more cumbersome. And, you'd be right. `bitcoin-cli` has pretty complete RPC functionality, so anything that you do through `curl` you can probably do through `bitcoin-cli`. Which is why we're going to continue concentrating on `bitcoin-cli` following this digression.
|
||||
|
||||
But there are still reasons you'd use `curl` instead of `bitcoin-cli`:
|
||||
|
||||
_What is the power of curl?_ Most obviously, `curl` takes out one level of indirection. Instead of working with `bitcoin-cli` which sends RPC commands to `bitcoind`, you're sending those RPC commands directly. This allows for more robust programming, because you don't have to worry about what unexpected things that `bitcoin-cli` might do or how it might change over time. However, you're also taking your first steps toward using a more comprehensive programming language than the poor options offered by a shell script. As you'll see in the last few chapters of this, you might actually see curl libraries are other functions to access the RPC commands in a variety of programming languages: but that's still a long ways away.
|
||||
> 🔥 **What is the power of curl?** Most obviously, `curl` takes out one level of indirection. Instead of working with `bitcoin-cli` which sends RPC commands to `bitcoind`, you're sending those RPC commands directly. This allows for more robust programming, because you don't have to worry about what unexpected things that `bitcoin-cli` might do or how it might change over time. However, you're also taking your first steps toward using a more comprehensive programming language than the poor options offered by a shell script. Ultimately, you might use libraries that provide access to curl functionality to access the RPC commands in a variety of programming languages—but that goes beyond the scope of the command line.
|
||||
|
||||
## What's Next?
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 4.5: Sending Coins with Automated Raw Transactions
|
||||
|
||||
This chapter lays out three ways to send funds via Bitcoin's cli interface. [§4.1](04_1_Sending_Coins_The_Easy_Way.md) described how to do so with a simple command, and [§4.4](04_4_Sending_Coins_with_a_Raw_Transaction.md) detailed how to use a more dangerous raw transaction. This final section splits the difference by showing how to make raw transactions simpler and safer.
|
||||
This chapter lays out three ways to send funds via Bitcoin's cli interface. [§4.1](04_1_Sending_Coins_The_Easy_Way.md) described how to do so with a simple command and [§4.4](04_4_Sending_Coins_with_a_Raw_Transaction.md) detailed how to use a more dangerous raw transaction. This final section splits the difference by showing how to make raw transactions simpler and safer using automation.
|
||||
|
||||
## Let Bitcoin Calculate For You
|
||||
|
||||
@ -8,23 +8,12 @@ The methodology for automated raw transactions is simple: you create a raw trans
|
||||
|
||||
In order to use this command, you'll need to ensure that your ~/.bitcoin/bitcoin.conf file contains rational variables for calculating transaction fees. Please see [§4.1: Sending Coins The Easy Way](04_1_Sending_Coins_The_Easy_Way.md) for more information on this.
|
||||
|
||||
For very conservative numbers, we suggested adding the following to the `bitcoin.conf`:
|
||||
```
|
||||
mintxfee=0.0001
|
||||
txconfirmtarget=6
|
||||
```
|
||||
To keep the tutorial moving along (and more generally to move money fast) we suggested the following:
|
||||
```
|
||||
mintxfee=0.001
|
||||
txconfirmtarget=1
|
||||
```
|
||||
|
||||
## Create a Bare Bones Raw Transaction
|
||||
|
||||
To use `fundrawtransaction` you first need to create a bare-bones raw transaction that lists _no_ inputs and _no_ change address. You'll just list your recipient and how much you want to send them, in this case `$recipient` and `0.0002` BTC.
|
||||
```
|
||||
$ recipient=n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi
|
||||
$ unfinishedtx=$(bitcoin-cli -named createrawtransaction inputs='''[]''' outputs='''{ "'$recipient'": 0.0002 }''')
|
||||
$ recipient=tb1qg3lau83hm9e9tdvzr5k7aqtw3uv0dwkfct4xdn
|
||||
$ unfinishedtx=$(bitcoin-cli -named createrawtransaction inputs='''[]''' outputs='''{ "'$recipient'": 0.002 }''')
|
||||
```
|
||||
|
||||
## Fund Your Bare Bones Transaction
|
||||
@ -33,12 +22,12 @@ You then tell `bitcoin-cli` to fund that bare-bones transaction:
|
||||
```
|
||||
$ bitcoin-cli -named fundrawtransaction hexstring=$unfinishedtx
|
||||
{
|
||||
"hex": "02000000012db87641c6a21e5a68b20c226428544978e6ac44964d5d8060d7388000c584eb0100000000feffffff02204e0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac781e0000000000001600140cc9cdcf45d4ea17f5227a7ead52367aad10a88400000000",
|
||||
"fee": 0.00022200,
|
||||
"hex": "02000000016524475f2cb9b7af59f86d25183d6dbe79b41b248a5a40c5e608ce79ca9f61800000000000fdffffff02400d030000000000160014447fde1e37d97255b5821d2dee816e8f18f6bac9be711b0000000000160014362520eaa80f35e99a8823ef8ac56e67e4a6c2af00000000",
|
||||
"fee": 0.00001410,
|
||||
"changepos": 1
|
||||
}
|
||||
```
|
||||
That provides a lot of useful information, but once you're confident with how it works, you'll want to use JQ to save your hex to a variable, as usual:
|
||||
That provides useful information such as the seelected fee, but once you're confident with how it works, you'll want to use JQ to save your hex to a variable, as usual:
|
||||
```
|
||||
$ rawtxhex3=$(bitcoin-cli -named fundrawtransaction hexstring=$unfinishedtx | jq -r '.hex')
|
||||
```
|
||||
@ -50,81 +39,77 @@ Running `decoderawtransaction` will show that the raw transaction is now laid ou
|
||||
```
|
||||
$ bitcoin-cli -named decoderawtransaction hexstring=$rawtxhex3
|
||||
{
|
||||
"txid": "b3b4c2057dbfbef6690e975ede92fde805ddea13c730f58401939a52c9ac1b99",
|
||||
"hash": "b3b4c2057dbfbef6690e975ede92fde805ddea13c730f58401939a52c9ac1b99",
|
||||
"txid": "031c88b5ef382f20773381543f00a7d34694d7372382d5d4f6029d9bf86693f5",
|
||||
"hash": "031c88b5ef382f20773381543f00a7d34694d7372382d5d4f6029d9bf86693f5",
|
||||
"version": 2,
|
||||
"size": 116,
|
||||
"vsize": 116,
|
||||
"weight": 464,
|
||||
"size": 113,
|
||||
"vsize": 113,
|
||||
"weight": 452,
|
||||
"locktime": 0,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "eb84c5008038d760805d4d9644ace67849542864220cb2685a1ea2c64176b82d",
|
||||
"vout": 1,
|
||||
"txid": "80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465",
|
||||
"vout": 0,
|
||||
"scriptSig": {
|
||||
"asm": "",
|
||||
"hex": ""
|
||||
},
|
||||
"sequence": 4294967294
|
||||
"sequence": 4294967293
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.00020000,
|
||||
"value": 0.01798590,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "OP_DUP OP_HASH160 e7c1345fc8f87c68170b3aa798a956c2fe6a9eff OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"hex": "76a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac",
|
||||
"reqSigs": 1,
|
||||
"type": "pubkeyhash",
|
||||
"addresses": [
|
||||
"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
|
||||
]
|
||||
"asm": "0 fe1f80781617de742b087aa63df65179fe3c2512",
|
||||
"desc": "addr(tb1qlc0cq7qkzl08g2cg02nrmaj308lrcfgjzec9lx)#7kazgeeu",
|
||||
"hex": "0014fe1f80781617de742b087aa63df65179fe3c2512",
|
||||
"address": "tb1qlc0cq7qkzl08g2cg02nrmaj308lrcfgjzec9lx",
|
||||
"type": "witness_v0_keyhash"
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 0.00007800,
|
||||
"value": 0.00200000,
|
||||
"n": 1,
|
||||
"scriptPubKey": {
|
||||
"asm": "0 a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"hex": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"reqSigs": 1,
|
||||
"type": "witness_v0_keyhash",
|
||||
"addresses": [
|
||||
"tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r"
|
||||
]
|
||||
"asm": "0 447fde1e37d97255b5821d2dee816e8f18f6bac9",
|
||||
"desc": "addr(tb1qg3lau83hm9e9tdvzr5k7aqtw3uv0dwkfct4xdn)#zau8pzqg",
|
||||
"hex": "0014447fde1e37d97255b5821d2dee816e8f18f6bac9",
|
||||
"address": "tb1qg3lau83hm9e9tdvzr5k7aqtw3uv0dwkfct4xdn",
|
||||
"type": "witness_v0_keyhash"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
One thing of interest here is the change address, which is the second `vout`. Note that it's a `tb1` address, which means that it's Bech32; when we gave Bitcoin Core the total ability to manage our change, it did so using its default address type, Bech32, and it worked fine. That's why our change to SegWit addresses in [§4.6](04_6_Creating_a_Segwit_Transaction.md) really isn't that big of a deal, but there are some gotchas for wider usage, which we'll talk about there.
|
||||
|
||||
Though we saw the fee in the `fundrawtransaction` output, it's not visible here. However, you can verify it with the `txfee-calc.sh` JQ script created in the [JQ Interlude](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/04_2__Interlude_Using_JQ.md):
|
||||
```
|
||||
$ ~/txfee-calc.sh $rawtxhex3
|
||||
.000222
|
||||
.00001400
|
||||
```
|
||||
Finally, you can use `getaddressinfo` to see that the generated change address really belongs to you:
|
||||
Finally, you can use `getaddressinfo` to see that the generated change address (the one receiving the surplus funds of 0.01798590) really belongs to you:
|
||||
```
|
||||
$ bitcoin-cli -named getaddressinfo address=tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r
|
||||
$ bitcoin-cli -named getaddressinfo address=tb1qlc0cq7qkzl08g2cg02nrmaj308lrcfgjzec9lx
|
||||
{
|
||||
"address": "tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
|
||||
"scriptPubKey": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"address": "tb1qlc0cq7qkzl08g2cg02nrmaj308lrcfgjzec9lx",
|
||||
"scriptPubKey": "0014fe1f80781617de742b087aa63df65179fe3c2512",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([d6043800/0'/1'/10']038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5)#zpv26nar",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/1/8]0305e3de867c6d9927dc671845e46ea29149ec23dc91d367e4cbdcde4457b8566b)#hwpl2vrq",
|
||||
"parent_desc": "wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/1/*)#eeegkjmk",
|
||||
"iswatchonly": false,
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"pubkey": "038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5",
|
||||
"witness_program": "fe1f80781617de742b087aa63df65179fe3c2512",
|
||||
"pubkey": "0305e3de867c6d9927dc671845e46ea29149ec23dc91d367e4cbdcde4457b8566b",
|
||||
"ischange": true,
|
||||
"timestamp": 1592335137,
|
||||
"hdkeypath": "m/0'/1'/10'",
|
||||
"hdseedid": "fdea8e2630f00d29a9d6ff2af7bf5b358d061078",
|
||||
"hdmasterfingerprint": "d6043800",
|
||||
"timestamp": 1772127861,
|
||||
"hdkeypath": "m/84h/1h/0h/1/8",
|
||||
"hdseedid": "0000000000000000000000000000000000000000",
|
||||
"hdmasterfingerprint": "b8309bae",
|
||||
"labels": [
|
||||
]
|
||||
}
|
||||
@ -144,15 +129,18 @@ In several minutes, you'll have your change back:
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
{
|
||||
"txid": "8b9dd66c999966462a3d88d6ac9405d09e2aa409c0aa830bdd08dbcbd34a36fa",
|
||||
"vout": 1,
|
||||
"address": "tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
|
||||
"scriptPubKey": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"amount": 0.00007800,
|
||||
"txid": "031c88b5ef382f20773381543f00a7d34694d7372382d5d4f6029d9bf86693f5",
|
||||
"vout": 0,
|
||||
"address": "tb1qlc0cq7qkzl08g2cg02nrmaj308lrcfgjzec9lx",
|
||||
"scriptPubKey": "0014fe1f80781617de742b087aa63df65179fe3c2512",
|
||||
"amount": 0.01798590,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([d6043800/0'/1'/10']038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5)#zpv26nar",
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/1/8]0305e3de867c6d9927dc671845e46ea29149ec23dc91d367e4cbdcde4457b8566b)#hwpl2vrq",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/1/*)#eeegkjmk"
|
||||
],
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
@ -160,7 +148,97 @@ $ bitcoin-cli listunspent
|
||||
|
||||
## Freeze Your Coins
|
||||
|
||||
[towrite]
|
||||
The `fundrawtransaction` makes it easy to fund raw transactions by automatically selecting your UTXOs, saving you from having to search them up. But sometimes there might be UTXOs that you _don't_ want to use, most frequently because they might correlate activities that you don't want correlated (e.g., if you do programming for politicians under a pseudonym, you might not want to spend money earned in that way on a family vacation, because it could break your pseudonymity).
|
||||
|
||||
To prevent this sort of correlation from accidentally happening, you can "lock" a sensitive UTXO so that it's never selected for automatic fund creation, such as with `fundrawtransaction`.
|
||||
|
||||
First, you need to identify the problematic UTXO:
|
||||
```
|
||||
$ txid="031c88b5ef382f20773381543f00a7d34694d7372382d5d4f6029d9bf86693f5"
|
||||
$ vout="0"
|
||||
```
|
||||
Then you need to run the `lockunspent` command with an `unlock=false` (e.g., "lock") argument and a JSON array of orbjects that each contain a UTXO.
|
||||
```
|
||||
$ bitcoin-cli -named lockunspent unlock=false transactions='''[ { "txid": "'$txid'", "vout": '$vout' } ]'''
|
||||
true
|
||||
```
|
||||
This will maintain the lock in memory. If you want it instead written to the wallet database, chose:
|
||||
```
|
||||
$ bitcoin-cli -named lockunspent unlock=false transactions='''[ { "txid": "'$txid'", "vout": '$vout' } ]''' persistent=true
|
||||
true
|
||||
```
|
||||
You can see the UTXO is locked with `listlockunspent`:
|
||||
```
|
||||
$ bitcoin-cli listlockunspent
|
||||
[
|
||||
{
|
||||
"txid": "031c88b5ef382f20773381543f00a7d34694d7372382d5d4f6029d9bf86693f5",
|
||||
"vout": 0
|
||||
}
|
||||
]
|
||||
```
|
||||
It's now also missing from your `listunspent` list:
|
||||
```
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
{
|
||||
"txid": "8a0d9ab73d81a1ce043d1ede0e737136e6d3352d3e0bc9590f9e8bbd91036dc2",
|
||||
"vout": 0,
|
||||
"address": "tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl",
|
||||
"label": "",
|
||||
"scriptPubKey": "0014f1ad72d46aa89d5e622e42bbbb75064eebd9d101",
|
||||
"amount": 0.00099000,
|
||||
"confirmations": 15,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/0/5]027650c44c6f71d50a173f3f18858490cf26d2661a1d9929deba9aca57c76d1e5b)#7ss7jfnn",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
|
||||
],
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "d4ce7ab7db122373567addca4aa5a2866fc617b720db8147748b4108834144ff",
|
||||
"vout": 1,
|
||||
"address": "tb1q79st28w04n57z6ht8zasfrdy9804qe9u5l4ahf",
|
||||
"scriptPubKey": "0014f160b51dcface9e16aeb38bb048da429df5064bc",
|
||||
"amount": 0.00050000,
|
||||
"confirmations": 3,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([b8309bae/84h/1h/0h/1/6]0202c9ea711bd943d8c34a9a5ffb848a58609deacb432de4b097c5dfc32dc5595c)#4zwtrgdu",
|
||||
"parent_descs": [
|
||||
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/1/*)#eeegkjmk"
|
||||
],
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
```
|
||||
Most importantly if you try try to fund an unfunded transaction, the locked UTXO cannot be spent:
|
||||
```
|
||||
nolock=$(bitcoin-cli -named createrawtransaction inputs='''[]''' outputs='''{ "'$recipient'": 0.01 }''')
|
||||
```
|
||||
In this case, the wallet has sufficient funds, but only if the locked UTXO is used, so `fundrawtransaction` refuses:
|
||||
```
|
||||
$ bitcoin-cli -named fundrawtransaction hexstring=$nolock
|
||||
error code: -4
|
||||
error message:
|
||||
Insufficient funds
|
||||
```
|
||||
The lock can be removed just by changing the `unlock` variable to `true`. (`persistent` no longer matters.)
|
||||
```
|
||||
$ bitcoin-cli -named lockunspent unlock=true transactions='''[ { "txid": "'$txid'", "vout": '$vout' } ]'''
|
||||
true
|
||||
```
|
||||
And now that raw transaction will fund correctly:
|
||||
```
|
||||
$ bitcoin-cli -named fundrawtransaction hexstring=$nolock
|
||||
{
|
||||
"hex": "0200000001f59366f89b9d02f6d4d5822337d79446d3a7003f54813377202f38efb5881c030000000000fdffffff02fc290c00000000001600142d5717c0d7b3a2d68d56be8d9231ed7a65d4d3f840420f0000000000160014447fde1e37d97255b5821d2dee816e8f18f6bac900000000",
|
||||
"fee": 0.00001410,
|
||||
"changepos": 0
|
||||
}
|
||||
```
|
||||
|
||||
## Summary: Sending Coins with Automated Raw Transactions
|
||||
|
||||
@ -170,9 +248,9 @@ If you must send funds with raw transactions then `fundrawtransaction` gives you
|
||||
|
||||
> _The advantages._ It provides a nice balance. If you're sending funds by hand and `sendtoaddress` doesn't offer enough control for whatever reason, you can get some of the advantages of raw transactions without the dangers. This methodology should be used whenever possible if you're sending raw transactions by hand.
|
||||
|
||||
> _The disadvantages._ It's a hodge-podge. Though there are a few additional options for the `fundrawtransaction` command that weren't mentioned here, your control is still limited. You'd probably never want to use this method if you were writing a program where the whole goal is to know exactly what's going on.
|
||||
> _The disadvantages._ It's a hodge-podge. Though there are a few additional options for the `fundrawtransaction` command that weren't mentioned here, but even with the ability to lock UTXOs, your control is still limited. You'd probably never want to use this method if you were writing a program where the whole goal is to know exactly what's going on.
|
||||
|
||||
## What's Next?
|
||||
|
||||
Complete your "Sending of Bitcoin Transactions" with [§4.6: Creating a Segwit Transaction](04_6_Creating_a_Segwit_Transaction.md).
|
||||
Complete your "Sending of Bitcoin Transactions" with [§4.6: Sending Coins to Other Addresses](04_6_Sending_Coins_to_Other_Addresses.md).
|
||||
|
||||
|
||||
@ -1,286 +0,0 @@
|
||||
# 4.6: Creating a SegWit Transaction
|
||||
|
||||
> :information_source: **NOTE:** This section has been recently added to the course and is an early draft that may still be awaiting review. Caveat reader.
|
||||
|
||||
Once upon a time, the Bitcoin heavens shook with the blocksize wars. Fees were skyrocketing, and users were worried about scaling. The Bitcoin Core developers were reluctant to simply increase the blocksize, but they came upon a compromise: SegWit, the Segregated Witness. Segregated Witness is a fancy way of saying "Separated Signature". It creates new sorts of transactions that remove signatures to the end of the transaction. By combining this with increased block sizes that only are visible to upgraded nodes, SegWit resolved the scaling problems for Bitcoin at the time (and also resolved a nasty malleability bug that had previously made even better scaling with layer-2 protocols like Lightning impractical).
|
||||
|
||||
The catch? SegWit uses different addresses, some of which are compatible with older nodes, and some of which are not.
|
||||
|
||||
## Understand a SegWit Transaction
|
||||
|
||||
In classic transactions, signature (witness) information was stored toward the middle of the transaction, while in SegWit transactions, it's at the bottom. This goes hand-in-hand with the blocksize increases that were introduced in the SegWit upgrade. The blocksize was increased from 1M to a variable amount based on how many SegWit transactions are in a block, starting as low as 1M (no SegWit transactions) and going as high as 4M (all SegWit transactions). This variable size was created to accomodate classic nodes, so that everything remains backward compatible. If a classic node sees a SegWit transaction, it throws out the witness information (resulting in a smaller sized block, under the old 1M limit), while if a new node sees a SegWit transaction, it keeps the witness information (resulting in a larger sized block, up to the new 4M limit).
|
||||
|
||||
So that's the what and how of SegWit transactions. Not that you need to know any of it to use them. Most transactions on the Bitcoin network are now SegWit. They're what you're going to natively use for more transactions and receipts of money. The details are no more relevant at this point than the details of how most of Bitcoin works.
|
||||
|
||||
## Create a SegWit Address
|
||||
|
||||
You create a SegWit address the same way as any other address, with the `getnewaddress` and the `getrawchangeaddress` commands.
|
||||
|
||||
If you need to create an address for someone who can't send to the newer Bech32 addresses, then use the `p2sh-segwit` addresstype:
|
||||
```
|
||||
$ bitcoin-cli -named getnewaddress address_type=p2sh-segwit
|
||||
2N5h2r4karVqN7uFtpcn8xnA3t5cbpszgyN
|
||||
```
|
||||
Seeing an address with a "2" prefix means that you did it right.
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** "3" for Mainnet.
|
||||
|
||||
However, if the person you're interacting with has a fully mature client, they'll be able to send to a Bech32 address, which you create using the commands in the default way:
|
||||
```
|
||||
$ bitcoin-cli getnewaddress
|
||||
tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6
|
||||
```
|
||||
As we've already seen, change addresses generated from within `bitcoin-cli` interact fine with Bech32 addresses, so there's no point in using the `legacy` flag there either:
|
||||
```
|
||||
$ bitcoin-cli getrawchangeaddress
|
||||
tb1q05wx5tyadm8qe83exdqdyqvqqzjt3m38vfu8ff
|
||||
```
|
||||
|
||||
Here, note that the unique "tb1" prefix denoted Bech32.
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** "bc1" for mainnet.
|
||||
|
||||
Bitcoin-cli doesn't care which address type you're using. You can run a command like `listaddressgroupings` and it will freely mix addresses of the different types:
|
||||
```
|
||||
$ bitcoin-cli listaddressgroupings
|
||||
[
|
||||
[
|
||||
[
|
||||
"mfsiRhxbQxcD7HLS4PiAim99oeGyb9QY7m",
|
||||
0.01000000,
|
||||
""
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
|
||||
0.00000000,
|
||||
""
|
||||
],
|
||||
[
|
||||
"tb1q6dak4e9fz77vsulk89t5z92l2e0zm37yvre4gt",
|
||||
0.00000000
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
0.00022000,
|
||||
""
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
|
||||
0.00000000
|
||||
],
|
||||
[
|
||||
"mqjrdY5raxKzXQf5t2VvVvzhvFAgersu9B",
|
||||
0.00000000
|
||||
],
|
||||
[
|
||||
"mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
|
||||
0.00000000,
|
||||
""
|
||||
],
|
||||
[
|
||||
"tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
|
||||
0.00007800
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"mpVLL7iqPr4d7BJkEG54mcdm7WmrAhaW6q",
|
||||
0.01000000,
|
||||
""
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6",
|
||||
0.01000000,
|
||||
""
|
||||
]
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
## Send a SegWit Transaction The Easy Way
|
||||
|
||||
So how do you send a Segwit transaction? Exactly like any other transaction. It doesn't matter if the UTXO is SegWit, the address is SegWit, or some combination thereof. You can expect `bitcoin-cli` to do the right thing. Though you can tell the differences via the addresses, they don't matter for interacting with things at the `bitcoin-cli` or RPC level. (And this is one of the advantages of using the command line and the RPC interface, as suggested in this tutorial: experts have already done the hard work for you, including things like how to send to both legacy and Bech32 addresses. You just get to use that functionality to your own advantage.)
|
||||
|
||||
Here's an example of sending to a SegWit address, the easy way:
|
||||
```
|
||||
$ bitcoin-cli sendtoaddress tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx 0.005
|
||||
854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42
|
||||
```
|
||||
If you look at your transaction, you can see the use of the Bech32 address:
|
||||
```
|
||||
$ bitcoin-cli -named gettransaction txid="854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42" verbose=true
|
||||
{
|
||||
"amount": -0.00500000,
|
||||
"fee": -0.00036600,
|
||||
"confirmations": 0,
|
||||
"trusted": true,
|
||||
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
|
||||
"walletconflicts": [
|
||||
],
|
||||
"time": 1592948795,
|
||||
"timereceived": 1592948795,
|
||||
"bip125-replaceable": "no",
|
||||
"details": [
|
||||
{
|
||||
"address": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx",
|
||||
"category": "send",
|
||||
"amount": -0.00500000,
|
||||
"vout": 1,
|
||||
"fee": -0.00036600,
|
||||
"abandoned": false
|
||||
}
|
||||
],
|
||||
"hex": "0200000002114d5a4c3b847bc796b2dc166ca7120607b874aa6904d4a43dd5f9e0ea79d4ba010000006a47304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7012103ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042dfeffffffa71321e81ef039af490251379143f7247ad91613c26c8f3e3404184218361733000000006a47304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a31601210339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7efeffffff026854160000000000160014d591091b8074a2375ed9985a9c4b18efecfd416520a1070000000000160014751e76e8199196d454941c45d1b3a323f1433bd6c60e1b00",
|
||||
"decoded": {
|
||||
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
|
||||
"hash": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
|
||||
"version": 2,
|
||||
"size": 366,
|
||||
"vsize": 366,
|
||||
"weight": 1464,
|
||||
"locktime": 1773254,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "bad479eae0f9d53da4d40469aa74b8070612a76c16dcb296c77b843b4c5a4d11",
|
||||
"vout": 1,
|
||||
"scriptSig": {
|
||||
"asm": "304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7[ALL] 03ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042d",
|
||||
"hex": "47304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7012103ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042d"
|
||||
},
|
||||
"sequence": 4294967294
|
||||
},
|
||||
{
|
||||
"txid": "33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7",
|
||||
"vout": 0,
|
||||
"scriptSig": {
|
||||
"asm": "304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a316[ALL] 0339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7e",
|
||||
"hex": "47304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a31601210339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7e"
|
||||
},
|
||||
"sequence": 4294967294
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.01463400,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "0 d591091b8074a2375ed9985a9c4b18efecfd4165",
|
||||
"hex": "0014d591091b8074a2375ed9985a9c4b18efecfd4165",
|
||||
"reqSigs": 1,
|
||||
"type": "witness_v0_keyhash",
|
||||
"addresses": [
|
||||
"tb1q6kgsjxuqwj3rwhkenpdfcjccalk06st9z0k0kh"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 0.00500000,
|
||||
"n": 1,
|
||||
"scriptPubKey": {
|
||||
"asm": "0 751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||
"hex": "0014751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||
"reqSigs": 1,
|
||||
"type": "witness_v0_keyhash",
|
||||
"addresses": [
|
||||
"tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
In fact, both of the `vouts` use Bech32 addresses: your recipient and the automatically generated change address.
|
||||
|
||||
But when we backtrack our `vin`, we discover that came from a legacy address. Because it doesn't matter:
|
||||
```
|
||||
$ bitcoin-cli -named gettransaction txid="33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7"
|
||||
{
|
||||
"amount": 0.01000000,
|
||||
"confirmations": 43,
|
||||
"blockhash": "00000000000000e2365d2f814d1774b063d9a04356f482010cdfdd537b1a24bb",
|
||||
"blockheight": 1773212,
|
||||
"blockindex": 103,
|
||||
"blocktime": 1592937103,
|
||||
"txid": "33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7",
|
||||
"walletconflicts": [
|
||||
],
|
||||
"time": 1592936845,
|
||||
"timereceived": 1592936845,
|
||||
"bip125-replaceable": "no",
|
||||
"details": [
|
||||
{
|
||||
"address": "mpVLL7iqPr4d7BJkEG54mcdm7WmrAhaW6q",
|
||||
"category": "receive",
|
||||
"amount": 0.01000000,
|
||||
"label": "",
|
||||
"vout": 0
|
||||
}
|
||||
],
|
||||
"hex": "020000000001016a66efa334f06e2c54963e48d049a35d7a1bda44633b7464621cae302f35174a0100000017160014f17b16c6404e85165af6f123173e0705ba31ec25feffffff0240420f00000000001976a914626ab1ca41d98f597d18d1ff8151e31a40d4967288acd2125d000000000017a914d5e76abfe5362704ff6bbb000db9cdfa43cd2881870247304402203b3ba83f51c1895b5f639e9bfc40124715e2495ef2c79d4e49c0f8f70fbf2feb02203d50710abe3cf37df4d2a73680dadf3cecbe4f2b5d0b276dbe7711d0c2fa971a012102e64f83ee1c6548bcf44cb965ffdb803f30224459bd2e57a5df97cb41ba476b119b0e1b00"
|
||||
}
|
||||
```
|
||||
|
||||
## Send a SegWit Transaction The Hard Way
|
||||
|
||||
You can similarly fund a transaction with a Bech32 address with no difference to the techniques you've learned so far. Here's an exactly of doing so with a complete raw transaction:
|
||||
```
|
||||
$ changeaddress=$(bitcoin-cli getrawchangeaddress)
|
||||
$ echo $changeaddress
|
||||
tb1q4xje3mx9xn7f8khv7p69ekfn0q72kfs8x3ay4j
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
...
|
||||
{
|
||||
"txid": "003bfdca5578c0045a76768281f05d5e6f57774be399a76f387e2a0e99e4e452",
|
||||
"vout": 0,
|
||||
"address": "tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6",
|
||||
"label": "",
|
||||
"scriptPubKey": "0014a226e1dfd08537b02de04f667a49bd46f9b9f578",
|
||||
"amount": 0.01000000,
|
||||
"confirmations": 5,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([d6043800/0'/0'/5']0327dbe2d58d9ed2dbeca28cd26e18f48aa94c127fa6fb4b60e4188f6360317640)#hd66hknp",
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
$ recipient=tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx
|
||||
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[2] | .txid')
|
||||
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[2] | .vout')
|
||||
$ echo $utxo_txid $utxo_vout
|
||||
003bfdca5578c0045a76768281f05d5e6f57774be399a76f387e2a0e99e4e452 0
|
||||
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.002, "'$changeaddress'": 0.007 }''')
|
||||
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
|
||||
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
|
||||
e02568b706b21bcb56fcf9c4bb7ba63fdbdec1cf2866168c4f50bc0ad693f26c
|
||||
```
|
||||
It all works exactly the same as other sorts of transactions!
|
||||
|
||||
### Recognize the New Descriptor
|
||||
|
||||
If you look at the `desc` field, you'll note that the SegWit address has a different style descriptor than those encountered in [§3.5: Understanding the Descriptor](03_5_Understanding_the_Descriptor.md). A legacy descriptor described in that section looked like this: `pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk`. Our new SegWit descriptor instead looks like this: `wpkh([d6043800/0'/0'/5']0327dbe2d58d9ed2dbeca28cd26e18f48aa94c127fa6fb4b60e4188f6360317640)#hd66hknp"`.
|
||||
|
||||
The big thing to note is that function has changed. It was previously `pkh`, which is a standard P2PKH hashed public-key address. The SegWit address is instead `wpkh`, which means that it's a P2WPKH native SegWit address. This underlines the :fire: ***power of descriptors***. They describe how to create an address from a key or other information, with the functions unambiguously defining how to make the address based on its type.
|
||||
|
||||
## Summary: Creating a SegWit Transaction
|
||||
|
||||
There's really no complexity to creating SegWit transactions. Internally, they're structured differently from legacy transactions, but from the command line there's no difference: you just use an address with a different prefix. The only thing to watch for is that some people may not be able to send to a Bech32 address if they're using obsolete software.
|
||||
|
||||
> :fire: ***What's the power of sending coins with SegWit?***
|
||||
|
||||
> _The Advantages._ SegWit transactions are smaller, and so will be cheaper to send than legacy transactions due to lower fees. Bech32 doubles down on this advantage, and also creates addresses that are harder to foul up when transcribing — and that's pretty important, given that user error is one of the most likely ways to lose your bitcoins.
|
||||
|
||||
> _The Disadvantages._ SegWit addresses may not be supported by obsolete Bitcoin software. In particular, people may not be able to send to your Bech32 address.
|
||||
|
||||
## What's Next?
|
||||
|
||||
Advance through "bitcoin-cli" with [Chapter Five: Controlling Bitcoin Transactions](05_0_Controlling_Bitcoin_Transactions.md).
|
||||
51
04_6_Sending_Coins_to_Other_Addresses.md
Normal file
51
04_6_Sending_Coins_to_Other_Addresses.md
Normal file
@ -0,0 +1,51 @@
|
||||
# 4.6: Sending Coins to Other Addresses
|
||||
|
||||
You've sent coins to P2WPKH addresses by a variety of means. But what if you want to send coins to other address types?
|
||||
|
||||
It turns out that it's so simple that you don't have to think about it.
|
||||
|
||||
## Send Coins to Supported Addresses
|
||||
|
||||
If you want to send a coin to any supported address described in [§3.5](03_5_Understanding_the_Address.md) you can do so with any of the methodologies described to date. There's nothing more: it just works, because Bitcoin is backward compatible and because Bitcoin Core is going to always be on the leading edge of new address types.
|
||||
|
||||
Here's some examples, using the simple `sendtoaddress` command from [§4.1](04_1_Sending_Coins_The_Easy_Way.md). (Addresses are drawn from the [recycle page](https://signet257.bublina.eu.org/about.html#recycle) on the [Alt Signet Faucet](https://signet257.bublina.eu.org/).
|
||||
|
||||
**P2PKH:**
|
||||
```
|
||||
$ bitcoin-cli sendtoaddress mmDZXXiHqydn31zgbUaKiLNBxwNCcX6Eam 0.001
|
||||
2f60126b63260ce814a7d636df4d27d68dc73fbd145877a102d80c7747d89f55
|
||||
```
|
||||
|
||||
**P2SH-P2WPKH:**
|
||||
```
|
||||
$ bitcoin-cli sendtoaddress 2NEDviSjc3UP8c4VpUPgjyovY1m6KvyJq1m 0.001
|
||||
a3028893d2b5d4843d25abd562023eb05e447b4af163c17811facc69423d02b1
|
||||
```
|
||||
|
||||
**P2TR:**
|
||||
```
|
||||
$ bitcoin-cli sendtoaddress tb1p4tp4l6glyr2gs94neqcpr5gha7344nfyznfkc8szkreflscsdkgqsdent4 0.001
|
||||
75884b60ca03b17a5bb68590b375ba676566383d8bd77da304aeb0aa6f040f89
|
||||
```
|
||||
|
||||
However, `bitcoin-cli` will no longer send to some of the most outdated addresses. The following are examples of the oldest P2PK addresses (one compressed, the other not):
|
||||
```
|
||||
$ bitcoin-cli sendtoaddress 04a8c3fa3dbc022ca7c9a2214c5e673833317b3cff37c0fc170fc347f1a2f6b6e2a53db4d023387f89209de481cd014a44040e1b09c3226d40fed02c0bc8d0f548 0.001
|
||||
error code: -5
|
||||
error message:
|
||||
Invalid Bitcoin address: 04a8c3fa3dbc022ca7c9a2214c5e673833317b3cff37c0fc170fc347f1a2f6b6e2a53db4d023387f89209de481cd014a44040e1b09c3226d40fed02c0bc8d0f548
|
||||
|
||||
$ bitcoin-cli sendtoaddress 02a8c3fa3dbc022ca7c9a2214c5e673833317b3cff37c0fc170fc347f1a2f6b6e2 0.001
|
||||
error code: -5
|
||||
error message:
|
||||
Invalid Bitcoin address: 02a8c3fa3dbc022ca7c9a2214c5e673833317b3cff37c0fc170fc347f1a2f6b6e2
|
||||
```
|
||||
That doesn't meant the addresses aren't valid. These still are, and they contain large amounts of Bitcoin; the Bitcoin Core engineers have just decided that there's no reason to send additional funds to those older addresses that will be insecure in the case of a Quantum Computer breakthrough (and in fact there are [discussions](https://www.coindesk.com/tech/2025/07/16/bitcoin-devs-float-proposal-to-freeze-quantum-vulnerable-addresses-even-satoshi-nakamoto-s) about freezing the funds due to their vulnerability, though that would be a rather dramatic change to traditional Bitcoin consensus).
|
||||
|
||||
## Summary: Sending Coins to Other Addresses
|
||||
|
||||
Now that you know how to send coins via a variety of means, you can send them to any sort of address. Bitcoin Core and the protocols take care of the specifics. The only exceptions are addresses that are so old that they haven't been used for over a decade, and which are largely considered dead.
|
||||
|
||||
## What's Next?
|
||||
|
||||
Advance through "bitcoin-cli" with [Chapter Five: Controlling Bitcoin Transactions](05_0_Controlling_Bitcoin_Transactions.md).
|
||||
13
README.md
13
README.md
@ -41,14 +41,13 @@ If you'd like to make your own translation, please see [Contributing](https://gi
|
||||
* [Interlude: Using Command-Line Variables](03_7a_Interlude_Using_Command-Line_Variables.md)
|
||||
* [4.0: Sending Bitcoin Transactions](04_0_Sending_Bitcoin_Transactions.md)
|
||||
* [4.1: Sending Coins the Easy Way](04_1_Sending_Coins_The_Easy_Way.md)
|
||||
* [4.2: Creating a Raw Transaction](04_2_Creating_a_Raw_Transaction.md) [**TO UPDATE FOR SEGWIT**]
|
||||
* [Interlude: Using JQ](04_2a_Interlude_Using_JQ.md) [**TO UPDATE FOR SEGWIT**]
|
||||
* [4.3: Creating a Raw Transaction with Named Arguments](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md) [**TO UPDATE FOR SEGWIT**]
|
||||
* [4.4: Sending Coins with Raw Transactions](04_4_Sending_Coins_with_a_Raw_Transaction.md) [**TO UPDATE**]
|
||||
* [4.2: Creating a Raw Transaction](04_2_Creating_a_Raw_Transaction.md)
|
||||
* [Interlude: Using JQ](04_2a_Interlude_Using_JQ.md)
|
||||
* [4.3: Creating a Raw Transaction with Named Arguments](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md)
|
||||
* [4.4: Sending Coins with Raw Transactions](04_4_Sending_Coins_with_a_Raw_Transaction.md)
|
||||
* [Interlude: Using Curl](04_4a_Interlude_Using_Curl.md)
|
||||
* [4.5: Sending Coins with Automated Raw Transactions](04_5_Sending_Coins_with_Automated_Raw_Transactions.md) [**TO UPDATE FOR SEGWIT**]
|
||||
* [4.6: Creating a Segwit Transaction](04_6_Creating_a_Segwit_Transaction.md) [**TO REMOVE**]
|
||||
* [4.6: Sending Other Types of Transactions](04_6_Sending_Other_Types_of_Transactions.md) [**TO WRITE MAYBE**]
|
||||
* [4.5: Sending Coins with Automated Raw Transactions](04_5_Sending_Coins_with_Automated_Raw_Transactions.md)
|
||||
* [4.6: Sending Other Types of Transactions](04_6_Sending_Coins_to_Other_Addresses.md)
|
||||
* [5.0: Controlling Bitcoin Transactions](05_0_Controlling_Bitcoin_Transactions.md)
|
||||
* [5.1 Watching for Stuck Transactions](05_1_Watching_for_Stuck_Transactions.md)
|
||||
* [5.2: Resending a Transaction with RBF](05_2_Resending_a_Transaction_with_RBF.md) [**TO UPDATE**]
|
||||
|
||||
30
TODO.md
30
TODO.md
@ -2,16 +2,14 @@
|
||||
|
||||
The following TODO items are intended for a 3.0 version of Learning Bitcoin from the Command Line
|
||||
|
||||
## Immediate TODO (for 2/26): Sending Transactions
|
||||
## Immediate TODO (for 3/12): Cleanup
|
||||
|
||||
1. <strike>Rewrite transaction fees in §4.1 to talk about vB, et al</strike>
|
||||
2. <strike>Add sendall RPC to §4.1</strike>
|
||||
3. <strike>Add args variable option to §4.3</strike>
|
||||
4. Change §4.1-4.5 to use P2WPKH
|
||||
5. Add Freezing Coins to §4.4
|
||||
6. Remove §4.6 on Segwit
|
||||
7. Add Info On Sending to Other Addresses (no biggie)
|
||||
8. Full Review of §4.1-4.5
|
||||
1. Bring chapter 1 up to date
|
||||
2. Bring chapter 2 up to date
|
||||
3. Double check §3.1 + 3.2
|
||||
4. Put in some discussions about how we'll later import seed words, etc. into whatever chapter that is.
|
||||
5. Edit/Update Chapter 5
|
||||
6. Update RBF Discussions in §5.2 for it now being default
|
||||
|
||||
## Longer-Term TODO (Small Tasks)
|
||||
|
||||
@ -104,6 +102,10 @@ The following updates could be part of v3.0 or could be further future, dependin
|
||||
* 15.2: Using Bitcoin Dev Kit (BDK)
|
||||
* 15.3: Planning for the Future
|
||||
|
||||
As part of this, a new chapter
|
||||
* Put seed words into keytool to create xprv for Bitcoin Core
|
||||
* Convert Xprv from Bitcoin Core into SSKR
|
||||
|
||||
## Lightning Updates
|
||||
|
||||
The Lightning content _may_ be moved to a separate document. That decision would be made before the following potential updates happen.
|
||||
@ -232,6 +234,16 @@ See [release notes](https://bitcoincore.org/en/releases/0.21.0/).
|
||||
|
||||
# Progress Log
|
||||
|
||||
## Immediate TODO (for 2/26): Sending Transactions
|
||||
|
||||
1. <strike>Rewrite transaction fees in §4.1 to talk about vB, et al</strike>
|
||||
2. <strike>Add sendall RPC to §4.1</strike>
|
||||
3. <strike>Add args variable option to §4.3</strike>
|
||||
4. <strike>Add Freezing Coins to §4.4</strike>
|
||||
4. <strike>Check & Revise §4.1-4.5</strike>
|
||||
6. <strike>Remove §4.6 on Segwit</strike>
|
||||
7. <strike>Write New §4.6 on Sending to Different Addresses</strike>
|
||||
|
||||
## Immediate TODO (for 2/19): Segwit
|
||||
|
||||
1. <strike>Reorg of Chapter 3</strike>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user