diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index 5744de929..2f778e402 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 899abed63..a901c1678 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); @@ -1363,10 +1363,12 @@ static void send_revocation(struct peer *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, - channel_feerate(peer->channel, LOCAL), + peer->channel->fee_states, commit_sig, htlc_sigs, added, shared_secret, @@ -1516,7 +1518,7 @@ 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); @@ -1535,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; } @@ -1595,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); @@ -2945,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; @@ -2963,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, @@ -3020,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), @@ -3028,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); @@ -3062,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], @@ -3097,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 f0d947fb8..7dc5c71e3 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -92,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, @@ -102,16 +102,13 @@ struct channel *new_full_channel(const tal_t *ctx, bool option_static_remotekey, enum side funder) { - /* FIXME: Support full feestates! */ - struct fee_states *fee_states = new_fee_states(NULL, funder, - &feerate_per_kw[funder]); struct channel *channel = new_initial_channel(ctx, funding_txid, funding_txout, minimum_depth, funding, local_msat, - take(fee_states), + fee_states, local, remote, local_basepoints, remote_basepoints, diff --git a/channeld/full_channel.h b/channeld/full_channel.h index 8fde9087f..1cfd950c1 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 1ff9be67e..63dbaec3e 100644 --- a/channeld/test/run-full_channel.c +++ b/channeld/test/run-full_channel.c @@ -469,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, @@ -479,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, @@ -655,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/devtools/mkcommit.c b/devtools/mkcommit.c index f7202f37e..b4e827f50 100644 --- a/devtools/mkcommit.c +++ b/devtools/mkcommit.c @@ -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 0f74f5af8..45603626b 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 6601bff79..a34de0f4f 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 9fe6e8b24..af3b1a063 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 71c6f88bd..374d4f72d 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 c83ba774f..21a33de06 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 676f4fa17..c51d5cd19 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 a43b9807e..5dd88833f 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 f6634d12b..c3fecb29b 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 eab27f7d3..d4bd272bc 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/tools/generate-wire.py b/tools/generate-wire.py index 882350c03..6b507cfa5 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/test/Makefile b/wallet/test/Makefile index c0ed67fa4..fca59ea10 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 98cc0b127..02f8fe95c 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 3379c2b97..e9be1947f 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 @@ fail: 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++)