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

Splice: Interop Final (probably) with Eclair #8021

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
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
213 changes: 149 additions & 64 deletions channeld/channeld.c

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ msgtype,channeld_update_inflight,7219
msgdata,channeld_update_inflight,psbt,wally_psbt,
msgdata,channeld_update_inflight,last_tx,?bitcoin_tx,
msgdata,channeld_update_inflight,last_sig,?bitcoin_signature,
msgdata,channeld_update_inflight,is_locked,bool,

# channeld->master: A funding error has occured
msgtype,channeld_splice_funding_error,7220
Expand Down
2 changes: 2 additions & 0 deletions channeld/inflight.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t *
}
inflight->i_am_initiator = fromwire_bool(cursor, max);
inflight->force_sign_first = fromwire_bool(cursor, max);
inflight->is_locked = fromwire_bool(cursor, max);

return inflight;
}
Expand All @@ -44,4 +45,5 @@ void towire_inflight(u8 **pptr, const struct inflight *inflight)
}
towire_bool(pptr, inflight->i_am_initiator);
towire_bool(pptr, inflight->force_sign_first);
towire_bool(pptr, inflight->is_locked);
}
1 change: 1 addition & 0 deletions channeld/inflight.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <common/amount.h>

struct inflight {
/* The new channel outpoint */
struct bitcoin_outpoint outpoint;
struct pubkey remote_funding;
struct amount_sat amnt;
Expand Down
1 change: 1 addition & 0 deletions channeld/splice.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct splice_state *splice_state_new(const tal_t *ctx)
splice_state->locked_ready[REMOTE] = false;
splice_state->await_commitment_succcess = false;
splice_state->inflights = NULL;
splice_state->remote_locked_txid = NULL;

return splice_state;
}
Expand Down
2 changes: 2 additions & 0 deletions channeld/splice.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ struct splice_state {
bool await_commitment_succcess;
/* The txid of which splice inflight was confirmed */
struct bitcoin_txid locked_txid;
/* The txid our peer locked their splice on */
struct bitcoin_txid *remote_locked_txid;
/* The number of splices that are active (awaiting confirmation) */
u32 count;
};
Expand Down
23 changes: 17 additions & 6 deletions common/interactivetx.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,19 +227,35 @@ static char *send_next(const tal_t *ctx,

/* If this the shared channel input, we send funding txid in
* in tlvs and do not send prevtx */
if (ictx->shared_outpoint) {
status_debug("ictx->shared_outpoint=%s",
fmt_bitcoin_outpoint(tmpctx,
ictx->shared_outpoint));
}
else {
status_debug("ictx->shared_outpoint = NULL");
}
status_debug("point=%s", fmt_bitcoin_outpoint(tmpctx, &point));

if (ictx->shared_outpoint
&& bitcoin_outpoint_eq(&point, ictx->shared_outpoint)) {
struct tlv_tx_add_input_tlvs *tlvs = tal(tmpctx, struct tlv_tx_add_input_tlvs);
struct tlv_tx_add_input_tlvs *tlvs = tlv_tx_add_input_tlvs_new(tmpctx);
tlvs->shared_input_txid = tal_dup(tlvs,
struct bitcoin_txid,
&point.txid);
status_debug("Adding shared input %s",
tal_hexstr(ctx, &serial_id,
sizeof(serial_id)));
msg = towire_tx_add_input(NULL, cid, serial_id,
NULL, in->input.index,
in->input.sequence, tlvs);
} else {
msg = towire_tx_add_input(NULL, cid, serial_id,
prevtx, in->input.index,
in->input.sequence, NULL);
status_debug("Adding splice input %s",
tal_hexstr(ctx, &serial_id,
sizeof(serial_id)));
}

tal_arr_remove(&set->added_ins, 0);
Expand Down Expand Up @@ -392,9 +408,6 @@ char *process_interactivetx_updates(const tal_t *ctx,
* Otherwise we advance `current_psbt` to `next_psbt` and begin
* processing the change set in `ictx->change_set` */
if (ictx->current_psbt != next_psbt) {
/* psbt_get_changeset requires we keep the current_psbt until
* we're done withh change_set */
tal_steal(ictx->change_set, ictx->current_psbt);
ictx->current_psbt = next_psbt;
}

Expand Down Expand Up @@ -784,7 +797,5 @@ char *process_interactivetx_updates(const tal_t *ctx,
/* Sort psbt! */
psbt_sort_by_serial_id(ictx->current_psbt);

tal_steal(ictx, ictx->current_psbt);

return NULL;
}
1 change: 1 addition & 0 deletions lightningd/channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ new_inflight(struct channel *channel,

inflight->i_am_initiator = i_am_initiator;
inflight->force_sign_first = force_sign_first;
inflight->is_locked = false;
inflight->splice_locked_memonly = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be great to add this to wallet/tests/run-wallet.c for the inflights

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added


list_add_tail(&channel->inflights, &inflight->list);
Expand Down
5 changes: 5 additions & 0 deletions lightningd/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ struct channel_inflight {
/* On reestablish recovery; should I sign first? */
bool force_sign_first;

/* Has this inflight reached sufficent depth on chain? This is needed
* for splices that need to coordinate `splice_locked` with their
* peer through reconnect flows. */
bool is_locked;

/* Note: This field is not stored in the database.
*
* After splice_locked, we need a way to stop the chain watchers from
Expand Down
43 changes: 42 additions & 1 deletion lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ struct splice_command {
struct channel_id **channel_ids;
/* For multi-channel stfu command: the pending result */
struct stfu_result **results;
/* The user provided PSBT's version */
u32 user_psbt_ver;
};

void channel_update_feerates(struct lightningd *ld, const struct channel *channel)
Expand Down Expand Up @@ -409,6 +411,13 @@ static void handle_splice_confirmed_init(struct lightningd *ld,
return;
}

if (psbt->version != cc->user_psbt_ver
&& !psbt_set_version(psbt, cc->user_psbt_ver))
channel_internal_error(channel, "Splice failed to convert from"
" internal version "PRIu32" to user"
" version "PRIu32, psbt->version,
cc->user_psbt_ver);

struct json_stream *response = json_stream_success(cc->cmd);
json_add_string(response, "psbt", fmt_wally_psbt(tmpctx, psbt));

Expand Down Expand Up @@ -443,6 +452,13 @@ static void handle_splice_confirmed_update(struct lightningd *ld,
return;
}

if (psbt->version != cc->user_psbt_ver
&& !psbt_set_version(psbt, cc->user_psbt_ver))
channel_internal_error(channel, "Splice failed to convert from"
" internal version "PRIu32" to user"
" version "PRIu32, psbt->version,
cc->user_psbt_ver);

struct json_stream *response = json_stream_success(cc->cmd);
json_add_string(response, "psbt", fmt_wally_psbt(tmpctx, psbt));
json_add_bool(response, "commitments_secured", commitments_secured);
Expand Down Expand Up @@ -886,9 +902,10 @@ static void handle_update_inflight(struct lightningd *ld,
struct bitcoin_txid txid;
struct bitcoin_tx *last_tx;
struct bitcoin_signature *last_sig;
bool is_locked;

if (!fromwire_channeld_update_inflight(tmpctx, msg, &psbt, &last_tx,
&last_sig)) {
&last_sig, &is_locked)) {
channel_internal_error(channel,
"bad channel_add_inflight %s",
tal_hex(channel, msg));
Expand Down Expand Up @@ -916,6 +933,8 @@ static void handle_update_inflight(struct lightningd *ld,
if (last_sig)
inflight->last_sig = *last_sig;

inflight->is_locked = is_locked;

tal_wally_start();
if (wally_psbt_combine(inflight->funding_psbt, psbt) != WALLY_OK) {
channel_internal_error(channel,
Expand Down Expand Up @@ -1812,6 +1831,7 @@ bool peer_start_channeld(struct channel *channel,
infcopy->last_sig = inflight->last_sig;
infcopy->i_am_initiator = inflight->i_am_initiator;
infcopy->force_sign_first = inflight->force_sign_first;
infcopy->is_locked = inflight->is_locked;

tal_wally_start();
wally_psbt_clone_alloc(inflight->funding_psbt, 0, &infcopy->psbt);
Expand Down Expand Up @@ -2267,6 +2287,12 @@ static struct command_result *json_splice_init(struct command *cmd,
cc->channel = channel;
cc->channel_ids = NULL;
cc->results = NULL;
cc->user_psbt_ver = initialpsbt->version;

if (initialpsbt->version != 2 && !psbt_set_version(initialpsbt, 2))
return command_fail(cmd,
SPLICE_INPUT_ERROR,
"Splice failed to convert to v2");

msg = towire_channeld_splice_init(NULL, initialpsbt, *relative_amount,
*feerate_per_kw, *force_feerate,
Expand Down Expand Up @@ -2313,6 +2339,12 @@ static struct command_result *json_splice_update(struct command *cmd,
cc->channel = channel;
cc->channel_ids = NULL;
cc->results = NULL;
cc->user_psbt_ver = psbt->version;

if (psbt->version != 2 && !psbt_set_version(psbt, 2))
return command_fail(cmd,
SPLICE_INPUT_ERROR,
"Splice failed to convert to v2");

subd_send_msg(channel->owner,
take(towire_channeld_splice_update(NULL, psbt)));
Expand Down Expand Up @@ -2343,6 +2375,12 @@ static struct command_result *single_splice_signed(struct command *cmd,
cc->channel = channel;
cc->channel_ids = NULL;
cc->results = NULL;
cc->user_psbt_ver = psbt->version;

if (psbt->version != 2 && !psbt_set_version(psbt, 2))
return command_fail(cmd,
SPLICE_INPUT_ERROR,
"Splice failed to convert to v2");

msg = towire_channeld_splice_signed(tmpctx, psbt, sign_first);
subd_send_msg(channel->owner, take(msg));
Expand Down Expand Up @@ -2374,6 +2412,9 @@ static struct command_result *json_splice_signed(struct command *cmd,
return command_fail(cmd, SPLICE_INPUT_ERROR,
"PSBT failed to validate.");

log_debug(cmd->ld->log, "splice_signed input PSBT version %d",
psbt->version);

/* If a single channel is specified, we do that and finish. */
if (channel) {
if (command_check_only(cmd))
Expand Down
5 changes: 3 additions & 2 deletions tests/fuzz/fuzz-wire-splice_locked.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@

struct splice_locked {
struct channel_id channel_id;
struct bitcoin_txid txid;
};

static void *encode(const tal_t *ctx, const struct splice_locked *s)
{
return towire_splice_locked(ctx, &s->channel_id);
return towire_splice_locked(ctx, &s->channel_id, &s->txid);
}

static struct splice_locked *decode(const tal_t *ctx, const void *p)
{
struct splice_locked *s = tal(ctx, struct splice_locked);

if (fromwire_splice_locked(p, &s->channel_id))
if (fromwire_splice_locked(p, &s->channel_id, &s->txid))
return s;
return tal_free(s);
}
Expand Down
1 change: 1 addition & 0 deletions wallet/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,7 @@ static struct migration dbmigrations[] = {
{SQL("ALTER TABLE channel_funding_inflights ADD remote_funding BLOB DEFAULT NULL;"), NULL},
{SQL("ALTER TABLE peers ADD last_known_address BLOB DEFAULT NULL;"), NULL},
{SQL("ALTER TABLE channels ADD close_attempt_height INTEGER DEFAULT 0;"), NULL},
{SQL("ALTER TABLE channel_funding_inflights ADD locked_onchain INTEGER DEFAULT 0;"), NULL},
};

/**
Expand Down
6 changes: 6 additions & 0 deletions wallet/test/run-wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,8 @@ static bool channel_inflightseq(struct channel_inflight *i1,
CHECK(i1->lease_chan_max_msat == i2->lease_chan_max_msat);
CHECK(i1->lease_chan_max_ppt == i2->lease_chan_max_ppt);
CHECK(i1->lease_blockheight_start == i2->lease_blockheight_start);
CHECK(i1->is_locked == i2->is_locked);
CHECK(i1->splice_locked_memonly == i2->splice_locked_memonly);

return true;
}
Expand Down Expand Up @@ -2037,6 +2039,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx)
0,
false,
false);
inflight->splice_locked_memonly = true;
inflight->is_locked = true;

inflight_set_last_tx(inflight, last_tx, sig);

Expand Down Expand Up @@ -2064,6 +2068,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx)
0,
false,
false);
inflight->splice_locked_memonly = false;
inflight->is_locked = false;
inflight_set_last_tx(inflight, last_tx, sig);
wallet_inflight_add(w, inflight);
CHECK_MSG(c2 = wallet_channel_load(w, chan->dbid),
Expand Down
17 changes: 12 additions & 5 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1244,8 +1244,9 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight)
", i_am_initiator"
", force_sign_first"
", remote_funding"
", locked_onchain"
") VALUES ("
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));

db_bind_u64(stmt, inflight->channel->dbid);
db_bind_txid(stmt, &inflight->funding->outpoint.txid);
Expand Down Expand Up @@ -1288,6 +1289,7 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight)
db_bind_pubkey(stmt, inflight->funding->splice_remote_funding);
else
db_bind_null(stmt);
db_bind_int(stmt, inflight->is_locked);

db_exec_prepared_v2(stmt);
assert(!stmt->error);
Expand Down Expand Up @@ -1316,17 +1318,18 @@ void wallet_inflight_save(struct wallet *w,
struct db_stmt *stmt;
/* The *only* thing you can update on an
* inflight is the funding PSBT (to add sigs)
* and the last_tx/last_sig if this is for a splice */
* and the last_tx/last_sig or locked_onchain if this is for a splice */
stmt = db_prepare_v2(w->db,
SQL("UPDATE channel_funding_inflights SET"
" funding_psbt=?" // 0
", funding_tx_remote_sigs_received=?" // 1
", last_tx=?" // 2
", last_sig=?" // 3
", locked_onchain=?" // 4
" WHERE"
" channel_id=?" // 4
" AND funding_tx_id=?" // 5
" AND funding_tx_outnum=?")); // 6
" channel_id=?" // 5
" AND funding_tx_id=?" // 6
" AND funding_tx_outnum=?")); // 7
db_bind_psbt(stmt, inflight->funding_psbt);
db_bind_int(stmt, inflight->remote_tx_sigs);
if (inflight->last_tx) {
Expand All @@ -1336,6 +1339,7 @@ void wallet_inflight_save(struct wallet *w,
db_bind_null(stmt);
db_bind_null(stmt);
}
db_bind_int(stmt, inflight->is_locked);
db_bind_u64(stmt, inflight->channel->dbid);
db_bind_txid(stmt, &inflight->funding->outpoint.txid);
db_bind_int(stmt, inflight->funding->outpoint.n);
Expand Down Expand Up @@ -1434,6 +1438,8 @@ wallet_stmt2inflight(struct wallet *w, struct db_stmt *stmt,
i_am_initiator,
force_sign_first);

inflight->is_locked = db_col_int(stmt, "locked_onchain");

/* last_tx is null for not yet committed
* channels + static channel backup recoveries */
if (!db_col_is_null(stmt, "last_tx")) {
Expand Down Expand Up @@ -1485,6 +1491,7 @@ static bool wallet_channel_load_inflights(struct wallet *w,
", i_am_initiator"
", force_sign_first"
", remote_funding"
", locked_onchain"
" FROM channel_funding_inflights"
" WHERE channel_id = ?"
" ORDER BY funding_feerate"));
Expand Down
1 change: 1 addition & 0 deletions wire/peer_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ msgdata,splice_ack,relative_satoshis,s64,
msgdata,splice_ack,funding_pubkey,point,
msgtype,splice_locked,77,
msgdata,splice_locked,channel_id,channel_id,
msgdata,splice_locked,splice_txid,sha256,
msgtype,shutdown,38
msgdata,shutdown,channel_id,channel_id,
msgdata,shutdown,len,u16,
Expand Down
Loading