fully integrated into chapter 4

This commit is contained in:
Shannon Appelcline 2020-06-19 15:18:54 -10:00 committed by GitHub
parent 99a7310350
commit c8356d06f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,14 +1,14 @@
_TODO: THIS NEEDS TO BE REWRITTEN TO REPOSITION THIS INTO THE FLOW OF CHAPTER 4._ # Interlude: Using Curl
# 12.1: Accessing Bitcoind with Curl
> **NOTE:** This is a draft in progress, so that I can get some feedback from early reviewers. It is not yet ready for learning. > **NOTE:** This is a draft in progress, so that I can get some feedback from early reviewers. It is not yet ready for learning.
`bitcoin-cli`, the heart of chapters 3-6, is ultimately just a wrapper. It's a way to interface with `bitcoind` from the command line, providing simplified access to its many RPC commands. But RPC can, of course, be accessed directly. That's what this chapter is about: directly connecting to RPC with the `curl` command. `bitcoin-cli` is ultimately just a wrapper. It's a way to interface with `bitcoind` from the command line, providing simplified access to its many RPC commands. But RPC can, of course, be accessed directly. That's what this interlude is about: directly connecting to RPC with the `curl` command.
It won't be used much in the future chapters, but it's an important building block that you can see as an alternative access to `bitcoind` is you so prefer.
## Know Your Curl ## Know Your Curl
`curl`, short for "see URL", is a command-line tool that allows you to directly access URLs in a programmatic way. It's an easy way to interact with servers like `bitcoind` that listen to ports on the internet and that speak a variety of protocols. Curl is also available as a library for many programming languages, such as C, Java, PHP, and Python. So, once you know how to work with Curl, you'll have a strong foundation for using a lot of different APIs — as we'll touch on in the next few chapters. `curl`, short for "see URL", is a command-line tool that allows you to directly access URLs in a programmatic way. It's an easy way to interact with servers like `bitcoind` that listen to ports on the internet and that speak a variety of protocols. Curl is also available as a library for many programming languages, such as C, Java, PHP, and Python. So, once you know how to work with Curl, you'll have a strong foundation for using a lot of different API.
In order to use `curl` with `bitcoind`, you must know three things: the standard format, the user name and password, and the correct port. In order to use `curl` with `bitcoind`, you must know three things: the standard format, the user name and password, and the correct port.
@ -21,21 +21,20 @@ getmininginfo
Returns a json object containing mining-related information. Returns a json object containing mining-related information.
Result: Result:
{ { (json object)
"blocks": nnn, (numeric) The current block "blocks" : n, (numeric) The current block
"currentblocksize": nnn, (numeric) The last block size "currentblockweight" : n, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)
"currentblockweight": nnn, (numeric) The last block weight "currentblocktx" : n, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)
"currentblocktx": nnn, (numeric) The last block transaction "difficulty" : n, (numeric) The current difficulty
"difficulty": xxx.xxxxx (numeric) The current difficulty "networkhashps" : n, (numeric) The network hashes per second
"errors": "..." (string) Current errors "pooledtx" : n, (numeric) The size of the mempool
"networkhashps": nnn, (numeric) The network hashes per second "chain" : "str", (string) current network name (main, test, regtest)
"pooledtx": n (numeric) The size of the mempool "warnings" : "str" (string) any network and blockchain warnings
"chain": "xxxx", (string) current network name as defined in BIP70 (main, test, regtest)
} }
Examples: Examples:
> bitcoin-cli getmininginfo > 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": "1.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: text/plain;' 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. 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.
@ -49,42 +48,49 @@ In order to speak with the `bitcoind` port, you need a user name and password. T
For example, here's our current setup: For example, here's our current setup:
``` ```
$ more ~/.bitcoin/bitcoin.conf $ cat ~/.bitcoin/bitcoin.conf
server=1 server=1
dbcache=1536 dbcache=1536
par=1 par=1
blocksonly=1
maxuploadtarget=137 maxuploadtarget=137
maxconnections=16 maxconnections=16
rpcuser=bitcoinrpc rpcuser=StandUp
rpcpassword=73bd45ba60ab8f9ff9846b6404769487 rpcpassword=8eaf562eaf45c33c3328bc66008f2dd1
rpcallowip=127.0.0.1 rpcallowip=127.0.0.1
txindex=1 debug=tor
prune=550
testnet=1 testnet=1
mintxfee=0.001
txconfirmtarget=1
[test]
rpcbind=127.0.0.1
rpcport=18332
[main]
rpcbind=127.0.0.1
rpcport=8332
[regtest]
rpcbind=127.0.0.1
rpcport=18443
``` ```
Our user name is `bitcoinrpc` and our password is `73bd45ba60ab8f9ff9846b6404769487`. Our user name is `StandUp` and our password is `8eaf562eaf45c33c3328bc66008f2dd1`.
> **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. 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.
The secure way to RPC with `bitcoind` is as follows: The secure way to RPC with `bitcoind` is as follows:
``` ```
$ curl --user bitcoinrpc --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/ $ curl --user StandUp --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
Enter host password for user 'bitcoinrpc': Enter host password for user 'bitcoinrpc':
``` ```
As noted, you will be prompted for your password. As noted, you will be prompted for your password.
> :link: **TESTNET vs MAINNET:** Testnet uses a URL with port 18332 and mainnet uses a URL with port 8332. Take a look in your `bitcoin.conf`, it's all laid out there.
The insecure way to do so is as follows: The insecure way to do so is as follows:
``` ```
$ curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/ $ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
``` ```
> **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 testnet. If you want to do it anywhere else, make sure you know what you're doing! > **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 testnet. If you want to do it anywhere else, make sure you know what you're doing!
### Know Your Port
The port should be easy, it's the `http://127.0.0.1:8332/` shown in the tutorials, right? Not exactly. It depends on whether you're using testnet or mainnet.
> **MAINNET VS. TESTNET.** To access RPC commands on the mainnet, use port 8332, but to do so on testnet, use port 18332.
### Know Your Command & Parameters ### Know Your Command & Parameters
With all of that in hand, you're ready to send off standard RPC commands with `curl` ... but you still need to know how to incorporate the two elements that tend to change in the `curl` command. With all of that in hand, you're ready to send off standard RPC commands with `curl` ... but you still need to know how to incorporate the two elements that tend to change in the `curl` command.
@ -99,38 +105,33 @@ Here's what some parameter arrays will look like:
* `["000b4430a7a2ba60891b01b718747eaf9665cb93fbc0c619c99419b5b5cf3ad2"]` — An array with data * `["000b4430a7a2ba60891b01b718747eaf9665cb93fbc0c619c99419b5b5cf3ad2"]` — An array with data
* `["'$signedhex'"]` — An array with a variable * `["'$signedhex'"]` — An array with a variable
* `[6, 9999999]` — An array with two parameters * `[6, 9999999]` — An array with two parameters
* `{}` - An empty object
* `[''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.298, "'$changeaddress'": 1.0}'']` — An array with an array containing an object and a bare object * `[''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.298, "'$changeaddress'": 1.0}'']` — An array with an array containing an object and a bare object
## Get Information ## Get Information
You can now send your first `curl` command by accessing the `getmininginfo` RPC: You can now send your first `curl` command by accessing the `getmininginfo` RPC:
``` ```
$ curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ $ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
{"result":{"blocks":1128599,"currentblocksize":0,"currentblockweight":0,"currentblocktx":0,"difficulty":1,"errors":"Warning: unknown new rules activated (versionbit 28)","networkhashps":8658807967387.751,"pooledtx":0,"chain":"test"},"error":null,"id":"curltest"} {"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"}```
```
Note that we provided the method, `getmininginfo`, and the parameter, `[]`, but that everything else was the standard `curl` command line. 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 18332 (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:** 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 18332 (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`: 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 bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.' $ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
% Total % Received % Xferd Average Speed Time Time Time Current
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed Dload Upload Total Spent Left Speed
100 354 100 277 100 77 65546 18220 --:--:-- --:--:-- --:--:-- 92333 100 295 100 218 100 77 72666 25666 --:--:-- --:--:-- --:--:-- 98333
{ {
"result": { "result": {
"blocks": 1128609, "blocks": 1772429,
"currentblocksize": 0, "difficulty": 10178811.40698772,
"currentblockweight": 0, "networkhashps": 90580030969896.44,
"currentblocktx": 0, "pooledtx": 4,
"difficulty": 2777757.750498331, "chain": "test",
"errors": "Warning: unknown new rules activated (versionbit 28)", "warnings": "Warning: unknown new rules activated (versionbit 28)"
"networkhashps": 8795436830406.6,
"pooledtx": 0,
"chain": "test"
}, },
"error": null, "error": null,
"id": "curltest" "id": "curltest"
@ -144,32 +145,35 @@ Though you're accessing `bitcoind` directly, you'll still get access to wallet f
### Look Up Addresses ### Look Up Addresses
Use the `getaddressesbyaccount` RPC to list all of your current addresses: Use the `getaddressesbylabel` RPC to list all of your current addresses:
``` ```
$ curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbylabel", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.' $ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbylabel", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
{
{ "result": {
"result": [ "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE": {
"mg7YqyvK8HUFvpgZ5iYTfZ5vjfaJWnNTd9", "purpose": "receive"
"mkMkhbUzcSPdEHUoRQkBKHe8otP1SzWWeb", },
"moXjRArk4rWUYZvAiDHnMXQHmwyf3TtAb8", "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff": {
"mp3qqSTEYqhm3iuo9nM5GnzCGuoEvb9KrK", "purpose": "receive"
"msW5tzCMJRECSATENN11ATmxx3PLwjGEaW", },
"msZ5bMbZC4HQPRuJCoivDWYExAB7ssE5o8", "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B": {
"mx3wUEVp526gkqzMteK6NwsPffgtFB3CGX", "purpose": "receive"
"mxwLPpo2X1VXXAiLHNVb55H4JASeLMDm7A", },
"n2AfUVXq9MzsJohCjCKNXKj2SYHfdbrcqy", "mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d": {
"n2fGxDXKozkZjpi9DqW93NZ65TnQDqd49V", "purpose": "receive"
"n4cqjJE6fqcmeWpftygwPoKMMDva6BpyHf", },
"2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8", "tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6": {
"2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz", "purpose": "receive"
"2NDx9HTeLagiEqWrYvBuPkG3gwdhQ32Jz4B" },
], "tb1qmtucvjtga68kgrvkl7q05x4t9lylxhku7kqdpr": {
"purpose": "receive"
}
},
"error": null, "error": null,
"id": "curltest" "id": "curltest"
} }
``` ```
This is our first example of a real parameter, `""`. This is the required `account` parameter for `getaddressbyaccount`, but all of our addresses are in the default account, so nothing special was required here. This is our first example of a real parameter, `""`. This is the required `label` parameter for `getaddressesbylabel`, but all of our addresses are under the default label, so nothing special was required here.
The result is a list of all the addresses that have been used by this wallet ... some of which presumably contain funds. The result is a list of all the addresses that have been used by this wallet ... some of which presumably contain funds.
@ -177,64 +181,33 @@ 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: Use the `listunspent` RPC to list the funds that you have available:
``` ```
$ curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.' $ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
{ {
"result": [ "result": [
{ {
"txid": "6a184a2f07fa30189f4831d6f041d52653a103b3883d2bec2f79187331fd7f0e", "txid": "e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d",
"vout": 0, "vout": 1,
"address": "mnsdQUxpGa6UsroUJhJGupPrPcuvQbPzmV", "address": "mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
"scriptPubKey": "76a91450b1d90a130c4f3f1e5fbfa7320fd36b7265db0488ac", "scriptPubKey": "76a91432db726320e4ad170c9c1ee83cd4d8a243c3435988ac",
"amount": 1.2985, "amount": 0.0009,
"confirmations": 1260, "confirmations": 4,
"spendable": true, "spendable": true,
"solvable": true "solvable": true,
"desc": "pkh([d6043800/0'/1'/2']02881697d252d8bf181d08c58de1f02aec088cd2d468fc5fd888c6e39909f7fabf)#p6k7dptk",
"safe": true
}, },
{ {
"txid": "966099e0fd330007eac0394d97a36985980ff971d64b865c5d474f1931eeec3a", "txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0, "vout": 0,
"address": "2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz", "address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"account": "", "label": "",
"scriptPubKey": "a914babf9063cee8ab6e9334f95f6d4e9148d0e551c287", "scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 1.2985, "amount": 0.00022,
"confirmations": 3681, "confirmations": 19,
"spendable": false,
"solvable": false
},
{
"txid": "e31f747cb97a364a1a00b56a3d9d43a97c6e02938a47e599ad54d7cf710f056f",
"vout": 0,
"address": "2NDx9HTeLagiEqWrYvBuPkG3gwdhQ32Jz4B",
"account": "",
"redeemScript": "52210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd81921029bf628adf0698a089137294975c8589cf0cc6be050f92d944faaa8c8a623430352ae",
"scriptPubKey": "a914e31fa4be1f718e068ba5cbb2f12a59bba66a2da687",
"amount": 1.3,
"confirmations": 6515,
"spendable": false,
"solvable": true
},
{
"txid": "88e5d5f3077517d76f5a61491fa52e6aaae078c52bc62d849f09507ef0cfada2",
"vout": 0,
"address": "n4cqjJE6fqcmeWpftygwPoKMMDva6BpyHf",
"account": "",
"scriptPubKey": "76a914fd67e8a7c7813e7a5c376eb71074f373d924d96888ac",
"amount": 0.47,
"confirmations": 38043,
"spendable": true, "spendable": true,
"solvable": true "solvable": true,
}, "desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
{ "safe": true
"txid": "7e8abac5040a14f74fc8c44300c89cf93ce7f59f1e1c1d1711fdddd7012941c1",
"vout": 0,
"address": "moXjRArk4rWUYZvAiDHnMXQHmwyf3TtAb8",
"account": "",
"scriptPubKey": "76a91457e6ac3cfbc9c34c292ca59f105a2d7a819db7a488ac",
"amount": 0.65,
"confirmations": 6586,
"spendable": true,
"solvable": true
} }
], ],
"error": null, "error": null,
@ -247,20 +220,19 @@ This is almost exactly the same output that you receive when you type `bitcoin-c
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:
``` ```
$ curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.' $ 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:18332/ | jq -r '.'
{
{ "result": "mrSqN37TPs89GcidSZTvXmMzjxoJZ6RKoz",
"result": "mznccEt2ozGFN6oVaYU5BGgTzcdH8Zj8wf",
"error": null, "error": null,
"id": "curltest" "id": "curltest"
} }
``` ```
At this point, we can even revert to our standard practice of saving results to variables with additional help from `jq`: At this point, we can even revert to our standard practice of saving results to variables with additional help from `jq`:
``` ```
$ changeaddress=$(curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result') $ 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:18332/ | jq -r '.result')
$ echo $changeaddress $ echo $changeaddress
mmDWRH3CbeXwCqBwdHCj7E9d3oWTuuizxc mqdfnjgWr2r3sCCeuTDfe8fJ1CnycF2e6R
``` ```
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. 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.
@ -274,29 +246,28 @@ Just as with `bitcoin-cli`, in order to create a transaction by curling RPC comm
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 1.2985 BTC in funds listed in the first unspent transaction above:
``` ```
$ utxo_txid=$(curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .[0] | .txid') $ 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:18332/ | jq -r '.result | .[0] | .txid')
$ utxo_vout=$(curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .[0] | .vout') $ 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:18332/ | jq -r '.result | .[0] | .vout')
$ recipient=mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf $ recipient=mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
$ changeaddress=$(curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result') $ 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:18332/ | jq -r '.result')
$ echo $utxo_txid $ echo $utxo_txid
6a184a2f07fa30189f4831d6f041d52653a103b3883d2bec2f79187331fd7f0e e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d
$ echo $utxo_vout $ echo $utxo_vout
0 1
$ echo $recipient $ echo $recipient
mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
$ echo $changeaddress $ echo $changeaddress
mmDWRH3CbeXwCqBwdHCj7E9d3oWTuuizxc n2jf3MzeFpFGa7wq8rXKVnVuv5FoNSJZ1N
``` ```
### Create the Transaction ### Create the Transaction
The transaction created with `curl` is very similar to the transaction created with `bitcoin-cli`, but with a few subtle differences: The transaction created with `curl` is very similar to the transaction created with `bitcoin-cli`, but with a few subtle differences:
``` ```
$ curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.298, "'$changeaddress'": 1.0}'']}' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.' $ 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:18332/ | jq -r '.'
{
{ "result": "02000000010d6acd0356db222ca3a7ee7fa1e3044316223ceec1f64b58aeb2e0de921007e70100000000ffffffff0230750000000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac50c30000000000001976a9147021efec134057043386decfaa6a6aa4ee5f19eb88ac00000000",
"result": "02000000010e7ffd317318792fec2b3d88b303a15326d541f0d631489f1830fa072f4a186a0000000000ffffffff0240b6c601000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac00e1f505000000001976a9143e84156731d67c80c3dff6c1cc3b4f58460e642388ac00000000",
"error": null, "error": null,
"id": "curltest" "id": "curltest"
} }
@ -313,7 +284,7 @@ However, there's one last thing of note in this example, and it can be _maddenin
Having verified that things work, you probably want to save the hex code into a variable: Having verified that things work, you probably want to save the hex code into a variable:
``` ```
$ hexcode=$(curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.298, "'$changeaddress'": 1.0}'']}' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result') $ 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:18332/ | jq -r '.result')
``` ```
### Sign and Send ### Sign and Send
@ -321,17 +292,19 @@ $ hexcode=$(curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binar
Signing and sending your transaction using `curl` is an easy use of the `signrawtransactionwithwallet` and `sendrawtransaction` RPC: Signing and sending your transaction using `curl` is an easy use of the `signrawtransactionwithwallet` and `sendrawtransaction` RPC:
``` ```
$ signedhex=$(curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransactionwithwallet", "params": ["'$hexcode'"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .hex') $ 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:18332/ | jq -r '.result | .hex')
$ curl --user bitcoinrpc:73bd45ba60ab8f9ff9846b6404769487 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["'$signedhex'"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.' $ 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:18332/ | jq -r '.'
{ {
"result": "000b4430a7a2ba60891b01b718747eaf9665cb93fbc0c619c99419b5b5cf3ad2", "result": "eb84c5008038d760805d4d9644ace67849542864220cb2685a1ea2c64176b82d",
"error": null, "error": null,
"id": "curltest" "id": "curltest"
} }
``` ```
## Summary: Accessing Bitcoind with Curl ## 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`. 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.
_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. But for that, you'll need to use a `curl` library within a more familiar language like C. In other words, command-line `curl` was just the first step, the basis to better explain what you're doing as you move forward. 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.