Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 56 additions & 19 deletions lightningd/bitcoind.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,35 @@ static void bitcoin_plugin_error(struct bitcoind *bitcoind, const char *buf,
toks->end - toks->start, buf + toks->start);
}

/* Check response for error (fatal if found) and return result token (fatal if not found). */
static const jsmntok_t *get_bitcoin_result(struct bitcoind *bitcoind,
const char *buf,
const jsmntok_t *toks,
const char *method)
{
const jsmntok_t *err_tok, *msg_tok, *result_tok;

err_tok = json_get_member(buf, toks, "error");
if (err_tok) {
msg_tok = json_get_member(buf, err_tok, "message");
if (msg_tok)
bitcoin_plugin_error(bitcoind, buf, toks, method,
"%.*s", json_tok_full_len(msg_tok),
json_tok_full(buf, msg_tok));
else
bitcoin_plugin_error(bitcoind, buf, toks, method,
"%.*s", json_tok_full_len(err_tok),
json_tok_full(buf, err_tok));
}

result_tok = json_get_member(buf, toks, "result");
if (!result_tok)
bitcoin_plugin_error(bitcoind, buf, toks, method,
"missing 'result' field");

return result_tok;
}

/* Send a request to the Bitcoin plugin which registered that method,
* if it's still alive. */
static void bitcoin_plugin_send(struct bitcoind *bitcoind,
Expand Down Expand Up @@ -287,11 +316,7 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,
struct feerate_est *feerates;
u32 floor;

resulttok = json_get_member(buf, toks, "result");
if (!resulttok)
bitcoin_plugin_error(call->bitcoind, buf, toks,
"estimatefees",
"bad 'result' field");
resulttok = get_bitcoin_result(call->bitcoind, buf, toks, "estimatefees");

/* Modern style has floor. */
floortok = json_get_member(buf, resulttok, "feerate_floor");
Expand Down Expand Up @@ -386,21 +411,24 @@ static void sendrawtx_callback(const char *buf, const jsmntok_t *toks,
const jsmntok_t *idtok,
struct sendrawtx_call *call)
{
const jsmntok_t *resulttok;
const char *err;
const char *errmsg = NULL;
bool success = false;

err = json_scan(tmpctx, buf, toks, "{result:{success:%}}",
resulttok = get_bitcoin_result(call->bitcoind, buf, toks, "sendrawtransaction");

err = json_scan(tmpctx, buf, resulttok, "{success:%}",
JSON_SCAN(json_to_bool, &success));
if (err) {
bitcoin_plugin_error(call->bitcoind, buf, toks,
bitcoin_plugin_error(call->bitcoind, buf, resulttok,
"sendrawtransaction",
"bad 'result' field: %s", err);
} else if (!success) {
err = json_scan(tmpctx, buf, toks, "{result:{errmsg:%}}",
err = json_scan(tmpctx, buf, resulttok, "{errmsg:%}",
JSON_SCAN_TAL(tmpctx, json_strdup, &errmsg));
if (err)
bitcoin_plugin_error(call->bitcoind, buf, toks,
bitcoin_plugin_error(call->bitcoind, buf, resulttok,
"sendrawtransaction",
"bad 'errmsg' field: %s",
err);
Expand Down Expand Up @@ -465,38 +493,41 @@ getrawblockbyheight_callback(const char *buf, const jsmntok_t *toks,
const jsmntok_t *idtok,
struct getrawblockbyheight_call *call)
{
const jsmntok_t *resulttok;
const char *block_str, *err;
struct bitcoin_blkid blkid;
struct bitcoin_block *blk;
const tal_t *ctx;
trace_span_resume(call);
trace_span_end(call);

resulttok = get_bitcoin_result(call->bitcoind, buf, toks, "getrawblockbyheight");

/* Callback may free parent of call, so steal onto context to
* free if it doesn't */
ctx = tal(NULL, char);
tal_steal(ctx, call);

/* If block hash is `null`, this means not found! Call the callback
* with NULL values. */
err = json_scan(tmpctx, buf, toks, "{result:{blockhash:null}}");
err = json_scan(tmpctx, buf, resulttok, "{blockhash:null}");
if (!err) {
call->cb(call->bitcoind, call->height, NULL, NULL, call->cb_arg);
goto clean;
}

err = json_scan(tmpctx, buf, toks, "{result:{blockhash:%,block:%}}",
err = json_scan(tmpctx, buf, resulttok, "{blockhash:%,block:%}",
JSON_SCAN(json_to_sha256, &blkid.shad.sha),
JSON_SCAN_TAL(tmpctx, json_strdup, &block_str));
if (err)
bitcoin_plugin_error(call->bitcoind, buf, toks,
bitcoin_plugin_error(call->bitcoind, buf, resulttok,
"getrawblockbyheight",
"bad 'result' field: %s", err);

blk = bitcoin_block_from_hex(tmpctx, chainparams, block_str,
strlen(block_str));
if (!blk)
bitcoin_plugin_error(call->bitcoind, buf, toks,
bitcoin_plugin_error(call->bitcoind, buf, resulttok,
"getrawblockbyheight",
"bad block");

Expand Down Expand Up @@ -565,18 +596,21 @@ static void getchaininfo_callback(const char *buf, const jsmntok_t *toks,
const jsmntok_t *idtok,
struct getchaininfo_call *call)
{
const jsmntok_t *resulttok;
const char *err, *chain;
u32 headers, blocks;
bool ibd;

err = json_scan(tmpctx, buf, toks,
"{result:{chain:%,headercount:%,blockcount:%,ibd:%}}",
resulttok = get_bitcoin_result(call->bitcoind, buf, toks, "getchaininfo");

err = json_scan(tmpctx, buf, resulttok,
"{chain:%,headercount:%,blockcount:%,ibd:%}",
JSON_SCAN_TAL(tmpctx, json_strdup, &chain),
JSON_SCAN(json_to_number, &headers),
JSON_SCAN(json_to_number, &blocks),
JSON_SCAN(json_to_bool, &ibd));
if (err)
bitcoin_plugin_error(call->bitcoind, buf, toks, "getchaininfo",
bitcoin_plugin_error(call->bitcoind, buf, resulttok, "getchaininfo",
"bad 'result' field: %s", err);

call->cb(call->bitcoind, chain, headers, blocks, ibd,
Expand Down Expand Up @@ -636,24 +670,27 @@ static void getutxout_callback(const char *buf, const jsmntok_t *toks,
const jsmntok_t *idtok,
struct getutxout_call *call)
{
const jsmntok_t *resulttok;
const char *err;
struct bitcoin_tx_output txout;

/* Whatever happens, we want to free this. */
tal_steal(tmpctx, call);

err = json_scan(tmpctx, buf, toks, "{result:{script:null}}");
resulttok = get_bitcoin_result(call->bitcoind, buf, toks, "getutxout");

err = json_scan(tmpctx, buf, resulttok, "{script:null}");
if (!err) {
call->cb(call->bitcoind, NULL, call->cb_arg);
return;
}

err = json_scan(tmpctx, buf, toks, "{result:{script:%,amount:%}}",
err = json_scan(tmpctx, buf, resulttok, "{script:%,amount:%}",
JSON_SCAN_TAL(tmpctx, json_tok_bin_from_hex,
&txout.script),
JSON_SCAN(json_to_sat, &txout.amount));
if (err)
bitcoin_plugin_error(call->bitcoind, buf, toks, "getutxout",
bitcoin_plugin_error(call->bitcoind, buf, resulttok, "getutxout",
"bad 'result' field: %s", err);

call->cb(call->bitcoind, &txout, call->cb_arg);
Expand Down
Loading
Loading