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 <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2021-06-04 11:23:55 +09:30
parent 5473d66993
commit 2ffd344299
5 changed files with 30 additions and 11 deletions

View File

@@ -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))

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 */