From 062f18127d96ffcb2abcfb3233e0178a83f768d6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 21 Nov 2017 15:56:59 +1030 Subject: [PATCH] channeld: handle incoming feerate changes. We allow from the 100-confirm economical rate to 5x the immediate rate. Closes: #243 Signed-off-by: Rusty Russell --- channeld/channel.c | 85 +++++++++++++++++++++++++++++++++------ channeld/channel_wire.csv | 4 ++ lightningd/peer_control.c | 2 + lightningd/peer_htlcs.c | 17 +++++++- 4 files changed, 94 insertions(+), 14 deletions(-) diff --git a/channeld/channel.c b/channeld/channel.c index 3da64c486..0f7f66b5f 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -64,6 +64,9 @@ struct peer { bool funding_locked[NUM_SIDES]; u64 next_index[NUM_SIDES]; + /* Tolerable amounts for feerate (only relevant for fundee). */ + u32 feerate_min, feerate_max; + /* Remote's current per-commit point. */ struct pubkey remote_per_commit; @@ -430,6 +433,59 @@ static struct io_plan *handle_peer_add_htlc(struct io_conn *conn, return peer_read_message(conn, &peer->pcs, peer_in); } +static struct io_plan *handle_peer_feechange(struct io_conn *conn, + struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u32 feerate; + + if (!fromwire_update_fee(msg, NULL, &channel_id, &feerate)) { + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + "Bad update_fee %s", tal_hex(msg, msg)); + } + + /* BOLT #2: + * + * A receiving node MUST fail the channel if the sender is not + * responsible for paying the bitcoin fee. + */ + if (peer->channel->funder != REMOTE) + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + "update_fee from non-funder?"); + + /* BOLT #2: + * + * A receiving node SHOULD fail the channel if the `update_fee` is too + * low for timely processing, or unreasonably large. + */ + if (feerate < peer->feerate_min || feerate > peer->feerate_max) + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + "update_fee %u outside range %u-%u", + feerate, peer->feerate_min, peer->feerate_max); + + /* 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, but it MAY delay this check until the `update_fee` is + * committed. + */ + if (!channel_update_feerate(peer->channel, feerate)) + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + "update_fee %u unaffordable", + feerate); + + return peer_read_message(conn, &peer->pcs, peer_in); +} + static struct changed_htlc *changed_htlc_arr(const tal_t *ctx, const struct htlc **changed_htlcs) { @@ -446,6 +502,7 @@ static struct changed_htlc *changed_htlc_arr(const tal_t *ctx, static u8 *sending_commitsig_msg(const tal_t *ctx, u64 remote_commit_index, + u32 remote_feerate, const struct htlc **changed_htlcs, const secp256k1_ecdsa_signature *commit_sig, const secp256k1_ecdsa_signature *htlc_sigs) @@ -458,6 +515,7 @@ static u8 *sending_commitsig_msg(const tal_t *ctx, * committed to. */ changed = changed_htlc_arr(tmpctx, changed_htlcs); msg = towire_channel_sending_commitsig(ctx, remote_commit_index, + remote_feerate, changed, commit_sig, htlc_sigs); tal_free(tmpctx); return msg; @@ -665,6 +723,7 @@ static void send_commit(struct peer *peer) status_trace("Telling master we're about to commit..."); /* Tell master to save this next commit to database, then wait. */ msg = sending_commitsig_msg(tmpctx, peer->next_index[REMOTE], + channel_feerate(peer->channel, REMOTE), changed_htlcs, &peer->next_commit_sigs->commit_sig, peer->next_commit_sigs->htlc_sigs); @@ -798,6 +857,7 @@ static void get_shared_secret(const struct htlc *htlc, static u8 *got_commitsig_msg(const tal_t *ctx, u64 local_commit_index, + u32 local_feerate, const secp256k1_ecdsa_signature *commit_sig, const secp256k1_ecdsa_signature *htlc_sigs, const struct htlc **changed_htlcs, @@ -856,6 +916,7 @@ static u8 *got_commitsig_msg(const tal_t *ctx, } msg = towire_channel_got_commitsig(ctx, local_commit_index, + local_feerate, commit_sig, htlc_sigs, added, @@ -984,8 +1045,9 @@ static struct io_plan *handle_peer_commit_sig(struct io_conn *conn, tal_count(htlc_sigs)); /* Tell master daemon, then wait for ack. */ - msg = got_commitsig_msg(tmpctx, peer->next_index[LOCAL], &commit_sig, - htlc_sigs, changed_htlcs, txs[0]); + msg = got_commitsig_msg(tmpctx, peer->next_index[LOCAL], + channel_feerate(peer->channel, LOCAL), + &commit_sig, htlc_sigs, changed_htlcs, txs[0]); master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNEL_GOT_COMMITSIG_REPLY); @@ -1369,6 +1431,8 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg) return handle_peer_add_htlc(conn, peer, msg); case WIRE_COMMITMENT_SIGNED: return handle_peer_commit_sig(conn, peer, msg); + case WIRE_UPDATE_FEE: + return handle_peer_feechange(conn, peer, msg); case WIRE_REVOKE_AND_ACK: return handle_peer_revoke_and_ack(conn, peer, msg); case WIRE_UPDATE_FULFILL_HTLC: @@ -1391,15 +1455,8 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg) case WIRE_FUNDING_CREATED: case WIRE_FUNDING_SIGNED: case WIRE_CHANNEL_REESTABLISH: - goto badmessage; - case WIRE_CLOSING_SIGNED: - case WIRE_UPDATE_FEE: - peer_failed(io_conn_fd(peer->peer_conn), - &peer->pcs.cs, - &peer->channel_id, - "Unimplemented message %u (%s)", - type, wire_type_name(type)); + goto badmessage; } badmessage: @@ -2036,6 +2093,7 @@ static void init_channel(struct peer *peer) &funding_satoshi, &peer->conf[LOCAL], &peer->conf[REMOTE], feerate_per_kw, + &peer->feerate_min, &peer->feerate_max, &peer->their_commit_sig, &peer->pcs.cs, &funding_pubkey[REMOTE], @@ -2079,14 +2137,17 @@ static void init_channel(struct peer *peer) status_trace("init %s: remote_per_commit = %s, old_remote_per_commit = %s" " next_idx_local = %"PRIu64 " next_idx_remote = %"PRIu64 - " revocations_received = %"PRIu64, + " revocations_received = %"PRIu64 + " feerates %u/%u (range %u-%u)", side_to_str(funder), type_to_string(trc, struct pubkey, &peer->remote_per_commit), type_to_string(trc, struct pubkey, &peer->old_remote_per_commit), peer->next_index[LOCAL], peer->next_index[REMOTE], - peer->revocations_received); + peer->revocations_received, + feerate_per_kw[LOCAL], feerate_per_kw[REMOTE], + peer->feerate_min, peer->feerate_max); /* First commit is used for opening: if we've sent 0, we're on * index 1. */ diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index 68f994d79..5a9ad95f2 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -14,6 +14,8 @@ channel_init,,our_config,struct channel_config channel_init,,their_config,struct channel_config # FIXME: Fix generate-wire.py to allow NUM_SIDES*u32 here. channel_init,,feerate_per_kw,2*u32 +channel_init,,feerate_min,u32 +channel_init,,feerate_max,u32 channel_init,,first_commit_sig,secp256k1_ecdsa_signature channel_init,,crypto_state,struct crypto_state channel_init,,remote_fundingkey,struct pubkey @@ -118,6 +120,7 @@ channel_got_funding_locked,,next_per_commit_point,struct pubkey # When we send a commitment_signed message, tell master. channel_sending_commitsig,1020 channel_sending_commitsig,,commitnum,u64 +channel_sending_commitsig,,feerate,u32 # SENT_ADD_COMMIT, SENT_REMOVE_ACK_COMMIT, SENT_ADD_ACK_COMMIT, SENT_REMOVE_COMMIT channel_sending_commitsig,,num_changed,u16 channel_sending_commitsig,,changed,num_changed*struct changed_htlc @@ -131,6 +134,7 @@ channel_sending_commitsig_reply,1120 # When we have a commitment_signed message, tell master to remember. channel_got_commitsig,1021 channel_got_commitsig,,commitnum,u64 +channel_got_commitsig,,feerate,u32 channel_got_commitsig,,signature,secp256k1_ecdsa_signature channel_got_commitsig,,num_htlcs,u16 channel_got_commitsig,,htlc_signature,num_htlcs*secp256k1_ecdsa_signature diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 3bb475d1c..3b1981022 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -2108,6 +2108,8 @@ static bool peer_start_channeld(struct peer *peer, &peer->our_config, &peer->channel_info->their_config, peer->channel_info->feerate_per_kw, + get_feerate(peer->ld->topology, FEERATE_NORMAL), + get_feerate(peer->ld->topology, FEERATE_IMMEDIATE) * 5, peer->last_sig, cs, &peer->channel_info->remote_fundingkey, diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 164855286..299e0e6be 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -990,6 +990,7 @@ static bool peer_save_commitsig_sent(struct peer *peer, u64 commitnum) void peer_sending_commitsig(struct peer *peer, const u8 *msg) { u64 commitnum; + u32 feerate; struct changed_htlc *changed_htlcs; size_t i, maxid = 0, num_local_added = 0; secp256k1_ecdsa_signature commit_sig; @@ -997,6 +998,7 @@ void peer_sending_commitsig(struct peer *peer, const u8 *msg) if (!fromwire_channel_sending_commitsig(msg, msg, NULL, &commitnum, + &feerate, &changed_htlcs, &commit_sig, &htlc_sigs)) { peer_internal_error(peer, "bad channel_sending_commitsig %s", @@ -1033,6 +1035,9 @@ void peer_sending_commitsig(struct peer *peer, const u8 *msg) peer->next_htlc_id += num_local_added; } + /* Update their feerate. */ + peer->channel_info->feerate_per_kw[REMOTE] = feerate; + if (!peer_save_commitsig_sent(peer, commitnum)) return; @@ -1109,6 +1114,7 @@ static bool peer_sending_revocation(struct peer *peer, void peer_got_commitsig(struct peer *peer, const u8 *msg) { u64 commitnum; + u32 feerate; secp256k1_ecdsa_signature commit_sig; secp256k1_ecdsa_signature *htlc_sigs; struct added_htlc *added; @@ -1121,6 +1127,7 @@ void peer_got_commitsig(struct peer *peer, const u8 *msg) if (!fromwire_channel_got_commitsig(msg, msg, NULL, &commitnum, + &feerate, &commit_sig, &htlc_sigs, &added, @@ -1137,8 +1144,8 @@ void peer_got_commitsig(struct peer *peer, const u8 *msg) log_debug(peer->log, "got commitsig %"PRIu64 - ": %zu added, %zu fulfilled, %zu failed, %zu changed", - commitnum, tal_count(added), tal_count(fulfilled), + ": feerate %u, %zu added, %zu fulfilled, %zu failed, %zu changed", + commitnum, feerate, tal_count(added), tal_count(fulfilled), tal_count(failed), tal_count(changed)); /* FIXME: store commit & htlc signature information. */ @@ -1166,6 +1173,12 @@ void peer_got_commitsig(struct peer *peer, const u8 *msg) } } + /* Update both feerates: if we're funder, REMOTE should already be + * that feerate, if we're not, we're about to ACK anyway. */ + peer->channel_info->feerate_per_kw[LOCAL] + = peer->channel_info->feerate_per_kw[REMOTE] + = feerate; + /* Since we're about to send revoke, bump state again. */ if (!peer_sending_revocation(peer, added, fulfilled, failed, changed)) return;