diff --git a/channeld/Makefile b/channeld/Makefile index 128e39fb16d8..920879cb257f 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -46,6 +46,7 @@ CHANNELD_COMMON_OBJS := \ common/derive_basepoints.o \ common/dev_disconnect.o \ common/features.o \ + common/fee_states.o \ common/gen_status_wire.o \ common/gen_peer_status_wire.o \ common/gossip_rcvd_filter.o \ diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index 5744de929071..2f778e4020e7 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -1,6 +1,7 @@ #include #include #include +#include #include # Begin! (passes gossipd-client fd) @@ -12,8 +13,7 @@ msgdata,channel_init,funding_satoshi,amount_sat, msgdata,channel_init,minimum_depth,u32, msgdata,channel_init,our_config,channel_config, msgdata,channel_init,their_config,channel_config, -# FIXME: Fix generate-wire.py to allow NUM_SIDES*u32 here., -msgdata,channel_init,feerate_per_kw,u32,2 +msgdata,channel_init,fee_states,fee_states, msgdata,channel_init,feerate_min,u32, msgdata,channel_init,feerate_max,u32, msgdata,channel_init,first_commit_sig,bitcoin_signature, @@ -108,7 +108,7 @@ msgdata,channel_got_funding_locked,next_per_commit_point,pubkey, # When we send a commitment_signed message, tell master. msgtype,channel_sending_commitsig,1020 msgdata,channel_sending_commitsig,commitnum,u64, -msgdata,channel_sending_commitsig,feerate,u32, +msgdata,channel_sending_commitsig,fee_states,fee_states, # SENT_ADD_COMMIT, SENT_REMOVE_ACK_COMMIT, SENT_ADD_ACK_COMMIT, SENT_REMOVE_COMMIT msgdata,channel_sending_commitsig,num_changed,u16, msgdata,channel_sending_commitsig,changed,changed_htlc,num_changed @@ -122,7 +122,7 @@ msgtype,channel_sending_commitsig_reply,1120 # When we have a commitment_signed message, tell master to remember. msgtype,channel_got_commitsig,1021 msgdata,channel_got_commitsig,commitnum,u64, -msgdata,channel_got_commitsig,feerate,u32, +msgdata,channel_got_commitsig,fee_states,fee_states, msgdata,channel_got_commitsig,signature,bitcoin_signature, msgdata,channel_got_commitsig,num_htlcs,u16, msgdata,channel_got_commitsig,htlc_signature,secp256k1_ecdsa_signature,num_htlcs @@ -150,7 +150,7 @@ msgdata,channel_got_revoke,revokenum,u64, msgdata,channel_got_revoke,per_commitment_secret,secret, msgdata,channel_got_revoke,next_per_commit_point,pubkey, # RCVD_ADD_ACK_REVOCATION, RCVD_REMOVE_ACK_REVOCATION, RCVD_ADD_REVOCATION, RCVD_REMOVE_REVOCATION -msgdata,channel_got_revoke,feerate,u32, +msgdata,channel_got_revoke,fee_states,fee_states, msgdata,channel_got_revoke,num_changed,u16, msgdata,channel_got_revoke,changed,changed_htlc,num_changed # Wait for reply, to make sure it's on disk before we continue diff --git a/channeld/channeld.c b/channeld/channeld.c index 379c3ef93653..a901c167878c 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -721,7 +721,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 fee_states *fee_states, const struct htlc **changed_htlcs, const struct bitcoin_signature *commit_sig, const secp256k1_ecdsa_signature *htlc_sigs) @@ -733,7 +733,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, + fee_states, changed, commit_sig, htlc_sigs); return msg; } @@ -1180,7 +1180,7 @@ static void send_commit(struct peer *peer) status_debug("Telling master we're about to commit..."); /* Tell master to save this next commit to database, then wait. */ msg = sending_commitsig_msg(NULL, peer->next_index[REMOTE], - channel_feerate(peer->channel, REMOTE), + peer->channel->fee_states, changed_htlcs, &commit_sig, htlc_sigs); @@ -1259,44 +1259,20 @@ static u8 *make_revocation_msg(const struct peer *peer, u64 revoke_index, point); } -static void send_revocation(struct peer *peer) +/* Convert changed htlcs into parts which lightningd expects. */ +static void marshall_htlc_info(const tal_t *ctx, + const struct htlc **changed_htlcs, + struct changed_htlc **changed, + struct fulfilled_htlc **fulfilled, + const struct failed_htlc ***failed, + struct added_htlc **added, + struct secret **shared_secret) { - /* Revoke previous commit, get new point. */ - u8 *msg = make_revocation_msg(peer, peer->next_index[LOCAL]-1, - &peer->next_local_per_commit); - - /* From now on we apply changes to the next commitment */ - peer->next_index[LOCAL]++; - - /* If this queues more changes on the other end, send commit. */ - if (channel_sending_revoke_and_ack(peer->channel)) { - status_debug("revoke_and_ack made pending: commit timer"); - start_commit_timer(peer); - } - - sync_crypto_write_no_delay(peer->pps, take(msg)); -} - -static u8 *got_commitsig_msg(const tal_t *ctx, - u64 local_commit_index, - u32 local_feerate, - const struct bitcoin_signature *commit_sig, - const secp256k1_ecdsa_signature *htlc_sigs, - const struct htlc **changed_htlcs, - const struct bitcoin_tx *committx) -{ - struct changed_htlc *changed; - struct fulfilled_htlc *fulfilled; - const struct failed_htlc **failed; - struct added_htlc *added; - struct secret *shared_secret; - u8 *msg; - - changed = tal_arr(tmpctx, struct changed_htlc, 0); - added = tal_arr(tmpctx, struct added_htlc, 0); - shared_secret = tal_arr(tmpctx, struct secret, 0); - failed = tal_arr(tmpctx, const struct failed_htlc *, 0); - fulfilled = tal_arr(tmpctx, struct fulfilled_htlc, 0); + *changed = tal_arr(ctx, struct changed_htlc, 0); + *added = tal_arr(ctx, struct added_htlc, 0); + *shared_secret = tal_arr(ctx, struct secret, 0); + *failed = tal_arr(ctx, const struct failed_htlc *, 0); + *fulfilled = tal_arr(ctx, struct fulfilled_htlc, 0); for (size_t i = 0; i < tal_count(changed_htlcs); i++) { const struct htlc *htlc = changed_htlcs[i]; @@ -1317,25 +1293,25 @@ static u8 *got_commitsig_msg(const tal_t *ctx, memset(&s, 0, sizeof(s)); else s = *htlc->shared_secret; - tal_arr_expand(&added, a); - tal_arr_expand(&shared_secret, s); + tal_arr_expand(added, a); + tal_arr_expand(shared_secret, s); } else if (htlc->state == RCVD_REMOVE_COMMIT) { if (htlc->r) { struct fulfilled_htlc f; assert(!htlc->fail && !htlc->failcode); f.id = htlc->id; f.payment_preimage = *htlc->r; - tal_arr_expand(&fulfilled, f); + tal_arr_expand(fulfilled, f); } else { struct failed_htlc *f; assert(htlc->fail || htlc->failcode); - f = tal(failed, struct failed_htlc); + f = tal(*failed, struct failed_htlc); f->id = htlc->id; f->failcode = htlc->failcode; f->failreason = cast_const(u8 *, htlc->fail); f->scid = cast_const(struct short_channel_id *, htlc->failed_scid); - tal_arr_expand(&failed, f); + tal_arr_expand(failed, f); } } else { struct changed_htlc c; @@ -1344,21 +1320,67 @@ static u8 *got_commitsig_msg(const tal_t *ctx, c.id = htlc->id; c.newstate = htlc->state; - tal_arr_expand(&changed, c); + tal_arr_expand(changed, c); } } +} - msg = towire_channel_got_commitsig(ctx, local_commit_index, - local_feerate, - commit_sig, - htlc_sigs, - added, - shared_secret, - fulfilled, - failed, - changed, - committx); - return msg; +static void send_revocation(struct peer *peer, + const struct bitcoin_signature *commit_sig, + const secp256k1_ecdsa_signature *htlc_sigs, + const struct htlc **changed_htlcs, + const struct bitcoin_tx *committx) +{ + struct changed_htlc *changed; + struct fulfilled_htlc *fulfilled; + const struct failed_htlc **failed; + struct added_htlc *added; + struct secret *shared_secret; + const u8 *msg_for_master; + + /* Marshall it now before channel_sending_revoke_and_ack changes htlcs */ + /* FIXME: Make infrastructure handle state post-revoke_and_ack! */ + marshall_htlc_info(tmpctx, + changed_htlcs, + &changed, + &fulfilled, + &failed, + &added, + &shared_secret); + + /* Revoke previous commit, get new point. */ + u8 *msg = make_revocation_msg(peer, peer->next_index[LOCAL]-1, + &peer->next_local_per_commit); + + /* From now on we apply changes to the next commitment */ + peer->next_index[LOCAL]++; + + /* If this queues more changes on the other end, send commit. */ + if (channel_sending_revoke_and_ack(peer->channel)) { + status_debug("revoke_and_ack made pending: commit timer"); + start_commit_timer(peer); + } + + /* Tell master daemon about commitsig (and by implication, that we're + * sending revoke_and_ack), then wait for it to ack. */ + /* We had to do this after channel_sending_revoke_and_ack, since we + * want it to save the fee_states produced there. */ + msg_for_master + = towire_channel_got_commitsig(NULL, + peer->next_index[LOCAL] - 1, + peer->channel->fee_states, + commit_sig, htlc_sigs, + added, + shared_secret, + fulfilled, + failed, + changed, + committx); + master_wait_sync_reply(tmpctx, peer, take(msg_for_master), + WIRE_CHANNEL_GOT_COMMITSIG_REPLY); + + /* Now we can finally send revoke_and_ack to peer */ + sync_crypto_write_no_delay(peer->pps, take(msg)); } static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) @@ -1392,11 +1414,11 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) /* We were supposed to check this was affordable as we go. */ if (peer->channel->funder == REMOTE) { status_debug("Feerates are %u/%u", - peer->channel->view[LOCAL].feerate_per_kw, - peer->channel->view[REMOTE].feerate_per_kw); + channel_feerate(peer->channel, LOCAL), + channel_feerate(peer->channel, REMOTE)); assert(can_funder_afford_feerate(peer->channel, - peer->channel->view[LOCAL] - .feerate_per_kw)); + channel_feerate(peer->channel, + LOCAL))); } if (!fromwire_commitment_signed(tmpctx, msg, @@ -1443,7 +1465,7 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) type_to_string(msg, struct pubkey, &peer->channel->funding_pubkey [REMOTE]), - peer->channel->view[LOCAL].feerate_per_kw); + channel_feerate(peer->channel, LOCAL)); } /* BOLT #2: @@ -1488,21 +1510,15 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) status_debug("Received commit_sig with %zu htlc sigs", tal_count(htlc_sigs)); - /* Tell master daemon, then wait for ack. */ - msg = got_commitsig_msg(NULL, 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); - return send_revocation(peer); + return send_revocation(peer, + &commit_sig, htlc_sigs, changed_htlcs, txs[0]); } static u8 *got_revoke_msg(const tal_t *ctx, u64 revoke_num, const struct secret *per_commitment_secret, const struct pubkey *next_per_commit_point, const struct htlc **changed_htlcs, - u32 feerate) + const struct fee_states *fee_states) { u8 *msg; struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); @@ -1521,7 +1537,7 @@ static u8 *got_revoke_msg(const tal_t *ctx, u64 revoke_num, } msg = towire_channel_got_revoke(ctx, revoke_num, per_commitment_secret, - next_per_commit_point, feerate, changed); + next_per_commit_point, fee_states, changed); return msg; } @@ -1581,7 +1597,7 @@ static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg) msg = got_revoke_msg(NULL, peer->revocations_received++, &old_commit_secret, &next_per_commit, changed_htlcs, - channel_feerate(peer->channel, LOCAL)); + peer->channel->fee_states); master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNEL_GOT_REVOKE_REPLY); @@ -2517,15 +2533,6 @@ static void peer_reconnect(struct peer *peer, send_fail_or_fulfill(peer, htlc); } - /* Corner case: we will get upset with them if they send - * commitment_signed with no changes. But it could be that we sent a - * feechange, they acked, and now they want to commit it; we can't - * even tell by seeing if fees are different (short of saving full fee - * state in database) since it could be a tiny feechange, or two - * feechanges which cancelled out. */ - if (peer->channel->funder == LOCAL) - peer->channel->changes_pending[LOCAL] = true; - peer_billboard(true, "Reconnected, and reestablished."); /* BOLT #2: @@ -2940,7 +2947,7 @@ static void init_channel(struct peer *peer) bool reconnected; u8 *funding_signed; const u8 *msg; - u32 feerate_per_kw[NUM_SIDES]; + struct fee_states *fee_states; u32 minimum_depth, failheight; struct secret last_remote_per_commit_secret; secp256k1_ecdsa_signature *remote_ann_node_sig; @@ -2958,7 +2965,7 @@ static void init_channel(struct peer *peer) &funding, &minimum_depth, &conf[LOCAL], &conf[REMOTE], - feerate_per_kw, + &fee_states, &peer->feerate_min, &peer->feerate_max, &peer->their_commit_sig, &peer->pps, @@ -3015,7 +3022,7 @@ static void init_channel(struct peer *peer) " next_idx_local = %"PRIu64 " next_idx_remote = %"PRIu64 " revocations_received = %"PRIu64 - " feerates %u/%u (range %u-%u)", + " feerates %s range %u-%u", side_to_str(funder), type_to_string(tmpctx, struct pubkey, &peer->remote_per_commit), @@ -3023,7 +3030,7 @@ static void init_channel(struct peer *peer) &peer->old_remote_per_commit), peer->next_index[LOCAL], peer->next_index[REMOTE], peer->revocations_received, - feerate_per_kw[LOCAL], feerate_per_kw[REMOTE], + type_to_string(tmpctx, struct fee_states, fee_states), peer->feerate_min, peer->feerate_max); status_debug("option_static_remotekey = %u", option_static_remotekey); @@ -3057,7 +3064,7 @@ static void init_channel(struct peer *peer) minimum_depth, funding, local_msat, - feerate_per_kw, + take(fee_states), &conf[LOCAL], &conf[REMOTE], &points[LOCAL], &points[REMOTE], &funding_pubkey[LOCAL], @@ -3092,7 +3099,7 @@ static void init_channel(struct peer *peer) /* Default desired feerate is the feerate we set for them last. */ if (peer->channel->funder == LOCAL) - peer->desired_feerate = feerate_per_kw[REMOTE]; + peer->desired_feerate = channel_feerate(peer->channel, REMOTE); /* from now we need keep watch over WIRE_CHANNEL_FUNDING_DEPTH */ peer->depth_togo = minimum_depth; diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 98e9f51afca1..7dc5c71e31a5 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -91,7 +92,7 @@ struct channel *new_full_channel(const tal_t *ctx, u32 minimum_depth, struct amount_sat funding, struct amount_msat local_msat, - const u32 feerate_per_kw[NUM_SIDES], + const struct fee_states *fee_states, const struct channel_config *local, const struct channel_config *remote, const struct basepoints *local_basepoints, @@ -107,7 +108,7 @@ struct channel *new_full_channel(const tal_t *ctx, minimum_depth, funding, local_msat, - feerate_per_kw[LOCAL], + fee_states, local, remote, local_basepoints, remote_basepoints, @@ -117,8 +118,6 @@ struct channel *new_full_channel(const tal_t *ctx, funder); if (channel) { - /* Feerates can be different. */ - channel->view[REMOTE].feerate_per_kw = feerate_per_kw[REMOTE]; channel->htlcs = tal(channel, struct htlc_map); htlc_map_init(channel->htlcs); memleak_add_helper(channel->htlcs, memleak_help_htlcmap); @@ -231,7 +230,7 @@ static void add_htlcs(struct bitcoin_tx ***txs, { size_t i; struct bitcoin_txid txid; - u32 feerate_per_kw = channel->view[side].feerate_per_kw; + u32 feerate_per_kw = channel_feerate(channel, side); /* Get txid of commitment transaction */ bitcoin_txid((*txs)[0], &txid); @@ -306,7 +305,7 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, ctx, &channel->funding_txid, channel->funding_txout, channel->funding, channel->funder, channel->config[!side].to_self_delay, &keyset, - channel->view[side].feerate_per_kw, + channel_feerate(channel, side), channel->config[side].dust_limit, channel->view[side].owed[side], channel->view[side].owed[!side], committed, htlcmap, commitment_number ^ channel->commitment_number_obscurer, side); @@ -370,7 +369,7 @@ static struct amount_sat fee_for_htlcs(const struct channel *channel, const struct htlc **removing, enum side side) { - u32 feerate = view->feerate_per_kw; + u32 feerate = channel_feerate(channel, side); struct amount_sat dust_limit = channel->config[side].dust_limit; size_t untrimmed; @@ -622,13 +621,6 @@ static enum channel_add_err add_htlc(struct channel *channel, if (htlcp) *htlcp = htlc; - /* This is simply setting changes_pending[receiver] unless it's - * an exotic state (i.e. channel_force_htlcs) */ - if (htlc_state_flags(htlc->state) & HTLC_LOCAL_F_PENDING) - channel->changes_pending[LOCAL] = true; - if (htlc_state_flags(htlc->state) & HTLC_REMOTE_F_PENDING) - channel->changes_pending[REMOTE] = true; - return CHANNEL_ERR_ADD_OK; } @@ -718,8 +710,6 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, htlc->id, htlc_state_name(htlc->state)); return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; } - /* The HTLC owner is the recipient of the fulfillment. */ - channel->changes_pending[owner] = true; dump_htlc(htlc, "FULFILL:"); @@ -763,8 +753,6 @@ enum channel_remove_err channel_fail_htlc(struct channel *channel, htlc->id, htlc_state_name(htlc->state)); return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; } - /* The HTLC owner is the recipient of the failure. */ - channel->changes_pending[owner] = true; dump_htlc(htlc, "FAIL:"); if (htlcp) @@ -812,6 +800,37 @@ static void htlc_incstate(struct channel *channel, } } +/* Returns true if a change was made. */ +static bool fee_incstate(struct channel *channel, + enum side sidechanged, + enum htlc_state hstate) +{ + int preflags, postflags; + const int committed_f = HTLC_FLAG(sidechanged, HTLC_F_COMMITTED); + + preflags = htlc_state_flags(hstate); + postflags = htlc_state_flags(hstate + 1); + + /* You can't change sides. */ + assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) + == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); + + /* These only advance through ADDING states. */ + if (!(htlc_state_flags(hstate) & HTLC_ADDING)) + return false; + + if (!inc_fee_state(channel->fee_states, hstate)) + return false; + + if (!(preflags & committed_f) && (postflags & committed_f)) + status_debug("Feerate: %s->%s %s now %u", + htlc_state_name(hstate), + htlc_state_name(hstate+1), + side_to_str(sidechanged), + *channel->fee_states->feerate[hstate+1]); + return true; +} + /* Returns flags which were changed. */ static int change_htlcs(struct channel *channel, enum side sidechanged, @@ -855,6 +874,13 @@ static int change_htlcs(struct channel *channel, } } + /* Update fees. */ + for (i = 0; i < n_hstates; i++) { + if (fee_incstate(channel, sidechanged, htlc_states[i])) + cflags |= (htlc_state_flags(htlc_states[i]) + ^ htlc_state_flags(htlc_states[i]+1)); + } + return cflags; } @@ -967,34 +993,24 @@ bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw) status_debug("Setting %s feerate to %u", side_to_str(!channel->funder), feerate_per_kw); - channel->view[!channel->funder].feerate_per_kw = feerate_per_kw; - channel->changes_pending[!channel->funder] = true; + start_fee_update(channel->fee_states, channel->funder, feerate_per_kw); return true; } -u32 channel_feerate(const struct channel *channel, enum side side) -{ - return channel->view[side].feerate_per_kw; -} - bool channel_sending_commit(struct channel *channel, const struct htlc ***htlcs) { + int change; const enum htlc_state states[] = { SENT_ADD_HTLC, SENT_REMOVE_REVOCATION, SENT_ADD_REVOCATION, SENT_REMOVE_HTLC }; status_debug("Trying commit"); - if (!channel->changes_pending[REMOTE]) { - assert(change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), - htlcs, "testing sending_commit") == 0); + change = change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), + htlcs, "sending_commit"); + if (!change) return false; - } - - change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), - htlcs, "sending_commit"); - channel->changes_pending[REMOTE] = false; return true; } @@ -1013,42 +1029,23 @@ bool channel_rcvd_revoke_and_ack(struct channel *channel, htlcs, "rcvd_revoke_and_ack"); /* Their ack can queue changes on our side. */ - if (change & HTLC_LOCAL_F_PENDING) - channel->changes_pending[LOCAL] = true; - - /* For funder, ack also means time to apply new feerate locally. */ - if (channel->funder == LOCAL && - (channel->view[LOCAL].feerate_per_kw - != channel->view[REMOTE].feerate_per_kw)) { - status_debug("Applying feerate %u to LOCAL", - channel->view[REMOTE].feerate_per_kw); - channel->view[LOCAL].feerate_per_kw - = channel->view[REMOTE].feerate_per_kw; - channel->changes_pending[LOCAL] = true; - } - - return channel->changes_pending[LOCAL]; + return (change & HTLC_LOCAL_F_PENDING); } /* FIXME: We can actually merge these two... */ bool channel_rcvd_commit(struct channel *channel, const struct htlc ***htlcs) { + int change; const enum htlc_state states[] = { RCVD_ADD_REVOCATION, RCVD_REMOVE_HTLC, RCVD_ADD_HTLC, RCVD_REMOVE_REVOCATION }; status_debug("Received commit"); - if (!channel->changes_pending[LOCAL]) { - assert(change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), - htlcs, "testing rcvd_commit") == 0); + change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), + htlcs, "rcvd_commit"); + if (!change) return false; - } - - change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), htlcs, - "rcvd_commit"); - - channel->changes_pending[LOCAL] = false; return true; } @@ -1064,21 +1061,7 @@ bool channel_sending_revoke_and_ack(struct channel *channel) "sending_revoke_and_ack"); /* Our ack can queue changes on their side. */ - if (change & HTLC_REMOTE_F_PENDING) - channel->changes_pending[REMOTE] = true; - - /* For non-funder, sending ack means we apply any fund changes to them */ - if (channel->funder == REMOTE - && (channel->view[LOCAL].feerate_per_kw - != channel->view[REMOTE].feerate_per_kw)) { - status_debug("Applying feerate %u to REMOTE", - channel->view[LOCAL].feerate_per_kw); - channel->view[REMOTE].feerate_per_kw - = channel->view[LOCAL].feerate_per_kw; - channel->changes_pending[REMOTE] = true; - } - - return channel->changes_pending[REMOTE]; + return (change & HTLC_REMOTE_F_PENDING); } size_t num_channel_htlcs(const struct channel *channel) diff --git a/channeld/full_channel.h b/channeld/full_channel.h index 8fde9087f722..1cfd950c1682 100644 --- a/channeld/full_channel.h +++ b/channeld/full_channel.h @@ -15,8 +15,7 @@ * @minimum_depth: The minimum confirmations needed for funding transaction. * @funding: The commitment transaction amount. * @local_msat: The amount for the local side (remainder goes to remote) - * @feerate_per_kw: feerate per kiloweight (satoshis) for the commitment - * transaction and HTLCS for each side. + * @fee_states: The fee update states. * @local: local channel configuration * @remote: remote channel configuration * @local_basepoints: local basepoints. @@ -34,7 +33,7 @@ struct channel *new_full_channel(const tal_t *ctx, u32 minimum_depth, struct amount_sat funding, struct amount_msat local_msat, - const u32 feerate_per_kw[NUM_SIDES], + const struct fee_states *fee_states, const struct channel_config *local, const struct channel_config *remote, const struct basepoints *local_basepoints, diff --git a/channeld/test/run-full_channel.c b/channeld/test/run-full_channel.c index 6e9ba032c7d4..63dbaec3ec43 100644 --- a/channeld/test/run-full_channel.c +++ b/channeld/test/run-full_channel.c @@ -1,3 +1,4 @@ +#include "../../common/fee_states.c" #include "../../common/initial_channel.c" #include "../../common/keyset.c" #include "../full_channel.c" @@ -468,7 +469,8 @@ int main(void) lchannel = new_full_channel(tmpctx, &funding_txid, funding_output_index, 0, funding_amount, to_local, - feerate_per_kw, + take(new_fee_states(NULL, LOCAL, + &feerate_per_kw[LOCAL])), local_config, remote_config, &localbase, &remotebase, @@ -478,7 +480,8 @@ int main(void) rchannel = new_full_channel(tmpctx, &funding_txid, funding_output_index, 0, funding_amount, to_remote, - feerate_per_kw, + take(new_fee_states(NULL, REMOTE, + &feerate_per_kw[REMOTE])), remote_config, local_config, &remotebase, &localbase, @@ -629,8 +632,10 @@ int main(void) for (i = 0; i < ARRAY_SIZE(feerates); i++) { feerate_per_kw[LOCAL] = feerate_per_kw[REMOTE] = feerates[i]; - lchannel->view[LOCAL].feerate_per_kw = feerate_per_kw[LOCAL]; - rchannel->view[REMOTE].feerate_per_kw = feerate_per_kw[REMOTE]; + *lchannel->fee_states->feerate[SENT_ADD_ACK_REVOCATION] + = feerate_per_kw[LOCAL]; + *rchannel->fee_states->feerate[RCVD_ADD_ACK_REVOCATION] + = feerate_per_kw[REMOTE]; raw_tx = commit_tx( tmpctx, &funding_txid, funding_output_index, @@ -652,6 +657,7 @@ int main(void) /* No memory leaks please */ wally_cleanup(0); + take_cleanup(); tal_free(tmpctx); /* FIXME: Do BOLT comparison! */ diff --git a/common/Makefile b/common/Makefile index 0a3b37a56e85..46a7cc6c18e3 100644 --- a/common/Makefile +++ b/common/Makefile @@ -20,6 +20,7 @@ COMMON_SRC_NOGEN := \ common/derive_basepoints.c \ common/dev_disconnect.c \ common/features.c \ + common/fee_states.c \ common/funding_tx.c \ common/gossip_rcvd_filter.c \ common/gossip_store.c \ diff --git a/common/fee_states.c b/common/fee_states.c new file mode 100644 index 000000000000..b8cb60be16ff --- /dev/null +++ b/common/fee_states.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include + +/* If we're the finder, it's like an HTLC we added, if they are, it's like + * a HTLC they added. */ +enum htlc_state first_fee_state(enum side funder) +{ + if (funder == LOCAL) + return SENT_ADD_HTLC; + else + return RCVD_ADD_HTLC; +} + +enum htlc_state last_fee_state(enum side funder) +{ + if (funder == LOCAL) + return SENT_ADD_ACK_REVOCATION; + else + return RCVD_ADD_ACK_REVOCATION; +} + +struct fee_states *new_fee_states(const tal_t *ctx, + enum side funder, + const u32 *feerate_per_kw) +{ + struct fee_states *fee_states = tal(ctx, struct fee_states); + + /* Set to NULL except terminal value */ + for (size_t i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) + fee_states->feerate[i] = NULL; + if (feerate_per_kw) + fee_states->feerate[last_fee_state(funder)] + = tal_dup(fee_states, u32, feerate_per_kw); + return fee_states; +} + +struct fee_states *dup_fee_states(const tal_t *ctx, + const struct fee_states *fee_states TAKES) +{ + struct fee_states *n; + + if (taken(fee_states)) + return cast_const(struct fee_states *, + tal_steal(ctx, fee_states)); + n = tal_dup(ctx, struct fee_states, fee_states); + for (size_t i = 0; i < ARRAY_SIZE(n->feerate); i++) { + if (n->feerate[i]) + n->feerate[i] = tal_dup(n, u32, n->feerate[i]); + } + return n; +} + +u32 get_feerate(const struct fee_states *fee_states, + enum side funder, + enum side side) +{ + /* The first non-NULL feerate committed to this side is current */ + for (enum htlc_state i = first_fee_state(funder); + i <= last_fee_state(funder); + i++) { + if (!fee_states->feerate[i]) + continue; + if (!(htlc_state_flags(i) & HTLC_FLAG(side, HTLC_F_COMMITTED))) + continue; + return *fee_states->feerate[i]; + } + + /* Some feerate should always be set! */ + abort(); +} + +void start_fee_update(struct fee_states *fee_states, + enum side funder, + u32 feerate_per_kw) +{ + enum htlc_state start = first_fee_state(funder); + + /* BOLT #2: + * Unlike an HTLC, `update_fee` is never closed but simply replaced. + */ + if (fee_states->feerate[start] == NULL) + fee_states->feerate[start] = tal(fee_states, u32); + *fee_states->feerate[start] = feerate_per_kw; +} + +bool inc_fee_state(struct fee_states *fee_states, enum htlc_state hstate) +{ + /* These only advance through ADDING states. */ + assert(htlc_state_flags(hstate) & HTLC_ADDING); + + if (!fee_states->feerate[hstate]) + return false; + + /* FIXME: We can never clash, except at final state unless someone + * has violated protocol (eg, send two revoke_and_ack back-to-back) */ + tal_free(fee_states->feerate[hstate+1]); + fee_states->feerate[hstate+1] = fee_states->feerate[hstate]; + fee_states->feerate[hstate] = NULL; + return true; +} + +struct fee_states *fromwire_fee_states(const tal_t *ctx, + const u8 **cursor, size_t *max) +{ + struct fee_states *fee_states = tal(ctx, struct fee_states); + + for (enum htlc_state i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) { + if (fromwire_bool(cursor, max)) { + fee_states->feerate[i] = tal(fee_states, u32); + *fee_states->feerate[i] = fromwire_u32(cursor, max); + } else { + fee_states->feerate[i] = NULL; + } + } + if (!*cursor) + return tal_free(fee_states); + return fee_states; +} + +void towire_fee_states(u8 **pptr, const struct fee_states *fee_states) +{ + for (enum htlc_state i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) { + /* We don't send uncommitted feestates */ + if (!(htlc_state_flags(i) & (HTLC_REMOTE_F_COMMITTED + | HTLC_LOCAL_F_COMMITTED)) + || fee_states->feerate[i] == NULL) { + towire_bool(pptr, false); + continue; + } + towire_bool(pptr, true); + towire_u32(pptr, *fee_states->feerate[i]); + } +} + +/* FIXME: we don't know funder inside fromwire_fee_states, so can't do + * this there :( */ +bool fee_states_valid(const struct fee_states *fee_states, enum side funder) +{ + return fee_states->feerate[last_fee_state(funder)] != NULL; +} + +static const char *fmt_fee_states(const tal_t *ctx, + const struct fee_states *fee_states) +{ + char *ret = tal_strdup(ctx, "{"); + for (enum htlc_state i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) { + if (fee_states->feerate[i] != NULL) + tal_append_fmt(&ret, " %s:%u", + htlc_state_name(i), + *fee_states->feerate[i]); + } + tal_append_fmt(&ret, " }"); + return ret; +} +REGISTER_TYPE_TO_STRING(fee_states, fmt_fee_states); diff --git a/common/fee_states.h b/common/fee_states.h new file mode 100644 index 000000000000..606a057bd715 --- /dev/null +++ b/common/fee_states.h @@ -0,0 +1,88 @@ +#ifndef LIGHTNING_COMMON_FEE_STATES_H +#define LIGHTNING_COMMON_FEE_STATES_H +#include "config.h" +#include +#include + +struct fee_states { + /* Current feerate in satoshis per 1000 weight: goes through same + * state machine as htlc addition, but can only have one rate at a + * time in any state and are never removed. + * + * We need to know if there's an actual change pending though (even if + * it's a "change" to an idential feerate!) so we use pointers. + */ + u32 *feerate[HTLC_STATE_INVALID]; +}; + +/** + * new_fee_states: Initialize a fee_states structure as at open-of-channel. + * @ctx: the tal ctx to allocate off + * @funder: which side funded the channel (and thus, proposes fee updates). + * @feerate_per_kw: the initial feerate (if any). + */ +struct fee_states *new_fee_states(const tal_t *ctx, + enum side funder, + const u32 *feerate_per_kw); + +/** + * dup_fee_states: copy a fee_states structure. + * @ctx: the tal ctx to allocate off + * @fee_states: the fee_states to copy. + */ +struct fee_states *dup_fee_states(const tal_t *ctx, + const struct fee_states *fee_states TAKES); + +/** + * get_feerate: Get the current feerate + * @fee_states: the fee state machine + * @funder: which side funded the channel (and thus, proposes fee updates). + * @side: which side to get the feerate for + */ +u32 get_feerate(const struct fee_states *fee_states, + enum side funder, + enum side side); + +/** + * first_fee_state: get the initial fee state. + * @funder: which side funded the channel (and thus, proposes fee updates). + */ +enum htlc_state first_fee_state(enum side funder); + +/** + * last_fee_state: get the final fee state. + * @funder: which side funded the channel (and thus, proposes fee updates). + */ +enum htlc_state last_fee_state(enum side funder); + +/** + * start_fee_update: feed a new fee update into state machine. + * @fee_states: the fee state machine + * @funder: which side funded the channel (and thus, proposes fee updates). + * @feerate_per_kw: the new feerate. + */ +void start_fee_update(struct fee_states *fee_states, + enum side funder, + u32 feerate_per_kw); + +/** + * inc_fee_state: move this feerate to the next state. + * @fee_states: the fee state machine + * @hstate: state + * + * Moves fee_states[hstate] to fee_states[hstate+1], if not NULL. + * Returns true if it wasn't NULL. + */ +bool inc_fee_state(struct fee_states *fee_states, enum htlc_state hstate); + +/* Marshal and unmarshal */ +void towire_fee_states(u8 **pptr, const struct fee_states *fee_states); +/* FIXME: You must check that fee_states_valid! */ +struct fee_states *fromwire_fee_states(const tal_t *ctx, + const u8 **cursor, size_t *max); + +/** + * Is this fee_state struct valid for this funding side? + */ +bool fee_states_valid(const struct fee_states *fee_states, enum side funder); +#endif /* LIGHTNING_COMMON_FEE_STATES_H */ diff --git a/common/initial_channel.c b/common/initial_channel.c index a68ad9bcdcf5..6074ee585f81 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -14,7 +16,7 @@ struct channel *new_initial_channel(const tal_t *ctx, u32 minimum_depth, struct amount_sat funding, struct amount_msat local_msatoshi, - u32 feerate_per_kw, + const struct fee_states *fee_states TAKES, const struct channel_config *local, const struct channel_config *remote, const struct basepoints *local_basepoints, @@ -41,12 +43,9 @@ struct channel *new_initial_channel(const tal_t *ctx, channel->funding_pubkey[LOCAL] = *local_funding_pubkey; channel->funding_pubkey[REMOTE] = *remote_funding_pubkey; channel->htlcs = NULL; - channel->changes_pending[LOCAL] = channel->changes_pending[REMOTE] - = false; - channel->view[LOCAL].feerate_per_kw - = channel->view[REMOTE].feerate_per_kw - = feerate_per_kw; + /* takes() if necessary */ + channel->fee_states = dup_fee_states(channel, fee_states); channel->view[LOCAL].owed[LOCAL] = channel->view[REMOTE].owed[LOCAL] @@ -100,7 +99,7 @@ struct bitcoin_tx *initial_channel_tx(const tal_t *ctx, /* They specify our to_self_delay and v.v. */ channel->config[!side].to_self_delay, &keyset, - channel->view[side].feerate_per_kw, + channel_feerate(channel, side), channel->config[side].dust_limit, channel->view[side].owed[side], channel->view[side].owed[!side], @@ -110,19 +109,22 @@ struct bitcoin_tx *initial_channel_tx(const tal_t *ctx, err_reason); } +u32 channel_feerate(const struct channel *channel, enum side side) +{ + return get_feerate(channel->fee_states, channel->funder, side); +} + static char *fmt_channel_view(const tal_t *ctx, const struct channel_view *view) { - return tal_fmt(ctx, "{ feerate_per_kw=%"PRIu32"," - " owed_local=%s," + return tal_fmt(ctx, "{ owed_local=%s," " owed_remote=%s }", - view->feerate_per_kw, type_to_string(tmpctx, struct amount_msat, &view->owed[LOCAL]), type_to_string(tmpctx, struct amount_msat, &view->owed[REMOTE])); } -/* FIXME: This should reference HTLCs somehow. */ +/* FIXME: This should reference HTLCs somehow, and feerates! */ static char *fmt_channel(const tal_t *ctx, const struct channel *channel) { return tal_fmt(ctx, "{ funding=%s," diff --git a/common/initial_channel.h b/common/initial_channel.h index f5486a794ac7..cf202127ef82 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -20,9 +20,6 @@ struct fulfilled_htlc; /* View from each side */ struct channel_view { - /* Current feerate in satoshis per 1000 weight. */ - u32 feerate_per_kw; - /* How much is owed to each side (includes pending changes) */ struct amount_msat owed[NUM_SIDES]; }; @@ -56,8 +53,8 @@ struct channel { /* All live HTLCs for this channel */ struct htlc_map *htlcs; - /* Do we have changes pending for ourselves/other? */ - bool changes_pending[NUM_SIDES]; + /* Fee changes, some which may be in transit */ + struct fee_states *fee_states; /* What it looks like to each side. */ struct channel_view view[NUM_SIDES]; @@ -74,8 +71,7 @@ struct channel { * @minimum_depth: The minimum confirmations needed for funding transaction. * @funding_satoshis: The commitment transaction amount. * @local_msatoshi: The amount for the local side (remainder goes to remote) - * @feerate_per_kw: feerate per kiloweight (satoshis) for the commitment - * transaction and HTLCS (at this stage, same for both sides) + * @fee_states: The fee update states. * @local: local channel configuration * @remote: remote channel configuration * @local_basepoints: local basepoints. @@ -92,7 +88,7 @@ struct channel *new_initial_channel(const tal_t *ctx, u32 minimum_depth, struct amount_sat funding, struct amount_msat local_msatoshi, - u32 feerate_per_kw, + const struct fee_states *fee_states TAKES, const struct channel_config *local, const struct channel_config *remote, const struct basepoints *local_basepoints, @@ -122,4 +118,11 @@ struct bitcoin_tx *initial_channel_tx(const tal_t *ctx, enum side side, char** err_reason); +/** + * 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); + #endif /* LIGHTNING_COMMON_INITIAL_CHANNEL_H */ diff --git a/common/type_to_string.h b/common/type_to_string.h index e35d87b38598..209c26e6a5b1 100644 --- a/common/type_to_string.h +++ b/common/type_to_string.h @@ -33,6 +33,7 @@ union printable_types { const struct channel *channel; const struct amount_msat *amount_msat; const struct amount_sat *amount_sat; + const struct fee_states *fee_states; const char *charp_; }; diff --git a/devtools/Makefile b/devtools/Makefile index e6e04c7b869b..176345ad79a4 100644 --- a/devtools/Makefile +++ b/devtools/Makefile @@ -16,8 +16,10 @@ DEVTOOLS_COMMON_OBJS := \ common/crypto_state.o \ common/decode_array.o \ common/features.o \ + common/fee_states.o \ common/gossip_rcvd_filter.o \ common/hash_u5.o \ + common/htlc_state.o \ common/memleak.o \ common/node_id.o \ common/onion.o \ diff --git a/devtools/mkcommit.c b/devtools/mkcommit.c index f7202f37eccb..2af16d5dd5ae 100644 --- a/devtools/mkcommit.c +++ b/devtools/mkcommit.c @@ -3,8 +3,8 @@ * For example, in the spec tests we use the following: * * lightning/devtools/mkcommit 0 41085b995c1f591cfc3ae79ccde012bf0b37c7bde23d80a61c9732bdd6210b2f 0 999878sat 253 999878sat local \ - 5 546 9900sat \ - 6 546 9900sat \ + 5 546 9998sat \ + 6 546 9998sat \ 0000000000000000000000000000000000000000000000000000000000000020 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000021 0000000000000000000000000000000000000000000000000000000000000022 0000000000000000000000000000000000000000000000000000000000000023 0000000000000000000000000000000000000000000000000000000000000024 \ 0000000000000000000000000000000000000000000000000000000000000010 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0000000000000000000000000000000000000000000000000000000000000011 0000000000000000000000000000000000000000000000000000000000000012 0000000000000000000000000000000000000000000000000000000000000013 0000000000000000000000000000000000000000000000000000000000000014 */ @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -251,7 +252,7 @@ int main(int argc, char *argv[]) struct amount_sat funding_amount; struct bitcoin_txid funding_txid; unsigned int funding_outnum; - u32 feerate_per_kw[NUM_SIDES]; + u32 feerate_per_kw; struct pubkey local_per_commit_point, remote_per_commit_point; struct bitcoin_signature local_sig, remote_sig; struct channel_config localconfig, remoteconfig; @@ -318,7 +319,7 @@ int main(int argc, char *argv[]) if (!parse_amount_sat(&funding_amount, argv[argnum], strlen(argv[argnum]))) errx(1, "Bad funding-amount"); argnum++; - feerate_per_kw[LOCAL] = feerate_per_kw[REMOTE] = atoi(argv[argnum++]); + feerate_per_kw = atoi(argv[argnum++]); if (!parse_amount_msat(&local_msat, argv[argnum], strlen(argv[argnum]))) errx(1, "Bad local-msat"); @@ -384,7 +385,8 @@ int main(int argc, char *argv[]) &funding_txid, funding_outnum, 1, funding_amount, local_msat, - feerate_per_kw, + take(new_fee_states(NULL, fee_payer, + &feerate_per_kw)), &localconfig, &remoteconfig, &localbase, &remotebase, &funding_localkey, &funding_remotekey, diff --git a/lightningd/Makefile b/lightningd/Makefile index 0f74f5af8d99..45603626b2ae 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -29,6 +29,7 @@ LIGHTNINGD_COMMON_OBJS := \ common/daemon.o \ common/derive_basepoints.o \ common/features.o \ + common/fee_states.o \ common/funding_tx.o \ common/gen_peer_status_wire.o \ common/gen_status_wire.o \ diff --git a/lightningd/channel.c b/lightningd/channel.c index 6601bff79e04..a34de0f4fdcf 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -236,6 +237,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->last_sig = *last_sig; channel->last_htlc_sigs = tal_steal(channel, last_htlc_sigs); channel->channel_info = *channel_info; + channel->channel_info.fee_states + = dup_fee_states(channel, channel_info->fee_states); channel->shutdown_scriptpubkey[REMOTE] = tal_steal(channel, remote_shutdown_scriptpubkey); channel->final_key_idx = final_key_idx; diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 9fe6e8b242fa..af3b1a063a2c 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -429,7 +429,7 @@ void peer_start_channeld(struct channel *channel, channel->minimum_depth, &channel->our_config, &channel->channel_info.their_config, - channel->channel_info.feerate_per_kw, + channel->channel_info.fee_states, feerate_min(ld, NULL), feerate_max(ld, NULL), &channel->last_sig, diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index 71c6f88bd9e6..374d4f72d548 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -181,6 +182,7 @@ void peer_start_closingd(struct channel *channel, int hsmfd; struct secret last_remote_per_commit_secret; struct lightningd *ld = channel->peer->ld; + u32 final_commit_feerate; if (!channel->shutdown_scriptpubkey[REMOTE]) { channel_internal_error(channel, @@ -221,8 +223,9 @@ void peer_start_closingd(struct channel *channel, * fee of the final commitment transaction, as calculated in * [BOLT #3](03-transactions.md#fee-calculation). */ - feelimit = commit_tx_base_fee(channel->channel_info.feerate_per_kw[LOCAL], - 0); + final_commit_feerate = get_feerate(channel->channel_info.fee_states, + channel->funder, LOCAL); + feelimit = commit_tx_base_fee(final_commit_feerate, 0); /* Pick some value above slow feerate (or min possible if unknown) */ minfee = commit_tx_base_fee(feerate_min(ld, NULL), 0); @@ -230,7 +233,7 @@ void peer_start_closingd(struct channel *channel, /* If we can't determine feerate, start at half unilateral feerate. */ feerate = mutual_close_feerate(ld->topology); if (!feerate) { - feerate = channel->channel_info.feerate_per_kw[LOCAL] / 2; + feerate = final_commit_feerate / 2; if (feerate < feerate_floor()) feerate = feerate_floor(); } diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index c83ba774f899..21a33de06886 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -194,10 +195,8 @@ wallet_commit_channel(struct lightningd *ld, } else our_msat = push; - /* Feerates begin identical. */ - channel_info->feerate_per_kw[LOCAL] - = channel_info->feerate_per_kw[REMOTE] - = feerate; + channel_info->fee_states = new_fee_states(uc, uc->fc ? LOCAL : REMOTE, + &feerate); /* old_remote_per_commit not valid yet, copy valid one. */ channel_info->old_remote_per_commit = channel_info->remote_per_commit; diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 676f4fa17111..c51d5cd191dc 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -449,7 +449,8 @@ static void json_add_htlcs(struct lightningd *ld, struct htlc_in_map_iter ini; const struct htlc_out *hout; struct htlc_out_map_iter outi; - u32 local_feerate = channel->channel_info.feerate_per_kw[LOCAL]; + u32 local_feerate = get_feerate(channel->channel_info.fee_states, + channel->funder, LOCAL); /* FIXME: Add more fields. */ json_array_start(response, "htlcs"); @@ -519,7 +520,8 @@ static struct amount_sat commit_txfee(const struct channel *channel, const struct htlc_out *hout; struct htlc_out_map_iter outi; struct lightningd *ld = channel->peer->ld; - u32 local_feerate = channel->channel_info.feerate_per_kw[LOCAL]; + u32 local_feerate = get_feerate(channel->channel_info.fee_states, + channel->funder, LOCAL); size_t num_untrimmed_htlcs = 0; /* Assume we tried to spend "spendable" */ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index a43b9807e0b0..5dd88833f85e 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1347,10 +1347,18 @@ static bool peer_save_commitsig_sent(struct channel *channel, u64 commitnum) return true; } +static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) +{ + if (feerate > channel->max_possible_feerate) + channel->max_possible_feerate = feerate; + if (feerate < channel->min_possible_feerate) + channel->min_possible_feerate = feerate; +} + void peer_sending_commitsig(struct channel *channel, const u8 *msg) { u64 commitnum; - u32 feerate; + struct fee_states *fee_states; struct changed_htlc *changed_htlcs; size_t i, maxid = 0, num_local_added = 0; struct bitcoin_signature commit_sig; @@ -1361,9 +1369,10 @@ void peer_sending_commitsig(struct channel *channel, const u8 *msg) if (!fromwire_channel_sending_commitsig(msg, msg, &commitnum, - &feerate, + &fee_states, &changed_htlcs, - &commit_sig, &htlc_sigs)) { + &commit_sig, &htlc_sigs) + || !fee_states_valid(fee_states, channel->funder)) { channel_internal_error(channel, "bad channel_sending_commitsig %s", tal_hex(channel, msg)); return; @@ -1397,14 +1406,14 @@ void peer_sending_commitsig(struct channel *channel, const u8 *msg) channel->next_htlc_id += num_local_added; } - /* Update remote feerate if we are funder. */ - if (channel->funder == LOCAL) - channel->channel_info.feerate_per_kw[REMOTE] = feerate; - - if (feerate > channel->max_possible_feerate) - channel->max_possible_feerate = feerate; - if (feerate < channel->min_possible_feerate) - channel->min_possible_feerate = feerate; + /* FIXME: We could detect if this changed, and adjust bounds and write + * it to db iff it has. */ + tal_free(channel->channel_info.fee_states); + channel->channel_info.fee_states = tal_steal(channel, fee_states); + adjust_channel_feerate_bounds(channel, + get_feerate(fee_states, + channel->funder, + REMOTE)); if (!peer_save_commitsig_sent(channel, commitnum)) return; @@ -1523,7 +1532,7 @@ static void retry_deferred_commitsig(struct chain_topology *topo, void peer_got_commitsig(struct channel *channel, const u8 *msg) { u64 commitnum; - u32 feerate; + struct fee_states *fee_states; struct bitcoin_signature commit_sig; secp256k1_ecdsa_signature *htlc_sigs; struct added_htlc *added; @@ -1537,7 +1546,7 @@ void peer_got_commitsig(struct channel *channel, const u8 *msg) if (!fromwire_channel_got_commitsig(msg, msg, &commitnum, - &feerate, + &fee_states, &commit_sig, &htlc_sigs, &added, @@ -1545,7 +1554,8 @@ void peer_got_commitsig(struct channel *channel, const u8 *msg) &fulfilled, &failed, &changed, - &tx)) { + &tx) + || !fee_states_valid(fee_states, channel->funder)) { channel_internal_error(channel, "bad fromwire_channel_got_commitsig %s", tal_hex(channel, msg)); @@ -1575,7 +1585,8 @@ void peer_got_commitsig(struct channel *channel, const u8 *msg) log_debug(channel->log, "got commitsig %"PRIu64 ": feerate %u, %zu added, %zu fulfilled, %zu failed, %zu changed", - commitnum, feerate, tal_count(added), tal_count(fulfilled), + commitnum, get_feerate(fee_states, channel->funder, LOCAL), + tal_count(added), tal_count(fulfilled), tal_count(failed), tal_count(changed)); /* New HTLCs */ @@ -1603,17 +1614,12 @@ void peer_got_commitsig(struct channel *channel, const u8 *msg) } } - /* Update both feerates if we're not funder (for funder, receiving - * commitment_signed doesn't alter fees). */ - if (channel->funder == REMOTE) { - channel->channel_info.feerate_per_kw[LOCAL] - = channel->channel_info.feerate_per_kw[REMOTE] - = feerate; - } - if (feerate > channel->max_possible_feerate) - channel->max_possible_feerate = feerate; - if (feerate < channel->min_possible_feerate) - channel->min_possible_feerate = feerate; + tal_free(channel->channel_info.fee_states); + channel->channel_info.fee_states = tal_steal(channel, fee_states); + adjust_channel_feerate_bounds(channel, + get_feerate(fee_states, + channel->funder, + LOCAL)); /* Since we're about to send revoke, bump state again. */ if (!peer_sending_revocation(channel, added, fulfilled, failed, changed)) @@ -1652,13 +1658,14 @@ void peer_got_revoke(struct channel *channel, const u8 *msg) enum onion_type *failcodes; size_t i; struct lightningd *ld = channel->peer->ld; - u32 feerate; + struct fee_states *fee_states; if (!fromwire_channel_got_revoke(msg, msg, &revokenum, &per_commitment_secret, &next_per_commitment_point, - &feerate, - &changed)) { + &fee_states, + &changed) + || !fee_states_valid(fee_states, channel->funder)) { channel_internal_error(channel, "bad fromwire_channel_got_revoke %s", tal_hex(channel, msg)); return; @@ -1716,10 +1723,8 @@ void peer_got_revoke(struct channel *channel, const u8 *msg) return; } - /* Update feerate if we are funder, their revoke_and_ack has set - * this for local feerate. */ - if (channel->funder == LOCAL) - channel->channel_info.feerate_per_kw[LOCAL] = feerate; + tal_free(channel->channel_info.fee_states); + channel->channel_info.fee_states = tal_steal(channel, fee_states); /* FIXME: Check per_commitment_secret -> per_commit_point */ update_per_commit_point(channel, &next_per_commitment_point); diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index f6634d12b8ee..c3fecb29b234 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -25,8 +25,7 @@ struct channel_info { /* The old_remote_per_commit is for the locked-in remote commit_tx, * and the remote_per_commit is for the commit_tx we're modifying now. */ struct pubkey remote_per_commit, old_remote_per_commit; - /* In transition, these can be different! */ - u32 feerate_per_kw[NUM_SIDES]; + struct fee_states *fee_states; }; /* Get all HTLCs for a peer, to send in init message. */ diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index eab27f7d3346..d4bd272bc392 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -82,6 +82,10 @@ void connect_succeeded(struct lightningd *ld UNNEEDED, const struct node_id *id void delay_then_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UNNEEDED, const struct wireaddr_internal *addrhint TAKES UNNEEDED) { fprintf(stderr, "delay_then_reconnect called!\n"); abort(); } +/* Generated stub for dup_fee_states */ +struct fee_states *dup_fee_states(const tal_t *ctx UNNEEDED, + const struct fee_states *fee_states TAKES UNNEEDED) +{ fprintf(stderr, "dup_fee_states called!\n"); abort(); } /* Generated stub for encode_scriptpubkey_to_addr */ char *encode_scriptpubkey_to_addr(const tal_t *ctx UNNEEDED, const struct chainparams *chainparams UNNEEDED, @@ -120,6 +124,11 @@ bool fromwire_onchain_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEE /* Generated stub for get_block_height */ u32 get_block_height(const struct chain_topology *topo UNNEEDED) { fprintf(stderr, "get_block_height called!\n"); abort(); } +/* Generated stub for get_feerate */ +u32 get_feerate(const struct fee_states *fee_states UNNEEDED, + enum side funder UNNEEDED, + enum side side UNNEEDED) +{ fprintf(stderr, "get_feerate called!\n"); abort(); } /* Generated stub for get_offered_bolt11features */ u8 *get_offered_bolt11features(const tal_t *ctx UNNEEDED) { fprintf(stderr, "get_offered_bolt11features called!\n"); abort(); } diff --git a/openingd/Makefile b/openingd/Makefile index 31308c70504a..ea146d7e1a57 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -48,11 +48,13 @@ OPENINGD_COMMON_OBJS := \ common/derive_basepoints.o \ common/dev_disconnect.o \ common/features.o \ + common/fee_states.o \ common/funding_tx.o \ common/gen_status_wire.o \ common/gen_peer_status_wire.o \ common/gossip_rcvd_filter.o \ common/gossip_store.o \ + common/htlc_state.o \ common/htlc_wire.o \ common/initial_channel.o \ common/initial_commit_tx.o \ diff --git a/openingd/openingd.c b/openingd/openingd.c index 58f45e7a752e..d4d34e16efc1 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -670,7 +671,8 @@ static bool funder_finalize_channel_setup(struct state *state, state->minimum_depth, state->funding, local_msat, - state->feerate_per_kw, + take(new_fee_states(NULL, LOCAL, + &state->feerate_per_kw)), &state->localconf, &state->remoteconf, &state->our_points, @@ -1136,7 +1138,8 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) state->minimum_depth, state->funding, state->push_msat, - state->feerate_per_kw, + take(new_fee_states(NULL, REMOTE, + &state->feerate_per_kw)), &state->localconf, &state->remoteconf, &state->our_points, &theirs, diff --git a/tests/test_connection.py b/tests/test_connection.py index 277e49cdeddb..3cd056c8d766 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1499,7 +1499,7 @@ def test_update_fee_reconnect(node_factory, bitcoind): l1.daemon.wait_for_log(r'dev_disconnect: \+WIRE_COMMITMENT_SIGNED') # Wait for reconnect.... - l1.daemon.wait_for_log('Applying feerate 14000 to LOCAL') + l1.daemon.wait_for_log('Feerate:.*LOCAL now 14000') l1.pay(l2, 200000000) l2.pay(l1, 100000000) diff --git a/tools/generate-wire.py b/tools/generate-wire.py index 882350c03940..6b507cfa5249 100755 --- a/tools/generate-wire.py +++ b/tools/generate-wire.py @@ -221,6 +221,7 @@ class Type(FieldSet): 'per_peer_state', 'bitcoin_tx_output', 'exclude_entry', + 'fee_states', ] # Some BOLT types are re-typed based on their field name diff --git a/wallet/db.c b/wallet/db.c index 8652224b5122..c6ed48b3fbaf 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -561,6 +561,34 @@ static struct migration dbmigrations[] = { {SQL("DROP TABLE temp_payments;"), NULL}, {SQL("ALTER TABLE channel_htlcs ADD partid BIGINT;"), NULL}, {SQL("UPDATE channel_htlcs SET partid = 0;"), NULL}, + {SQL("CREATE TABLE channel_feerates (" + " channel_id BIGINT REFERENCES channels(id) ON DELETE CASCADE," + " hstate INTEGER," + " feerate_per_kw INTEGER," + " UNIQUE (channel_id, hstate)" + ");"), + NULL}, + /* Cast old-style per-side feerates into most likely layout for statewise + * feerates. */ + /* If we're funder (LOCAL=0): + * Then our feerate is set last (SENT_ADD_ACK_REVOCATION = 4) */ + {SQL("INSERT INTO channel_feerates(channel_id, hstate, feerate_per_kw)" + " SELECT id, 4, local_feerate_per_kw FROM channels WHERE funder = 0;"), + NULL}, + /* If different, assume their feerate is in state SENT_ADD_COMMIT = 1 */ + {SQL("INSERT INTO channel_feerates(channel_id, hstate, feerate_per_kw)" + " SELECT id, 1, remote_feerate_per_kw FROM channels WHERE funder = 0 and local_feerate_per_kw != remote_feerate_per_kw;"), + NULL}, + /* If they're funder (REMOTE=1): + * Then their feerate is set last (RCVD_ADD_ACK_REVOCATION = 14) */ + {SQL("INSERT INTO channel_feerates(channel_id, hstate, feerate_per_kw)" + " SELECT id, 14, remote_feerate_per_kw FROM channels WHERE funder = 1;"), + NULL}, + /* If different, assume their feerate is in state RCVD_ADD_COMMIT = 11 */ + {SQL("INSERT INTO channel_feerates(channel_id, hstate, feerate_per_kw)" + " SELECT id, 11, local_feerate_per_kw FROM channels WHERE funder = 1 and local_feerate_per_kw != remote_feerate_per_kw;"), + NULL}, + /* FIXME: Remove now-unused local_feerate_per_kw and remote_feerate_per_kw from channels */ }; /* Leak tracking. */ diff --git a/wallet/test/Makefile b/wallet/test/Makefile index c0ed67fa402d..fca59ea10ada 100644 --- a/wallet/test/Makefile +++ b/wallet/test/Makefile @@ -8,6 +8,7 @@ WALLET_TEST_COMMON_OBJS := \ common/derive_basepoints.o \ common/htlc_state.o \ common/htlc_wire.o \ + common/fee_states.o \ common/type_to_string.o \ common/memleak.o \ common/node_id.o \ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 98cc0b127bb6..02f8fe95c577 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -97,16 +97,16 @@ void fatal(const char *fmt UNNEEDED, ...) bool fromwire_channel_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED) { fprintf(stderr, "fromwire_channel_dev_memleak_reply called!\n"); abort(); } /* Generated stub for fromwire_channel_got_commitsig */ -bool fromwire_channel_got_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, u32 *feerate UNNEEDED, struct bitcoin_signature *signature UNNEEDED, secp256k1_ecdsa_signature **htlc_signature UNNEEDED, struct added_htlc **added UNNEEDED, struct secret **shared_secret UNNEEDED, struct fulfilled_htlc **fulfilled UNNEEDED, struct failed_htlc ***failed UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_tx **tx UNNEEDED) +bool fromwire_channel_got_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, struct fee_states **fee_states UNNEEDED, struct bitcoin_signature *signature UNNEEDED, secp256k1_ecdsa_signature **htlc_signature UNNEEDED, struct added_htlc **added UNNEEDED, struct secret **shared_secret UNNEEDED, struct fulfilled_htlc **fulfilled UNNEEDED, struct failed_htlc ***failed UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_tx **tx UNNEEDED) { fprintf(stderr, "fromwire_channel_got_commitsig called!\n"); abort(); } /* Generated stub for fromwire_channel_got_revoke */ -bool fromwire_channel_got_revoke(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *revokenum UNNEEDED, struct secret *per_commitment_secret UNNEEDED, struct pubkey *next_per_commit_point UNNEEDED, u32 *feerate UNNEEDED, struct changed_htlc **changed UNNEEDED) +bool fromwire_channel_got_revoke(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *revokenum UNNEEDED, struct secret *per_commitment_secret UNNEEDED, struct pubkey *next_per_commit_point UNNEEDED, struct fee_states **fee_states UNNEEDED, struct changed_htlc **changed UNNEEDED) { fprintf(stderr, "fromwire_channel_got_revoke called!\n"); abort(); } /* Generated stub for fromwire_channel_offer_htlc_reply */ bool fromwire_channel_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *id UNNEEDED, u16 *failure_code UNNEEDED, u8 **failurestr UNNEEDED) { fprintf(stderr, "fromwire_channel_offer_htlc_reply called!\n"); abort(); } /* Generated stub for fromwire_channel_sending_commitsig */ -bool fromwire_channel_sending_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, u32 *feerate UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_signature *commit_sig UNNEEDED, secp256k1_ecdsa_signature **htlc_sigs UNNEEDED) +bool fromwire_channel_sending_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, struct fee_states **fee_states UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_signature *commit_sig UNNEEDED, secp256k1_ecdsa_signature **htlc_sigs UNNEEDED) { fprintf(stderr, "fromwire_channel_sending_commitsig called!\n"); abort(); } /* Generated stub for fromwire_connect_peer_connected */ bool fromwire_connect_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct per_peer_state **pps UNNEEDED, u8 **features UNNEEDED) @@ -933,6 +933,17 @@ static bool channelseq(struct channel *c1, struct channel *c2) CHECK(pubkey_eq(&ci1->remote_per_commit, &ci2->remote_per_commit)); CHECK(pubkey_eq(&ci1->old_remote_per_commit, &ci2->old_remote_per_commit)); CHECK(ci1->their_config.id != 0 && ci1->their_config.id == ci2->their_config.id); + CHECK(fee_states_valid(ci1->fee_states, c1->funder)); + CHECK(fee_states_valid(ci2->fee_states, c2->funder)); + for (enum htlc_state i = 0; i < ARRAY_SIZE(ci1->fee_states->feerate); + i++) { + if (ci1->fee_states->feerate[i] == NULL) { + CHECK(ci2->fee_states->feerate[i] == NULL); + } else { + CHECK(*ci1->fee_states->feerate[i] + == *ci2->fee_states->feerate[i]); + } + } CHECK(c1->our_config.id != 0 && c1->our_config.id == c2->our_config.id); CHECK((lc1 != NULL) == (lc2 != NULL)); @@ -993,6 +1004,7 @@ static bool test_channel_crud(struct lightningd *ld, const tal_t *ctx) secp256k1_ecdsa_signature *node_sig1 = tal(w, secp256k1_ecdsa_signature); secp256k1_ecdsa_signature *bitcoin_sig1 = tal(w, secp256k1_ecdsa_signature); secp256k1_ecdsa_signature *node_sig2, *bitcoin_sig2; + u32 feerate; bool load; memset(&c1, 0, sizeof(c1)); @@ -1006,7 +1018,8 @@ static bool test_channel_crud(struct lightningd *ld, const tal_t *ctx) mempat(last_commit, tal_bytelen(last_commit)); pubkey_from_der(tal_hexdata(w, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &pk); node_id_from_pubkey(&id, &pk); - ci->feerate_per_kw[LOCAL] = ci->feerate_per_kw[REMOTE] = 31337; + feerate = 31337; + ci->fee_states = new_fee_states(w, c1.funder, &feerate); mempat(scriptpubkey, tal_count(scriptpubkey)); c1.first_blocknum = 1; parse_wireaddr_internal("localhost:1234", &addr, 0, false, false, false, diff --git a/wallet/wallet.c b/wallet/wallet.c index 3379c2b9702e..e9be1947fe02 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -2,8 +2,10 @@ #include "wallet.h" #include +#include #include #include +#include #include #include #include @@ -805,6 +807,42 @@ bool wallet_remote_ann_sigs_load(const tal_t *ctx, struct wallet *w, u64 id, return false; } +static struct fee_states *wallet_channel_fee_states_load(struct wallet *w, + const u64 id, + enum side funder) +{ + struct fee_states *fee_states; + struct db_stmt *stmt; + + stmt = db_prepare_v2(w->db, SQL("SELECT hstate, feerate_per_kw FROM channel_feerates WHERE channel_id = ?")); + db_bind_u64(stmt, 0, id); + db_query_prepared(stmt); + + /* Start with blank slate. */ + fee_states = new_fee_states(w, funder, NULL); + while (db_step(stmt)) { + enum htlc_state hstate = db_column_int(stmt, 0); + u32 feerate = db_column_int(stmt, 1); + + if (fee_states->feerate[hstate] != NULL) { + log_broken(w->log, + "duplicate channel_feerates for %s id %"PRIu64, + htlc_state_name(hstate), id); + fee_states = tal_free(fee_states); + break; + } + fee_states->feerate[hstate] = tal_dup(fee_states, u32, &feerate); + } + tal_free(stmt); + + if (fee_states && !fee_states_valid(fee_states, funder)) { + log_broken(w->log, + "invalid channel_feerates for id %"PRIu64, id); + fee_states = tal_free(fee_states); + } + return fee_states; +} + /** * wallet_stmt2channel - Helper to populate a wallet_channel from a `db_stmt` */ @@ -894,13 +932,19 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm db_column_pubkey(stmt, 22, &channel_info.theirbase.delayed_payment); db_column_pubkey(stmt, 23, &channel_info.remote_per_commit); db_column_pubkey(stmt, 24, &channel_info.old_remote_per_commit); - channel_info.feerate_per_kw[LOCAL] = db_column_int(stmt, 25); - channel_info.feerate_per_kw[REMOTE] = db_column_int(stmt, 26); wallet_channel_config_load(w, db_column_u64(stmt, 4), &channel_info.their_config); + channel_info.fee_states + = wallet_channel_fee_states_load(w, + db_column_u64(stmt, 0), + db_column_int(stmt, 6)); + if (!channel_info.fee_states) + ok = false; + if (!ok) { + tal_free(channel_info.fee_states); return NULL; } @@ -919,6 +963,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm db_column_amount_msat(stmt, 38, &msat_to_us_min); db_column_amount_msat(stmt, 39, &msat_to_us_max); + /* We want it to take this, rather than copy. */ + take(channel_info.fee_states); chan = new_channel(peer, db_column_u64(stmt, 0), &wshachain, db_column_int(stmt, 5), @@ -1011,6 +1057,7 @@ static bool wallet_channels_load_active(struct wallet *w) ", delayed_payment_basepoint_remote" ", per_commit_remote" ", old_per_commit_remote" + /* FIXME: We don't use these two: */ ", local_feerate_per_kw" ", remote_feerate_per_kw" ", shachain_remote_id" @@ -1358,8 +1405,6 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) " delayed_payment_basepoint_remote=?," " per_commit_remote=?," " old_per_commit_remote=?," - " local_feerate_per_kw=?," - " remote_feerate_per_kw=?," " channel_config_remote=?," " future_per_commitment_point=?" " WHERE id=?")); @@ -1370,16 +1415,33 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) db_bind_pubkey(stmt, 4, &chan->channel_info.theirbase.delayed_payment); db_bind_pubkey(stmt, 5, &chan->channel_info.remote_per_commit); db_bind_pubkey(stmt, 6, &chan->channel_info.old_remote_per_commit); - db_bind_int(stmt, 7, chan->channel_info.feerate_per_kw[LOCAL]); - db_bind_int(stmt, 8, chan->channel_info.feerate_per_kw[REMOTE]); - db_bind_u64(stmt, 9, chan->channel_info.their_config.id); + db_bind_u64(stmt, 7, chan->channel_info.their_config.id); if (chan->future_per_commitment_point) - db_bind_pubkey(stmt, 10, chan->future_per_commitment_point); + db_bind_pubkey(stmt, 8, chan->future_per_commitment_point); else - db_bind_null(stmt, 10); - db_bind_u64(stmt, 11, chan->dbid); + db_bind_null(stmt, 8); + db_bind_u64(stmt, 9, chan->dbid); db_exec_prepared_v2(take(stmt)); + /* FIXME: Updates channel_feerates by discarding and rewriting. */ + stmt = db_prepare_v2(w->db, SQL("DELETE FROM channel_feerates " + "WHERE channel_id=?")); + db_bind_u64(stmt, 0, chan->dbid); + db_exec_prepared_v2(take(stmt)); + + for (enum htlc_state i = 0; + i < ARRAY_SIZE(chan->channel_info.fee_states->feerate); + i++) { + if (!chan->channel_info.fee_states->feerate[i]) + continue; + stmt = db_prepare_v2(w->db, SQL("INSERT INTO channel_feerates " + " VALUES(?, ?, ?)")); + db_bind_u64(stmt, 0, chan->dbid); + db_bind_int(stmt, 1, i); + db_bind_int(stmt, 2, *chan->channel_info.fee_states->feerate[i]); + db_exec_prepared_v2(take(stmt)); + } + /* If we have a last_sent_commit, store it */ last_sent_commit = tal_arr(tmpctx, u8, 0); for (size_t i = 0; i < tal_count(chan->last_sent_commit); i++)