diff --git a/channeld/channel.c b/channeld/channel.c index 81d9c2ec6..4f95b8906 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -1046,6 +1046,12 @@ static struct io_plan *handle_peer_revoke_and_ack(struct io_conn *conn, "Bad revoke_and_ack %s", tal_hex(msg, msg)); } + if (!channel_awaiting_revoke_and_ack(peer->channel)) + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + "Unexpected revoke_and_ack"); + /* BOLT #2: * * A receiving node MUST check that `per_commitment_secret` generates diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 2a1b63bd3..99f112dfa 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -696,6 +696,8 @@ bool channel_sending_commit(struct channel *channel, assert(change & HTLC_REMOTE_F_COMMITTED); channel->changes_pending[REMOTE] = false; + assert(!channel->awaiting_revoke_and_ack); + channel->awaiting_revoke_and_ack = true; return true; } @@ -716,6 +718,9 @@ bool channel_rcvd_revoke_and_ack(struct channel *channel, if (change & HTLC_LOCAL_F_PENDING) channel->changes_pending[LOCAL] = true; + assert(channel->awaiting_revoke_and_ack); + channel->awaiting_revoke_and_ack = false; + return change & HTLC_LOCAL_F_PENDING; } @@ -762,25 +767,36 @@ 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) +static bool htlc_awaiting_revoke_and_ack(const struct htlc *h) { const enum htlc_state states[] = { SENT_ADD_COMMIT, SENT_REMOVE_ACK_COMMIT, SENT_ADD_ACK_COMMIT, SENT_REMOVE_COMMIT }; + + for (size_t i = 0; i < ARRAY_SIZE(states); i++) { + if (h->state == states[i]) { + return true; + } + } + return false; +} + +bool channel_awaiting_revoke_and_ack(const struct channel *channel) +{ struct htlc_map_iter it; struct htlc *h; - size_t i; + /* FIXME: remove debugging iteration. */ 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; + if (htlc_awaiting_revoke_and_ack(h)) { + assert(channel->awaiting_revoke_and_ack); + return true; + } } + assert(!channel->awaiting_revoke_and_ack); return false; } @@ -888,6 +904,8 @@ bool channel_force_htlcs(struct channel *channel, return false; } + if (htlc_awaiting_revoke_and_ack(htlc)) + channel->awaiting_revoke_and_ack = true; } for (i = 0; i < tal_count(fulfilled); i++) { diff --git a/common/initial_channel.c b/common/initial_channel.c index e23ce0b1d..0d0a90415 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -40,6 +40,7 @@ struct channel *new_initial_channel(const tal_t *ctx, channel->htlcs = NULL; channel->changes_pending[LOCAL] = channel->changes_pending[REMOTE] = false; + channel->awaiting_revoke_and_ack = false; channel->view[LOCAL].feerate_per_kw = channel->view[REMOTE].feerate_per_kw diff --git a/common/initial_channel.h b/common/initial_channel.h index 0477ca8bd..918815647 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -55,6 +55,9 @@ struct channel { /* Do we have changes pending for ourselves/other? */ bool changes_pending[NUM_SIDES]; + /* Are we waiting for their revoke_and_ack? */ + bool awaiting_revoke_and_ack; + /* What it looks like to each side. */ struct channel_view view[NUM_SIDES]; };