lightningd: provide callback in broadcast_tx() for refreshing tx.

We'll use this to do RBF.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2023-03-23 16:15:52 +10:30
parent 0b7c2bf519
commit fc54c19716
6 changed files with 73 additions and 31 deletions

View File

@ -155,6 +155,7 @@ static void rebroadcast_txs(struct chain_topology *topo)
struct txs_to_broadcast *txs;
struct outgoing_tx *otx;
struct outgoing_tx_map_iter it;
tal_t *cleanup_ctx = tal(NULL, char);
txs = tal(topo, struct txs_to_broadcast);
txs->cmd_id = tal_arr(txs, const char *, 0);
@ -167,10 +168,18 @@ static void rebroadcast_txs(struct chain_topology *topo)
if (wallet_transaction_height(topo->ld->wallet, &otx->txid))
continue;
/* Don't free from txmap inside loop! */
if (otx->refresh
&& !otx->refresh(otx->channel, &otx->tx, otx->refresh_arg)) {
tal_steal(cleanup_ctx, otx);
continue;
}
tal_arr_expand(&txs->txs, fmt_bitcoin_tx(txs->txs, otx->tx));
tal_arr_expand(&txs->cmd_id,
otx->cmd_id ? tal_strdup(txs, otx->cmd_id) : NULL);
}
tal_free(cleanup_ctx);
/* Let this do the dirty work. */
txs->cursor = (size_t)-1;
@ -220,12 +229,16 @@ static void broadcast_done(struct bitcoind *bitcoind,
}
}
void broadcast_tx(struct chain_topology *topo,
struct channel *channel, const struct bitcoin_tx *tx,
const char *cmd_id, bool allowhighfees,
void (*finished)(struct channel *channel,
bool success,
const char *err))
void broadcast_tx_(struct chain_topology *topo,
struct channel *channel, const struct bitcoin_tx *tx,
const char *cmd_id, bool allowhighfees,
void (*finished)(struct channel *channel,
bool success,
const char *err),
bool (*refresh)(struct channel *channel,
const struct bitcoin_tx **tx,
void *arg),
void *refresh_arg)
{
/* Channel might vanish: topo owns it to start with. */
struct outgoing_tx *otx = tal(topo, struct outgoing_tx);
@ -234,6 +247,10 @@ void broadcast_tx(struct chain_topology *topo,
bitcoin_txid(tx, &otx->txid);
otx->tx = clone_bitcoin_tx(otx, tx);
otx->finished = finished;
otx->refresh = refresh;
otx->refresh_arg = refresh_arg;
if (taken(otx->refresh_arg))
tal_steal(otx, otx->refresh_arg);
if (cmd_id)
otx->cmd_id = tal_strdup(otx, cmd_id);
else

View File

@ -23,6 +23,8 @@ struct outgoing_tx {
struct bitcoin_txid txid;
const char *cmd_id;
void (*finished)(struct channel *channel, bool success, const char *err);
bool (*refresh)(struct channel *, const struct bitcoin_tx **, void *arg);
void *refresh_arg;
};
struct block {
@ -179,14 +181,29 @@ u32 penalty_feerate(struct chain_topology *topo);
* @cmd_id: the JSON command id which triggered this (or NULL).
* @allowhighfees: set to true to override the high-fee checks in the backend.
* @finished: if non-NULL, call that and don't rebroadcast.
* @refresh: if non-NULL, callback before re-broadcasting (can replace tx):
* if returns false, delete.
* @refresh_arg: argument for @refresh
*/
void broadcast_tx(struct chain_topology *topo,
struct channel *channel,
const struct bitcoin_tx *tx TAKES,
const char *cmd_id, bool allowhighfees,
void (*finished)(struct channel *,
bool success,
const char *err));
#define broadcast_tx(topo, channel, tx, cmd_id, allowhighfees, \
finished, refresh, refresh_arg) \
broadcast_tx_((topo), (channel), (tx), (cmd_id), (allowhighfees), \
(finished), \
typesafe_cb_preargs(bool, void *, \
(refresh), (refresh_arg), \
struct channel *, \
const struct bitcoin_tx **), \
(refresh_arg))
void broadcast_tx_(struct chain_topology *topo,
struct channel *channel,
const struct bitcoin_tx *tx TAKES,
const char *cmd_id, bool allowhighfees,
void (*finished)(struct channel *,
bool success,
const char *err),
bool (*refresh)(struct channel *, const struct bitcoin_tx **, void *),
void *refresh_arg TAKES);
struct chain_topology *new_topology(struct lightningd *ld, struct log *log);
void setup_topology(struct chain_topology *topology,

View File

@ -346,7 +346,8 @@ static void handle_onchain_broadcast_tx(struct channel *channel,
* high feerates as protection against the MAD-HTLC attack. */
broadcast_tx(channel->peer->ld->topology, channel,
tx, NULL, is_rbf,
is_rbf ? &handle_onchain_broadcast_rbf_tx_cb : NULL);
is_rbf ? &handle_onchain_broadcast_rbf_tx_cb : NULL,
NULL, NULL);
}
static void handle_onchain_unwatch_tx(struct channel *channel, const u8 *msg)

View File

@ -284,7 +284,8 @@ static void sign_and_send_last(struct lightningd *ld,
/* Keep broadcasting until we say stop (can fail due to dup,
* if they beat us to the broadcast). */
broadcast_tx(ld->topology, channel, last_tx, cmd_id, false, NULL);
broadcast_tx(ld->topology, channel, last_tx, cmd_id, false, NULL,
NULL, NULL);
remove_sig(last_tx);
}

View File

@ -50,14 +50,17 @@ char *bolt11_encode_(const tal_t *ctx UNNEEDED,
void *arg) UNNEEDED,
void *arg UNNEEDED)
{ fprintf(stderr, "bolt11_encode_ called!\n"); abort(); }
/* Generated stub for broadcast_tx */
void broadcast_tx(struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED,
const char *cmd_id UNNEEDED, bool allowhighfees UNNEEDED,
void (*finished)(struct channel * UNNEEDED,
bool success UNNEEDED,
const char *err))
{ fprintf(stderr, "broadcast_tx called!\n"); abort(); }
/* Generated stub for broadcast_tx_ */
void broadcast_tx_(struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED,
const struct bitcoin_tx *tx TAKES UNNEEDED,
const char *cmd_id UNNEEDED, bool allowhighfees UNNEEDED,
void (*finished)(struct channel * UNNEEDED,
bool success UNNEEDED,
const char *err) UNNEEDED,
bool (*refresh)(struct channel * UNNEEDED, const struct bitcoin_tx ** UNNEEDED, void *) UNNEEDED,
void *refresh_arg TAKES UNNEEDED)
{ fprintf(stderr, "broadcast_tx_ called!\n"); abort(); }
/* Generated stub for channel_change_state_reason_str */
const char *channel_change_state_reason_str(enum state_change reason UNNEEDED)
{ fprintf(stderr, "channel_change_state_reason_str called!\n"); abort(); }

View File

@ -68,14 +68,17 @@ bool blinding_next_pubkey(const struct pubkey *pk UNNEEDED,
const struct sha256 *h UNNEEDED,
struct pubkey *next UNNEEDED)
{ fprintf(stderr, "blinding_next_pubkey called!\n"); abort(); }
/* Generated stub for broadcast_tx */
void broadcast_tx(struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED,
const char *cmd_id UNNEEDED, bool allowhighfees UNNEEDED,
void (*finished)(struct channel * UNNEEDED,
bool success UNNEEDED,
const char *err))
{ fprintf(stderr, "broadcast_tx called!\n"); abort(); }
/* Generated stub for broadcast_tx_ */
void broadcast_tx_(struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED,
const struct bitcoin_tx *tx TAKES UNNEEDED,
const char *cmd_id UNNEEDED, bool allowhighfees UNNEEDED,
void (*finished)(struct channel * UNNEEDED,
bool success UNNEEDED,
const char *err) UNNEEDED,
bool (*refresh)(struct channel * UNNEEDED, const struct bitcoin_tx ** UNNEEDED, void *) UNNEEDED,
void *refresh_arg TAKES UNNEEDED)
{ fprintf(stderr, "broadcast_tx_ called!\n"); abort(); }
/* Generated stub for channel_tell_depth */
bool channel_tell_depth(struct lightningd *ld UNNEEDED,
struct channel *channel UNNEEDED,