Skip to content

Commit

Permalink
splicing: Add channel state AWAITING_SPLICE
Browse files Browse the repository at this point in the history
Update gossip routiens and various other hecks on the channel state to consider AWAITING_SPLICE to be routable and treated similar to CHANNELD_NORMAL.

Small updates to psbt interface

Changelog-None
  • Loading branch information
ddustin authored and rustyrussell committed Jul 31, 2023
1 parent 108658a commit 50fe819
Show file tree
Hide file tree
Showing 17 changed files with 74 additions and 22 deletions.
2 changes: 1 addition & 1 deletion bitcoin/psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ bool psbt_is_finalized(const struct wally_psbt *psbt)
}

struct wally_psbt_input *psbt_add_input(struct wally_psbt *psbt,
struct wally_tx_input *input,
const struct wally_tx_input *input,
size_t insert_at)
{
const u32 flags = WALLY_PSBT_FLAG_NON_FINAL; /* Skip script/witness */
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ struct wally_tx *psbt_final_tx(const tal_t *ctx, const struct wally_psbt *psbt);
u8 *psbt_make_key(const tal_t *ctx, u8 key_subtype, const u8 *key_data);

struct wally_psbt_input *psbt_add_input(struct wally_psbt *psbt,
struct wally_tx_input *input,
const struct wally_tx_input *input,
size_t insert_at);

/* One stop shop for adding an input + metadata to a PSBT */
Expand Down
7 changes: 7 additions & 0 deletions common/jsonrpc_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ enum jsonrpc_errcode {
FUNDING_STATE_INVALID = 312,
FUND_CANNOT_AFFORD_WITH_EMERGENCY = 313,

/* Splice errors */
SPLICE_BROADCAST_FAIL = 350,
SPLICE_WRONG_OWNER = 351,
SPLICE_UNKNOWN_CHANNEL = 352,
SPLICE_INVALID_CHANNEL_STATE = 353,
SPLICE_NOT_SUPPORTED = 354,

/* `connect` errors */
CONNECT_NO_KNOWN_ADDRESS = 400,
CONNECT_ALL_ADDRESSES_FAILED = 401,
Expand Down
6 changes: 5 additions & 1 deletion common/psbt_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ void psbt_finalize_input(const tal_t *ctx,
const struct witness **
psbt_to_witnesses(const tal_t *ctx,
const struct wally_psbt *psbt,
enum tx_role side_to_stack)
enum tx_role side_to_stack,
int input_index_to_ignore)
{
u64 serial_id;
const struct witness **witnesses =
Expand All @@ -128,6 +129,9 @@ psbt_to_witnesses(const tal_t *ctx,
/* FIXME: throw an error ? */
return tal_free(witnesses);

if (input_index_to_ignore == i)
continue;

/* BOLT-f53ca2301232db780843e894f55d95d512f297f9 #2:
* - if is the *initiator*:
* - MUST send even `serial_id`s
Expand Down
4 changes: 3 additions & 1 deletion common/psbt_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ void psbt_finalize_input(const tal_t *ctx,
* @ctx - allocation context
* @psbt - PSBT to copy sigs from
* @side_to_stack - which side to stack witnesses of
* @input_index_to_ignore - which input to not include. Pass -1 to include all.
*/
const struct witness **
psbt_to_witnesses(const tal_t *ctx,
const struct wally_psbt *psbt,
enum tx_role side_to_stack);
enum tx_role side_to_stack,
int input_index_to_ignore);

/* psbt_input_weight - Calculate the tx weight for input index `in` */
size_t psbt_input_weight(struct wally_psbt *psbt,
Expand Down
4 changes: 2 additions & 2 deletions gossipd/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ static void remove_chan_from_node(struct routing_state *rstate,

/* Last channel? Simply delete node (and associated announce) */
if (num_chans == 0) {
if(node->rgraph.index != node->bcast.index)
if (node->rgraph.index != node->bcast.index)
gossip_store_delete(rstate->gs,
&node->rgraph,
WIRE_NODE_ANNOUNCEMENT);
Expand All @@ -522,7 +522,7 @@ static void remove_chan_from_node(struct routing_state *rstate,

/* Removed only public channel? Remove node announcement. */
if (!node_has_broadcastable_channels(node)) {
if(node->rgraph.index != node->bcast.index)
if (node->rgraph.index != node->bcast.index)
gossip_store_delete(rstate->gs,
&node->rgraph,
WIRE_NODE_ANNOUNCEMENT);
Expand Down
22 changes: 19 additions & 3 deletions lightningd/channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,11 @@ new_inflight(struct channel *channel,
inflight->funding_psbt = tal_steal(inflight, psbt);

/* Make a 'clone' of this tx */
last_tx_psbt_clone = clone_psbt(inflight, last_tx->psbt);
inflight->last_tx = bitcoin_tx_with_psbt(inflight, last_tx_psbt_clone);
inflight->last_tx = NULL;
if (last_tx) {
last_tx_psbt_clone = clone_psbt(inflight, last_tx->psbt);
inflight->last_tx = bitcoin_tx_with_psbt(inflight, last_tx_psbt_clone);
}
inflight->last_sig = last_sig;
inflight->tx_broadcast = false;

Expand Down Expand Up @@ -580,6 +583,18 @@ const char *channel_state_str(enum channel_state state)
return "unknown";
}

bool channel_state_normalish(const struct channel *channel)
{
return channel->state == CHANNELD_NORMAL
|| channel->state == CHANNELD_AWAITING_SPLICE;
}

bool channel_state_awaitish(const struct channel *channel)
{
return channel->state == CHANNELD_AWAITING_LOCKIN
|| channel->state == CHANNELD_AWAITING_SPLICE;
}

struct channel *peer_any_active_channel(struct peer *peer, bool *others)
{
struct channel *channel, *ret = NULL;
Expand Down Expand Up @@ -793,7 +808,8 @@ void channel_set_state(struct channel *channel,
struct timeabs timestamp;

/* set closer, if known */
if (state > CHANNELD_NORMAL && channel->closer == NUM_SIDES) {
if (!(state == CHANNELD_AWAITING_SPLICE)
&& state > CHANNELD_NORMAL && channel->closer == NUM_SIDES) {
if (reason == REASON_LOCAL) channel->closer = LOCAL;
if (reason == REASON_USER) channel->closer = LOCAL;
if (reason == REASON_REMOTE) channel->closer = REMOTE;
Expand Down
10 changes: 8 additions & 2 deletions lightningd/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,12 @@ void delete_channel(struct channel *channel STEALS);
const char *channel_state_name(const struct channel *channel);
const char *channel_state_str(enum channel_state state);

/* Is the channel in NORMAL or AWAITING_SPLICE state? */
bool channel_state_normalish(const struct channel *channel);

/* Is the channel in AWAITING_*? */
bool channel_state_awaitish(const struct channel *channel);

void channel_set_owner(struct channel *channel, struct subd *owner);

/* Channel has failed, but can try again. */
Expand Down Expand Up @@ -454,12 +460,12 @@ void channel_set_last_tx(struct channel *channel,

static inline bool channel_can_add_htlc(const struct channel *channel)
{
return channel->state == CHANNELD_NORMAL;
return channel_state_normalish(channel);
}

static inline bool channel_fees_can_change(const struct channel *channel)
{
return channel->state == CHANNELD_NORMAL
return channel_state_normalish(channel)
|| channel->state == CHANNELD_SHUTTING_DOWN;
}

Expand Down
7 changes: 4 additions & 3 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,8 @@ bool channel_tell_depth(struct lightningd *ld,
txid, depth);
return true;
} else if (channel->state != CHANNELD_AWAITING_LOCKIN
&& channel->state != CHANNELD_NORMAL) {
&& channel->state != CHANNELD_NORMAL
&& channel->state != CHANNELD_AWAITING_SPLICE) {
/* If not awaiting lockin/announce, it doesn't
* care any more */
log_debug(channel->log,
Expand Down Expand Up @@ -1187,7 +1188,7 @@ static struct command_result *json_dev_feerate(struct command *cmd,
return command_fail(cmd, LIGHTNINGD, "Peer not connected");

channel = peer_any_active_channel(peer, &more_than_one);
if (!channel || !channel->owner || channel->state != CHANNELD_NORMAL)
if (!channel || !channel->owner || !channel_state_normalish(channel))
return command_fail(cmd, LIGHTNINGD, "Peer bad state");
/* This is a dev command: fix the api if you need this! */
if (more_than_one)
Expand Down Expand Up @@ -1247,7 +1248,7 @@ static struct command_result *json_dev_quiesce(struct command *cmd,

/* FIXME: If this becomes a real API, check for OPT_QUIESCE! */
channel = peer_any_active_channel(peer, &more_than_one);
if (!channel || !channel->owner || channel->state != CHANNELD_NORMAL)
if (!channel || !channel->owner || !channel_state_normalish(channel))
return command_fail(cmd, LIGHTNINGD, "Peer bad state");
/* This is a dev command: fix the api if you need this! */
if (more_than_one)
Expand Down
5 changes: 4 additions & 1 deletion lightningd/channel_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ enum channel_state {

/* Dual-funded channel, waiting for lock-in */
DUALOPEND_AWAITING_LOCKIN,

/* Channel has started splice and is awaiting lock-in */
CHANNELD_AWAITING_SPLICE,
};
#define CHANNEL_STATE_MAX DUALOPEND_AWAITING_LOCKIN
#define CHANNEL_STATE_MAX CHANNELD_AWAITING_SPLICE

/* These are in the database, so don't renumber them! */
enum state_change {
Expand Down
1 change: 1 addition & 0 deletions lightningd/closing_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,7 @@ static struct command_result *json_close(struct command *cmd,
* waiting) */
switch (channel->state) {
case CHANNELD_NORMAL:
case CHANNELD_AWAITING_SPLICE:
case CHANNELD_AWAITING_LOCKIN:
case DUALOPEND_AWAITING_LOCKIN:
channel_set_state(channel,
Expand Down
7 changes: 6 additions & 1 deletion lightningd/peer_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,7 @@ static void connect_activate_subd(struct lightningd *ld, struct channel *channel

case CHANNELD_AWAITING_LOCKIN:
case CHANNELD_NORMAL:
case CHANNELD_AWAITING_SPLICE:
case CHANNELD_SHUTTING_DOWN:
case CLOSINGD_SIGEXCHANGE:
assert(!channel->owner);
Expand Down Expand Up @@ -1827,10 +1828,13 @@ static enum watch_result funding_depth_cb(struct lightningd *ld,
tal_free(txidstr);

bool min_depth_reached = depth >= channel->minimum_depth;
bool min_depth_no_scid = min_depth_reached && !channel->scid;
bool some_depth_has_scid = depth && channel->scid;

/* Reorg can change scid, so always update/save scid when possible (depth=0
* means the stale block with our funding tx was removed) */
if ((min_depth_reached && !channel->scid) || (depth && channel->scid)) {
if (channel->state != CHANNELD_AWAITING_SPLICE
&& (min_depth_no_scid || some_depth_has_scid)) {
struct txlocator *loc;
struct channel_inflight *inf;

Expand Down Expand Up @@ -2632,6 +2636,7 @@ static struct command_result *param_channel_or_all(struct command *cmd,
*channels = tal_arr(cmd, struct channel *, 0);
list_for_each(&peer->channels, channel, list) {
if (channel->state != CHANNELD_NORMAL
&& channel->state != CHANNELD_AWAITING_SPLICE
&& channel->state != CHANNELD_AWAITING_LOCKIN
&& channel->state != DUALOPEND_AWAITING_LOCKIN)
continue;
Expand Down
2 changes: 1 addition & 1 deletion lightningd/peer_htlcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ static void htlc_offer_timeout(struct htlc_out *out)
assert(out->hstate == SENT_ADD_HTLC);

/* If owner died, we should already be taken care of. */
if (!channel->owner || channel->state != CHANNELD_NORMAL)
if (!channel->owner || !channel_state_normalish(channel))
return;

log_unusual(channel->owner->log,
Expand Down
2 changes: 1 addition & 1 deletion openingd/dualopend.c
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ static u8 *psbt_to_tx_sigs_msg(const tal_t *ctx,
const struct wally_psbt *psbt)
{
const struct witness **ws =
psbt_to_witnesses(tmpctx, psbt, state->our_role);
psbt_to_witnesses(tmpctx, psbt, state->our_role, -1);

return towire_tx_signatures(ctx, &state->channel_id,
&state->tx_state->funding.txid,
Expand Down
3 changes: 2 additions & 1 deletion plugins/libplugin-pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -3291,7 +3291,8 @@ static struct command_result *direct_pay_listpeerchannels(struct command *cmd,
if (!chan->connected)
continue;

if (!streq(chan->state, "CHANNELD_NORMAL"))
if (!streq(chan->state, "CHANNELD_NORMAL")
&& !streq(chan->state, "CHANNELD_AWAITING_SPLICE"))
continue;

/* Must have either a local alias for zeroconf
Expand Down
7 changes: 5 additions & 2 deletions plugins/test/run-route-overlong.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,12 @@ static void update_connection(int store_fd,
bool disable)
{
secp256k1_ecdsa_signature dummy_sig;
u8 flags = node_id_idx(from, to);
u8 *msg;

if (disable)
flags |= ROUTING_FLAGS_DISABLED;

/* So valgrind doesn't complain */
memset(&dummy_sig, 0, sizeof(dummy_sig));

Expand All @@ -265,8 +269,7 @@ static void update_connection(int store_fd,
&chainparams->genesis_blockhash,
scid, 0,
ROUTING_OPT_HTLC_MAX_MSAT,
node_id_idx(from, to)
+ (disable ? ROUTING_FLAGS_DISABLED : 0),
flags,
delay,
min,
base_fee,
Expand Down
5 changes: 4 additions & 1 deletion plugins/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,10 @@ static struct node_map *local_connected(const tal_t *ctx,
/* Must also have a channel in CHANNELD_NORMAL */
normal_chan = json_tok_streq(buf,
json_get_member(buf, channel, "state"),
"CHANNELD_NORMAL");
"CHANNELD_NORMAL")
|| json_tok_streq(buf,
json_get_member(buf, channel, "state"),
"CHANNELD_AWAITING_SPLICE");

if (normal_chan)
node_map_add(connected,
Expand Down

0 comments on commit 50fe819

Please sign in to comment.