lightningd: pass explicit context for bitcoind request functions.

That way if you free the context, you free the call (i.e. the callback
will not be called).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-06-23 00:41:33 +09:30
parent 492ed84dbf
commit 928b7c83fc
10 changed files with 78 additions and 64 deletions

View File

@ -346,7 +346,8 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,
tal_free(call);
}
void bitcoind_estimate_fees_(struct bitcoind *bitcoind,
void bitcoind_estimate_fees_(const tal_t *ctx,
struct bitcoind *bitcoind,
void (*cb)(struct lightningd *ld,
u32 feerate_floor,
const struct feerate_est *feerates,
@ -354,13 +355,13 @@ void bitcoind_estimate_fees_(struct bitcoind *bitcoind,
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);
@ -508,7 +509,8 @@ 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,
@ -518,7 +520,7 @@ void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind,
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;
@ -529,7 +531,7 @@ void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind,
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);
@ -586,7 +588,8 @@ static void getchaininfo_callback(const char *buf, const jsmntok_t *toks,
tal_free(call);
}
void bitcoind_getchaininfo_(struct bitcoind *bitcoind,
void bitcoind_getchaininfo_(const tal_t *ctx,
struct bitcoind *bitcoind,
const u32 height,
void (*cb)(struct bitcoind *bitcoind,
const char *chain,
@ -597,13 +600,13 @@ void bitcoind_getchaininfo_(struct bitcoind *bitcoind,
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;
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);
@ -639,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:%}}",
@ -654,12 +660,10 @@ 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 *,
@ -667,13 +671,13 @@ void bitcoind_getutxout_(struct bitcoind *bitcoind,
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);
@ -717,8 +721,8 @@ 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);
@ -789,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);
}
}
@ -811,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);
}
}
@ -823,12 +826,18 @@ next:
* 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),
@ -836,7 +845,7 @@ void bitcoind_getfilteredblock_(struct bitcoind *bitcoind, u32 height,
{
/* 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;
@ -848,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);
}

View File

@ -55,8 +55,8 @@ struct bitcoind *new_bitcoind(const tal_t *ctx,
struct lightningd *ld,
struct logger *log);
#define bitcoind_estimate_fees(bitcoind_, cb, arg) \
bitcoind_estimate_fees_((bitcoind_), \
#define bitcoind_estimate_fees(ctx, bitcoind_, cb, arg) \
bitcoind_estimate_fees_((ctx), (bitcoind_), \
typesafe_cb_preargs(void, void *, \
(cb), (arg), \
struct lightningd *, \
@ -64,7 +64,8 @@ struct bitcoind *new_bitcoind(const tal_t *ctx,
const struct feerate_est *), \
(arg))
void bitcoind_estimate_fees_(struct bitcoind *bitcoind,
void bitcoind_estimate_fees_(const tal_t *ctx,
struct bitcoind *bitcoind,
void (*cb)(struct lightningd *ld,
u32 feerate_floor,
const struct feerate_est *feerates,
@ -89,13 +90,14 @@ void bitcoind_sendrawtx_(const tal_t *ctx,
bool, const char *), \
(arg))
void bitcoind_getfilteredblock_(struct bitcoind *bitcoind, u32 height,
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);
#define bitcoind_getfilteredblock(bitcoind_, height, cb, arg) \
bitcoind_getfilteredblock_((bitcoind_), \
#define bitcoind_getfilteredblock(ctx, bitcoind_, height, cb, arg) \
bitcoind_getfilteredblock_((ctx), (bitcoind_), \
(height), \
typesafe_cb_preargs(void, void *, \
(cb), (arg), \
@ -103,7 +105,8 @@ void bitcoind_getfilteredblock_(struct bitcoind *bitcoind, u32 height,
const struct filteredblock *), \
(arg))
void bitcoind_getchaininfo_(struct bitcoind *bitcoind,
void bitcoind_getchaininfo_(const tal_t *ctx,
struct bitcoind *bitcoind,
const u32 height,
void (*cb)(struct bitcoind *bitcoind,
const char *chain,
@ -112,8 +115,8 @@ void bitcoind_getchaininfo_(struct bitcoind *bitcoind,
bool ibd,
void *),
void *cb_arg);
#define bitcoind_getchaininfo(bitcoind_, height_, cb, arg) \
bitcoind_getchaininfo_((bitcoind_), (height_), \
#define bitcoind_getchaininfo(ctx, bitcoind_, height_, cb, arg) \
bitcoind_getchaininfo_((ctx), (bitcoind_), (height_), \
typesafe_cb_preargs(void, void *, \
(cb), (arg), \
struct bitcoind *, \
@ -121,7 +124,8 @@ void bitcoind_getchaininfo_(struct bitcoind *bitcoind,
bool), \
(arg))
void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind,
void bitcoind_getrawblockbyheight_(const tal_t *ctx,
struct bitcoind *bitcoind,
u32 height,
void (*cb)(struct bitcoind *bitcoind,
u32 height,
@ -129,8 +133,8 @@ void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind,
struct bitcoin_block *blk,
void *arg),
void *arg);
#define bitcoind_getrawblockbyheight(bitcoind_, height_, cb, arg) \
bitcoind_getrawblockbyheight_((bitcoind_), (height_), \
#define bitcoind_getrawblockbyheight(ctx, bitcoind_, height_, cb, arg) \
bitcoind_getrawblockbyheight_((ctx), (bitcoind_), (height_), \
typesafe_cb_preargs(void, void *, \
(cb), (arg), \
struct bitcoind *, \
@ -139,22 +143,21 @@ void bitcoind_getrawblockbyheight_(struct bitcoind *bitcoind,
struct bitcoin_block *),\
(arg))
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 *arg);
#define bitcoind_getutxout(bitcoind_, outpoint_, cb, arg) \
bitcoind_getutxout_((bitcoind_), (outpoint_), \
#define bitcoind_getutxout(ctx, bitcoind_, outpoint_, cb, arg) \
bitcoind_getutxout_((ctx), (bitcoind_), (outpoint_), \
typesafe_cb_preargs(void, void *, \
(cb), (arg), \
struct bitcoind *, \
struct bitcoin_tx_output *),\
const struct bitcoin_tx_output *),\
(arg))
void bitcoind_getclientversion(struct bitcoind *bitcoind);
void bitcoind_check_commands(struct bitcoind *bitcoind);
#endif /* LIGHTNING_LIGHTNINGD_BITCOIND_H */

View File

@ -565,7 +565,7 @@ static void start_fee_estimate(struct chain_topology *topo)
{
topo->updatefee_timer = NULL;
/* Based on timer, update fee estimates. */
bitcoind_estimate_fees(topo->bitcoind, update_feerates_repeat, NULL);
bitcoind_estimate_fees(topo, topo->bitcoind, update_feerates_repeat, NULL);
}
struct rate_conversion {
@ -1076,7 +1076,7 @@ static void try_extend_tip(struct chain_topology *topo)
{
topo->extend_timer = NULL;
trace_span_start("extend_tip", topo);
bitcoind_getrawblockbyheight(topo->bitcoind, topo->tip->height + 1,
bitcoind_getrawblockbyheight(topo, topo->bitcoind, topo->tip->height + 1,
get_new_block, topo);
}
@ -1277,7 +1277,7 @@ static void retry_sync_getchaininfo_done(struct bitcoind *bitcoind, const char *
static void retry_sync(struct chain_topology *topo)
{
topo->checkchain_timer = NULL;
bitcoind_getchaininfo(topo->bitcoind, get_block_height(topo),
bitcoind_getchaininfo(topo, topo->bitcoind, get_block_height(topo),
retry_sync_getchaininfo_done, topo);
}
@ -1349,7 +1349,7 @@ static void wait_until_height_reached(struct bitcoind *bitcoind, const char *cha
static void retry_height_reached(struct wait_for_height *wh)
{
bitcoind_getchaininfo(wh->bitcoind, wh->minheight,
bitcoind_getchaininfo(wh, wh->bitcoind, wh->minheight,
wait_until_height_reached, wh);
}
@ -1399,9 +1399,9 @@ void setup_topology(struct chain_topology *topo)
db_commit_transaction(topo->ld->wallet->db);
/* Sanity checks, then topology initialization. */
bitcoind_getchaininfo(topo->bitcoind, blockscan_start,
bitcoind_getchaininfo(chaininfo, topo->bitcoind, blockscan_start,
get_chaininfo_once, chaininfo);
bitcoind_estimate_fees(topo->bitcoind, get_feerates_once, feerates);
bitcoind_estimate_fees(feerates, topo->bitcoind, get_feerates_once, feerates);
/* Each one will break, order doesn't matter */
ret = io_loop_with_timers(topo->ld);
@ -1433,13 +1433,13 @@ void setup_topology(struct chain_topology *topo)
log_broken(topo->ld->log,
"bitcoind has gone backwards from %u to %u blocks, waiting...",
blockscan_start, chaininfo->blockcount);
bitcoind_getchaininfo(topo->bitcoind, blockscan_start,
bitcoind_getchaininfo(wh, topo->bitcoind, blockscan_start,
wait_until_height_reached, wh);
ret = io_loop_with_timers(topo->ld);
assert(ret == wh);
/* Might have been a while, so re-ask for fee estimates */
bitcoind_estimate_fees(topo->bitcoind, get_feerates_once, feerates);
bitcoind_estimate_fees(feerates, topo->bitcoind, get_feerates_once, feerates);
ret = io_loop_with_timers(topo->ld);
assert(ret == topo);
}
@ -1453,7 +1453,7 @@ void setup_topology(struct chain_topology *topo)
update_feerates(topo->ld, feerates->feerate_floor, feerates->rates, NULL);
/* Get the first block, so we can initialize topography. */
bitcoind_getrawblockbyheight(topo->bitcoind, blockscan_start,
bitcoind_getrawblockbyheight(topo, topo->bitcoind, blockscan_start,
get_block_once, &blk);
ret = io_loop_with_timers(topo->ld);
assert(ret == topo);

View File

@ -554,7 +554,7 @@ static void send_splice_tx_done(struct bitcoind *bitcoind UNUSED,
if (!success) {
info->err_msg = tal_strdup(info, msg);
bitcoind_getutxout(ld->topology->bitcoind, &outpoint,
bitcoind_getutxout(info, ld->topology->bitcoind, &outpoint,
check_utxo_block, info);
} else {
handle_tx_broadcast(info);
@ -1980,7 +1980,7 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd,
* the funding transaction isn't broadcast. We can't know if the funding
* is broadcast by external wallet and the transaction hasn't
* been onchain. */
bitcoind_getutxout(cmd->ld->topology->bitcoind,
bitcoind_getutxout(cc, cmd->ld->topology->bitcoind,
&cancel_channel->funding,
process_check_funding_broadcast,
/* Freed by callback */

View File

@ -1724,7 +1724,7 @@ static void sendfunding_done(struct bitcoind *bitcoind UNUSED,
* that the broadcast would fail. Verify that's not
* the case here. */
cs->err_msg = tal_strdup(cs, msg);
bitcoind_getutxout(ld->topology->bitcoind,
bitcoind_getutxout(cs, ld->topology->bitcoind,
&channel->funding,
check_utxo_block,
cs);
@ -2832,7 +2832,7 @@ static void validate_input_unspent(struct bitcoind *bitcoind,
pv->next_index = i + 1;
/* Confirm input is in a block */
bitcoind_getutxout(pv->channel->owner->ld->topology->bitcoind,
bitcoind_getutxout(pv, pv->channel->owner->ld->topology->bitcoind,
&outpoint,
validate_input_unspent,
pv);

View File

@ -114,7 +114,7 @@ static void get_txout(struct subd *gossip, const u8 *msg)
NULL, scid, AMOUNT_SAT(0), NULL)));
} else {
/* Make a pointer of a copy of scid here, for got_filteredblock */
bitcoind_getfilteredblock(topo->bitcoind,
bitcoind_getfilteredblock(topo->bitcoind, topo->bitcoind,
short_channel_id_blocknum(scid),
got_filteredblock,
tal_dup(gossip, struct short_channel_id, &scid));

View File

@ -3431,7 +3431,7 @@ static struct command_result *json_dev_forget_channel(struct command *cmd,
return command_check_done(cmd);
if (!channel_state_uncommitted(forget->channel->state))
bitcoind_getutxout(cmd->ld->topology->bitcoind,
bitcoind_getutxout(cmd, cmd->ld->topology->bitcoind,
&forget->channel->funding,
process_dev_forget_channel, forget);
return command_still_pending(cmd);

View File

@ -17,7 +17,8 @@ struct channel *any_channel_by_scid(struct lightningd *ld UNNEEDED,
void bip32_pubkey(struct lightningd *ld UNNEEDED, struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED)
{ fprintf(stderr, "bip32_pubkey called!\n"); abort(); }
/* Generated stub for bitcoind_getutxout_ */
void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED,
void bitcoind_getutxout_(const tal_t *ctx UNNEEDED,
struct bitcoind *bitcoind UNNEEDED,
const struct bitcoin_outpoint *outpoint UNNEEDED,
void (*cb)(struct bitcoind * UNNEEDED,
const struct bitcoin_tx_output * UNNEEDED,

View File

@ -49,7 +49,8 @@ void add_node_announcement_sig(u8 *nannounce UNNEEDED,
size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED)
{ fprintf(stderr, "bigsize_put called!\n"); abort(); }
/* Generated stub for bitcoind_getutxout_ */
void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED,
void bitcoind_getutxout_(const tal_t *ctx UNNEEDED,
struct bitcoind *bitcoind UNNEEDED,
const struct bitcoin_outpoint *outpoint UNNEEDED,
void (*cb)(struct bitcoind * UNNEEDED,
const struct bitcoin_tx_output * UNNEEDED,

View File

@ -410,9 +410,8 @@ struct txo_rescan {
static void process_utxo_result(struct bitcoind *bitcoind,
const struct bitcoin_tx_output *txout,
void *arg)
struct txo_rescan *rescan)
{
struct txo_rescan *rescan = arg;
struct json_stream *response = rescan->response;
struct utxo *u = rescan->utxos[0];
enum output_status newstate =
@ -436,7 +435,7 @@ static void process_utxo_result(struct bitcoind *bitcoind,
json_array_end(rescan->response);
was_pending(command_success(rescan->cmd, rescan->response));
} else {
bitcoind_getutxout(bitcoind->ld->topology->bitcoind,
bitcoind_getutxout(bitcoind, bitcoind,
&rescan->utxos[0]->outpoint,
process_utxo_result, rescan);
}
@ -462,7 +461,7 @@ static struct command_result *json_dev_rescan_outputs(struct command *cmd,
json_array_end(rescan->response);
return command_success(cmd, rescan->response);
}
bitcoind_getutxout(cmd->ld->topology->bitcoind,
bitcoind_getutxout(rescan, cmd->ld->topology->bitcoind,
&rescan->utxos[0]->outpoint,
process_utxo_result,
rescan);