lightningd: save funding PSBT to database if we're to withhold it.

Normally we don't care, but if we're withholding it, keep it around
so we can sign & broadcast later.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2025-11-18 14:42:04 +10:30
parent df5f38dbc1
commit ff433a17a8
11 changed files with 44 additions and 13 deletions

View file

@ -436,6 +436,7 @@ struct channel *new_unsaved_channel(struct peer *peer,
channel->channel_gossip = NULL;
channel->forgets = tal_arr(channel, struct command *, 0);
channel->funding_psbt = NULL;
channel->withheld = false;
list_add_tail(&peer->channels, &channel->list);
channel->rr_number = peer->ld->rr_counter++;
tal_add_destructor(channel, destroy_channel);
@ -558,7 +559,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
u64 last_stable_connection,
const struct channel_stats *stats,
struct channel_state_change **state_changes STEALS,
const struct wally_psbt *funding_psbt STEALS)
const struct wally_psbt *funding_psbt STEALS,
bool withheld)
{
struct channel *channel = tal(peer->ld, struct channel);
struct amount_msat htlc_min, htlc_max;
@ -735,6 +737,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
&channel->cid,
"We can't be together anymore.");
channel->funding_psbt = tal_steal(channel, funding_psbt);
channel->withheld = withheld;
return channel;
}

View file

@ -359,6 +359,9 @@ struct channel {
/* Unsigned PSBT if we initiated the open channel */
const struct wally_psbt *funding_psbt;
/* Are we not broadcasting the open tx? */
bool withheld;
};
/* Is channel owned (and should be talking to peer) */
@ -445,7 +448,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
u64 last_stable_connection,
const struct channel_stats *stats,
struct channel_state_change **state_changes STEALS,
const struct wally_psbt *funding_psbt STEALS);
const struct wally_psbt *funding_psbt STEALS,
bool withheld);
/* new_inflight - Create a new channel_inflight for a channel */
struct channel_inflight *new_inflight(struct channel *channel,

View file

@ -31,6 +31,7 @@ struct closed_channel {
/* NULL for older closed channels */
const struct shachain *their_shachain;
const struct wally_psbt *funding_psbt;
bool withheld;
};
static inline const struct channel_id *keyof_closed_channel(const struct closed_channel *cc)

View file

@ -104,6 +104,9 @@ struct funding_channel {
/* Were we the one to publish the commitment/splicing tx? */
const struct wally_psbt *funding_psbt;
/* Were we told to withhold the commitment tx? */
bool withheld;
};
struct uncommitted_channel *new_uncommitted_channel(struct peer *peer);

View file

@ -97,7 +97,8 @@ wallet_commit_channel(struct lightningd *ld,
const u8 *our_upfront_shutdown_script,
const u8 *remote_upfront_shutdown_script,
const struct channel_type *type,
const struct wally_psbt *funding_psbt)
const struct wally_psbt *funding_psbt,
bool withheld)
{
struct channel *channel;
struct amount_msat our_msat;
@ -237,7 +238,8 @@ wallet_commit_channel(struct lightningd *ld,
0,
&zero_channel_stats,
tal_arr(NULL, struct channel_state_change *, 0),
funding_psbt);
funding_psbt,
withheld);
/* Now we finally put it in the database. */
wallet_channel_insert(ld->wallet, channel);
@ -446,7 +448,8 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
fc->our_upfront_shutdown_script,
remote_upfront_shutdown_script,
type,
fc->funding_psbt);
fc->funding_psbt,
fc->withheld);
if (!channel) {
was_pending(command_fail(fc->cmd, LIGHTNINGD,
"Key generation failure"));
@ -550,7 +553,8 @@ static void opening_fundee_finished(struct subd *openingd,
local_upfront_shutdown_script,
remote_upfront_shutdown_script,
type,
NULL);
NULL,
false);
if (!channel) {
uncommitted_channel_disconnect(uc, LOG_BROKEN,
"Commit channel failed");
@ -1096,6 +1100,9 @@ static struct command_result *json_fundchannel_complete(struct command *cmd,
fc->funding_psbt = tal_steal(fc, funding_psbt);
/* FIXME: Set by option */
fc->withheld = false;
/* Set the cmd to this new cmd */
peer->uncommitted_channel->fc->cmd = cmd;
msg = towire_openingd_funder_complete(NULL,
@ -1644,7 +1651,8 @@ static struct channel *stub_chan(struct command *cmd,
0,
&zero_channel_stats,
tal_arr(NULL, struct channel_state_change *, 0),
NULL);
NULL,
false);
/* We don't want to gossip about this, ever. */
channel->channel_gossip = tal_free(channel->channel_gossip);

View file

@ -1101,6 +1101,7 @@ static struct migration dbmigrations[] = {
" PRIMARY KEY (id)"
")"), NULL},
{NULL, migrate_fail_pending_payments_without_htlcs},
{SQL("ALTER TABLE channels ADD withheld INTEGER DEFAULT 0;"), NULL},
};
/**

View file

@ -235,7 +235,8 @@ struct channel *new_channel(struct peer *peer UNNEEDED, u64 dbid UNNEEDED,
u64 last_stable_connection UNNEEDED,
const struct channel_stats *stats UNNEEDED,
struct channel_state_change **state_changes STEALS UNNEEDED,
const struct wally_psbt *funding_psbt STEALS UNNEEDED)
const struct wally_psbt *funding_psbt STEALS UNNEEDED,
bool withheld UNNEEDED)
{ fprintf(stderr, "new_channel called!\n"); abort(); }
/* Generated stub for new_channel_state_change */
struct channel_state_change *new_channel_state_change(const tal_t *ctx UNNEEDED,

View file

@ -243,7 +243,8 @@ struct channel *new_channel(struct peer *peer UNNEEDED, u64 dbid UNNEEDED,
u64 last_stable_connection UNNEEDED,
const struct channel_stats *stats UNNEEDED,
struct channel_state_change **state_changes STEALS UNNEEDED,
const struct wally_psbt *funding_psbt STEALS UNNEEDED)
const struct wally_psbt *funding_psbt STEALS UNNEEDED,
bool withheld UNNEEDED)
{ fprintf(stderr, "new_channel called!\n"); abort(); }
/* Generated stub for new_channel_state_change */
struct channel_state_change *new_channel_state_change(const tal_t *ctx UNNEEDED,

View file

@ -250,7 +250,8 @@ struct channel *new_channel(struct peer *peer UNNEEDED, u64 dbid UNNEEDED,
u64 last_stable_connection UNNEEDED,
const struct channel_stats *stats UNNEEDED,
struct channel_state_change **state_changes STEALS UNNEEDED,
const struct wally_psbt *funding_psbt STEALS UNNEEDED)
const struct wally_psbt *funding_psbt STEALS UNNEEDED,
bool withheld UNNEEDED)
{ fprintf(stderr, "new_channel called!\n"); abort(); }
/* Generated stub for new_channel_state_change */
struct channel_state_change *new_channel_state_change(const tal_t *ctx UNNEEDED,

View file

@ -1625,7 +1625,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx)
0,
stats,
tal_arr(NULL, struct channel_state_change *, 0),
NULL);
NULL,
false);
db_begin_transaction(w->db);
CHECK(!wallet_err);
wallet_channel_insert(w, chan);

