diff --git a/lightningd/channel.c b/lightningd/channel.c index ccf6430e6..5f37aebc9 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -733,6 +733,28 @@ bool channel_sending_revoke_and_ack(struct channel *channel) return change & HTLC_REMOTE_F_PENDING; } +/* FIXME: Trivial to optimize: set flag on channel_sending_commit, + * clear in channel_rcvd_revoke_and_ack. */ +bool channel_awaiting_revoke_and_ack(const struct channel *channel) +{ + const enum htlc_state states[] = { SENT_ADD_COMMIT, + SENT_REMOVE_ACK_COMMIT, + SENT_ADD_ACK_COMMIT, + SENT_REMOVE_COMMIT }; + struct htlc_map_iter it; + struct htlc *h; + size_t i; + + for (h = htlc_map_first(&channel->htlcs, &it); + h; + h = htlc_map_next(&channel->htlcs, &it)) { + for (i = 0; i < ARRAY_SIZE(states); i++) + if (h->state == states[i]) + return true; + } + return false; +} + static char *fmt_channel_view(const tal_t *ctx, const struct channel_view *view) { return tal_fmt(ctx, "{ feerate_per_kw=%"PRIu64"," diff --git a/lightningd/channel.h b/lightningd/channel.h index 16a49accc..82d38b3df 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -389,4 +389,11 @@ bool channel_rcvd_commit_(struct channel *channel, * anything changed for the remote commitment (ie. send a new commit).*/ bool channel_sending_revoke_and_ack(struct channel *channel); +/** + * channel_awaiting_revoke_and_ack: are we waiting for revoke_and_ack? + * @channel: the channel + * + * If true, we can't send a new commit message. + */ +bool channel_awaiting_revoke_and_ack(const struct channel *channel); #endif /* LIGHTNING_DAEMON_CHANNEL_H */ diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index e7d927730..4f5911181 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -275,6 +275,13 @@ static void send_commit(struct peer *peer) /* Timer has expired. */ peer->commit_timer = NULL; + /* FIXME: Document this requirement in BOLT 2! */ + /* We can't send two commits in a row. */ + if (channel_awaiting_revoke_and_ack(peer->channel)) { + tal_free(tmpctx); + return; + } + /* BOLT #2: * * A node MUST NOT send a `commitment_signed` message which does not