diff --git a/channeld/channel.c b/channeld/channel.c index 63a05cff1..3da64c486 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -893,6 +893,12 @@ static struct io_plan *handle_peer_commit_sig(struct io_conn *conn, "commit_sig with no changes"); } + /* We were supposed to check this was affordable as we go. */ + if (peer->channel->funder == REMOTE) + assert(can_funder_afford_feerate(peer->channel, + peer->channel->view[LOCAL] + .feerate_per_kw)); + if (!fromwire_commitment_signed(tmpctx, msg, NULL, &channel_id, &commit_sig, &htlc_sigs)) peer_failed(io_conn_fd(peer->peer_conn), diff --git a/channeld/full_channel.c b/channeld/full_channel.c index cf92ded49..a5223db4a 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -678,6 +678,53 @@ static int change_htlcs(struct channel *channel, return cflags; } +bool can_funder_afford_feerate(const struct channel *channel, u32 feerate_per_kw) +{ + u64 fee_msat, dust = dust_limit_satoshis(channel, !channel->funder); + size_t untrimmed; + const struct htlc **committed, **adding, **removing; + const tal_t *tmpctx = tal_tmpctx(channel); + + gather_htlcs(tmpctx, channel, !channel->funder, + &committed, &removing, &adding); + + untrimmed = commit_tx_num_untrimmed(committed, feerate_per_kw, dust, + !channel->funder) + + commit_tx_num_untrimmed(adding, feerate_per_kw, dust, + !channel->funder) + - commit_tx_num_untrimmed(removing, feerate_per_kw, dust, + !channel->funder); + + fee_msat = commit_tx_base_fee(feerate_per_kw, untrimmed); + + tal_free(tmpctx); + + /* BOLT #2: + * + * A receiving node SHOULD fail the channel if the sender cannot afford + * the new fee rate on the receiving node's current commitment + * transaction */ + /* Note: sender == funder */ + + /* How much does it think it has? Must be >= reserve + fee */ + return channel->view[!channel->funder].owed_msat[channel->funder] + >= channel_reserve_msat(channel, channel->funder) + fee_msat; +} + +bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw) +{ + if (!can_funder_afford_feerate(channel, feerate_per_kw)) + return false; + + channel->view[!channel->funder].feerate_per_kw = feerate_per_kw; + return true; +} + +u32 channel_feerate(const struct channel *channel, enum side side) +{ + return channel->view[side].feerate_per_kw; +} + /* FIXME: Handle fee changes too. */ bool channel_sending_commit(struct channel *channel, const struct htlc ***htlcs) diff --git a/channeld/full_channel.h b/channeld/full_channel.h index 0f5b8b4f4..f5ee6bec1 100644 --- a/channeld/full_channel.h +++ b/channeld/full_channel.h @@ -173,24 +173,33 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, * approx_max_feerate: what's the we (initiator) could raise fee rate to? * @channel: The channel state * - * This is not exact! To check if their offer is valid, use can_afford_feerate. + * This is not exact! To check if their offer is valid, try + * channel_update_feerate. */ u32 approx_max_feerate(const struct channel *channel); /** - * can_afford_feerate: could the initiator pay for the fee at fee_rate? + * can_funder_afford_feerate: could the funder pay the fee? * @channel: The channel state - * @feerate_per_kw: the new fee rate proposed + * @feerate: The feerate in satoshi per 1000 bytes. */ -bool can_afford_feerate(const struct channel *channel, u32 feerate_per_kw); +bool can_funder_afford_feerate(const struct channel *channel, u32 feerate); /** - * adjust_fee: Change fee rate. - * @channel: The channel state + * channel_update_feerate: Change fee rate on non-funder side. + * @channel: The channel * @feerate_per_kw: fee in satoshi per 1000 bytes. - * @side: which side to adjust. + * + * Returns true if it's affordable, otherwise does nothing. */ -void adjust_fee(struct channel *channel, u32 feerate_per_kw, enum side side); +bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw); + +/** + * channel_feerate: Get fee rate for this side of channel. + * @channel: The channel + * @side: the side + */ +u32 channel_feerate(const struct channel *channel, enum side side); /** * channel_sending_commit: commit all remote outstanding changes.