From 2ffd34429976b5e41724290ffdb19a0ae7390ccd Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 4 Jun 2021 11:23:55 +0930 Subject: [PATCH] channeld: tweak function to allow testing for pending *uncommitted* changes. For quiescence, we can't have sent any updates at all. But for upgrades on reconnection, we may have already added uncommitted HTLCs for retransmission, but they don't count towards "are we quiesced" since they're not sent yet. Signed-off-by: Rusty Russell --- channeld/channeld.c | 6 +++--- channeld/full_channel.c | 20 ++++++++++++++++---- channeld/full_channel.h | 4 +++- common/fee_states.c | 6 +++++- common/fee_states.h | 5 +++-- 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index d33e9da1e..95802ad13 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -290,7 +290,7 @@ static void maybe_send_stfu(struct peer *peer) if (!peer->stfu) return; - if (!peer->stfu_sent[LOCAL] && !pending_updates(peer->channel, LOCAL)) { + if (!peer->stfu_sent[LOCAL] && !pending_updates(peer->channel, LOCAL, false)) { u8 *msg = towire_stfu(NULL, &peer->channel_id, peer->stfu_initiator == LOCAL); sync_crypto_write(peer->pps, take(msg)); @@ -323,7 +323,7 @@ static void handle_stfu(struct peer *peer, const u8 *stfu) } /* Sanity check */ - if (pending_updates(peer->channel, REMOTE)) + if (pending_updates(peer->channel, REMOTE, false)) peer_failed_warn(peer->pps, &peer->channel_id, "STFU but you still have updates pending?"); @@ -1141,7 +1141,7 @@ static void send_commit(struct peer *peer) /* FIXME: We occasionally desynchronize with LND here, so * don't stress things by having more than one feerate change * in-flight! */ - if (feerate_changes_done(peer->channel->fee_states)) { + if (feerate_changes_done(peer->channel->fee_states, false)) { u8 *msg; if (!channel_update_feerate(peer->channel, feerate_target)) diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 7001712f4..59665eeb4 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -1269,26 +1269,38 @@ static bool adjust_balance(struct balance view_owed[NUM_SIDES][NUM_SIDES], return true; } -bool pending_updates(const struct channel *channel, enum side side) +bool pending_updates(const struct channel *channel, + enum side side, + bool uncommitted_ok) { struct htlc_map_iter it; const struct htlc *htlc; /* Initiator might have fee changes in play. */ if (side == channel->opener) { - if (!feerate_changes_done(channel->fee_states)) + if (!feerate_changes_done(channel->fee_states, uncommitted_ok)) return true; } for (htlc = htlc_map_first(channel->htlcs, &it); htlc; htlc = htlc_map_next(channel->htlcs, &it)) { - /* If it's still being added, it's owner added it. */ - if (htlc_state_flags(htlc->state) & HTLC_ADDING) { + int flags = htlc_state_flags(htlc->state); + + /* If it's still being added, its owner added it. */ + if (flags & HTLC_ADDING) { + /* It might be OK if it's added, but not committed */ + if (uncommitted_ok + && (flags & HTLC_FLAG(!side, HTLC_F_PENDING))) + continue; if (htlc_owner(htlc) == side) return true; /* If it's being removed, non-owner removed it */ } else if (htlc_state_flags(htlc->state) & HTLC_REMOVING) { + /* It might be OK if it's removed, but not committed */ + if (uncommitted_ok + && (flags & HTLC_FLAG(!side, HTLC_F_PENDING))) + continue; if (htlc_owner(htlc) != side) return true; } diff --git a/channeld/full_channel.h b/channeld/full_channel.h index 8f04547eb..e23deb3b1 100644 --- a/channeld/full_channel.h +++ b/channeld/full_channel.h @@ -258,8 +258,10 @@ void dump_htlcs(const struct channel *channel, const char *prefix); * pending_updates: does this side have updates pending in channel? * @channel: the channel * @side: the side who is offering or failing/fulfilling HTLC, or feechange + * @uncommitted_ok: don't count uncommitted changes. */ -bool pending_updates(const struct channel *channel, enum side side); +bool pending_updates(const struct channel *channel, enum side side, + bool uncommitted_ok); const char *channel_add_err_name(enum channel_add_err e); const char *channel_remove_err_name(enum channel_remove_err e); diff --git a/common/fee_states.c b/common/fee_states.c index c12470911..451d3849f 100644 --- a/common/fee_states.c +++ b/common/fee_states.c @@ -74,10 +74,14 @@ u32 get_feerate(const struct fee_states *fee_states, } /* Are feerates all agreed by both sides? */ -bool feerate_changes_done(const struct fee_states *fee_states) +bool feerate_changes_done(const struct fee_states *fee_states, + bool ignore_uncommitted) { size_t num_feerates = 0; for (size_t i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) { + if (ignore_uncommitted + && (i == RCVD_ADD_HTLC || i == SENT_ADD_HTLC)) + continue; num_feerates += (fee_states->feerate[i] != NULL); } return num_feerates == 1; diff --git a/common/fee_states.h b/common/fee_states.h index 40cc18ddc..cf846002b 100644 --- a/common/fee_states.h +++ b/common/fee_states.h @@ -86,7 +86,8 @@ struct fee_states *fromwire_fee_states(const tal_t *ctx, */ bool fee_states_valid(const struct fee_states *fee_states, enum side opener); -/* Are therre no more fee changes in-flight? */ -bool feerate_changes_done(const struct fee_states *fee_states); +/* Are there no more fee changes in-flight? */ +bool feerate_changes_done(const struct fee_states *fee_states, + bool ignore_uncommitted); #endif /* LIGHTNING_COMMON_FEE_STATES_H */