Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wait for bitcoind if it's gone backwards, don't abort. #7342

Merged
Merged
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
91 changes: 52 additions & 39 deletions lightningd/bitcoind.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ static void bitcoin_plugin_send(struct bitcoind *bitcoind,
struct estimatefee_call {
struct bitcoind *bitcoind;
void (*cb)(struct lightningd *ld, u32 feerate_floor,
const struct feerate_est *rates);
const struct feerate_est *rates, void *);
void *cb_arg;
};

/* Note: returns estimates in perkb, caller converts! */
Expand Down Expand Up @@ -341,22 +342,26 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,
feerates[i].rate = floor;
}

call->cb(call->bitcoind->ld, floor, feerates);
call->cb(call->bitcoind->ld, floor, feerates, call->cb_arg);
tal_free(call);
}

void bitcoind_estimate_fees(struct bitcoind *bitcoind,
void (*cb)(struct lightningd *ld,
u32 feerate_floor,
const struct feerate_est *feerates))
void bitcoind_estimate_fees_(const tal_t *ctx,
struct bitcoind *bitcoind,
void (*cb)(struct lightningd *ld,
u32 feerate_floor,
const struct feerate_est *feerates,
void *arg),
void *cb_arg)
{
struct jsonrpc_request *req;
struct estimatefee_call *call = tal(bitcoind, struct estimatefee_call);
struct estimatefee_call *call = tal(ctx, struct estimatefee_call);

call->bitcoind = bitcoind;
call->cb = cb;
call->cb_arg = cb_arg;

req = jsonrpc_request_start(bitcoind, "estimatefees", NULL, true,
req = jsonrpc_request_start(call, "estimatefees", NULL, true,
bitcoind->log,
NULL, estimatefees_callback, call);
jsonrpc_request_end(req);
Expand Down Expand Up @@ -455,7 +460,9 @@ void bitcoind_sendrawtx_(const tal_t *ctx,

struct getrawblockbyheight_call {
struct bitcoind *bitcoind;
u32 height;
void (*cb)(struct bitcoind *bitcoind,
u32 height,
struct bitcoin_blkid *blkid,
struct bitcoin_block *block,
void *);
Expand All @@ -477,7 +484,7 @@ getrawblockbyheight_callback(const char *buf, const jsmntok_t *toks,
* with NULL values. */
err = json_scan(tmpctx, buf, toks, "{result:{blockhash:null}}");
if (!err) {
call->cb(call->bitcoind, NULL, NULL, call->cb_arg);
call->cb(call->bitcoind, call->height, NULL, NULL, call->cb_arg);
goto clean;
}

Expand All @@ -496,32 +503,35 @@ getrawblockbyheight_callback(const char *buf, const jsmntok_t *toks,
"getrawblockbyheight",
"bad block");

call->cb(call->bitcoind, &blkid, blk, call->cb_arg);
call->cb(call->bitcoind, call->height, &blkid, blk, call->cb_arg);

clean:
tal_free(call);
}

void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind,
void bitcoind_getrawblockbyheight_(const tal_t *ctx,
struct bitcoind *bitcoind,
u32 height,
void (*cb)(struct bitcoind *bitcoind,
u32 blockheight,
struct bitcoin_blkid *blkid,
struct bitcoin_block *blk,
void *arg),
void *cb_arg)
{
struct jsonrpc_request *req;
struct getrawblockbyheight_call *call = tal(NULL,
struct getrawblockbyheight_call *call = tal(ctx,
struct getrawblockbyheight_call);

call->bitcoind = bitcoind;
call->cb = cb;
call->cb_arg = cb_arg;
call->height = height;

trace_span_start("plugin/bitcoind", call);
trace_span_tag(call, "method", "getrawblockbyheight");
trace_span_suspend(call);
req = jsonrpc_request_start(bitcoind, "getrawblockbyheight", NULL, true,
req = jsonrpc_request_start(call, "getrawblockbyheight", NULL, true,
bitcoind->log,
NULL, getrawblockbyheight_callback,
call);
Expand All @@ -545,14 +555,11 @@ void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind,

struct getchaininfo_call {
struct bitcoind *bitcoind;
/* Should we log verbosely? */
bool first_call;
void (*cb)(struct bitcoind *bitcoind,
const char *chain,
u32 headercount,
u32 blockcount,
const bool ibd,
const bool first_call,
void *);
void *cb_arg;
};
Expand All @@ -576,32 +583,30 @@ static void getchaininfo_callback(const char *buf, const jsmntok_t *toks,
"bad 'result' field: %s", err);

call->cb(call->bitcoind, chain, headers, blocks, ibd,
call->first_call, call->cb_arg);
call->cb_arg);

tal_free(call);
}

void bitcoind_getchaininfo_(struct bitcoind *bitcoind,
const bool first_call,
void bitcoind_getchaininfo_(const tal_t *ctx,
struct bitcoind *bitcoind,
const u32 height,
void (*cb)(struct bitcoind *bitcoind,
const char *chain,
u32 headercount,
u32 blockcount,
const bool ibd,
const bool first_call,
void *),
void *cb_arg)
{
struct jsonrpc_request *req;
struct getchaininfo_call *call = tal(bitcoind, struct getchaininfo_call);
struct getchaininfo_call *call = tal(ctx, struct getchaininfo_call);

call->bitcoind = bitcoind;
call->cb = cb;
call->cb_arg = cb_arg;
call->first_call = first_call;

req = jsonrpc_request_start(bitcoind, "getchaininfo", NULL, true,
req = jsonrpc_request_start(call, "getchaininfo", NULL, true,
bitcoind->log,
NULL, getchaininfo_callback, call);
json_add_u32(req->stream, "last_height", height);
Expand Down Expand Up @@ -637,10 +642,13 @@ static void getutxout_callback(const char *buf, const jsmntok_t *toks,
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}}");
if (!err) {
call->cb(call->bitcoind, NULL, call->cb_arg);
goto clean;
return;
}

err = json_scan(tmpctx, buf, toks, "{result:{script:%,amount:%}}",
Expand All @@ -652,26 +660,24 @@ static void getutxout_callback(const char *buf, const jsmntok_t *toks,
"bad 'result' field: %s", err);

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

clean:
tal_free(call);
}

void bitcoind_getutxout_(struct bitcoind *bitcoind,
void bitcoind_getutxout_(const tal_t *ctx,
struct bitcoind *bitcoind,
const struct bitcoin_outpoint *outpoint,
void (*cb)(struct bitcoind *,
const struct bitcoin_tx_output *,
void *),
void *cb_arg)
{
struct jsonrpc_request *req;
struct getutxout_call *call = tal(bitcoind, struct getutxout_call);
struct getutxout_call *call = tal(ctx, struct getutxout_call);

call->bitcoind = bitcoind;
call->cb = cb;
call->cb_arg = cb_arg;

req = jsonrpc_request_start(bitcoind, "getutxout", NULL, true,
req = jsonrpc_request_start(call, "getutxout", NULL, true,
bitcoind->log,
NULL, getutxout_callback, call);
json_add_txid(req->stream, "txid", &outpoint->txid);
Expand Down Expand Up @@ -715,15 +721,16 @@ process_getfilteredblock_step2(struct bitcoind *bitcoind,
call->current_outpoint++;
if (call->current_outpoint < tal_count(call->outpoints)) {
o = call->outpoints[call->current_outpoint];
bitcoind_getutxout(bitcoind, &o->outpoint,
process_getfilteredblock_step2, call);
bitcoind_getutxout(call, bitcoind, &o->outpoint,
process_getfilteredblock_step2, call);
} else {
/* If there were no more outpoints to check, we call the callback. */
process_getfiltered_block_final(bitcoind, call);
}
}

static void process_getfilteredblock_step1(struct bitcoind *bitcoind,
u32 height,
struct bitcoin_blkid *blkid,
struct bitcoin_block *block,
struct filteredblock_call *call)
Expand Down Expand Up @@ -786,8 +793,8 @@ static void process_getfilteredblock_step1(struct bitcoind *bitcoind,
* store the one's that are unspent in
* call->result->outpoints. */
o = call->outpoints[call->current_outpoint];
bitcoind_getutxout(bitcoind, &o->outpoint,
process_getfilteredblock_step2, call);
bitcoind_getutxout(call, bitcoind, &o->outpoint,
process_getfilteredblock_step2, call);
}
}

Expand All @@ -808,7 +815,6 @@ process_getfiltered_block_final(struct bitcoind *bitcoind,
list_for_each_safe(&bitcoind->pending_getfilteredblock, c, next, list) {
if (c->height == height) {
c->cb(bitcoind, fb, c->arg);
list_del(&c->list);
tal_free(c);
}
}
Expand All @@ -820,20 +826,26 @@ process_getfiltered_block_final(struct bitcoind *bitcoind,
* pop here. */
if (!list_empty(&bitcoind->pending_getfilteredblock)) {
c = list_top(&bitcoind->pending_getfilteredblock, struct filteredblock_call, list);
bitcoind_getrawblockbyheight(bitcoind, c->height,
bitcoind_getrawblockbyheight(bitcoind, bitcoind, c->height,
process_getfilteredblock_step1, c);
}
}

void bitcoind_getfilteredblock_(struct bitcoind *bitcoind, u32 height,
static void destroy_filteredblock_call(struct filteredblock_call *call)
{
list_del(&call->list);
}

void bitcoind_getfilteredblock_(const tal_t *ctx,
struct bitcoind *bitcoind, u32 height,
void (*cb)(struct bitcoind *bitcoind,
const struct filteredblock *fb,
void *arg),
void *arg)
{
/* Stash the call context for when we need to call the callback after
* all the bitcoind calls we need to perform. */
struct filteredblock_call *call = tal(bitcoind, struct filteredblock_call);
struct filteredblock_call *call = tal(ctx, struct filteredblock_call);
/* If this is the first request, we should start processing it. */
bool start = list_empty(&bitcoind->pending_getfilteredblock);
call->cb = cb;
Expand All @@ -845,8 +857,9 @@ void bitcoind_getfilteredblock_(struct bitcoind *bitcoind, u32 height,
call->current_outpoint = 0;

list_add_tail(&bitcoind->pending_getfilteredblock, &call->list);
tal_add_destructor(call, destroy_filteredblock_call);
if (start)
bitcoind_getrawblockbyheight(bitcoind, height,
bitcoind_getrawblockbyheight(call, bitcoind, height,
process_getfilteredblock_step1, call);
}

Expand Down
Loading