View file

@ -2184,7 +2184,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm
db_col_u64(stmt, "last_stable_connection"),
&stats,
state_changes,
funding_psbt);
funding_psbt,
db_col_int(stmt, "withheld"));
if (!wallet_channel_load_inflights(w, chan)) {
tal_free(chan);
@ -2242,6 +2243,7 @@ static struct closed_channel *wallet_stmt2closed_channel(const tal_t *ctx,
cc->funding_psbt = db_col_psbt(cc, stmt, "funding_psbt");
else
cc->funding_psbt = NULL;
cc->withheld = db_col_int(stmt, "withheld");
return cc;
}
@ -2278,6 +2280,7 @@ void wallet_load_closed_channels(struct wallet *w,
", last_stable_connection"
", shachain_remote_id"
", funding_psbt"
", withheld"
" FROM channels"
" LEFT JOIN peers p ON p.id = peer_id"
" WHERE state = ?;"));
@ -2324,6 +2327,7 @@ void wallet_load_one_closed_channel(struct wallet *w,
", last_stable_connection"
", shachain_remote_id"
", funding_psbt"
", withheld"
" FROM channels"
" LEFT JOIN peers p ON p.id = peer_id"
" WHERE channels.id = ?;"));
@ -2444,6 +2448,7 @@ static bool wallet_channels_load_active(struct wallet *w)
", out_msatoshi_fulfilled"
", close_attempt_height"
", funding_psbt"
", withheld"
" FROM channels"
" WHERE state != ?;")); //? 0
db_bind_int(stmt, CLOSED);
@ -2696,7 +2701,8 @@ void wallet_channel_save(struct wallet *w, struct channel *chan)
" last_stable_connection=?,"
" require_confirm_inputs_remote=?,"
" close_attempt_height=?,"
" funding_psbt=?"
" funding_psbt=?,"
" withheld=?"
" WHERE id=?"));
db_bind_u64(stmt, chan->their_shachain.id);
if (chan->scid)
@ -2798,6 +2804,7 @@ void wallet_channel_save(struct wallet *w, struct channel *chan)
db_bind_psbt(stmt, chan->funding_psbt);
else
db_bind_null(stmt);
db_bind_int(stmt, chan->withheld);
db_bind_u64(stmt, chan->dbid);
db_exec_prepared_v2(take(stmt));