From bec47102e80d8bd20a078d2556a059e8c71beb18 Mon Sep 17 00:00:00 2001 From: Shannon Appelcline Date: Wed, 21 Jun 2017 10:52:28 -0700 Subject: [PATCH] Update 12_3_Programming_Bitcoind_with_C.md --- 12_3_Programming_Bitcoind_with_C.md | 85 ++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/12_3_Programming_Bitcoind_with_C.md b/12_3_Programming_Bitcoind_with_C.md index 4517358..a0fbe07 100644 --- a/12_3_Programming_Bitcoind_with_C.md +++ b/12_3_Programming_Bitcoind_with_C.md @@ -59,7 +59,90 @@ float tx_total = tx_amount + tx_fee; > **WARNING:** A real program would calculate a fee that minimized cost while ensuring the speed was sufficient for the sender. -### X. Prepare Your RPC +### X. Prepare Your RPC + +Obviously, you're going to need to get all of your variables ready again, as discussed in [ยง12.2: Accessing Bitcoind with C](12_2_Accessing_Bitcoind_with_C.md). You also need to initialize your library, connect your RPC client, and prepare your response object: +``` +bitcoinrpc_global_init(); +rpc_client = bitcoinrpc_cl_init_params ("bitcoinrpc", "73bd45ba60ab8f9ff9846b6404769487", "127.0.0.1", 18332); +btcresponse = bitcoinrpc_resp_init(); +``` ### 3. Find a UTXO +To find a UTXO you must call the `listunspent` RPC: +``` +rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_LISTUNSPENT); +bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror); +``` +However, the real work comes in decoding the response. We said that the `jansson` library was "somewhat clunky" and this is why: you have to create (and clear) a very large set of `json_t` objects in order to dig down to what you want. + +First, you must retrieve the `result` field from JSON: +``` +json_t *lu_response = NULL; +json_t *lu_result = NULL; + +lu_response = bitcoinrpc_resp_get (btcresponse); +lu_result = json_object_get(lu_response,"result"); +``` +Then, you go into a loop, examining each unspent transaction, which appears as an element in your JSON result array: +``` +int i; + +const char *tx_id = 0; +int tx_vout = 0; +double tx_amount = 0.0; + +for (i = 0 ; i < json_array_size(lu_result) ; i++) { + + json_t *lu_data = NULL; + lu_data = json_array_get(lu_result, i); + + json_t *lu_amount = NULL; + lu_amount = json_object_get(lu_data,"amount"); + tx_amount = json_real_value(lu_amount); +``` +Is the UTXO large enough to pay out your transaction? If so, grab it! +``` + if (tx_amount > tx_total) { + + json_t *lu_txid = NULL; + lu_txid = json_object_get(lu_data,"txid"); + tx_id = strdup(json_string_value(lu_txid)); + + json_t *lu_vout = NULL; + lu_vout = json_object_get(lu_data,"vout"); + tx_vout = json_integer_value(lu_vout); + + json_decref(lu_amount); + json_decref(lu_txid); + json_decref(lu_vout); + json_decref(lu_data); + break; + + } +``` +Make sure to clean things up as you go through failed loops: +``` + json_decref(lu_amount); + json_decref(lu_data); + +} + +json_decref(lu_result); +json_decref(lu_response); +``` +If you didn't find any large-enough UTXOs, you'll have to report that sad fact to the user ... and perhaps suggest that they should use a better sending program that will correctly merge UTXOs. +``` +if (!tx_id) { + + printf("Very Sad: You don't have any UTXOs larger than %f",tx_total); + exit(-1); +} + +printf("We are using txid %s with vout %i\n",tx_id,tx_vout); +``` + +> **WARNING:** A real program would use subroutines for this sort of lookup, so that you could confidentally call various RPCs from a library of C functions. We're just going to blob it all into `main` as part of our KISS philosophy of simple examples. + +### 4. Create a Change Address